diff --git a/CMakeLists.txt b/CMakeLists.txt index 60350bc42..fee1f725e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,24 +35,23 @@ string(REGEX REPLACE "([a-zA-Z_]+)\\.po" "\\1" LINPHONE_ALL_LANGS_LIST "${LINPHO string(REPLACE ";" " " LINPHONE_ALL_LANGS "${LINPHONE_ALL_LANGS_LIST}") include(CMakeDependentOption) +include(cmake/Tools.cmake) option(ENABLE_SHARED "Build shared library." YES) option(ENABLE_STATIC "Build static library." YES) option(ENABLE_CONSOLE_UI "Turn on or off compilation of console interface." YES) option(ENABLE_CSHARP_WRAPPER "Build the C# wrapper for Liblinphone." OFF) +option(ENABLE_JAVA_WRAPPER "Build the Java wrapper for Liblinphone." OFF) option(ENABLE_CXX_WRAPPER "Build the C++ wrapper for Liblinphone." YES) option(ENABLE_DAEMON "Enable the linphone daemon interface." YES) option(ENABLE_DATE "Use build date in internal version number." NO) option(ENABLE_DEBUG_LOGS "Turn on or off debug level logs." NO) -option(ENABLE_DOC "Enable documentation generation with Doxygen." YES) -option(ENABLE_GTK_UI "Turn on or off compilation of gtk interface." NO) +option(ENABLE_DOC "Enable API documentation generation." NO) option(ENABLE_JAVADOC "Add a target to generate documentation for Java API" NO) option(ENABLE_LDAP "Enable LDAP support." NO) -option(ENABLE_NLS "Build with internationalisation support" YES) option(ENABLE_RELATIVE_PREFIX "Find resources relatively to the installation directory." NO) option(ENABLE_ROOTCA_DOWNLOAD "Download rootca.pem at build time." YES) -option(ENABLE_SOCI_STORAGE "Turn on compilation soci storage, for messages, contacts, history" YES) option(ENABLE_SQLITE_STORAGE "Turn on compilation sqlite storage, for messages, contacts, history" YES) option(ENABLE_STRICT "Build with strict compile options." YES) option(ENABLE_TOOLS "Turn on or off compilation of tools." YES) @@ -66,14 +65,16 @@ option(ENABLE_VIDEO "Build with video support." YES) cmake_dependent_option(ENABLE_LIME "Enable Instant Messaging Encryption." YES "ENABLE_SQLITE_STORAGE" NO) cmake_dependent_option(ENABLE_NOTIFY "Enable libnotify support." YES "ENABLE_GTK_UI;NOT APPLE" NO) cmake_dependent_option(ENABLE_ASSISTANT "Turn on assistant compiling." YES "ENABLE_GTK_UI" NO) -cmake_dependent_option(ENABLE_SPHINX_DOC "Turn on the generation of the multi-language API documentation based on Sphinx." NO "ENABLE_DOC" NO) set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_EXTENSIONS NO) -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG") -set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -DNDEBUG") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DNDEBUG") -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release") +endif() +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + add_definitions("-DDEBUG") +endif() if(ENABLE_STATIC) set(LINPHONE_LIBS_FOR_TOOLS linphone-static) @@ -89,6 +90,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(CheckSymbolExists) include(CMakePushCheckState) include(GNUInstallDirs) +include(CheckCXXCompilerFlag) if(NOT CMAKE_INSTALL_RPATH AND CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_FULL_LIBDIR}) @@ -132,6 +134,7 @@ else() find_package(Belr REQUIRED) endif() find_package(XML2 REQUIRED) +find_package(LibXsd REQUIRED) find_package(Soci) find_package(ZLIB) if(ENABLE_TUNNEL) @@ -157,32 +160,9 @@ if(ENABLE_NOTIFY) set(ENABLE_NOTIFY OFF CACHE BOOL "Enable libnotify support." FORCE) endif() endif() -if(ENABLE_GTK_UI) - if(WIN32) - set(GTK2_ADDITIONAL_SUFFIXES "../lib/glib-2.0/include" "../lib/gtk-2.0/include") - endif() - find_package(GTK2 2.18 REQUIRED gtk) - if(ENABLE_ASSISTANT AND GTK2_VERSION VERSION_LESS 2.22) - message(WARNING "You need at least GTK 2.22 to enable the assistant") - set(ENABLE_ASSISTANT OFF CACHE BOOL "Turn on assistant compiling." FORCE) - endif() - if(APPLE) - find_package(GtkMacIntegration) - if(GTKMACINTEGRATION_FOUND) - set(HAVE_GTK_OSX 1) - add_definitions("${GTKMACINTEGRATION_CPPFLAGS}") - else() - message(WARNING "gtk-mac-integration not found. Please install gtk-osx-application package.") - endif() - endif() -endif() if(ENABLE_ASSISTANT) set(BUILD_WIZARD 1) endif() -if(ENABLE_NLS) - find_package(Gettext REQUIRED) - find_package(Intl REQUIRED) -endif() if(ENABLE_LIME) #bzrtp is only required for LIME if(LINPHONE_BUILDER_GROUP_EXTERNAL_SOURCE_PATH_BUILDERS) @@ -192,8 +172,15 @@ if(ENABLE_LIME) endif() set(HAVE_LIME 1) endif() -if(ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_SPHINX_DOC) +if(ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRAPPER OR ENABLE_DOC) find_package(PythonInterp REQUIRED) + check_python_module(pystache) + check_python_module(six) + if(ENABLE_DOC) + check_python_module(sphinx) + check_python_module(javasphinx) + check_python_module(sphinx_csharp) + endif() endif() if(UNIX AND NOT APPLE) @@ -201,9 +188,22 @@ if(UNIX AND NOT APPLE) check_include_files(libudev.h HAVE_LIBUDEV_H) endif() +if(MSVC AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + find_library(LIBGCC NAMES gcc) + find_library(LIBMINGWEX NAMES mingwex) +endif() + +if(NOT WIN32) + find_package(Iconv QUIET) +endif() +if(ANDROID) + find_package(CpuFeatures REQUIRED) + find_package(Support REQUIRED) +endif() + set(LINPHONE_LDFLAGS "${BELLESIP_LDFLAGS} ${MEDIASTREAMER2_LDFLAGS}") if(BELCARD_FOUND AND APPLE) - set(LINPHONE_LDFLAGS "${LINPHONE_LDFLAGS} -stdlib=libc++") + set(LINPHONE_LDFLAGS "${LINPHONE_LDFLAGS} -stdlib=libc++") endif() # include_directories must be called only UNDER THIS LINE in order to use our @@ -254,7 +254,6 @@ if(MSVC) include_directories(${MSVC_INCLUDE_DIR}) endif() -add_definitions("-DLINPHONE_EXPORTS") set(LINPHONE_CPPFLAGS ${BELCARD_CPPFLAGS} ${BELLESIP_CPPFLAGS} ${MEDIASTREAMER2_CPPFLAGS} ${BCTOOLBOX_CPPFLAGS} ${BELR_CPPFLAGS}) if(ENABLE_STATIC) list(APPEND LINPHONE_CPPFLAGS "-DLINPHONE_STATIC") @@ -268,6 +267,11 @@ if(ENABLE_DEBUG_LOGS) add_definitions("-DDEBUG_LOGS") endif() +# Enable stdint.h limit macros on C++ files. (Windows only.) +if(MSVC) + add_definitions("-D__STDC_LIMIT_MACROS") +endif() + set(STRICT_OPTIONS_CPP ) set(STRICT_OPTIONS_C ) set(STRICT_OPTIONS_CXX ) @@ -279,7 +283,26 @@ if(MSVC) list(APPEND STRICT_OPTIONS_CPP "/WX") endif() else() - list(APPEND STRICT_OPTIONS_CPP "-Wall" "-Wuninitialized" "-Wno-error=deprecated-declarations") + list(APPEND STRICT_OPTIONS_CPP + "-Wall" + "-Wcast-align" + "-Wconversion" + "-Werror=return-type" + "-Wfloat-equal" + "-Winit-self" + "-Wno-error=deprecated-declarations" + "-Wpointer-arith" + "-Wuninitialized" + "-Wunused" + ) + list(APPEND STRICT_OPTIONS_CXX + "-Wnon-virtual-dtor" + "-Woverloaded-virtual" + ) + CHECK_CXX_COMPILER_FLAG("-Wsuggest-override" SUGGEST_OVERRIDE) + if (SUGGEST_OVERRIDE) + list(APPEND STRICT_OPTIONS_CXX "-Wsuggest-override" "-Wno-error=suggest-override" ) + endif () list(APPEND STRICT_OPTIONS_C "-Wstrict-prototypes" "-Werror=strict-prototypes") if(CMAKE_C_COMPILER_ID STREQUAL "GNU") list(APPEND STRICT_OPTIONS_C "-fno-inline-small-functions") @@ -305,7 +328,6 @@ if(STRICT_OPTIONS_C) list(REMOVE_DUPLICATES STRICT_OPTIONS_C) endif() - set(GETTEXT_PACKAGE "linphone") if(ENABLE_RELATIVE_PREFIX) set(LINPHONE_DATA_DIR ".") @@ -318,6 +340,7 @@ if(WIN32) endif() set(PACKAGE_LOCALE_DIR "${LINPHONE_DATA_DIR}/${CMAKE_INSTALL_DATADIR}/locale") set(PACKAGE_DATA_DIR "${LINPHONE_DATA_DIR}/${CMAKE_INSTALL_DATADIR}") +set(PACKAGE_GRAMMAR_DIR "${LINPHONE_DATA_DIR}/${CMAKE_INSTALL_DATADIR}/belr/grammars") set(PACKAGE_SOUND_DIR "${LINPHONE_DATA_DIR}/${CMAKE_INSTALL_DATADIR}/sounds/linphone") set(PACKAGE_RING_DIR "${PACKAGE_SOUND_DIR}/rings") set(PACKAGE_FREEDESKTOP_DIR "${PACKAGE_DATA_DIR}/applications") @@ -339,8 +362,11 @@ endif() add_subdirectory(include) add_subdirectory(java) -add_subdirectory(src) +if(ENABLE_JAVA_WRAPPER) + add_subdirectory(wrappers/java) +endif() add_subdirectory(coreapi) +add_subdirectory(src) add_subdirectory(share) if(ENABLE_CONSOLE_UI) add_subdirectory(console) @@ -348,11 +374,6 @@ endif() if(ENABLE_DAEMON) add_subdirectory(daemon) endif() -if(ENABLE_GTK_UI) - add_subdirectory(gtk) - add_subdirectory(pixmaps) - add_subdirectory(po) -endif() if(ENABLE_TOOLS) add_subdirectory(tools) endif() diff --git a/README.md b/README.md index 49a4d684f..8e2dede38 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,22 @@ Building liblinphone ### Required dependencies -* *BcToolbox[2]*: portability layer -* *BelleSIP[3]*: SIP stack -* *Mediastreamer2[4]*: multimedia engine -* *Belcard[5]*: VCard support -* libxml2 -* zlib -* libsqlite3: user data storage (disablable) -* gettext and libintl: internationalization support (disablable) +* **BcToolbox[2]:** portability layer +* **BelleSIP[3]:** SIP stack +* **Mediastreamer2[4]:** multimedia engine +* **Belcard[5]:** VCard support +* **libxml2** +* **zlib** +* **libsqlite3:** user data storage (disablable) +* **gettext** and **libintl**: internationalization support (disablable) +* **python interpreter** and **pystache**, **six** python module (needed for C++ wrapper and API documentaiton) +* **doxygen** and **dot** (needed for C++ wrapper and API documentation) ### Opitonal dependencies -* *Bzrtp[6]*: zrtp stack used for Linphone Instant Messaging Encryption +* **Bzrtp[6]**: zrtp stack used for Linphone Instant Messaging Encryption. +* For API documentatino generation: **sphinx**, **javasphinx**, **sphinx_csharp** python modules are needed. ### Build instructions @@ -38,18 +41,17 @@ Building liblinphone ### Supported build opitons -* `CMAKE_INSTALL_PREFIX=` : install prefix -* `CMAKE_PREFIX_PATH=` : column-separated list of prefixes where to search for dependencies -* `ENABLE_SHARED=NO` : do not build the shared library -* `ENABLE_STATIC=NO` : do not build the static library -* `ENABLE_STRICT=NO` : build without strict compilation flags (-Wall -Werror) -* `ENABLE_DOC=NO` : do not generate the reference documentation of liblinphone -* `ENABLE_UNIT_TESTS=NO` : do not build testing binaries -* `ENABLE_VCARD=NO` : disable VCard support -* `ENABLE_SQLITE_STORAGE=NO` : disable SQlite user data storage (message, history, contacts list) -* `ENABLE_TOOLS=NO` : do not build tool binaries -* `ENABLE_NLS=NO` : disable internationalization -* `ENABLE_LIME=YES` : disable Linphone Instant Messaging Encryption +* **`CMAKE_INSTALL_PREFIX=`** : install prefix +* **`CMAKE_PREFIX_PATH=`** : column-separated list of prefixes where to search for dependencies +* **`ENABLE_SHARED=NO`** : do not build the shared library +* **`ENABLE_STATIC=NO`** : do not build the static library +* **`ENABLE_STRICT=NO`** : build without strict compilation flags (-Wall -Werror) +* **`ENABLE_DOC=YES`** : Make the reference documentation of liblinphone to generated +* **`ENABLE_UNIT_TESTS=NO`** : do not build testing binaries +* **`ENABLE_VCARD=NO`** : disable VCard support +* **`ENABLE_SQLITE_STORAGE=NO`** : disable SQlite user data storage (message, history, contacts list) +* **`ENABLE_TOOLS=NO`** : do not build tool binaries +* **`ENABLE_LIME=YES`** : disable Linphone Instant Messaging Encryption ### Note for packagers @@ -92,4 +94,4 @@ Here is a short description of the content of the source tree. - [3] belle-sip: git://git.linphone.org/belle-sip.git *or* - [4] mediastreamer2: git://git.linphone.org/mediastreamer2.git *or* - [5] belcard: git://git.linphone.org/belcard.git *or* -- [5] bzrtp: git://git.linphone.org/bzrtp.git *or* +- [6] bzrtp: git://git.linphone.org/bzrtp.git *or* diff --git a/build/rpm/liblinphone.spec.cmake b/build/rpm/liblinphone.spec.cmake index 79af78e00..cb487577f 100755 --- a/build/rpm/liblinphone.spec.cmake +++ b/build/rpm/liblinphone.spec.cmake @@ -30,9 +30,13 @@ Requires: %{pkg_prefix}bctoolbox Requires: %{pkg_prefix}ortp Requires: %{pkg_prefix}mediastreamer Requires: %{pkg_prefix}belle-sip +Requires: %{pkg_prefix}belr %if @ENABLE_VCARD@ Requires: %{pkg_prefix}belcard %endif +%if @ENABLE_SOCI_STORAGE@ +Requires: %{pkg_prefix}soci +%endif %description liblinphone is the voip sdk used by Linphone @@ -116,6 +120,7 @@ rm -rf $RPM_BUILD_ROOT %endif %{_datadir}/Linphone/cmake/*.cmake %{_datadir}/LinphoneCxx/cmake/*.cmake +%{_datadir}/belr/grammars/cpim_grammar %changelog diff --git a/cmake/FindGtkMacIntegration.cmake b/cmake/FindGtkMacIntegration.cmake deleted file mode 100644 index 17c8efc8c..000000000 --- a/cmake/FindGtkMacIntegration.cmake +++ /dev/null @@ -1,54 +0,0 @@ -############################################################################ -# FindGtkMacIntegration.txt -# Copyright (C) 2015 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -############################################################################ -# -# - Find the libgtkmacintegration include file and library -# -# GTKMACINTEGRATION_FOUND - system has libgtkmacintegration -# GTKMACINTEGRATION_INCLUDE_DIRS - the libgtkmacintegration include directory -# GTKMACINTEGRATION_LIBRARIES - The libraries needed to use libgtkmacintegration -# GTKMACINTEGRATION_CPPFLAGS - The cflags needed to use libgtkmacintegration - -set(_GTKMACINTEGRATION_ROOT_PATHS - ${CMAKE_INSTALL_PREFIX} -) - -find_path(GTKMACINTEGRATION_INCLUDE_DIRS - NAMES gtkosxapplication.h - HINTS _GTKMACINTEGRATION_ROOT_PATHS - PATH_SUFFIXES include/gtkmacintegration-gtk2 include/gtkmacintegration -) - -find_library(GTKMACINTEGRATION_LIBRARIES - NAMES gtkmacintegration-gtk2 gtkmacintegration - HINTS ${_GTKMACINTEGRATION_ROOT_PATHS} - PATH_SUFFIXES bin lib -) - -set(GTKMACINTEGRATION_CPPFLAGS "-DMAC_INTEGRATION") - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GTKMACINTEGRATION - DEFAULT_MSG - GTKMACINTEGRATION_INCLUDE_DIRS GTKMACINTEGRATION_LIBRARIES GTKMACINTEGRATION_CPPFLAGS -) - -mark_as_advanced(GTKMACINTEGRATION_INCLUDE_DIRS GTKMACINTEGRATION_LIBRARIES GTKMACINTEGRATION_CPPFLAGS) diff --git a/cmake/FindIntl.cmake b/cmake/FindLibXsd.cmake similarity index 58% rename from cmake/FindIntl.cmake rename to cmake/FindLibXsd.cmake index 97dfea8e0..2e37c38fe 100644 --- a/cmake/FindIntl.cmake +++ b/cmake/FindLibXsd.cmake @@ -1,6 +1,6 @@ ############################################################################ -# FindIntl.cmake -# Copyright (C) 2014 Belledonne Communications, Grenoble France +# FindLibXsd.cmake +# Copyright (C) 2017 Belledonne Communications, Grenoble France # ############################################################################ # @@ -20,37 +20,29 @@ # ############################################################################ # -# - Find the libintl include file and library +# - Find the libxsd library # -# INTL_FOUND - system has libintl -# INTL_INCLUDE_DIRS - the libintl include directory -# INTL_LIBRARIES - The libraries needed to use libintl +# LIBXSD_FOUND - system has libxsd +# LIBXSD_INCLUDE_DIRS - the libxsd include directory +# LIBXSD_LIBRARIES - The libraries needed to use libxsd -set(_INTL_ROOT_PATHS - ${CMAKE_INSTALL_PREFIX} -) -find_path(INTL_INCLUDE_DIRS - NAMES libintl.h - HINTS _INTL_ROOT_PATHS +find_package(XercesC) + +find_path(LIBXSD_INCLUDE_DIRS + NAMES xsd/cxx/config.hxx PATH_SUFFIXES include ) -if(INTL_INCLUDE_DIRS) - set(HAVE_LIBINTL_H 1) -endif() - -set(INTL_ARGS INTL_INCLUDE_DIRS HAVE_LIBINTL_H) -if(NOT UNIX OR APPLE) - find_library(INTL_LIBRARIES - NAMES intl - HINTS ${_INTL_ROOT_PATHS} - PATH_SUFFIXES bin lib - ) - list(APPEND INTL_ARGS INTL_LIBRARIES) +if(LIBXSD_INCLUDE_DIRS) + list(APPEND LIBXSD_INCLUDE_DIRS ${XercesC_INCLUDE_DIRS}) endif() +set(LIBXSD_LIBRARIES ${XercesC_LIBRARIES}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Intl DEFAULT_MSG ${INTL_ARGS}) +find_package_handle_standard_args(LibXsd + DEFAULT_MSG + LIBXSD_INCLUDE_DIRS LIBXSD_LIBRARIES +) -mark_as_advanced(${INTL_ARGS}) +mark_as_advanced(LIBXSD_INCLUDE_DIRS LIBXSD_LIBRARIES) diff --git a/cmake/FindSoci.cmake b/cmake/FindSoci.cmake index 91c4e376d..a2257ad05 100644 --- a/cmake/FindSoci.cmake +++ b/cmake/FindSoci.cmake @@ -25,6 +25,7 @@ # SET(_SOCI_ALL_PLUGINS mysql sqlite3) SET(_SOCI_REQUIRED_VARS SOCI_INCLUDE_DIRS SOCI_LIBRARIES) +SET(_SOCI_VERSION "_4_0") # ### FIRST STEP: Find the soci headers. @@ -37,7 +38,7 @@ MARK_AS_ADVANCED(SOCI_INCLUDE_DIRS) ### SECOND STEP: Find the soci core library. Respect LIB_SUFFIX # FIND_LIBRARY(SOCI_LIBRARIES - NAMES soci_core + NAMES soci_core soci_core${_SOCI_VERSION} PATH_SUFFIXES lib lib64) MARK_AS_ADVANCED(SOCI_LIBRARIES) @@ -54,13 +55,17 @@ IF(SOCI_INCLUDE_DIRS AND SOCI_LIBRARIES) FIND_LIBRARY( SOCI_${plugin}_PLUGIN - NAMES soci_${plugin} + NAMES soci_${plugin} soci_${plugin}${_SOCI_VERSION} PATH_SUFFIXES lib lib64) MARK_AS_ADVANCED(SOCI_${plugin}_PLUGIN) IF(SOCI_${plugin}_PLUGIN) MESSAGE(STATUS " * Plugin ${plugin} found ${SOCI_${plugin}_PLUGIN}.") SET(SOCI_${plugin}_FOUND True) + + if(IOS OR ANDROID) + list(APPEND SOCI_LIBRARIES ${SOCI_${plugin}_PLUGIN}) + endif() ELSE() MESSAGE(STATUS " * Plugin ${plugin} not found.") SET(SOCI_${plugin}_FOUND False) @@ -84,4 +89,3 @@ ENDIF() # include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Soci DEFAULT_MSG ${_SOCI_REQUIRED_VARS}) - diff --git a/po/CMakeLists.txt b/cmake/Tools.cmake similarity index 68% rename from po/CMakeLists.txt rename to cmake/Tools.cmake index b51481639..8c3d3d0c7 100644 --- a/po/CMakeLists.txt +++ b/cmake/Tools.cmake @@ -1,6 +1,6 @@ ############################################################################ -# CMakeLists.txt -# Copyright (C) 2014 Belledonne Communications, Grenoble France +# LinphoneUtils.cmake +# Copyright (C) 2018 Belledonne Communications, Grenoble France # ############################################################################ # @@ -20,13 +20,14 @@ # ############################################################################ -if(GETTEXT_FOUND) - foreach(language ${LINPHONE_ALL_LANGS_LIST}) - GETTEXT_PROCESS_PO_FILES(${language} ALL PO_FILES ${language}.po) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${language}.gmo - DESTINATION ${PACKAGE_LOCALE_DIR}/${language}/LC_MESSAGES - RENAME linphone.mo - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - ) - endforeach() -endif() +function(check_python_module module_name) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import ${module_name}" + RESULT_VARIABLE result + OUTPUT_QUIET + ERROR_QUIET) + if(result EQUAL 0) + message(STATUS "'${module_name}' python module found") + else() + message(FATAL_ERROR "'${module_name}' python module not found") + endif() +endfunction() diff --git a/config.h.cmake b/config.h.cmake index 5de3f36a3..50538b14b 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -35,16 +35,15 @@ #define PACKAGE_LOCALE_DIR "${PACKAGE_LOCALE_DIR}" #define PACKAGE_DATA_DIR "${PACKAGE_DATA_DIR}" +#define PACKAGE_GRAMMAR_DIR "${PACKAGE_GRAMMAR_DIR}" #define PACKAGE_SOUND_DIR "${PACKAGE_SOUND_DIR}" #define PACKAGE_RING_DIR "${PACKAGE_RING_DIR}" #cmakedefine BUILD_WIZARD -#cmakedefine HAVE_GTK_OSX 1 #cmakedefine HAVE_NOTIFY4 #cmakedefine HAVE_ZLIB 1 #cmakedefine HAVE_CU_GET_SUITE 1 #cmakedefine HAVE_CU_CURSES 1 #cmakedefine HAVE_LIBUDEV_H 0 #cmakedefine HAVE_LIME -#cmakedefine ENABLE_NLS 1 #cmakedefine ENABLE_UPDATE_CHECK 1 diff --git a/console/CMakeLists.txt b/console/CMakeLists.txt index 532084b5f..c48c5cbab 100644 --- a/console/CMakeLists.txt +++ b/console/CMakeLists.txt @@ -37,7 +37,7 @@ if(MSVC) endif() add_executable(linphonec ${LINPHONEC_SOURCE_FILES}) -target_link_libraries(linphonec ${LINPHONE_LIBS_FOR_TOOLS} ${BCTOOLBOX_CORE_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES}) +target_link_libraries(linphonec ${LINPHONE_LIBS_FOR_TOOLS} ${BCTOOLBOX_CORE_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(linphonec PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") if(INTL_FOUND) @@ -46,7 +46,7 @@ endif() if(WIN32) add_executable(linphoned WIN32 ${LINPHONEC_SOURCE_FILES}) - target_link_libraries(linphoned ${LINPHONE_LIBS_FOR_TOOLS} ${BCTOOLBOX_CORE_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES}) + target_link_libraries(linphoned ${LINPHONE_LIBS_FOR_TOOLS} ${BCTOOLBOX_CORE_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${XSD_LIBRARIES}) if(INTL_FOUND) target_link_libraries(linphoned ${INTL_LIBRARIES}) endif() diff --git a/console/commands.c b/console/commands.c index 3c3b502f0..f8334b79e 100644 --- a/console/commands.c +++ b/console/commands.c @@ -456,14 +456,15 @@ linphonec_parse_command_line(LinphoneCore *lc, char *cl) char * linphonec_command_generator(const char *text, int state) { - static int index, len, adv; + static size_t len; + static int index, adv; char *name; if ( ! state ) { index=0; adv=0; - len=(int)strlen(text); + len=strlen(text); } /* * Return the next name which partially matches @@ -665,8 +666,8 @@ lpc_cmd_transfer(LinphoneCore *lc, char *args) const char *refer_to=NULL; char arg1[256]={0}; char arg2[266]={0}; - long id2=0; - int n=sscanf(args,"%255s %265s %li",arg1,arg2,&id2); + int id2=0; + int n=sscanf(args,"%255s %265s %d",arg1,arg2,&id2); if (n==1 || isalpha(*arg1)){ call=linphone_core_get_current_call(lc); if (call==NULL && bctbx_list_size(linphone_core_get_calls(lc))==1){ @@ -679,13 +680,13 @@ lpc_cmd_transfer(LinphoneCore *lc, char *args) } linphone_call_transfer(call, refer_to); }else if (n==2){ - long id=atoi(arg1); + int id=atoi(arg1); refer_to=args+strlen(arg1)+1; call=linphonec_get_call(id); if (call==NULL) return 0; linphone_call_transfer(call, refer_to); }else if (n==3){ - long id=atoi(arg1); + int id=atoi(arg1); call=linphonec_get_call(id); call2=linphonec_get_call(id2); if (call==NULL || call2==NULL) return 0; @@ -723,7 +724,7 @@ lpc_cmd_terminate(LinphoneCore *lc, char *args) return 1; }else{ /*the argument is a linphonec call id */ - long id=atoi(args); + int id=atoi(args); LinphoneCall *call=linphonec_get_call(id); if (call){ if (linphone_call_terminate(call)==-1){ @@ -764,9 +765,9 @@ lpc_cmd_redirect(LinphoneCore *lc, char *args){ } } else { char space; - long id; + int id; int charRead; - if ( sscanf(args, "%li%c%n", &id, &space, &charRead) == 2 && space == ' ') { + if ( sscanf(args, "%d%c%n", &id, &space, &charRead) == 2 && space == ' ') { LinphoneCall * call = linphonec_get_call(id); if ( call != NULL ) { if (linphone_call_get_state(call)!=LinphoneCallIncomingReceived) { @@ -799,8 +800,8 @@ lpc_cmd_answer(LinphoneCore *lc, char *args){ } return 1; }else{ - long id; - if (sscanf(args,"%li",&id)==1){ + int id; + if (sscanf(args,"%d",&id)==1){ LinphoneCall *call=linphonec_get_call (id); if (linphone_call_accept(call)==-1){ linphonec_out("Fail to accept call %i\n",id); @@ -929,6 +930,7 @@ lpc_cmd_firewall(LinphoneCore *lc, char *args) return 1; } linphone_core_set_firewall_policy(lc,LinphonePolicyUseNatAddress); + setting = linphone_core_get_nat_address(lc); } } @@ -1003,14 +1005,14 @@ lpc_cmd_friend(LinphoneCore *lc, char *args) { args+=4; if ( ! *args ) return 0; - friend_num = strtol(args, NULL, 10); + friend_num = (int)strtol(args, NULL, 10); #ifndef _WIN32_WCE if ( errno == ERANGE ) { linphonec_out("Invalid friend number\n"); return 0; } #endif /*_WIN32_WCE*/ - linphonec_friend_call(lc, friend_num); + linphonec_friend_call(lc, (unsigned int)friend_num); return 1; } else if ( !strncmp(args, "delete", 6) ) @@ -1025,7 +1027,7 @@ lpc_cmd_friend(LinphoneCore *lc, char *args) } else { - friend_num = strtol(args, NULL, 10); + friend_num = (int)strtol(args, NULL, 10); #ifndef _WIN32_WCE if ( errno == ERANGE ) { linphonec_out("Invalid friend number\n"); @@ -1470,10 +1472,10 @@ static int lpc_cmd_resume(LinphoneCore *lc, char *args){ } if (args) { - long id; - int n = sscanf(args, "%li", &id); + int id; + int n = sscanf(args, "%d", &id); if (n == 1){ - LinphoneCall *call=linphonec_get_call (id); + LinphoneCall *call=linphonec_get_call(id); if (call){ if(linphone_call_resume(call)==-1){ linphonec_out("There was a problem to resume the call check the remote address you gave %s\n",args); @@ -1505,11 +1507,11 @@ static int lpc_cmd_resume(LinphoneCore *lc, char *args){ } static int lpc_cmd_conference(LinphoneCore *lc, char *args){ - long id; + int id; char subcommand[32]={0}; int n; if (args==NULL) return 0; - n=sscanf(args, "%31s %li", subcommand,&id); + n=sscanf(args, "%31s %d", subcommand,&id); if (n == 2){ LinphoneCall *call=linphonec_get_call(id); if (call==NULL) return 1; @@ -2411,12 +2413,12 @@ static int lpc_cmd_rtp_no_xmit_on_audio_mute(LinphoneCore *lc, char *args) #ifdef VIDEO_ENABLED static int _lpc_cmd_video_window(LinphoneCore *lc, char *args, bool_t is_preview){ char subcommand[64]; - long a,b; + int a,b; int err; VideoParams *params=is_preview ? &lpc_preview_params : &lpc_video_params; if (!args) return 0; - err=sscanf(args,"%63s %ld %ld",subcommand,&a,&b); + err=sscanf(args,"%63s %d %d",subcommand,&a,&b); if (err>=1){ if (strcmp(subcommand,"pos")==0){ if (err<3) return 0; @@ -2442,11 +2444,11 @@ static int _lpc_cmd_video_window(LinphoneCore *lc, char *args, bool_t is_preview linphone_core_get_native_video_window_id (lc)); return 1; } else if (err != 2) return 0; - params->wid=(void *)a; + params->wid=(void *)(long)a; if (is_preview) - linphone_core_set_native_preview_window_id(lc, (void *)a); + linphone_core_set_native_preview_window_id(lc, (void *)(long)a); else - linphone_core_set_native_video_window_id(lc, (void *)a); + linphone_core_set_native_video_window_id(lc, (void *)(long)a); }else if (is_preview==TRUE){ if (strcmp(subcommand,"integrated")==0){ linphone_core_use_preview_window (lc,FALSE); @@ -2491,7 +2493,7 @@ static void lpc_display_call_states(LinphoneCore *lc){ tmp=linphone_call_get_remote_address_as_string (call); flag=in_conference ? "conferencing" : ""; flag=linphone_call_has_transfer_pending(call) ? "transfer pending" : flag; - linphonec_out("%-2i | %-35s | %-15s | %s\n",VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)), + linphonec_out("%-2i | %-35s | %-15s | %s\n",VOIDPTR_TO_INT(linphone_call_get_user_data(call)), tmp,linphone_call_state_to_string(linphone_call_get_state(call))+strlen("LinphoneCall"),flag); ms_free(tmp); } diff --git a/console/linphonec.c b/console/linphonec.c index 0ff82a624..b786288b4 100644 --- a/console/linphonec.c +++ b/console/linphonec.c @@ -28,7 +28,6 @@ #include #include #include -#include "private.h" /*coreapi/private.h, needed for LINPHONE_VERSION */ #endif /*_WIN32_WCE*/ #include #include @@ -111,9 +110,6 @@ static char **linephonec_readline_completion(const char *text, /* These are callback for linphone core */ static void linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *username, const char *domain); static void linphonec_display_refer (LinphoneCore * lc, const char *refer_to); -static void linphonec_display_something (LinphoneCore * lc, const char *something); -static void linphonec_display_url (LinphoneCore * lc, const char *something, const char *url); -static void linphonec_display_warning (LinphoneCore * lc, const char *something); static void linphonec_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState new_call_state); static void linphonec_notify_presence_received(LinphoneCore *lc,LinphoneFriend *fid); @@ -122,7 +118,6 @@ static void linphonec_new_unknown_subscriber(LinphoneCore *lc, static void linphonec_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, const LinphoneAddress *from, const char *msg); -static void linphonec_display_status (LinphoneCore * lc, const char *something); static void linphonec_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf); static void print_prompt(LinphoneCore *opm); void linphonec_out(const char *fmt,...); @@ -175,7 +170,7 @@ bool_t linphonec_camera_enabled=TRUE; void linphonec_call_identify(LinphoneCall* call){ static int callid=1; - linphone_call_set_user_pointer (call,INT_TO_VOIDPTR(callid)); + linphone_call_set_user_data (call,INT_TO_VOIDPTR(callid)); callid++; } @@ -183,7 +178,7 @@ LinphoneCall *linphonec_get_call(int id){ const MSList *elem=linphone_core_get_calls(linphonec); for (;elem!=NULL;elem=elem->next){ LinphoneCall *call=(LinphoneCall*)elem->data; - if (VOIDPTR_TO_INT(linphone_call_get_user_pointer(call))==id){ + if (VOIDPTR_TO_INT(linphone_call_get_user_data(call))==id){ return call; } } @@ -206,45 +201,6 @@ linphonec_display_refer (LinphoneCore * lc, const char *refer_to) linphonec_out("Receiving out of call refer to %s\n", refer_to); } -/* - * Linphone core callback - */ -static void -linphonec_display_something (LinphoneCore * lc, const char *something) -{ - fprintf (stdout, "%s\n%s", something,prompt); - fflush(stdout); -} - -/* - * Linphone core callback - */ -static void -linphonec_display_status (LinphoneCore * lc, const char *something) -{ - fprintf (stdout, "%s\n%s", something,prompt); - fflush(stdout); -} - -/* - * Linphone core callback - */ -static void -linphonec_display_warning (LinphoneCore * lc, const char *something) -{ - fprintf (stdout, "Warning: %s\n%s", something,prompt); - fflush(stdout); -} - -/* - * Linphone core callback - */ -static void -linphonec_display_url (LinphoneCore * lc, const char *something, const char *url) -{ - fprintf (stdout, "%s : %s\n", something, url); -} - /* * Linphone core callback */ @@ -279,7 +235,7 @@ linphonec_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneC char *remote=linphone_call_get_remote_address_as_string(call); if (new_call_state==LinphoneCallConnected){ linphonec_out("The distant endpoint %s of call %i has been transfered, you can safely close the call.\n", - remote,VOIDPTR_TO_INT(linphone_call_get_user_pointer(call))); + remote,VOIDPTR_TO_INT(linphone_call_get_user_data(call))); } ms_free(remote); } @@ -322,7 +278,7 @@ static void linphonec_call_updated(LinphoneCall *call){ } static void linphonec_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t encrypted, const char *auth_token) { - int id=VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)); + int id=VOIDPTR_TO_INT(linphone_call_get_user_data(call)); if (!encrypted) { linphonec_out("Call %i is not fully encrypted and auth token is %s.\n", id, (auth_token != NULL) ? auth_token : "absent"); @@ -334,7 +290,7 @@ static void linphonec_call_encryption_changed(LinphoneCore *lc, LinphoneCall *ca static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState st, const char *msg){ char *from=linphone_call_get_remote_address_as_string(call); - int id=VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)); + int id=VOIDPTR_TO_INT(linphone_call_get_user_data(call)); switch(st){ case LinphoneCallEnd: linphonec_out("Call %i with %s ended (%s).\n", id, from, linphone_reason_to_string(linphone_call_get_reason(call))); @@ -357,7 +313,7 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L case LinphoneCallIncomingReceived: linphonec_call_identify(call); linphone_call_enable_camera (call,linphonec_camera_enabled); - id=VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)); + id=VOIDPTR_TO_INT(linphone_call_get_user_data(call)); linphonec_set_caller(from); linphonec_out("Receiving new incoming call from %s, assigned id %i\n", from,id); if ( auto_answer) { @@ -373,7 +329,7 @@ static void linphonec_call_state_changed(LinphoneCore *lc, LinphoneCall *call, L break; case LinphoneCallOutgoingInit: linphonec_call_identify(call); - id=VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)); + id=VOIDPTR_TO_INT(linphone_call_get_user_data(call)); linphonec_out("Establishing call id to %s, assigned id %i\n", from,id); break; case LinphoneCallUpdatedByRemote: @@ -637,10 +593,6 @@ main (int argc, char *argv[]) { linphonec_vtable.notify_presence_received = linphonec_notify_presence_received; linphonec_vtable.new_subscription_requested = linphonec_new_unknown_subscriber; linphonec_vtable.auth_info_requested = linphonec_prompt_for_auth; - linphonec_vtable.display_status = linphonec_display_status; - linphonec_vtable.display_message=linphonec_display_something; - linphonec_vtable.display_warning=linphonec_display_warning; - linphonec_vtable.display_url=linphonec_display_url; linphonec_vtable.text_received=linphonec_text_received; linphonec_vtable.dtmf_received=linphonec_dtmf_received; linphonec_vtable.refer_received=linphonec_display_refer; @@ -837,7 +789,7 @@ linphonec_prompt_for_auth_final(LinphoneCore *lc) pending_auth=auth_stack.elem[auth_stack.nitems-1]; snprintf(auth_prompt, 256, "Password for %s on %s: ", - pending_auth->username, pending_auth->realm); + linphone_auth_info_get_username(pending_auth), linphone_auth_info_get_realm(pending_auth)); printf("\n"); #ifdef HAVE_READLINE diff --git a/coreapi/CMakeLists.txt b/coreapi/CMakeLists.txt index d14655d5d..be6515224 100644 --- a/coreapi/CMakeLists.txt +++ b/coreapi/CMakeLists.txt @@ -20,25 +20,12 @@ # ############################################################################ -if(MSVC AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - find_library(LIBGCC NAMES gcc) - find_library(LIBMINGWEX NAMES mingwex) -endif() - -if(NOT WIN32) - find_package(Iconv QUIET) -endif() -if(ANDROID) - find_package(CpuFeatures REQUIRED) - find_package(Support REQUIRED) -endif() - - list(APPEND LINPHONE_PRIVATE_HEADER_FILES bellesip_sal/sal_impl.h carddav.h conference_private.h contact_providers_priv.h + core_private.h enum.h lime.h lpc2xml.h @@ -48,35 +35,22 @@ list(APPEND LINPHONE_PRIVATE_HEADER_FILES sqlite3_bctbx_vfs.h vcard_private.h xml2lpc.h - platform-helpers.h ) set(LINPHONE_SOURCE_FILES_C account_creator.c account_creator_service.c - address.c authentication.c bellesip_sal/sal_address_impl.c bellesip_sal/sal_impl.c - bellesip_sal/sal_op_call.c - bellesip_sal/sal_op_call_transfer.c - bellesip_sal/sal_op_events.c bellesip_sal/sal_op_impl.c - bellesip_sal/sal_op_info.c - bellesip_sal/sal_op_message.c - bellesip_sal/sal_op_presence.c - bellesip_sal/sal_op_publish.c - bellesip_sal/sal_op_registration.c bellesip_sal/sal_sdp.c buffer.c callbacks.c call_log.c - call_params.c carddav.c chat.c - chat_file_transfer.c contactprovider.c - content.c dial_plan.c dict.c ec-calibrator.c @@ -100,7 +74,6 @@ set(LINPHONE_SOURCE_FILES_C lpc2xml.c lpconfig.c lsd.c - message_storage.c misc.c nat_policy.c offeranswer.c @@ -111,7 +84,6 @@ set(LINPHONE_SOURCE_FILES_C quality_reporting.c remote_provisioning.c ringtoneplayer.c - sal.c siplogin.c sipsetup.c sqlite3_bctbx_vfs.c @@ -123,13 +95,16 @@ set(LINPHONE_SOURCE_FILES_C ) set(LINPHONE_SOURCE_FILES_CXX conference.cc - platform-helpers.cpp - android-helpers.cpp - ios-helpers.cpp + tester_utils.cpp ) -if(ANDROID) - list(APPEND LINPHONE_SOURCE_FILES_CXX linphonecore_jni.cc) - set_source_files_properties(linphonecore_jni.cc PROPERTIES COMPILE_DEFINITIONS "USE_JAVAH") + +if(ENABLE_JAVA_WRAPPER) + list(APPEND LINPHONE_SOURCE_FILES_CXX ${LINPHONE_JNI_SOURCES}) + set_source_files_properties(${LINPHONE_JNI_SOURCES} PROPERTIES GENERATED TRUE) +else() + if(ANDROID) + list(APPEND LINPHONE_SOURCE_FILES_C linphonecore_jni.cc) + endif() endif() set(LINPHONE_SOURCE_FILES_OBJC) @@ -149,54 +124,7 @@ else() list(APPEND LINPHONE_SOURCE_FILES_C linphone_tunnel_stubs.c) endif() -bc_git_version(liblinphone ${PROJECT_VERSION}) - -add_definitions( - -DUSE_BELLESIP - -DLIBLINPHONE_EXPORTS - -DBCTBX_LOG_DOMAIN="liblinphone" -) - -set(LIBS - ${BCTOOLBOX_CORE_LIBRARIES} - ${BELLESIP_LIBRARIES} - ${MEDIASTREAMER2_LIBRARIES} - ${ORTP_LIBRARIES} - ${XML2_LIBRARIES} - ${BELR_LIBRARIES} -) -if(WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - list(APPEND LIBS "Ws2_32") -endif() -if(ENABLE_LIME) - list(APPEND LIBS ${BZRTP_LIBRARIES}) -endif() -if(ZLIB_FOUND) - list(APPEND LIBS ${ZLIB_LIBRARIES}) -endif() -if(SOCI_FOUND) - list(APPEND LIBS ${SOCI_LIBRARIES}) -endif() -if(SQLITE3_FOUND) - list(APPEND LIBS ${SQLITE3_LIBRARIES}) -endif() -if(ICONV_FOUND) - list(APPEND LIBS ${ICONV_LIBRARIES}) -endif() -if(ENABLE_TUNNEL) - list(APPEND LIBS ${TUNNEL_LIBRARIES}) -endif() -if(MSVC AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - list(APPEND LIBS ${LIBGCC} ${LIBMINGWEX}) -endif() -if(WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - list(APPEND LIBS shlwapi) -endif() -if(INTL_FOUND) - list(APPEND LIBS ${INTL_LIBRARIES}) -endif() if(BELCARD_FOUND) - list(APPEND LIBS ${BELCARD_LIBRARIES}) list(APPEND LINPHONE_SOURCE_FILES_CXX vcard.cc) if(NOT MSVC) list(APPEND STRICT_OPTIONS_CXX "-std=c++11") @@ -208,103 +136,43 @@ else() list(APPEND LINPHONE_SOURCE_FILES_C vcard_stubs.c) endif() + +bc_git_version(liblinphone ${PROJECT_VERSION}) + +add_definitions( + -DUSE_BELLESIP + -DBCTBX_LOG_DOMAIN="liblinphone" + -DLINPHONE_EXPORTS +) + set_source_files_properties(${LINPHONE_SOURCE_FILES_C} PROPERTIES LANGUAGE CXX) bc_apply_compile_flags(LINPHONE_SOURCE_FILES_C STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX) bc_apply_compile_flags(LINPHONE_SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX) bc_apply_compile_flags(LINPHONE_SOURCE_FILES_OBJC STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC) -if(ENABLE_STATIC) - add_library(linphone-static STATIC ${LINPHONE_HEADER_FILES} ${LINPHONE_PRIVATE_HEADER_FILES} - ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX} ${LINPHONE_SOURCE_FILES_OBJC} - $ - ) - set_target_properties(linphone-static PROPERTIES OUTPUT_NAME linphone) - add_dependencies(linphone-static liblinphone-git-version) - target_include_directories(linphone-static PUBLIC ${LINPHONE_INCLUDE_DIRS}) - target_link_libraries(linphone-static INTERFACE ${LIBS}) - if(ANDROID) - add_dependencies(linphone-static linphonecore-jni-header) - endif() - if(IOS) - target_link_libraries(linphone-static INTERFACE "-framework Foundation" "-framework AVFoundation") - endif() - install(TARGETS linphone-static EXPORT ${EXPORT_TARGETS_NAME}Targets - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - ) -endif() -if(ENABLE_SHARED) - add_library(linphone SHARED ${LINPHONE_HEADER_FILES} ${LINPHONE_PRIVATE_HEADER_FILES} - ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX} ${LINPHONE_SOURCE_FILES_OBJC} - $ - ) - if(IOS) - if(IOS) - set(MIN_OS ${LINPHONE_IOS_DEPLOYMENT_TARGET}) - else() - set(MIN_OS ${CMAKE_OSX_DEPLOYMENT_TARGET}) - endif() - set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/build/osx/") - set_target_properties(linphone PROPERTIES - FRAMEWORK TRUE - MACOSX_FRAMEWORK_IDENTIFIER org.linphone.linphone - MACOSX_FRAMEWORK_INFO_PLIST Info.plist.in - PUBLIC_HEADER "${LINPHONE_HEADER_FILES}" - ) - endif() - if(BELCARD_FOUND) - if(APPLE) - set_target_properties(linphone PROPERTIES LINK_FLAGS "-stdlib=libc++") - endif() - endif() - set_target_properties(linphone PROPERTIES LINKER_LANGUAGE CXX) - if(NOT ANDROID) - # Do not version shared library on Android - set_target_properties(linphone PROPERTIES SOVERSION ${LINPHONE_SO_VERSION}) - endif() - add_dependencies(linphone liblinphone-git-version) - target_include_directories(linphone PUBLIC ${LINPHONE_INCLUDE_DIRS}) - target_link_libraries(linphone PRIVATE ${LIBS}) - if(WIN32 AND CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - set_target_properties(linphone PROPERTIES PREFIX "lib") - elseif(ANDROID) - target_link_libraries(linphone PUBLIC "log" ${SUPPORT_LIBRARIES} ${CPUFEATURES_LIBRARIES}) - add_dependencies(linphone linphonecore-jni-header) - endif() - if(MSVC) - if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/linphone.pdb - DESTINATION ${CMAKE_INSTALL_BINDIR} - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - ) - endif() - endif() - install(TARGETS linphone EXPORT ${EXPORT_TARGETS_NAME}Targets - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - FRAMEWORK DESTINATION Frameworks - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE +if (ENABLE_STATIC) + add_library(linphone-coreapi-static OBJECT + ${LINPHONE_PRIVATE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX} ${LINPHONE_SOURCE_FILES_OBJC} ) -endif() -if(ICONV_FOUND) - if(APPLE) - # Prevent conflict between the system iconv.h header and the one from macports. - if(ENABLE_STATIC) - target_compile_options(linphone-static PRIVATE "-include" "${ICONV_INCLUDE_DIRS}/iconv.h") - endif() - if(ENABLE_SHARED) - target_compile_options(linphone PRIVATE "-include" "${ICONV_INCLUDE_DIRS}/iconv.h") - endif() - else() - if(ENABLE_STATIC) - target_include_directories(linphone-static PRIVATE ${ICONV_INCLUDE_DIRS}) - endif() - if(ENABLE_SHARED) - target_include_directories(linphone PRIVATE ${ICONV_INCLUDE_DIRS}) - endif() + target_include_directories(linphone-coreapi-static SYSTEM PRIVATE ${LINPHONE_INCLUDE_DIRS}) + add_dependencies(linphone-coreapi-static liblinphone-git-version) + if (ENABLE_JAVA_WRAPPER) + add_dependencies(linphone-coreapi-static linphonej) endif() -endif() +endif () + +if (ENABLE_SHARED) + add_library(linphone-coreapi OBJECT + ${LINPHONE_PRIVATE_HEADER_FILES} ${LINPHONE_SOURCE_FILES_C} ${LINPHONE_SOURCE_FILES_CXX} ${LINPHONE_SOURCE_FILES_OBJC} + ) + target_include_directories(linphone-coreapi SYSTEM PRIVATE ${LINPHONE_INCLUDE_DIRS}) + target_compile_options(linphone-coreapi PRIVATE "-fPIC") + add_dependencies(linphone-coreapi liblinphone-git-version) + if (ENABLE_JAVA_WRAPPER) + add_dependencies(linphone-coreapi linphonej) + endif() +endif () + add_subdirectory(help) diff --git a/coreapi/Makefile.am b/coreapi/Makefile.am index 4e63d8879..c2b2ee53b 100644 --- a/coreapi/Makefile.am +++ b/coreapi/Makefile.am @@ -39,7 +39,6 @@ liblinphone_la_SOURCES=\ chat_file_transfer.c \ conference.cc conference_private.h \ contactprovider.c contact_providers_priv.h \ - content.c \ dial_plan.c \ dict.c \ ec-calibrator.c \ diff --git a/coreapi/TunnelManager.cc b/coreapi/TunnelManager.cc index dd55a45d4..43b1be150 100644 --- a/coreapi/TunnelManager.cc +++ b/coreapi/TunnelManager.cc @@ -33,7 +33,7 @@ void TunnelManager::addServer(const char *ip, int port,unsigned int udpMirrorPor return; } addServer(ip,port); - mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip,udpMirrorPort),delay)); + mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip, (int)udpMirrorPort), delay)); } void TunnelManager::addServer(const char *ip, int port) { @@ -45,7 +45,7 @@ void TunnelManager::addServer(const char *ip, int port) { ms_warning("TunnelManager is configured in dual mode, use addServerPair instead"); return; } - + mServerAddrs.push_back(ServerAddr(ip,port)); if (mTunnelClient && !mUseDualClient) { static_cast(mTunnelClient)->addServer(ip,port); @@ -58,7 +58,7 @@ void TunnelManager::addServerPair(const char *ip1, int port1, const char *ip2, i return; } addServerPair(ip1, port1, ip2, port2); - mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip1, udpMirrorPort), delay)); + mUdpMirrorClients.push_back(UdpMirrorClient(ServerAddr(ip1, (int)udpMirrorPort), delay)); } void TunnelManager::addServerPair(const char *ip1, int port1, const char *ip2, int port2) { @@ -70,7 +70,7 @@ void TunnelManager::addServerPair(const char *ip1, int port1, const char *ip2, i ms_warning("TunnelManager is configured in single mode, use addServer instead"); return; } - + mDualServerAddrs.push_back(DualServerAddr(ip1, port1, ip2, port2)); if (mTunnelClient && mUseDualClient) { static_cast(mTunnelClient)->addServerPair(ip1, port1, ip2, port2); @@ -84,11 +84,8 @@ void TunnelManager::cleanServers() { sal_end_background_task(mLongRunningTaskId); mLongRunningTaskId = 0; } - UdpMirrorClientList::iterator it; - for (it = mUdpMirrorClients.begin(); it != mUdpMirrorClients.end();) { - UdpMirrorClient& s=*it++; - s.stop(); - } + for (auto &udpMirrorClient : mUdpMirrorClients) + udpMirrorClient.stop(); mUdpMirrorClients.clear(); mCurrentUdpMirrorClient = mUdpMirrorClients.end(); if (mTunnelClient) mTunnelClient->cleanServers(); @@ -141,7 +138,7 @@ RtpTransport *TunnelManager::createRtpTransport(int port){ dualSocket->recvSocket = ((DualTunnelClient *)mTunnelClient)->createSocket(TunnelRecvOnly, port); dualSocket->recvSocket->setUserPointer(this); } - + RtpTransport *t = ms_new0(RtpTransport,1); t->t_getsocket=NULL; t->t_recvfrom=customRecvfrom; @@ -161,15 +158,15 @@ void TunnelManager::startClient() { } else { mTunnelClient = TunnelClient::create(TRUE); } - - sal_set_tunnel(mCore->sal, mTunnelClient); + + mCore->sal->setTunnel(mTunnelClient); if (!mUseDualClient) { static_cast(mTunnelClient)->setCallback(tunnelCallback,this); } else { static_cast(mTunnelClient)->setCallback(tunnelCallback2,this); } } - + if (mVerifyServerCertificate) { const char *rootCertificatePath = linphone_core_get_root_ca(mCore); if (rootCertificatePath != NULL) { @@ -193,7 +190,7 @@ void TunnelManager::startClient() { static_cast(mTunnelClient)->addServer(addr.mAddr.c_str(), addr.mPort); } } - + mTunnelClient->setHttpProxy(mHttpProxyHost.c_str(), mHttpProxyPort, mHttpUserName.c_str(), mHttpPasswd.c_str()); if (!mTunnelClient->isStarted()) { ms_message("Starting tunnel client"); @@ -223,21 +220,21 @@ bool TunnelManager::isConnected() const { int TunnelManager::customSendto(struct _RtpTransport *t, mblk_t *msg , int flags, const struct sockaddr *to, socklen_t tolen){ int size; DualSocket *ds = (DualSocket *)t->data; - msgpullup(msg,-1); - size=msgdsize(msg); - ds->sendSocket->sendto(msg->b_rptr,size,to,tolen); + msgpullup(msg, (size_t)-1); + size = (int)msgdsize(msg); + ds->sendSocket->sendto(msg->b_rptr, (size_t)size, to, tolen); return size; } int TunnelManager::customRecvfrom(struct _RtpTransport *t, mblk_t *msg, int flags, struct sockaddr *from, socklen_t *fromlen){ DualSocket *ds = (DualSocket *)t->data; memset(&msg->recv_addr,0,sizeof(msg->recv_addr)); - int err=ds->recvSocket->recvfrom(msg->b_wptr,dblk_lim(msg->b_datap)-dblk_base(msg->b_datap),from,*fromlen); + long err=ds->recvSocket->recvfrom(msg->b_wptr, (size_t)(dblk_lim(msg->b_datap) - dblk_base(msg->b_datap)), from, *fromlen); //to make ice happy inet_aton(((TunnelManager*)(ds->recvSocket)->getUserPointer())->mLocalAddr,&msg->recv_addr.addr.ipi_addr); msg->recv_addr.family = AF_INET; msg->recv_addr.port = htons((unsigned short)(ds->recvSocket)->getPort()); - if (err>0) return err; + if (err>0) return (int)err; return 0; } @@ -284,7 +281,7 @@ TunnelManager::~TunnelManager(){ mTunnelClient->stop(); delete mTunnelClient; } - sal_set_tunnel(mCore->sal,NULL); + mCore->sal->setTunnel(NULL); linphone_core_remove_listener(mCore, mVTable); linphone_core_v_table_destroy(mVTable); } @@ -380,7 +377,7 @@ void TunnelManager::setMode(LinphoneTunnelMode mode) { linphone_tunnel_mode_to_string(mode)); mMode = mode; applyMode(); - + } void TunnelManager::stopLongRunningTask() { @@ -393,7 +390,7 @@ void TunnelManager::stopLongRunningTask() { void TunnelManager::tunnelCallback(bool connected, void *user_pointer){ TunnelManager *zis = static_cast(user_pointer); Event ev; - + ev.mType=TunnelEvent; ev.mData.mConnected=connected; zis->postEvent(ev); @@ -402,7 +399,7 @@ void TunnelManager::tunnelCallback(bool connected, void *user_pointer){ void TunnelManager::tunnelCallback2(TunnelDirection direction, bool connected, void *user_pointer){ TunnelManager *zis = static_cast(user_pointer); Event ev; - + ev.mType=TunnelEvent; ev.mData.mConnected=connected; zis->postEvent(ev); @@ -515,7 +512,7 @@ void TunnelManager::sUdpMirrorClientCallback(bool isUdpAvailable, void* data) { void TunnelManager::networkReachableCb(LinphoneCore *lc, bool_t reachable) { TunnelManager *tunnel = bcTunnel(linphone_core_get_tunnel(lc)); - + if (reachable) { linphone_core_get_local_ip_for(AF_INET, NULL,tunnel->mLocalAddr); if (tunnel->getMode() == LinphoneTunnelModeAuto){ diff --git a/coreapi/account_creator.c b/coreapi/account_creator.c index 222568552..c28e510a7 100644 --- a/coreapi/account_creator.c +++ b/coreapi/account_creator.c @@ -1,6 +1,6 @@ /* linphone -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -20,11 +20,22 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/account_creator.h" #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" + + +#include "c-wrapper/c-wrapper.h" +#include "dial-plan/dial-plan.h" + #include "bctoolbox/crypto.h" #include "bctoolbox/regex.h" +// TODO: From coreapi. Remove me later. +#include "private.h" + +// ============================================================================= + +using namespace LinphonePrivate; + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreatorCbs); BELLE_SIP_INSTANCIATE_VPTR(LinphoneAccountCreatorCbs, belle_sip_object_t, @@ -43,7 +54,7 @@ static const char* ha1_for_passwd(const char* username, const char* realm, const static unsigned int validate_uri(const char* username, const char* domain, const char* display_name) { LinphoneAddress* addr; - int status = 0; + unsigned int status = 0; LinphoneProxyConfig* proxy = linphone_proxy_config_new(); linphone_proxy_config_set_identity(proxy, "sip:?@domain.com"); @@ -79,7 +90,18 @@ static char* _get_identity(const LinphoneAccountCreator *creator) { LinphoneAddress* addr; addr = linphone_proxy_config_normalize_sip_uri(proxy, creator->username ? creator->username : creator->phone_number); - if (addr == NULL) goto end; + if (addr == NULL) { + if (creator->username && creator->domain) { + char *url = ms_strdup_printf("sip:%s@%s", creator->username, creator->domain); + addr = linphone_address_new(url); + ms_free(url); + if (addr == NULL) { + goto end; + } + } else { + goto end; + } + } identity = linphone_address_as_string(addr); linphone_address_unref(addr); @@ -103,11 +125,14 @@ LinphoneProxyConfig * linphone_account_creator_create_proxy_config(const Linphon if (creator->phone_country_code) { linphone_proxy_config_set_dial_prefix(cfg, creator->phone_country_code); } else if (creator->phone_number) { - int dial_prefix_number = linphone_dial_plan_lookup_ccc_from_e164(creator->phone_number); + int dial_prefix_number = DialPlan::lookupCccFromE164(creator->phone_number); char buff[4]; snprintf(buff, sizeof(buff), "%d", dial_prefix_number); linphone_proxy_config_set_dial_prefix(cfg, buff); } + if (linphone_proxy_config_get_server_addr(cfg) == NULL && creator->domain != NULL) { + linphone_proxy_config_set_server_addr(cfg, creator->domain); + } linphone_proxy_config_enable_register(cfg, TRUE); @@ -332,7 +357,7 @@ void linphone_account_creator_set_user_data(LinphoneAccountCreator *creator, voi LinphoneAccountCreatorUsernameStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username) { int min_length = lp_config_get_int(creator->core->config, "assistant", "username_min_length", -1); int max_length = lp_config_get_int(creator->core->config, "assistant", "username_max_length", -1); - bool_t use_phone_number = lp_config_get_int(creator->core->config, "assistant", "use_phone_number", 0); + bool_t use_phone_number = !!lp_config_get_int(creator->core->config, "assistant", "use_phone_number", 0); const char* regex = lp_config_get_string(creator->core->config, "assistant", "username_regex", 0); if (!username) { creator->username = NULL; @@ -379,15 +404,15 @@ LinphoneAccountCreatorPhoneNumberStatusMask linphone_account_creator_set_phone_n // if phone is valid, we lastly want to check that length is OK { - const LinphoneDialPlan* plan = linphone_dial_plan_by_ccc(creator->phone_country_code); + const DialPlan &plan = DialPlan::findByCcc(creator->phone_country_code); int size = (int)strlen(phone_number); - if (linphone_dial_plan_is_generic(plan)) { + if (plan.isGeneric()) { return_status = LinphoneAccountCreatorPhoneNumberStatusInvalidCountryCode; } - if (size < plan->nnl - 1) { + if (size < plan.getNationalNumberLength() - 1) { return_status += LinphoneAccountCreatorPhoneNumberStatusTooShort; goto end; - } else if (size > plan->nnl + 1) { + } else if (size > plan.getNationalNumberLength() + 1) { return_status += LinphoneAccountCreatorPhoneNumberStatusTooLong; goto end; } else if (return_status & LinphoneAccountCreatorPhoneNumberStatusInvalidCountryCode) { @@ -1107,9 +1132,9 @@ LinphoneAccountCreatorStatus linphone_account_creator_update_password_linphone(L return LinphoneAccountCreatorStatusMissingArguments; } - const char * username = creator->username ? creator->username : creator->phone_number; - const char * ha1 = ms_strdup(creator->ha1 ? creator->ha1 : ha1_for_passwd(username, linphone_proxy_config_get_domain(creator->proxy_cfg), creator->password) ); - const char * new_ha1 = ms_strdup(ha1_for_passwd(username, linphone_proxy_config_get_domain(creator->proxy_cfg), new_pwd)); + const char *username = creator->username ? creator->username : creator->phone_number; + char *ha1 = bctbx_strdup(creator->ha1 ? creator->ha1 : ha1_for_passwd(username, linphone_proxy_config_get_domain(creator->proxy_cfg), creator->password) ); + char *new_ha1 = bctbx_strdup(ha1_for_passwd(username, linphone_proxy_config_get_domain(creator->proxy_cfg), new_pwd)); ms_debug("Account creator: update_password (username=%s, domain=%s)", creator->username, @@ -1125,6 +1150,9 @@ LinphoneAccountCreatorStatus linphone_account_creator_update_password_linphone(L linphone_xml_rpc_session_send_request(creator->xmlrpc_session, request); linphone_xml_rpc_request_unref(request); + bctbx_free(ha1); + bctbx_free(new_ha1); + return LinphoneAccountCreatorStatusRequestOk; } /****************** END OF UPDATE ACCOUNT **************************/ diff --git a/coreapi/account_creator_private.h b/coreapi/account_creator_private.h new file mode 100644 index 000000000..a848d7ccb --- /dev/null +++ b/coreapi/account_creator_private.h @@ -0,0 +1,201 @@ +/* +account_creator.h +Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _ACCOUNT_CREATOR_PRIVATE_H_ +#define _ACCOUNT_CREATOR_PRIVATE_H_ + +#include "linphone/defs.h" +#include +#include "linphone/account_creator_service.h" +#include "linphone/account_creator.h" + +struct _LinphoneAccountCreatorService { + belle_sip_object_t base; + void *user_data; + + LinphoneAccountCreatorRequestFunc account_creator_service_constructor_cb; /**< Constructor */ + LinphoneAccountCreatorRequestFunc account_creator_service_destructor_cb; /**< Destructor */ + + LinphoneAccountCreatorRequestFunc create_account_request_cb; /**< Request to create account */ + LinphoneAccountCreatorRequestFunc is_account_exist_request_cb; /**< Request to know if account exist */ + + LinphoneAccountCreatorRequestFunc activate_account_request_cb; /**< Request to activate account */ + LinphoneAccountCreatorRequestFunc is_account_activated_request_cb; /**< Request to know if account is activated */ + + LinphoneAccountCreatorRequestFunc link_account_request_cb; /**< Request to link account with an alias */ + LinphoneAccountCreatorRequestFunc activate_alias_request_cb; /**< Request to activate the link of alias */ + LinphoneAccountCreatorRequestFunc is_alias_used_request_cb; /**< Request to know if alias is used */ + LinphoneAccountCreatorRequestFunc is_account_linked_request_cb; /**< Request to know if account is linked with an alias */ + + LinphoneAccountCreatorRequestFunc recover_account_request_cb; /**< Request to recover account */ + LinphoneAccountCreatorRequestFunc update_account_request_cb; /**< Request to update account */ +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorService); + +struct _LinphoneAccountCreatorCbs { + belle_sip_object_t base; + void *user_data; + + LinphoneAccountCreatorCbsStatusCb create_account_response_cb; /**< Response of create_account request */ + LinphoneAccountCreatorCbsStatusCb is_account_exist_response_cb; /**< Response of is_account_exist request */ + + LinphoneAccountCreatorCbsStatusCb activate_account_response_cb; /**< Response of activate_account request */ + LinphoneAccountCreatorCbsStatusCb is_account_activated_response_cb; /**< Response of is_account_activated request */ + + LinphoneAccountCreatorCbsStatusCb link_account_response_cb; /**< Response of link_account request */ + LinphoneAccountCreatorCbsStatusCb activate_alias_response_cb; /**< Response of activation alias */ + LinphoneAccountCreatorCbsStatusCb is_alias_used_response_cb; /**< Response of is_alias_used request */ + LinphoneAccountCreatorCbsStatusCb is_account_linked_response_cb; /**< Response of is_account_linked request */ + + LinphoneAccountCreatorCbsStatusCb recover_account_response_cb; /**< Response of recover_account request */ + LinphoneAccountCreatorCbsStatusCb update_account_response_cb; /**< Response of update_account request */ +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorCbs); + +struct _LinphoneAccountCreator { + belle_sip_object_t base; + void *user_data; + LinphoneCore *core; + + /* AccountCreator */ + LinphoneAccountCreatorService *service; /**< Account creator service */ + LinphoneAccountCreatorCbs *cbs; /**< Account creator cbs */ + LinphoneXmlRpcSession *xmlrpc_session; /**< XML-RPC session */ + LinphoneProxyConfig *proxy_cfg; /**< Default proxy config */ + + /* User */ + char *username; /**< Username */ + char *display_name; /**< Display name */ + /* Password */ + char *password; /**< Plain text password */ + char *ha1; /**< Hash password */ + /* Phone Number(Alias) */ + char *phone_number; /**< User phone number*/ + char *phone_country_code; /**< User phone number country code */ + /* Email(Alias) */ + char *email; /**< User email */ + /* Misc */ + char *language; /**< User language */ + char *activation_code; /**< Account validation code */ + char *domain; /**< Domain */ + LinphoneTransportType transport; /**< Transport used */ + + /* Deprecated */ + char *route; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreator); + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Account creator custom to set Linphone default values + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_constructor_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to test the existence of a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to create a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to activate a Linphone account with phone number. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to activate a Linphone account with email. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_email_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to test the validation of a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to test the existence a phone number with a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_phone_number_used_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to link a phone number with a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_link_phone_number_with_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to activate the link of a phone number with a Linphone account. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_phone_number_link_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to a Linphone account with the phone number. + * @param[in] creator LinphoneAccountCreator object + * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_recover_phone_account_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to ask if an account is linked with a phone number + * @param[in] creator LinphoneAccountCreator object + * @return if this account is linked with a phone number +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked_linphone(LinphoneAccountCreator *creator); + +/** + * Send an XML-RPC request to ask if an account is linked with a phone number + * @param[in] creator LinphoneAccountCreator object + * @param[in] new_pwd const char * : new password for the account creator + * @return LinphoneAccountCreatorStatusRequestOk if everything is OK, or a specific error otherwise. +**/ +LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_update_password_linphone(LinphoneAccountCreator *creator); + +#ifdef __cplusplus +} +#endif + +#endif // _ACCOUNT_CREATOR_PRIVATE_H_ diff --git a/coreapi/account_creator_service.c b/coreapi/account_creator_service.c index cd090148f..26ee9fc4f 100644 --- a/coreapi/account_creator_service.c +++ b/coreapi/account_creator_service.c @@ -19,6 +19,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/account_creator_service.h" #include "linphone/core.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. #include "private.h" BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneAccountCreatorService); diff --git a/coreapi/address.c b/coreapi/address.c deleted file mode 100644 index 696ff0ba8..000000000 --- a/coreapi/address.c +++ /dev/null @@ -1,221 +0,0 @@ -/* -linphone -Copyright (C) 2009 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone/core.h" -#include "linphone/lpconfig.h" -#include "private.h" - -LinphoneAddress * _linphone_address_new(const char *addr){ - SalAddress *saddr=sal_address_new(addr); - if (saddr==NULL) - ms_error("Cannot create LinphoneAddress, bad uri [%s]",addr); - return saddr; -} - -LinphoneAddress * linphone_address_new(const char *addr) { - return _linphone_address_new(addr); -} - -LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr){ - return sal_address_clone(addr); -} - -LinphoneAddress * linphone_address_ref(LinphoneAddress *addr){ - return sal_address_ref(addr); -} - -void linphone_address_unref(LinphoneAddress *addr){ - sal_address_unref(addr); -} - -const char *linphone_address_get_scheme(const LinphoneAddress *u){ - return sal_address_get_scheme(u); -} - -const char *linphone_address_get_display_name(const LinphoneAddress* u){ - return sal_address_get_display_name(u); -} - -const char *linphone_address_get_username(const LinphoneAddress *u){ - return sal_address_get_username(u); -} - -const char *linphone_address_get_domain(const LinphoneAddress *u){ - return sal_address_get_domain(u); -} - -int linphone_address_get_port(const LinphoneAddress *u) { - return sal_address_get_port(u); -} - -LinphoneStatus linphone_address_set_display_name(LinphoneAddress *u, const char *display_name){ - sal_address_set_display_name(u,display_name); - return 0; -} - -LinphoneStatus linphone_address_set_username(LinphoneAddress *uri, const char *username) { - sal_address_set_username(uri,username); - return 0; -} - -LinphoneStatus linphone_address_set_domain(LinphoneAddress *uri, const char *host){ - sal_address_set_domain(uri,host); - return 0; -} - -LinphoneStatus linphone_address_set_port(LinphoneAddress *uri, int port){ - sal_address_set_port(uri,port); - return 0; -} - -LinphoneStatus linphone_address_set_transport(LinphoneAddress *uri, LinphoneTransportType tp){ - sal_address_set_transport(uri,(SalTransport)tp); - return 0; -} - -LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri){ - return (LinphoneTransportType)sal_address_get_transport(uri); -} - -void linphone_address_set_method_param(LinphoneAddress *addr, const char *method) { - sal_address_set_method_param(addr, method); -} - -const char *linphone_address_get_method_param(const LinphoneAddress *addr) { - return sal_address_get_method_param(addr); -} - -void linphone_address_clean(LinphoneAddress *uri){ - sal_address_clean(uri); -} - -char *linphone_address_as_string(const LinphoneAddress *u){ - return sal_address_as_string(u); -} - -char *linphone_address_as_string_uri_only(const LinphoneAddress *u){ - return sal_address_as_string_uri_only(u); -} - -bool_t linphone_address_is_secure(const LinphoneAddress *uri){ - return sal_address_is_secure(uri); -} - -bool_t linphone_address_get_secure(const LinphoneAddress *uri){ - return sal_address_is_secure(uri); -} - -void linphone_address_set_secure(LinphoneAddress *addr, bool_t enabled){ - sal_address_set_secure(addr, enabled); -} - -bool_t linphone_address_is_sip(const LinphoneAddress *uri){ - return sal_address_is_sip(uri); -} - -static bool_t strings_equals(const char *s1, const char *s2){ - if (s1==NULL && s2==NULL) return TRUE; - if (s1!=NULL && s2!=NULL && strcmp(s1,s2)==0) return TRUE; - return FALSE; -} - -bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2){ - const char *u1,*u2; - const char *h1,*h2; - int p1,p2; - u1=linphone_address_get_username(a1); - u2=linphone_address_get_username(a2); - p1=linphone_address_get_port(a1); - p2=linphone_address_get_port(a2); - h1=linphone_address_get_domain(a1); - h2=linphone_address_get_domain(a2); - return strings_equals(u1,u2) && strings_equals(h1,h2) && p1==p2; -} - -bool_t linphone_address_equal(const LinphoneAddress *a1, const LinphoneAddress *a2) { - char *s1; - char *s2; - bool_t res; - if ((a1 == NULL) && (a2 == NULL)) return TRUE; - if ((a1 == NULL) || (a2 == NULL)) return FALSE; - s1 = linphone_address_as_string(a1); - s2 = linphone_address_as_string(a2); - res = (strcmp(s1, s2) == 0) ? TRUE : FALSE; - ms_free(s1); - ms_free(s2); - return res; -} - -void linphone_address_destroy(LinphoneAddress *u){ - linphone_address_unref(u); -} - -void linphone_address_set_password(LinphoneAddress *addr, const char *passwd){ - sal_address_set_password(addr,passwd); -} - -const char *linphone_address_get_password(const LinphoneAddress *addr){ - return sal_address_get_password(addr); -} - -void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value){ - sal_address_set_header(addr,header_name,header_value); -} - -const char *linphone_address_get_header(const LinphoneAddress *addr, const char *name){ - return sal_address_get_header(addr,name); -} - -bool_t linphone_address_has_param(const LinphoneAddress *addr, const char *name) { - return sal_address_has_param(addr, name); -} - -const char * linphone_address_get_param(const LinphoneAddress *addr, const char *name) { - return sal_address_get_param(addr, name); -} - -void linphone_address_set_param(LinphoneAddress *addr, const char *name, const char *value) { - sal_address_set_param(addr, name, value); -} - -void linphone_address_set_params(LinphoneAddress *addr, const char *params) { - sal_address_set_params(addr, params); -} - -void linphone_address_set_uri_param(LinphoneAddress *addr, const char *name, const char *value) { - sal_address_set_uri_param(addr, name, value); -} - -void linphone_address_set_uri_params(LinphoneAddress *addr, const char *params) { - sal_address_set_uri_params(addr, params); -} - -bool_t linphone_address_has_uri_param(const LinphoneAddress *addr, const char *name) { - return sal_address_has_uri_param(addr, name); -} - -const char * linphone_address_get_uri_param(const LinphoneAddress *addr, const char *name) { - return sal_address_get_uri_param(addr, name); -} - -LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) { - return linphone_address_new(address); -} - -/** @} */ diff --git a/coreapi/android-helpers.cpp b/coreapi/android-helpers.cpp deleted file mode 100644 index f4f911261..000000000 --- a/coreapi/android-helpers.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* -linphone -Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifdef __ANDROID__ - -#include "private.h" -#include "platform-helpers.h" -#include - - - - - -namespace LinphonePrivate{ - -class AndroidPlatformHelpers : public PlatformHelpers{ -public: - AndroidPlatformHelpers(LinphoneCore *lc, void *system_context); - virtual void setDnsServers(); - virtual void acquireWifiLock(); - virtual void releaseWifiLock(); - virtual void acquireMcastLock(); - virtual void releaseMcastLock(); - virtual void acquireCpuLock(); - virtual void releaseCpuLock(); - ~AndroidPlatformHelpers(); -private: - int callVoidMethod(jmethodID id); - static jmethodID getMethodId(JNIEnv *env, jclass klass, const char *method, const char *signature); - jobject mJavaHelper; - jmethodID mWifiLockAcquireId; - jmethodID mWifiLockReleaseId; - jmethodID mMcastLockAcquireId; - jmethodID mMcastLockReleaseId; - jmethodID mCpuLockAcquireId; - jmethodID mCpuLockReleaseId; - jmethodID mGetDnsServersId; - jmethodID mGetPowerManagerId; - -}; - -jmethodID AndroidPlatformHelpers::getMethodId(JNIEnv *env, jclass klass, const char *method, const char *signature){ - jmethodID id = env->GetMethodID(klass, method, signature); - if (id == 0){ - ms_fatal("Could not find java method '%s %s'", method, signature); - } - return id; -} - -AndroidPlatformHelpers::AndroidPlatformHelpers(LinphoneCore *lc, void *system_context) : PlatformHelpers(lc) { - JNIEnv *env=ms_get_jni_env(); - jclass klass = env->FindClass("org/linphone/core/util/AndroidPlatformHelper"); - if (!klass){ - ms_fatal("Could not find java AndroidPlatformHelper class"); - return; - } - jmethodID ctor = env->GetMethodID(klass,"", "(Ljava/lang/Object;)V"); - mJavaHelper = env->NewObject(klass, ctor, (jobject)system_context); - if (!mJavaHelper){ - ms_error("Could not instanciate AndroidPlatformHelper object."); - return; - } - mJavaHelper = (jobject) env->NewGlobalRef(mJavaHelper); - - mWifiLockAcquireId = getMethodId(env, klass, "acquireWifiLock", "()V"); - mWifiLockReleaseId = getMethodId(env, klass, "releaseWifiLock", "()V"); - mMcastLockAcquireId = getMethodId(env, klass, "acquireMcastLock", "()V"); - mMcastLockReleaseId = getMethodId(env, klass, "releaseMcastLock", "()V"); - mCpuLockAcquireId = getMethodId(env, klass, "acquireCpuLock", "()V"); - mCpuLockReleaseId = getMethodId(env, klass, "releaseCpuLock", "()V"); - mGetDnsServersId = getMethodId(env, klass, "getDnsServers", "()[Ljava/lang/String;"); - mGetPowerManagerId = getMethodId(env, klass, "getPowerManager", "()Ljava/lang/Object;"); - - jobject pm = env->CallObjectMethod(mJavaHelper,mGetPowerManagerId); - belle_sip_wake_lock_init(env, pm); - - ms_message("AndroidPlatformHelpers is fully initialised"); -} - -AndroidPlatformHelpers::~AndroidPlatformHelpers(){ - if (mJavaHelper){ - JNIEnv *env = ms_get_jni_env(); - belle_sip_wake_lock_uninit(env); - env->DeleteGlobalRef(mJavaHelper); - mJavaHelper = NULL; - } -} - - -void AndroidPlatformHelpers::setDnsServers(){ - if (!mJavaHelper || linphone_core_get_dns_set_by_app(mCore)) return; - JNIEnv *env=ms_get_jni_env(); - if (env && mJavaHelper) { - jobjectArray jservers = (jobjectArray)env->CallObjectMethod(mJavaHelper,mGetDnsServersId); - bctbx_list_t *l = NULL; - if (env->ExceptionCheck()) { - env->ExceptionClear(); - ms_error("AndroidPlatformHelpers::setDnsServers() exception"); - return; - } - if (jservers != NULL){ - int count = env->GetArrayLength(jservers); - - for (int i=0; i < count; i++) { - jstring jserver = (jstring) env->GetObjectArrayElement(jservers, i); - const char *str = env->GetStringUTFChars(jserver, NULL); - if (str){ - l = bctbx_list_append(l, ms_strdup(str)); - env->ReleaseStringUTFChars(jserver, str); - } - } - } - linphone_core_set_dns_servers(mCore, l); - bctbx_list_free_with_data(l, ms_free); - } -} - -void AndroidPlatformHelpers::acquireWifiLock(){ - callVoidMethod(mWifiLockAcquireId); -} - -void AndroidPlatformHelpers::releaseWifiLock(){ - callVoidMethod(mWifiLockReleaseId); -} - -void AndroidPlatformHelpers::acquireMcastLock(){ - callVoidMethod(mMcastLockAcquireId); -} - -void AndroidPlatformHelpers::releaseMcastLock(){ - callVoidMethod(mMcastLockReleaseId); -} - -void AndroidPlatformHelpers::acquireCpuLock(){ - callVoidMethod(mCpuLockAcquireId); -} - -void AndroidPlatformHelpers::releaseCpuLock(){ - callVoidMethod(mCpuLockReleaseId); -} - - -int AndroidPlatformHelpers::callVoidMethod(jmethodID id) { - JNIEnv *env=ms_get_jni_env(); - if (env && mJavaHelper) { - env->CallVoidMethod(mJavaHelper,id); - if (env->ExceptionCheck()) { - env->ExceptionClear(); - return -1; - } else - return 0; - } else - return -1; -} - -PlatformHelpers *createAndroidPlatformHelpers(LinphoneCore *lc, void *system_context){ - return new AndroidPlatformHelpers(lc, system_context); -} - -}//end of namespace - - - - -#endif diff --git a/coreapi/authentication.c b/coreapi/authentication.c index fe07f9240..2832b8c46 100644 --- a/coreapi/authentication.c +++ b/coreapi/authentication.c @@ -23,8 +23,13 @@ */ #include "linphone/core.h" -#include "private.h" #include "linphone/lpconfig.h" +#include "sal/sal.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" static void _linphone_auth_info_uninit(LinphoneAuthInfo *obj); static void _linphone_auth_info_copy(LinphoneAuthInfo *dst, const LinphoneAuthInfo *src); @@ -41,6 +46,10 @@ BELLE_SIP_INSTANCIATE_VPTR( ); LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain){ + return linphone_auth_info_new_for_algorithm(username, userid, passwd, ha1, realm, domain, NULL); +} + +LinphoneAuthInfo *linphone_auth_info_new_for_algorithm(const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain, const char *algorithm){ LinphoneAuthInfo *obj=belle_sip_object_new(LinphoneAuthInfo); if (username!=NULL && (strlen(username)>0) ) obj->username=ms_strdup(username); if (userid!=NULL && (strlen(userid)>0)) obj->userid=ms_strdup(userid); @@ -48,6 +57,17 @@ LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *useri if (ha1!=NULL && (strlen(ha1)>0)) obj->ha1=ms_strdup(ha1); if (realm!=NULL && (strlen(realm)>0)) obj->realm=ms_strdup(realm); if (domain!=NULL && (strlen(domain)>0)) obj->domain=ms_strdup(domain); + + if (!algorithm) + obj->algorithm = ms_strdup("MD5"); + + if(algorithm && strcasecmp(algorithm, "MD5") && strcasecmp(algorithm, "SHA-256")){ + ms_error("Given algorithm %s is not correct.", algorithm); + return NULL; + } + + if(algorithm) + obj->algorithm=ms_strdup(algorithm); return obj; } @@ -62,6 +82,7 @@ static void _linphone_auth_info_copy(LinphoneAuthInfo *dst, const LinphoneAuthIn if (src->tls_key) dst->tls_key = ms_strdup(src->tls_key); if (src->tls_cert_path) dst->tls_cert_path = ms_strdup(src->tls_cert_path); if (src->tls_key_path) dst->tls_key_path = ms_strdup(src->tls_key_path); + if (src->algorithm) dst->algorithm = ms_strdup(src->algorithm); } LinphoneAuthInfo *linphone_auth_info_clone(const LinphoneAuthInfo *ai){ @@ -81,6 +102,10 @@ const char *linphone_auth_info_get_username(const LinphoneAuthInfo *i) { } const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *i) { + return linphone_auth_info_get_password(i); +} + +const char *linphone_auth_info_get_password(const LinphoneAuthInfo *i) { return i->passwd; } @@ -116,8 +141,11 @@ const char *linphone_auth_info_get_tls_key_path(const LinphoneAuthInfo *i) { return i->tls_key_path; } - void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd) { + linphone_auth_info_set_password(info, passwd); +} + +void linphone_auth_info_set_password(LinphoneAuthInfo *info, const char *passwd) { if (info->passwd) { ms_free(info->passwd); info->passwd = NULL; @@ -208,6 +236,7 @@ static void _linphone_auth_info_uninit(LinphoneAuthInfo *obj) { if (obj->tls_key != NULL) ms_free(obj->tls_key); if (obj->tls_cert_path != NULL) ms_free(obj->tls_cert_path); if (obj->tls_key_path != NULL) ms_free(obj->tls_key_path); + if (obj->algorithm != NULL) ms_free(obj->algorithm); } /** @@ -219,7 +248,7 @@ void linphone_auth_info_destroy(LinphoneAuthInfo *obj){ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, int pos) { char key[50]; - bool_t store_ha1_passwd = lp_config_get_int(config, "sip", "store_ha1_passwd", 1); + bool_t store_ha1_passwd = !!lp_config_get_int(config, "sip", "store_ha1_passwd", 1); sprintf(key, "auth_info_%i", pos); lp_config_clean_section(config, key); @@ -228,9 +257,16 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in return; } if (!obj->ha1 && obj->realm && obj->passwd && (obj->username || obj->userid) && store_ha1_passwd) { - /*compute ha1 to avoid storing clear text password*/ - obj->ha1 = reinterpret_cast(ms_malloc(33)); - sal_auth_compute_ha1(obj->userid ? obj->userid : obj->username, obj->realm, obj->passwd, obj->ha1); + /* Default algorithm is MD5 if it's NULL */ + if((obj->algorithm==NULL)||(!(strcasecmp(obj->algorithm, "MD5")))){ + obj->ha1 = reinterpret_cast(ms_malloc(33)); + sal_auth_compute_ha1(obj->userid ? obj->userid : obj->username, obj->realm, obj->passwd, obj->ha1); + } + /* If algorithm is SHA-256, calcul ha1 by sha256*/ + if((obj->algorithm)&&(!(strcasecmp(obj->algorithm, "SHA-256")))){ + obj->ha1 = reinterpret_cast(ms_malloc(65)); + sal_auth_compute_ha1_for_algorithm(obj->userid ? obj->userid : obj->username, obj->realm, obj->passwd, obj->ha1,65, obj->algorithm); + } } if (obj->username != NULL) { lp_config_set_string(config, key, "username", obj->username); @@ -262,6 +298,9 @@ void linphone_auth_info_write_config(LpConfig *config, LinphoneAuthInfo *obj, in if (obj->tls_key_path != NULL) { lp_config_set_string(config, key, "client_cert_key", obj->tls_key_path); } + if (obj->algorithm != NULL) { + lp_config_set_string(config, key, "algorithm", obj->algorithm); + } } LinphoneAuthInfo *linphone_auth_info_new_from_config_file(LpConfig * config, int pos) @@ -413,8 +452,6 @@ LinphoneAuthInfo * linphone_core_create_auth_info(LinphoneCore *lc, const char * void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info){ LinphoneAuthInfo *ai; - bctbx_list_t *elem; - bctbx_list_t *l; int restarted_op_count=0; bool_t updating=FALSE; @@ -433,10 +470,10 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) lc->auth_info=bctbx_list_append(lc->auth_info,linphone_auth_info_clone(info)); /* retry pending authentication operations */ - for(l=elem=sal_get_pending_auths(lc->sal);elem!=NULL;elem=elem->next){ - SalOp *op=(SalOp*)elem->data; + auto pendingAuths = lc->sal->getPendingAuths(); + for (const auto &op : pendingAuths) { LinphoneAuthInfo *ai; - const SalAuthInfo *req_sai=sal_op_get_auth_requested(op); + const SalAuthInfo *req_sai=op->getAuthRequested(); ai=(LinphoneAuthInfo*)_linphone_core_find_auth_info(lc,req_sai->realm,req_sai->username,req_sai->domain, FALSE); if (ai){ SalAuthInfo sai; @@ -446,6 +483,7 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) sai.realm=ai->realm; sai.password=ai->passwd; sai.ha1=ai->ha1; + sai.algorithm=ai->algorithm; if (ai->tls_cert && ai->tls_key) { sal_certificates_chain_parse(&sai, ai->tls_cert, SAL_CERTIFICATE_RAW_FORMAT_PEM); sal_signing_key_parse(&sai, ai->tls_key, ""); @@ -455,16 +493,16 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) } /*proxy case*/ for (proxy=(bctbx_list_t*)linphone_core_get_proxy_config_list(lc);proxy!=NULL;proxy=proxy->next) { - if (proxy->data == sal_op_get_user_pointer(op)) { + if (proxy->data == op->getUserPointer()) { linphone_proxy_config_set_state((LinphoneProxyConfig*)(proxy->data),LinphoneRegistrationProgress,"Authentication..."); break; } } - sal_op_authenticate(op,&sai); + op->authenticate(&sai); restarted_op_count++; } } - if (l){ + if (!pendingAuths.empty()) { ms_message("linphone_core_add_auth_info(): restarted [%i] operation(s) after %s auth info for\n" "\tusername: [%s]\n" "\trealm [%s]\n" @@ -475,7 +513,6 @@ void linphone_core_add_auth_info(LinphoneCore *lc, const LinphoneAuthInfo *info) info->realm ? info->realm : "", info->domain ? info->domain : ""); } - bctbx_list_free(l); write_auth_infos(lc); } diff --git a/coreapi/bellesip_sal/sal_address_impl.c b/coreapi/bellesip_sal/sal_address_impl.c index d3f5c088a..8ee6b0f8e 100644 --- a/coreapi/bellesip_sal/sal_address_impl.c +++ b/coreapi/bellesip_sal/sal_address_impl.c @@ -33,7 +33,7 @@ SalAddress * sal_address_new(const char *uri){ } SalAddress * sal_address_clone(const SalAddress *addr){ - return (SalAddress *) belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(addr))); + return (SalAddress *) belle_sip_object_ref(belle_sip_header_address_clone(BELLE_SIP_HEADER_ADDRESS(addr))); } const char *sal_address_get_scheme(const SalAddress *addr){ @@ -58,7 +58,7 @@ void sal_address_set_secure(SalAddress *addr, bool_t enabled){ bool_t sal_address_is_secure(const SalAddress *addr){ belle_sip_header_address_t* header_addr = BELLE_SIP_HEADER_ADDRESS(addr); belle_sip_uri_t* uri = belle_sip_header_address_get_uri(header_addr); - if (uri) return belle_sip_uri_is_secure(uri); + if (uri) return !!belle_sip_uri_is_secure(uri); return FALSE; } @@ -199,7 +199,7 @@ void sal_address_set_param(SalAddress *addr,const char* name,const char* value){ bool_t sal_address_has_param(const SalAddress *addr, const char *name){ belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(addr); - return belle_sip_parameters_has_parameter(parameters, name); + return !!belle_sip_parameters_has_parameter(parameters, name); } const char * sal_address_get_param(const SalAddress *addr, const char *name) { @@ -224,7 +224,7 @@ void sal_address_set_uri_params(SalAddress *addr, const char *params){ bool_t sal_address_has_uri_param(const SalAddress *addr, const char *name){ belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr))); - return belle_sip_parameters_has_parameter(parameters, name); + return !!belle_sip_parameters_has_parameter(parameters, name); } const char * sal_address_get_uri_param(const SalAddress *addr, const char *name) { @@ -282,4 +282,3 @@ bool_t sal_address_is_ipv6(const SalAddress *addr){ void sal_address_destroy(SalAddress *addr){ sal_address_unref(addr); } - diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index 4059d3f0b..3f7126b65 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -23,41 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "config.h" #endif -/* -rfc3323 -4.2 Expressing Privacy Preferences -When a Privacy header is constructed, it MUST consist of either the - value 'none', or one or more of the values 'user', 'header' and - 'session' (each of which MUST appear at most once) which MAY in turn - be followed by the 'critical' indicator. - */ -void sal_op_set_privacy_from_message(SalOp* op,belle_sip_message_t* msg) { - belle_sip_header_privacy_t* privacy = belle_sip_message_get_header_by_type(msg,belle_sip_header_privacy_t); - if (!privacy) { - sal_op_set_privacy(op,SalPrivacyNone); - } else { - belle_sip_list_t* privacy_list=belle_sip_header_privacy_get_privacy(privacy); - sal_op_set_privacy(op,0); - for (;privacy_list!=NULL;privacy_list=privacy_list->next) { - char* privacy_value=(char*)privacy_list->data; - if(strcmp(sal_privacy_to_string(SalPrivacyCritical),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyCritical); - if(strcmp(sal_privacy_to_string(SalPrivacyHeader),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyHeader); - if(strcmp(sal_privacy_to_string(SalPrivacyId),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyId); - if(strcmp(sal_privacy_to_string(SalPrivacyNone),privacy_value) == 0) { - sal_op_set_privacy(op,SalPrivacyNone); - break; - } - if(strcmp(sal_privacy_to_string(SalPrivacySession),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacySession); - if(strcmp(sal_privacy_to_string(SalPrivacyUser),privacy_value) == 0) - sal_op_set_privacy(op,sal_op_get_privacy(op)|SalPrivacyUser); - } - } -} -static void set_tls_properties(Sal *ctx); void sal_enable_log(){ sal_set_log_level(ORTP_MESSAGE); @@ -84,7 +49,7 @@ void sal_set_log_level(OrtpLogLevel level) { if (((level&ORTP_DEBUG) != 0) || ((level&ORTP_TRACE) != 0)) { belle_sip_level = BELLE_SIP_LOG_DEBUG; } - + belle_sip_set_log_level(belle_sip_level); } static BctbxLogFunc _belle_sip_log_handler = bctbx_logv_out; @@ -93,825 +58,6 @@ void sal_set_log_handler(BctbxLogFunc log_handler) { _belle_sip_log_handler = log_handler; belle_sip_set_log_handler(log_handler); } -void sal_add_pending_auth(Sal *sal, SalOp *op){ - if (bctbx_list_find(sal->pending_auths,op)==NULL){ - sal->pending_auths=bctbx_list_append(sal->pending_auths,op); - op->has_auth_pending=TRUE; - } -} - -void sal_remove_pending_auth(Sal *sal, SalOp *op){ - if (op->has_auth_pending){ - op->has_auth_pending=FALSE; - if (bctbx_list_find(sal->pending_auths,op)){ - sal->pending_auths=bctbx_list_remove(sal->pending_auths,op); - } - } -} - -void sal_process_authentication(SalOp *op) { - belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_auth_transaction); - belle_sip_request_t* new_request; - bool_t is_within_dialog=FALSE; - belle_sip_list_t* auth_list=NULL; - belle_sip_auth_event_t* auth_event; - belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)op->pending_auth_transaction); - belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t); - belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from); - - if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){ - /*prefer using the from from the SalOp*/ - from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)sal_op_get_from_address(op)); - } - - if (op->dialog && belle_sip_dialog_get_state(op->dialog)==BELLE_SIP_DIALOG_CONFIRMED) { - new_request = belle_sip_dialog_create_request_from(op->dialog,initial_request); - if (!new_request) - new_request = belle_sip_dialog_create_queued_request_from(op->dialog,initial_request); - is_within_dialog=TRUE; - } else { - new_request=initial_request; - belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION); - belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION); - } - if (new_request==NULL) { - ms_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",op); - return; - } - - 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 { - sal_op_resend_request(op,new_request); - } - sal_remove_pending_auth(op->base.root,op); - }else { - belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(response,belle_sip_header_from_t); - char *tmp=belle_sip_object_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); - ms_message("No auth info found for [%s]",tmp); - belle_sip_free(tmp); - sal_add_pending_auth(op->base.root,op); - - if (is_within_dialog) { - belle_sip_object_unref(new_request); - } - } - /*always store auth info, for case of wrong credential*/ - if (op->auth_info) { - sal_auth_info_delete(op->auth_info); - op->auth_info=NULL; - } - if (auth_list){ - auth_event=(belle_sip_auth_event_t*)(auth_list->data); - op->auth_info=sal_auth_info_create(auth_event); - belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy); - } -} - -static void process_dialog_terminated(void *sal, const belle_sip_dialog_terminated_event_t *event){ - belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_event_get_dialog(event); - SalOp* op = reinterpret_cast(belle_sip_dialog_get_application_data(dialog)); - if (op && op->callbacks && op->callbacks->process_dialog_terminated) { - op->callbacks->process_dialog_terminated(op,event); - } else { - ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog); - } -} - -static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - belle_sip_client_transaction_t*client_transaction; - SalOp* op; - if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) { - client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event)); - op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); - /*also reset auth count on IO error*/ - op->auth_requests=0; - if (op->callbacks && op->callbacks->process_io_error) { - op->callbacks->process_io_error(op,event); - } - } else { - /*ms_error("sal process_io_error not implemented yet for non transaction");*/ - /*nop, because already handle at transaction layer*/ - } -} - -static void process_request_event(void *ud, const belle_sip_request_event_t *event) { - Sal *sal=(Sal*)ud; - SalOp* op=NULL; - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_dialog_t* dialog=belle_sip_request_event_get_dialog(event); - belle_sip_header_address_t* origin_address; - belle_sip_header_address_t* address=NULL; - belle_sip_header_from_t* from_header; - belle_sip_header_to_t* to; - belle_sip_header_diversion_t* diversion; - belle_sip_response_t* resp; - belle_sip_header_t *evh; - const char *method=belle_sip_request_get_method(req); - belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); - - from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); - - if (dialog) { - op=(SalOp*)belle_sip_dialog_get_application_data(dialog); - - if (op == NULL && strcmp("NOTIFY",method) == 0) { - /*special case for Dialog created by notify mathing subscribe*/ - belle_sip_transaction_t * sub_trans = belle_sip_dialog_get_last_transaction(dialog); - op = (SalOp*)belle_sip_transaction_get_application_data(sub_trans); - } - if (op==NULL || op->state==SalOpStateTerminated){ - ms_warning("Receiving request for null or terminated op [%p], ignored",op); - return; - } - }else{ - /*handle the case where we are receiving a request with to tag but it is not belonging to any dialog*/ - belle_sip_header_to_t *to = belle_sip_message_get_header_by_type(req, belle_sip_header_to_t); - if ((strcmp("INVITE",method)==0 || strcmp("NOTIFY",method)==0) && (belle_sip_header_to_get_tag(to) != NULL)) { - ms_warning("Receiving %s with to-tag but no know dialog here. Rejecting.", method); - resp=belle_sip_response_create_from_request(req,481); - belle_sip_provider_send_response(sal->prov,resp); - return; - /* by default (eg. when a to-tag is present), out of dialog ACK are automatically - handled in lower layers (belle-sip) but in case it misses, it will be forwarded to us */ - } else if (strcmp("ACK",method)==0 && (belle_sip_header_to_get_tag(to) == NULL)) { - ms_warning("Receiving ACK without to-tag but no know dialog here. Ignoring"); - return; - } - - if (strcmp("INVITE",method)==0) { - op=sal_op_new(sal); - op->dir=SalOpDirIncoming; - sal_op_call_fill_cbs(op); - }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { - op=sal_op_new(sal); - op->dir=SalOpDirIncoming; - if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ - sal_op_presence_fill_cbs(op); - }else - sal_op_subscribe_fill_cbs(op); - }else if (strcmp("MESSAGE",method)==0) { - op=sal_op_new(sal); - op->dir=SalOpDirIncoming; - sal_op_message_fill_cbs(op); - }else if (strcmp("OPTIONS",method)==0) { - resp=belle_sip_response_create_from_request(req,200); - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (strcmp("INFO",method)==0) { - resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/ - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (strcmp("BYE",method)==0) { - resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */ - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (strcmp("CANCEL",method)==0) { - resp=belle_sip_response_create_from_request(req,481);/*out of dialog CANCEL */ - belle_sip_provider_send_response(sal->prov,resp); - return; - }else if (sal->enable_test_features && strcmp("PUBLISH",method)==0) { - resp=belle_sip_response_create_from_request(req,200);/*out of dialog PUBLISH */ - belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA")); - belle_sip_provider_send_response(sal->prov,resp); - return; - }else { - ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); - resp=belle_sip_response_create_from_request(req,405); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp) - ,BELLE_SIP_HEADER(belle_sip_header_allow_create("INVITE, CANCEL, ACK, BYE, SUBSCRIBE, NOTIFY, MESSAGE, OPTIONS, INFO"))); - belle_sip_provider_send_response(sal->prov,resp); - return; - } - } - - if (!op->base.from_address) { - if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))) - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); - else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header)))) - address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) - ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); - else - ms_error("Cannot not find from uri from request [%p]",req); - sal_op_set_from_address(op,(SalAddress*)address); - belle_sip_object_unref(address); - } - - if( remote_contact ){ - __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); - } - - if (!op->base.to_address) { - to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); - if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))) - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))); - else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to)))) - address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) - ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to))); - else - ms_error("Cannot not find to uri from request [%p]",req); - - sal_op_set_to_address(op,(SalAddress*)address); - belle_sip_object_unref(address); - } - - if(!op->base.diversion_address){ - diversion=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_diversion_t); - if (diversion) { - if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))) - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); - else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion)))) - address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) - ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); - else - ms_warning("Cannot not find diversion header from request [%p]",req); - if (address) { - sal_op_set_diversion_address(op,(SalAddress*)address); - belle_sip_object_unref(address); - } - } - } - - if (!op->base.origin) { - /*set origin uri*/ - origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req)); - __sal_op_set_network_origin_address(op,(SalAddress*)origin_address); - belle_sip_object_unref(origin_address); - } - if (!op->base.remote_ua) { - sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(req)); - } - - if (!op->base.call_id) { - op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t)))); - } - /*It is worth noting that proxies can (and will) remove this header field*/ - sal_op_set_privacy_from_message(op,(belle_sip_message_t*)req); - - if (strcmp("ACK",method) != 0){ - /*The ACK custom header is processed specifically later on*/ - sal_op_assign_recv_headers(op,(belle_sip_message_t*)req); - } - if (op->callbacks && op->callbacks->process_request_event) { - op->callbacks->process_request_event(op,event); - } else { - ms_error("sal process_request_event not implemented yet"); - } - -} - -static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){ - belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); - belle_sip_response_t* response = belle_sip_response_event_get_response(event); - int response_code = belle_sip_response_get_status_code(response); - - if (!client_transaction) { - ms_warning("Discarding stateless response [%i]",response_code); - return; - } else { - SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); - belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); - belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(response, belle_sip_header_contact_t); - - if (op->state == SalOpStateTerminated) { - belle_sip_message("Op [%p] is terminated, nothing to do with this [%i]", op, response_code); - return; - } - /*do it all the time, since we can receive provisional responses from a different instance than the final one*/ - sal_op_set_remote_ua(op,BELLE_SIP_MESSAGE(response)); - - if(remote_contact) { - __sal_op_set_remote_contact(op, belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); - } - - if (!op->base.call_id) { - op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t)))); - } - - sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); - - if (op->callbacks && op->callbacks->process_response_event) { - /*handle authorization*/ - switch (response_code) { - case 200: - break; - case 401: - case 407: - if (op->state == SalOpStateTerminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { - /*only bye are completed*/ - belle_sip_message("Op is in state terminating, nothing else to do "); - } else { - if (op->pending_auth_transaction){ - belle_sip_object_unref(op->pending_auth_transaction); - op->pending_auth_transaction=NULL; - } - if (++op->auth_requests > 2) { - ms_warning("Auth info cannot be found for op [%s/%s] after 2 attempts, giving up",sal_op_get_from(op) - ,sal_op_get_to(op)); - op->base.root->callbacks.auth_failure(op,op->auth_info); - sal_remove_pending_auth(op->base.root,op); - } else { - op->pending_auth_transaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); - sal_process_authentication(op); - return; - } - } - break; - case 403: - if (op->auth_info) op->base.root->callbacks.auth_failure(op,op->auth_info); - break; - } - if (response_code >= 180 && response_code !=401 && response_code !=407 && response_code !=403) { - /*not an auth request*/ - op->auth_requests=0; - } - op->callbacks->process_response_event(op,event); - } else { - ms_error("Unhandled event response [%p]",event); - } - } -} - -static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); - SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); - if (op && op->callbacks && op->callbacks->process_timeout) { - op->callbacks->process_timeout(op,event); - } else { - ms_error("Unhandled event timeout [%p]",event); - } -} - -static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { - belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event); - belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event); - belle_sip_transaction_t* trans; - SalOp* op; - - if(client_transaction) - trans=BELLE_SIP_TRANSACTION(client_transaction); - else - trans=BELLE_SIP_TRANSACTION(server_transaction); - - op = (SalOp*)belle_sip_transaction_get_application_data(trans); - if (op && op->callbacks && op->callbacks->process_transaction_terminated) { - op->callbacks->process_transaction_terminated(op,event); - } else { - ms_message("Unhandled transaction terminated [%p]",trans); - } - if (op) { - sal_op_unref(op); /*because every transaction ref op*/ - belle_sip_transaction_set_application_data(trans,NULL); /*no longuer reference something we do not ref to avoid futur access of a released op*/ - } -} - - -static void process_auth_requested(void *sal, belle_sip_auth_event_t *event) { - SalAuthInfo* auth_info = sal_auth_info_create(event); - ((Sal*)sal)->callbacks.auth_requested(reinterpret_cast(sal),auth_info); - belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password); - belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1); - belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid); - belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key); - belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates); - sal_auth_info_delete(auth_info); -} - -Sal * sal_init(MSFactory *factory){ - belle_sip_listener_callbacks_t listener_callbacks; - Sal * sal=ms_new0(Sal,1); - - /*belle_sip_object_enable_marshal_check(TRUE);*/ - sal->auto_contacts=TRUE; - sal->factory = factory; - /*first create the stack, which initializes the belle-sip object's pool for this thread*/ - sal->stack = belle_sip_stack_new(NULL); - - sal->user_agent=belle_sip_header_user_agent_new(); -#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION) - belle_sip_header_user_agent_add_product(sal->user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION); -#else - belle_sip_header_user_agent_add_product(sal->user_agent, "Unknown"); -#endif - sal_append_stack_string_to_user_agent(sal); - belle_sip_object_ref(sal->user_agent); - - sal->prov = belle_sip_stack_create_provider(sal->stack,NULL); - sal_nat_helper_enable(sal,TRUE); - memset(&listener_callbacks,0,sizeof(listener_callbacks)); - listener_callbacks.process_dialog_terminated=process_dialog_terminated; - listener_callbacks.process_io_error=process_io_error; - listener_callbacks.process_request_event=process_request_event; - listener_callbacks.process_response_event=process_response_event; - listener_callbacks.process_timeout=process_timeout; - listener_callbacks.process_transaction_terminated=process_transaction_terminated; - listener_callbacks.process_auth_requested=process_auth_requested; - sal->listener=belle_sip_listener_create_from_callbacks(&listener_callbacks,sal); - belle_sip_provider_add_sip_listener(sal->prov,sal->listener); - sal->tls_verify=TRUE; - sal->tls_verify_cn=TRUE; - sal->refresher_retry_after=60000; /*default value in ms*/ - sal->enable_sip_update=TRUE; - sal->pending_trans_checking=TRUE; - sal->ssl_config = NULL; - return sal; -} - -void sal_set_user_pointer(Sal *sal, void *user_data){ - sal->up=user_data; -} - -void *sal_get_user_pointer(const Sal *sal){ - return sal->up; -} - -static void unimplemented_stub(void){ - ms_warning("Unimplemented SAL callback"); -} - -void sal_set_callbacks(Sal *ctx, const SalCallbacks *cbs){ - memcpy(&ctx->callbacks,cbs,sizeof(*cbs)); - if (ctx->callbacks.call_received==NULL) - ctx->callbacks.call_received=(SalOnCallReceived)unimplemented_stub; - if (ctx->callbacks.call_ringing==NULL) - ctx->callbacks.call_ringing=(SalOnCallRinging)unimplemented_stub; - if (ctx->callbacks.call_accepted==NULL) - ctx->callbacks.call_accepted=(SalOnCallAccepted)unimplemented_stub; - if (ctx->callbacks.call_failure==NULL) - ctx->callbacks.call_failure=(SalOnCallFailure)unimplemented_stub; - if (ctx->callbacks.call_terminated==NULL) - ctx->callbacks.call_terminated=(SalOnCallTerminated)unimplemented_stub; - if (ctx->callbacks.call_released==NULL) - ctx->callbacks.call_released=(SalOnCallReleased)unimplemented_stub; - if (ctx->callbacks.call_updating==NULL) - ctx->callbacks.call_updating=(SalOnCallUpdating)unimplemented_stub; - if (ctx->callbacks.auth_failure==NULL) - ctx->callbacks.auth_failure=(SalOnAuthFailure)unimplemented_stub; - if (ctx->callbacks.register_success==NULL) - ctx->callbacks.register_success=(SalOnRegisterSuccess)unimplemented_stub; - if (ctx->callbacks.register_failure==NULL) - ctx->callbacks.register_failure=(SalOnRegisterFailure)unimplemented_stub; - if (ctx->callbacks.dtmf_received==NULL) - ctx->callbacks.dtmf_received=(SalOnDtmfReceived)unimplemented_stub; - if (ctx->callbacks.notify==NULL) - ctx->callbacks.notify=(SalOnNotify)unimplemented_stub; - if (ctx->callbacks.subscribe_received==NULL) - ctx->callbacks.subscribe_received=(SalOnSubscribeReceived)unimplemented_stub; - if (ctx->callbacks.incoming_subscribe_closed==NULL) - ctx->callbacks.incoming_subscribe_closed=(SalOnIncomingSubscribeClosed)unimplemented_stub; - if (ctx->callbacks.parse_presence_requested==NULL) - ctx->callbacks.parse_presence_requested=(SalOnParsePresenceRequested)unimplemented_stub; - if (ctx->callbacks.convert_presence_to_xml_requested==NULL) - ctx->callbacks.convert_presence_to_xml_requested=(SalOnConvertPresenceToXMLRequested)unimplemented_stub; - if (ctx->callbacks.notify_presence==NULL) - ctx->callbacks.notify_presence=(SalOnNotifyPresence)unimplemented_stub; - if (ctx->callbacks.subscribe_presence_received==NULL) - ctx->callbacks.subscribe_presence_received=(SalOnSubscribePresenceReceived)unimplemented_stub; - if (ctx->callbacks.message_received==NULL) - ctx->callbacks.message_received=(SalOnMessageReceived)unimplemented_stub; - if (ctx->callbacks.ping_reply==NULL) - ctx->callbacks.ping_reply=(SalOnPingReply)unimplemented_stub; - if (ctx->callbacks.auth_requested==NULL) - ctx->callbacks.auth_requested=(SalOnAuthRequested)unimplemented_stub; - if (ctx->callbacks.info_received==NULL) - ctx->callbacks.info_received=(SalOnInfoReceived)unimplemented_stub; - if (ctx->callbacks.on_publish_response==NULL) - ctx->callbacks.on_publish_response=(SalOnPublishResponse)unimplemented_stub; - if (ctx->callbacks.on_expire==NULL) - ctx->callbacks.on_expire=(SalOnExpire)unimplemented_stub; -} - - - -void sal_uninit(Sal* sal){ - belle_sip_object_unref(sal->user_agent); - 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); - bctbx_list_free_with_data(sal->supported_tags,ms_free); - bctbx_list_free_with_data(sal->supported_content_types, ms_free); - if (sal->uuid) ms_free(sal->uuid); - if (sal->root_ca) ms_free(sal->root_ca); - if (sal->root_ca_data) ms_free(sal->root_ca_data); - ms_free(sal); -}; - -int sal_transport_available(Sal *sal, SalTransport t){ - switch(t){ - case SalTransportUDP: - case SalTransportTCP: - return TRUE; - case SalTransportTLS: - return belle_sip_stack_tls_available(sal->stack); - case SalTransportDTLS: - return FALSE; - } - return FALSE; -} - -bool_t sal_content_encoding_available(Sal *sal, const char *content_encoding) { - return (bool_t)belle_sip_stack_content_encoding_available(sal->stack, content_encoding); -} - -static int sal_add_listen_port(Sal *ctx, SalAddress* addr, bool_t is_tunneled){ - int result; - belle_sip_listening_point_t* lp; - if (is_tunneled){ -#ifdef TUNNEL_ENABLED - if (sal_address_get_transport(addr)!=SalTransportUDP){ - ms_error("Tunneled mode is only available for UDP kind of transports."); - return -1; - } - lp = belle_sip_tunnel_listening_point_new(ctx->stack, ctx->tunnel_client); - if (!lp){ - ms_error("Could not create tunnel listening point."); - return -1; - } -#else - ms_error("No tunnel support in library."); - return -1; -#endif - }else{ - lp = belle_sip_stack_create_listening_point(ctx->stack, - sal_address_get_domain(addr), - sal_address_get_port(addr), - sal_transport_to_string(sal_address_get_transport(addr))); - } - if (lp) { - belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive); - result = belle_sip_provider_add_listening_point(ctx->prov,lp); - if (sal_address_get_transport(addr)==SalTransportTLS) { - set_tls_properties(ctx); - } - } else { - return -1; - } - return result; -} - -int sal_listen_port(Sal *ctx, const char *addr, int port, SalTransport tr, int is_tunneled) { - SalAddress* sal_addr = sal_address_new(NULL); - int result; - sal_address_set_domain(sal_addr,addr); - sal_address_set_port(sal_addr,port); - sal_address_set_transport(sal_addr,tr); - result = sal_add_listen_port(ctx, sal_addr, is_tunneled); - sal_address_destroy(sal_addr); - return result; -} - -static void remove_listening_point(belle_sip_listening_point_t* lp,belle_sip_provider_t* prov) { - belle_sip_provider_remove_listening_point(prov,lp); -} - -int sal_get_listening_port(Sal *ctx, SalTransport tr){ - const char *tpn=sal_transport_to_string(tr); - belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov, tpn); - if (lp){ - return belle_sip_listening_point_get_port(lp); - } - return 0; -} - -int sal_unlisten_ports(Sal *ctx){ - const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(ctx->prov); - belle_sip_list_t * tmp_list = belle_sip_list_copy(lps); - belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))remove_listening_point,ctx->prov); - belle_sip_list_free(tmp_list); - ms_message("sal_unlisten_ports done"); - return 0; -} - -ortp_socket_t sal_get_socket(Sal *ctx){ - ms_warning("sal_get_socket is deprecated"); - return -1; -} - -void sal_set_user_agent(Sal *ctx, const char *user_agent){ - belle_sip_header_user_agent_set_products(ctx->user_agent,NULL); - belle_sip_header_user_agent_add_product(ctx->user_agent,user_agent); - return ; -} - -const char* sal_get_user_agent(Sal *ctx){ - static char user_agent[255]; - belle_sip_header_user_agent_get_products_as_string(ctx->user_agent, user_agent, 254); - return user_agent; -} - -void sal_append_stack_string_to_user_agent(Sal *ctx) { - char stack_string[64]; - snprintf(stack_string, sizeof(stack_string) - 1, "(belle-sip/%s)", belle_sip_version_to_string()); - belle_sip_header_user_agent_add_product(ctx->user_agent, stack_string); -} - -/*keepalive period in ms*/ -void sal_set_keepalive_period(Sal *ctx,unsigned int value){ - const belle_sip_list_t* iterator; - belle_sip_listening_point_t* lp; - ctx->keep_alive=value; - for (iterator=belle_sip_provider_get_listening_points(ctx->prov);iterator!=NULL;iterator=iterator->next) { - lp=(belle_sip_listening_point_t*)iterator->data; - if (ctx->use_tcp_tls_keep_alive || strcasecmp(belle_sip_listening_point_get_transport(lp),"udp")==0) { - belle_sip_listening_point_set_keep_alive(lp,ctx->keep_alive); - } - } -} -int sal_set_tunnel(Sal *ctx, void *tunnelclient) { -#ifdef TUNNEL_ENABLED - ctx->tunnel_client=tunnelclient; - return 0; -#else - return -1; -#endif -} - -/** - * returns keepalive period in ms - * 0 desactiaved - * */ -unsigned int sal_get_keepalive_period(Sal *ctx){ - return ctx->keep_alive; -} -void sal_use_session_timers(Sal *ctx, int expires){ - ctx->session_expires=expires; - return ; -} - -void sal_use_one_matching_codec_policy(Sal *ctx, bool_t one_matching_codec){ - ctx->one_matching_codec=one_matching_codec; -} - -void sal_use_rport(Sal *ctx, bool_t use_rports){ - belle_sip_provider_enable_rport(ctx->prov,use_rports); - ms_message("Sal use rport [%s]",use_rports?"enabled":"disabled"); - return ; -} - -static void set_tls_properties(Sal *ctx){ - belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(ctx->prov,"TLS"); - if (lp){ - belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp); - belle_tls_crypto_config_t *crypto_config = belle_tls_crypto_config_new(); - int verify_exceptions = BELLE_TLS_VERIFY_NONE; - if (!ctx->tls_verify) verify_exceptions = BELLE_TLS_VERIFY_ANY_REASON; - else if (!ctx->tls_verify_cn) verify_exceptions = BELLE_TLS_VERIFY_CN_MISMATCH; - belle_tls_crypto_config_set_verify_exceptions(crypto_config, verify_exceptions); - if (ctx->root_ca != NULL) belle_tls_crypto_config_set_root_ca(crypto_config, ctx->root_ca); - if (ctx->root_ca_data != NULL) belle_tls_crypto_config_set_root_ca_data(crypto_config, ctx->root_ca_data); - if (ctx->ssl_config != NULL) belle_tls_crypto_config_set_ssl_config(crypto_config, ctx->ssl_config); - if (ctx->tls_postcheck_cb) belle_tls_crypto_config_set_postcheck_callback(crypto_config, ctx->tls_postcheck_cb, ctx->tls_postcheck_cb_data); - belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config); - belle_sip_object_unref(crypto_config); - } -} - -void sal_set_tls_postcheck_callback(Sal *ctx, int (*cb)(void *, const bctbx_x509_certificate_t *), void *data){ - ctx->tls_postcheck_cb = cb; - ctx->tls_postcheck_cb_data = data; -} - -void sal_set_root_ca(Sal* ctx, const char* rootCa) { - if (ctx->root_ca) { - ms_free(ctx->root_ca); - ctx->root_ca = NULL; - } - if (rootCa) - ctx->root_ca = ms_strdup(rootCa); - set_tls_properties(ctx); - return; -} - -void sal_set_root_ca_data(Sal* ctx, const char* data) { - if (ctx->root_ca_data) { - ms_free(ctx->root_ca_data); - ctx->root_ca_data = NULL; - } - if (data) - ctx->root_ca_data = ms_strdup(data); - set_tls_properties(ctx); - return; -} - -void sal_verify_server_certificates(Sal *ctx, bool_t verify){ - ctx->tls_verify=verify; - set_tls_properties(ctx); - return ; -} - -void sal_verify_server_cn(Sal *ctx, bool_t verify){ - ctx->tls_verify_cn=verify; - set_tls_properties(ctx); - return ; -} - -void sal_set_ssl_config(Sal *ctx, void *ssl_config) { - ctx->ssl_config = ssl_config; - set_tls_properties(ctx); - return ; -} - -void sal_use_tcp_tls_keepalive(Sal *ctx, bool_t enabled) { - ctx->use_tcp_tls_keep_alive=enabled; -} - -int sal_iterate(Sal *sal){ - belle_sip_stack_sleep(sal->stack,0); - return 0; -} -bctbx_list_t * sal_get_pending_auths(Sal *sal){ - return bctbx_list_copy(sal->pending_auths); -} - -/*misc*/ -void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen){ - strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen); - ms_error("sal_get_default_local_ip() is deprecated."); -} - -const char *sal_get_root_ca(Sal* ctx) { - return ctx->root_ca; -} - -int sal_reset_transports(Sal *ctx){ - ms_message("Reseting transports"); - belle_sip_provider_clean_channels(ctx->prov); - return 0; -} - -void sal_set_dscp(Sal *ctx, int dscp){ - belle_sip_stack_set_default_dscp(ctx->stack,dscp); -} - -void sal_set_send_error(Sal *sal,int value) { - belle_sip_stack_set_send_error(sal->stack,value); -} -void sal_set_recv_error(Sal *sal,int value) { - belle_sip_provider_set_recv_error(sal->prov,value); -} -void sal_nat_helper_enable(Sal *sal,bool_t enable) { - sal->nat_helper_enabled=enable; - belle_sip_provider_enable_nat_helper(sal->prov,enable); - ms_message("Sal nat helper [%s]",enable?"enabled":"disabled"); -} -bool_t sal_nat_helper_enabled(Sal *sal) { - return sal->nat_helper_enabled; -} -void sal_set_dns_timeout(Sal* sal,int timeout) { - belle_sip_stack_set_dns_timeout(sal->stack, timeout); -} - -int sal_get_dns_timeout(const Sal* sal) { - return belle_sip_stack_get_dns_timeout(sal->stack); -} - -void sal_set_transport_timeout(Sal* sal,int timeout) { - belle_sip_stack_set_transport_timeout(sal->stack, timeout); -} - -int sal_get_transport_timeout(const Sal* sal) { - return belle_sip_stack_get_transport_timeout(sal->stack); -} - -void sal_set_dns_servers(Sal *sal, const bctbx_list_t *servers){ - belle_sip_list_t *l = NULL; - - /*we have to convert the bctbx_list_t into a belle_sip_list_t first*/ - for (; servers != NULL; servers = servers->next){ - l = belle_sip_list_append(l, servers->data); - } - belle_sip_stack_set_dns_servers(sal->stack, l); - belle_sip_list_free(l); -} - -void sal_enable_dns_srv(Sal *sal, bool_t enable) { - belle_sip_stack_enable_dns_srv(sal->stack, (unsigned char)enable); -} - -bool_t sal_dns_srv_enabled(const Sal *sal) { - return (bool_t)belle_sip_stack_dns_srv_enabled(sal->stack); -} - -void sal_enable_dns_search(Sal *sal, bool_t enable) { - belle_sip_stack_enable_dns_search(sal->stack, (unsigned char)enable); -} - -bool_t sal_dns_search_enabled(const Sal *sal) { - return (bool_t)belle_sip_stack_dns_search_enabled(sal->stack); -} - -void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) { - belle_sip_stack_set_dns_user_hosts_file(sal->stack, hosts_file); -} - -const char * sal_get_dns_user_hosts_file(const Sal *sal) { - return belle_sip_stack_get_dns_user_hosts_file(sal->stack); -} SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) { SalAuthInfo* auth_info = sal_auth_info_new(); @@ -919,6 +65,7 @@ SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) { auth_info->username = ms_strdup(belle_sip_auth_event_get_username(event)); auth_info->domain = ms_strdup(belle_sip_auth_event_get_domain(event)); auth_info->mode = (SalAuthMode)belle_sip_auth_event_get_mode(event); + auth_info->algorithm = ms_strdup(belle_sip_auth_event_get_algorithm(event)); return auth_info; } @@ -933,25 +80,21 @@ void sal_signing_key_delete(belle_sip_signing_key_t *key) { belle_sip_object_unref((belle_sip_object_t *)key); } -const char* sal_op_type_to_string(const SalOpType type) { - switch(type) { - case SalOpRegister: return "SalOpRegister"; - case SalOpCall: return "SalOpCall"; - case SalOpMessage: return "SalOpMessage"; - case SalOpPresence: return "SalOpPresence"; - default: - return "SalOpUnknown"; - } -} - -void sal_use_dates(Sal *ctx, bool_t enabled){ - ctx->use_dates=enabled; -} - int sal_auth_compute_ha1(const char* userid,const char* realm,const char* password, char ha1[33]) { return belle_sip_auth_helper_compute_ha1(userid, realm, password, ha1); } +int sal_auth_compute_ha1_for_algorithm( + const char *userid, + const char *realm, + const char *password, + char *ha1, + size_t size, + const char *algo +) { + return belle_sip_auth_helper_compute_ha1_for_algorithm(userid, realm, password, ha1, size, algo); +} + SalCustomHeader *sal_custom_header_ref(SalCustomHeader *ch){ if (ch == NULL) return NULL; belle_sip_object_ref(ch); @@ -994,7 +137,7 @@ const char *sal_custom_header_find(const SalCustomHeader *ch, const char *name){ SalCustomHeader *sal_custom_header_remove(SalCustomHeader *ch, const char *name) { belle_sip_message_t *msg=(belle_sip_message_t*)ch; if (msg==NULL) return NULL; - + belle_sip_message_remove_header(msg, name); return (SalCustomHeader*)msg; } @@ -1009,11 +152,6 @@ SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch){ return (SalCustomHeader*)belle_sip_object_ref((belle_sip_message_t*)ch); } -const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op){ - SalOpBase *b=(SalOpBase *)op; - return b->recv_custom_headers; -} - SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value) { belle_sdp_session_description_t *desc = (belle_sdp_session_description_t *)csa; belle_sdp_attribute_t *attr; @@ -1048,167 +186,6 @@ SalCustomSdpAttribute * sal_custom_sdp_attribute_clone(const SalCustomSdpAttribu return (SalCustomSdpAttribute *)belle_sip_object_ref((belle_sdp_session_description_t *)csa); } -void sal_set_uuid(Sal *sal, const char *uuid){ - if (sal->uuid){ - ms_free(sal->uuid); - sal->uuid=NULL; - } - if (uuid) - sal->uuid=ms_strdup(uuid); -} - -typedef struct { - unsigned int time_low; - unsigned short time_mid; - unsigned short time_hi_and_version; - unsigned char clock_seq_hi_and_reserved; - unsigned char clock_seq_low; - unsigned char node[6]; -} sal_uuid_t; - -int sal_generate_uuid(char *uuid, size_t len) { - sal_uuid_t uuid_struct; - int i; - int written; - - if (len==0) return -1; - /*create an UUID as described in RFC4122, 4.4 */ - belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(sal_uuid_t)); - uuid_struct.clock_seq_hi_and_reserved&=~(1<<6); - uuid_struct.clock_seq_hi_and_reserved|=1<<7; - uuid_struct.time_hi_and_version&=~(0xf<<12); - uuid_struct.time_hi_and_version|=4<<12; - - written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.time_low, uuid_struct.time_mid, - uuid_struct.time_hi_and_version, uuid_struct.clock_seq_hi_and_reserved, - uuid_struct.clock_seq_low); - if ((written < 0) || ((size_t)written > (len +13))) { - ms_error("sal_create_uuid(): buffer is too short !"); - return -1; - } - for (i = 0; i < 6; i++) - written+=snprintf(uuid+written,len-written,"%2.2x", uuid_struct.node[i]); - uuid[len-1]='\0'; - return 0; -} - -int sal_create_uuid(Sal*ctx, char *uuid, size_t len) { - if (sal_generate_uuid(uuid, len) == 0) { - sal_set_uuid(ctx, uuid); - return 0; - } - return -1; -} - -static void make_supported_header(Sal *sal){ - bctbx_list_t *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=reinterpret_cast(ms_realloc(alltags,(buflen=buflen*2))); - written+=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=bctbx_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=bctbx_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){ - bctbx_list_t *elem=bctbx_list_find_custom(ctx->supported_tags,(bctbx_compare_func)strcasecmp,tag); - if (!elem){ - ctx->supported_tags=bctbx_list_append(ctx->supported_tags,ms_strdup(tag)); - make_supported_header(ctx); - } - -} - -void sal_remove_supported_tag(Sal *ctx, const char* tag){ - bctbx_list_t *elem=bctbx_list_find_custom(ctx->supported_tags,(bctbx_compare_func)strcasecmp,tag); - if (elem){ - ms_free(elem->data); - ctx->supported_tags=bctbx_list_erase_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->supported); - return resp; -} - -void sal_set_refresher_retry_after(Sal *sal,int value) { - sal->refresher_retry_after=value; -} - -int sal_get_refresher_retry_after(const Sal *sal) { - return sal->refresher_retry_after; -} - -void sal_enable_auto_contacts(Sal *ctx, bool_t enabled){ - ctx->auto_contacts=enabled; -} - -void sal_enable_test_features(Sal*ctx, bool_t enabled){ - ctx->enable_test_features=enabled; -} - -void sal_use_no_initial_route(Sal *ctx, bool_t enabled){ - ctx->no_initial_route=enabled; -} - -belle_sip_resolver_context_t * sal_resolve_a(Sal* sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data){ - return belle_sip_stack_resolve_a(sal->stack,name,port,family,cb,data); -} - -belle_sip_resolver_context_t * sal_resolve(Sal *sal, const char *service, const char *transport, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) { - return belle_sip_stack_resolve(sal->stack, service, transport, name, port, family, cb, data); -} - - -void sal_enable_unconditional_answer(Sal *sal,int value) { - belle_sip_provider_enable_unconditional_answer(sal->prov,value); -} - /** Parse a file containing either a certificate chain order in PEM format or a single DER cert * @param auth_info structure where to store the result of parsing * @param path path to certificate chain file @@ -1295,7 +272,7 @@ unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size){ } char *sal_get_random_token(int size){ - return belle_sip_random_token(reinterpret_cast(ms_malloc(size)),size); + return belle_sip_random_token(reinterpret_cast(ms_malloc((size_t)size)),(size_t)size); } unsigned int sal_get_random(void){ @@ -1304,16 +281,6 @@ unsigned int sal_get_random(void){ return ret; } -belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name) { - belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack); - return belle_sip_main_loop_create_timeout(ml, func, data, timeout_value_ms, timer_name); -} - -void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer) { - belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(sal->stack); - belle_sip_main_loop_remove_source(ml, timer); -} - unsigned long sal_begin_background_task(const char *name, void (*max_time_reached)(void *), void *data){ return belle_sip_begin_background_task(name, max_time_reached, data); } @@ -1322,39 +289,6 @@ void sal_end_background_task(unsigned long id){ belle_sip_end_background_task(id); } - -void sal_enable_sip_update_method(Sal *ctx,bool_t value) { - ctx->enable_sip_update=value; -} - -void sal_default_set_sdp_handling(Sal *sal, SalOpSDPHandling sdp_handling_method) { - if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", sal); - sal->default_sdp_handling = sdp_handling_method; -} - -bool_t sal_pending_trans_checking_enabled(const Sal *sal) { - return sal->pending_trans_checking; -} - -int sal_enable_pending_trans_checking(Sal *sal, bool_t value) { - sal->pending_trans_checking = value; - return 0; -} -void sal_set_http_proxy_host(Sal *sal, const char *host) { - belle_sip_stack_set_http_proxy_host(sal->stack, host); -} - -void sal_set_http_proxy_port(Sal *sal, int port) { - belle_sip_stack_set_http_proxy_port(sal->stack, port); -} -const char *sal_get_http_proxy_host(const Sal *sal) { - return belle_sip_stack_get_http_proxy_host(sal->stack); -} - -int sal_get_http_proxy_port(const Sal *sal) { - return belle_sip_stack_get_http_proxy_port(sal->stack); -} - static belle_sip_header_t * sal_body_handler_find_header(const SalBodyHandler *body_handler, const char *header_name) { belle_sip_body_handler_t *bsbh = BELLE_SIP_BODY_HANDLER(body_handler); const belle_sip_list_t *l = belle_sip_body_handler_get_headers(bsbh); @@ -1414,6 +348,29 @@ void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subt belle_sip_header_content_type_set_subtype(content_type, subtype); } +const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + return belle_sip_parameters_get_parameter_names(BELLE_SIP_PARAMETERS(content_type)); + } + return NULL; +} + +const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + return belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type), name); + } + return NULL; +} + +void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue) { + belle_sip_header_content_type_t *content_type = BELLE_SIP_HEADER_CONTENT_TYPE(sal_body_handler_find_header(body_handler, "Content-Type")); + if (content_type != NULL) { + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(content_type), paramName, paramValue); + } +} + const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler) { belle_sip_header_t *content_encoding = sal_body_handler_find_header(body_handler, "Content-Encoding"); if (content_encoding != NULL) { @@ -1462,6 +419,11 @@ SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, i return (SalBodyHandler *)belle_sip_list_nth_data(l, idx); } +const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler) { + if (!sal_body_handler_is_multipart(body_handler)) return NULL; + return belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); +} + SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value) { const belle_sip_list_t *l = belle_sip_multipart_body_handler_get_parts(BELLE_SIP_MULTIPART_BODY_HANDLER(body_handler)); for (; l != NULL; l = l->next) { @@ -1485,29 +447,7 @@ const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, con return NULL; } -void *sal_get_stack_impl(Sal *sal) { - return sal->stack; +const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler) { + return belle_sip_body_handler_get_headers(BELLE_SIP_BODY_HANDLER(body_handler)); } -bool_t sal_is_content_type_supported(const Sal *sal, const char *content_type) { - bctbx_list_t *item; - for (item = sal->supported_content_types; item != NULL; item = bctbx_list_next(item)) { - const char *item_content_type = (const char *)bctbx_list_get_data(item); - if (strcmp(item_content_type, content_type) == 0) return TRUE; - } - return FALSE; -} - -void sal_add_content_type_support(Sal *sal, const char *content_type) { - if ((content_type != NULL) && (sal_is_content_type_supported(sal, content_type) == FALSE)) { - sal->supported_content_types = bctbx_list_append(sal->supported_content_types, ms_strdup(content_type)); - } -} - -void sal_remove_content_type_support(Sal *sal, const char *content_type) { - if (content_type != NULL) { - if (bctbx_list_find(sal->supported_content_types, content_type)) { - sal->supported_content_types = bctbx_list_remove(sal->supported_content_types, (char *)content_type); - } - } -} diff --git a/coreapi/bellesip_sal/sal_impl.h b/coreapi/bellesip_sal/sal_impl.h index 88e901f5b..7ce5a10b9 100644 --- a/coreapi/bellesip_sal/sal_impl.h +++ b/coreapi/bellesip_sal/sal_impl.h @@ -20,167 +20,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef SAL_IMPL_H_ #define SAL_IMPL_H_ -#include "sal/sal.h" +#include "c-wrapper/internal/c-sal.h" #include "belle-sip/belle-sip.h" #include "belle-sip/belle-sdp.h" -struct Sal{ - MSFactory *factory; - SalCallbacks callbacks; - MSList *pending_auths;/*MSList of SalOp */ - belle_sip_stack_t* stack; - belle_sip_provider_t *prov; - belle_sip_header_user_agent_t* user_agent; - belle_sip_listener_t *listener; - void *tunnel_client; - void *up; /*user pointer*/ - int session_expires; - unsigned int keep_alive; - char *root_ca; - char *root_ca_data; - 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; - bool_t tls_verify; - bool_t tls_verify_cn; - bool_t use_dates; - bool_t auto_contacts; - bool_t enable_test_features; - bool_t no_initial_route; - bool_t enable_sip_update; /*true by default*/ - SalOpSDPHandling default_sdp_handling; - bool_t pending_trans_checking; /*testing purpose*/ - void *ssl_config; - bctbx_list_t *supported_content_types; /* list of char* */ - belle_tls_crypto_config_postcheck_callback_t tls_postcheck_cb; - void *tls_postcheck_cb_data; -}; -typedef enum SalOpState { - SalOpStateEarly=0 - ,SalOpStateActive - ,SalOpStateTerminating /*this state is used to wait until a proceeding state, so we can send the cancel*/ - ,SalOpStateTerminated -}SalOpState; - -const char* sal_op_state_to_string(SalOpState value); - -typedef enum SalOpDir { - SalOpDirIncoming=0 - ,SalOpDirOutgoing -}SalOpDir; -typedef enum SalOpType { - SalOpUnknown, - SalOpRegister, - SalOpCall, - SalOpMessage, - SalOpPresence, - SalOpPublish, - SalOpSubscribe -}SalOpType; - -const char* sal_op_type_to_string(SalOpType type); - -struct SalOp{ - SalOpBase base; - const belle_sip_listener_callbacks_t *callbacks; - SalErrorInfo error_info; - SalErrorInfo reason_error_info; - belle_sip_client_transaction_t *pending_auth_transaction; - belle_sip_server_transaction_t* pending_server_trans; - belle_sip_server_transaction_t* pending_update_server_trans; - belle_sip_client_transaction_t* pending_client_trans; - SalAuthInfo* auth_info; - belle_sip_dialog_t* dialog; - belle_sip_header_replaces_t *replaces; - belle_sip_header_referred_by_t *referred_by; - SalMediaDescription *result; - belle_sdp_session_description_t *sdp_answer; - SalOpState state; - SalOpDir dir; - belle_sip_refresher_t* refresher; - int ref; - SalOpType type; - SalPrivacyMask privacy; - belle_sip_header_event_t *event; /*used by SalOpSubscribe kinds*/ - SalOpSDPHandling sdp_handling; - int auth_requests; /*number of auth requested for this op*/ - bool_t cnx_ip_to_0000_if_sendonly_enabled; - bool_t auto_answer_asked; - bool_t sdp_offering; - bool_t call_released; - bool_t manual_refresher; - bool_t has_auth_pending; - bool_t supports_session_timers; - bool_t op_released; -}; - - -belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *sal); +belle_sdp_session_description_t * media_description_to_sdp(const SalMediaDescription *desc); int sdp_to_media_description(belle_sdp_session_description_t *sdp, SalMediaDescription *desc); -belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method); - - -void sal_op_call_fill_cbs(SalOp*op); -void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog); - -/*return reffed op*/ -SalOp* sal_op_ref(SalOp* op); -/*return null, destroy op if ref count =0*/ -void* sal_op_unref(SalOp* op); -void sal_op_release_impl(SalOp *op); - -void sal_op_set_replaces(SalOp* op,belle_sip_header_replaces_t* replaces); -void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message); -int sal_op_send_request(SalOp* op, belle_sip_request_t* request); -int sal_op_send_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires); -void sal_op_resend_request(SalOp* op, belle_sip_request_t* request); -int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener ); -belle_sip_response_t *sal_op_create_response_from_request(SalOp *op, belle_sip_request_t *req, int code); - -/* - * return true if both from and to uri are sips - * */ -bool_t sal_op_is_secure(const SalOp* op); - -void sal_process_authentication(SalOp *op); -belle_sip_header_contact_t* sal_op_create_contact(SalOp *op) ; bool_t _sal_compute_sal_errors(belle_sip_response_t* response, SalReason* sal_reason, char* reason, size_t reason_size); SalReason _sal_reason_from_sip_code(int code); -void sal_op_set_reason_error_info(SalOp *op, belle_sip_message_t *msg); -void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response); -/*presence*/ -void sal_op_presence_fill_cbs(SalOp*op); -/*messaging*/ -void sal_op_message_fill_cbs(SalOp*op); -void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event); -void sal_op_subscribe_fill_cbs(SalOp*op); - -/*call transfer*/ -void sal_op_process_refer(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *tr); -void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *tr); /*create SalAuthInfo by copying username and realm from suth event*/ SalAuthInfo* sal_auth_info_create(belle_sip_auth_event_t* event) ; -void sal_add_pending_auth(Sal *sal, SalOp *op); -void sal_remove_pending_auth(Sal *sal, SalOp *op); -void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence); - -belle_sip_response_t *sal_create_response_from_request(Sal *sal, belle_sip_request_t *req, int code); - -void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming); - -SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg); - -int sal_reason_to_sip_code(SalReason r); - -void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg); - -SalSubscribeStatus belle_sip_message_get_subscription_state(const 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 deleted file mode 100644 index 695a71ac5..000000000 --- a/coreapi/bellesip_sal/sal_op_call.c +++ /dev/null @@ -1,1246 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" -#include "offeranswer.h" - -#include - -static int extract_sdp(SalOp* op,belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error); - -/*used for calls terminated before creation of a dialog*/ -static void call_set_released(SalOp* op){ - if (!op->call_released){ - op->state=SalOpStateTerminated; - op->base.root->callbacks.call_released(op); - op->call_released=TRUE; - /*be aware that the following line may destroy the op*/ - set_or_update_dialog(op,NULL); - } -} - -static void call_set_error(SalOp* op,belle_sip_response_t* response, bool_t fatal){ - sal_op_set_error_info_from_response(op,response); - if (fatal) op->state = SalOpStateTerminating; - op->base.root->callbacks.call_failure(op); -} -static void set_addr_to_0000(char value[], size_t sz) { - if (ms_is_ipv6(value)) { - strncpy(value,"::0", sz); - } else { - strncpy(value,"0.0.0.0", sz); - } - return; -} -static void sdp_process(SalOp *h){ - ms_message("Doing SDP offer/answer process of type %s",h->sdp_offering ? "outgoing" : "incoming"); - if (h->result){ - sal_media_description_unref(h->result); - h->result = NULL; - } - - /* if SDP was invalid */ - if (h->base.remote_media == NULL) return; - - h->result=sal_media_description_new(); - if (h->sdp_offering){ - offer_answer_initiate_outgoing(h->base.root->factory, h->base.local_media,h->base.remote_media,h->result); - }else{ - int i; - if (h->sdp_answer){ - belle_sip_object_unref(h->sdp_answer); - } - offer_answer_initiate_incoming(h->base.root->factory, h->base.local_media,h->base.remote_media,h->result,h->base.root->one_matching_codec); - /*for backward compatibility purpose*/ - if(h->cnx_ip_to_0000_if_sendonly_enabled && sal_media_description_has_dir(h->result,SalStreamSendOnly)) { - set_addr_to_0000(h->result->addr, sizeof(h->result->addr)); - for(i=0;iresult->streams[i].dir == SalStreamSendOnly) { - set_addr_to_0000(h->result->streams[i].rtp_addr, sizeof(h->result->streams[i].rtp_addr)); - set_addr_to_0000(h->result->streams[i].rtcp_addr, sizeof(h->result->streams[i].rtcp_addr)); - } - } - } - h->sdp_answer=(belle_sdp_session_description_t *)belle_sip_object_ref(media_description_to_sdp(h->result)); - /*once we have generated the SDP answer, we modify the result description for processing by the upper layer. - It should contains media parameters constraint from the remote offer, not our response*/ - strcpy(h->result->addr,h->base.remote_media->addr); - h->result->bandwidth=h->base.remote_media->bandwidth; - - for(i=0;iresult->streams[i].rtp_port!=0){ /*if stream was accepted*/ - strcpy(h->result->streams[i].rtp_addr,h->base.remote_media->streams[i].rtp_addr); - h->result->streams[i].ptime=h->base.remote_media->streams[i].ptime; - h->result->streams[i].bandwidth=h->base.remote_media->streams[i].bandwidth; - h->result->streams[i].rtp_port=h->base.remote_media->streams[i].rtp_port; - strcpy(h->result->streams[i].rtcp_addr,h->base.remote_media->streams[i].rtcp_addr); - h->result->streams[i].rtcp_port=h->base.remote_media->streams[i].rtcp_port; - - if (sal_stream_description_has_srtp(&h->result->streams[i])) { - h->result->streams[i].crypto[0] = h->base.remote_media->streams[i].crypto[0]; - } - } - } - } -} - -static int set_sdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) { - belle_sip_header_content_type_t* content_type ; - belle_sip_header_content_length_t* content_length; - belle_sip_error_code error = BELLE_SIP_BUFFER_OVERFLOW; - size_t length = 0; - - if (session_desc) { - size_t bufLen = 2048; - size_t hardlimit = 16*1024; /* 16k SDP limit seems reasonable */ - char* buff = reinterpret_cast(belle_sip_malloc(bufLen)); - content_type = belle_sip_header_content_type_create("application","sdp"); - - /* try to marshal the description. This could go higher than 2k so we iterate */ - while( error != BELLE_SIP_OK && bufLen <= hardlimit && buff != NULL){ - error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff,bufLen,&length); - if( error != BELLE_SIP_OK ){ - bufLen *= 2; - length = 0; - buff = reinterpret_cast(belle_sip_realloc(buff,bufLen)); - } - } - /* give up if hard limit reached */ - if (error != BELLE_SIP_OK || buff == NULL) { - ms_error("Buffer too small (%d) or not enough memory, giving up SDP", (int)bufLen); - return -1; - } - - content_length = belle_sip_header_content_length_create(length); - belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_type)); - belle_sip_message_add_header(msg,BELLE_SIP_HEADER(content_length)); - belle_sip_message_assign_body(msg,buff,length); - return 0; - } else { - return -1; - } -} -static int set_sdp_from_desc(belle_sip_message_t *msg, const SalMediaDescription *desc){ - int err; - belle_sdp_session_description_t *sdp=media_description_to_sdp(desc); - err=set_sdp(msg,sdp); - belle_sip_object_unref(sdp); - return err; - -} - -static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event) { - SalOp *op = (SalOp *)user_ctx; - - if (op->state == SalOpStateTerminated) return; - - if (op->pending_client_trans && (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_INIT)) { - - sal_error_info_set(&op->error_info, SalReasonIOError, "SIP", 503, "IO error", NULL); - op->base.root->callbacks.call_failure(op); - - if (!op->dialog || belle_sip_dialog_get_state(op->dialog) != BELLE_SIP_DIALOG_CONFIRMED){ - /* Call terminated very very early, before INVITE is even sent, probably DNS resolution timeout. */ - op->state = SalOpStateTerminating; - call_set_released(op); - } - } else { - /* Nothing to be done. If the error comes from a connectivity loss, - * the call will be marked as broken, and an attempt to repair it will be done. */ - } -} - -static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) { - SalOp* op=(SalOp*)ctx; - - if (op->dialog && op->dialog==belle_sip_dialog_terminated_event_get_dialog(event)) { - /*belle_sip_transaction_t* trans=belle_sip_dialog_get_last_transaction(op->dialog);*/ - ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op); - - switch(belle_sip_dialog_get_previous_state(op->dialog)) { - case BELLE_SIP_DIALOG_EARLY: - case BELLE_SIP_DIALOG_NULL: - if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) { - /*this is an early termination due to incorrect response received*/ - op->base.root->callbacks.call_failure(op); - op->state=SalOpStateTerminating; - } - break; - case BELLE_SIP_DIALOG_CONFIRMED: - if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) { - /*this is probably a normal termination from a BYE*/ - op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); - op->state=SalOpStateTerminating; - } - break; - default: - break; - } - belle_sip_main_loop_do_later(belle_sip_stack_get_main_loop(op->base.root->stack) - ,(belle_sip_callback_t) call_set_released - , op); - } else { - ms_error("dialog unknown for op "); - } -} - -static void handle_sdp_from_response(SalOp* op,belle_sip_response_t* response) { - belle_sdp_session_description_t* sdp; - SalReason reason; - if (op->base.remote_media){ - sal_media_description_unref(op->base.remote_media); - op->base.remote_media=NULL; - } - if (extract_sdp(op,BELLE_SIP_MESSAGE(response),&sdp,&reason)==0) { - if (sdp){ - op->base.remote_media=sal_media_description_new(); - sdp_to_media_description(sdp,op->base.remote_media); - }/*if no sdp in response, what can we do ?*/ - } - /* process sdp in any case to reset result media description*/ - if (op->base.local_media) sdp_process(op); -} - -int sal_call_cancel_invite(SalOp *op) { - return sal_call_cancel_invite_with_info(op,NULL); -} - -static void cancelling_invite(SalOp *op, const SalErrorInfo *info) { - sal_call_cancel_invite_with_info(op, info); - op->state=SalOpStateTerminating; -} - -static int vfu_retry (void *user_data, unsigned int events) { - SalOp *op=(SalOp *)user_data; - sal_call_send_vfu_request(op); - sal_op_unref(op); - return BELLE_SIP_STOP; -} - -static void call_process_response(void *op_base, const belle_sip_response_event_t *event){ - SalOp* op = (SalOp*)op_base; - belle_sip_request_t* ack; - belle_sip_dialog_state_t dialog_state; - belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); - belle_sip_request_t* req; - belle_sip_response_t* response=belle_sip_response_event_get_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); - return; - } - 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)); - /*to make sure no cb will destroy op*/ - sal_op_ref(op); - switch(dialog_state) { - case BELLE_SIP_DIALOG_NULL: - case BELLE_SIP_DIALOG_EARLY: { - 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) { - /*it wasn't sent */ - if (code<200) { - cancelling_invite(op, NULL); - }else{ - /* no need to send the INVITE because the UAS rejected the INVITE*/ - if (op->dialog==NULL) call_set_released(op); - } - } else { - /*it was sent already, so just expect the 487 or any error response to send the call_released() notification*/ - if (code>=300){ - if (op->dialog==NULL) call_set_released(op); - } - } - } else if (code >= 180 && code<200) { - belle_sip_response_t *prev_response=reinterpret_cast(belle_sip_object_data_get(BELLE_SIP_OBJECT(dialog),"early_response")); - if (!prev_response || code>belle_sip_response_get_status_code(prev_response)){ - handle_sdp_from_response(op,response); - op->base.root->callbacks.call_ringing(op); - } - belle_sip_object_data_set(BELLE_SIP_OBJECT(dialog),"early_response",belle_sip_object_ref(response),belle_sip_object_unref); - } else if (code>=300){ - call_set_error(op, response, TRUE); - if (op->dialog==NULL) call_set_released(op); - } - } else if (code >=200 && code<300) { - if (strcmp("UPDATE",method)==0) { - handle_sdp_from_response(op,response); - op->base.root->callbacks.call_accepted(op); - } else if (strcmp("CANCEL", method) == 0) { - op->base.root->callbacks.call_cancel_done(op); - } - } - } - break; - case BELLE_SIP_DIALOG_CONFIRMED: { - switch (op->state) { - case SalOpStateEarly:/*invite case*/ - 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_message_add_header(BELLE_SIP_MESSAGE(ack),BELLE_SIP_HEADER(op->base.root->user_agent)); - op->base.root->callbacks.call_accepted(op); /*INVITE*/ - op->base.root->callbacks.call_ack_being_sent(op, (SalCustomHeader*)ack); - belle_sip_dialog_send_ack(op->dialog,ack); - op->state=SalOpStateActive; - }else if (code >= 300){ - call_set_error(op,response, FALSE); - } - }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) { - unsigned int retry_in = (unsigned int)(1000*((float)rand()/RAND_MAX)); - 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 if (strcmp("UPDATE",method)==0){ - op->base.root->callbacks.call_accepted(op); /*INVITE*/ - }else if (strcmp("CANCEL",method)==0){ - op->base.root->callbacks.call_cancel_done(op); - } - break; - case SalOpStateTerminating: - sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE")); - break; - case SalOpStateTerminated: - default: - ms_error("Call op [%p] receives unexpected answer [%i] while in state [%s].",op,code, sal_op_state_to_string(op->state)); - } - } - break; - case BELLE_SIP_DIALOG_TERMINATED: { - if (strcmp("INVITE",method)==0 && code >= 300){ - call_set_error(op,response, TRUE); - } - } - break; - default: { - ms_error("call op [%p] receive answer [%i] not implemented",op,code); - } - break; - } - sal_op_unref(op); -} - -static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp* op=(SalOp*)user_ctx; - - if (op->state==SalOpStateTerminated) return; - - if (!op->dialog) { - /*call terminated very early*/ - sal_error_info_set(&op->error_info, SalReasonRequestTimeout, "SIP", 408, "Request timeout", NULL); - op->base.root->callbacks.call_failure(op); - op->state = SalOpStateTerminating; - call_set_released(op); - } else { - /*dialog will terminated shortly, nothing to do*/ - } -} - -static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { - SalOp* op = (SalOp*)user_ctx; - belle_sip_client_transaction_t *client_transaction=belle_sip_transaction_terminated_event_get_client_transaction(event); - belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event); - belle_sip_request_t* req; - belle_sip_response_t* resp; - int code = 0; - bool_t release_call=FALSE; - - if (client_transaction) { - req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); - resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction)); - } else { - req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); - resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(server_transaction)); - } - if (resp) code = belle_sip_response_get_status_code(resp); - - if (op->state == SalOpStateTerminating - && strcmp("BYE",belle_sip_request_get_method(req))==0 - && (!resp || (belle_sip_response_get_status_code(resp) != 401 - && belle_sip_response_get_status_code(resp) != 407)) - && op->dialog==NULL) { - release_call=TRUE; - }else if (op->state == SalOpStateEarly && code < 200){ - /*call terminated early*/ - sal_error_info_set(&op->error_info, SalReasonIOError, "SIP", 503, "I/O error", NULL); - op->state = SalOpStateTerminating; - op->base.root->callbacks.call_failure(op); - release_call=TRUE; - } - if (server_transaction){ - if (op->pending_server_trans==server_transaction){ - belle_sip_object_unref(op->pending_server_trans); - op->pending_server_trans=NULL; - } - if (op->pending_update_server_trans==server_transaction){ - belle_sip_object_unref(op->pending_update_server_trans); - op->pending_update_server_trans=NULL; - } - } - if (release_call) call_set_released(op); -} - -static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, int status_code, belle_sip_request_t* cancel_request) { - belle_sip_response_t* resp; - belle_sip_request_t* server_req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); - op->state = SalOpStateTerminating; - sal_op_set_reason_error_info(op, BELLE_SIP_MESSAGE(cancel_request ? cancel_request : server_req)); - resp=sal_op_create_response_from_request(op,server_req,status_code); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op)); -} - -static void unsupported_method(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request) { - belle_sip_response_t* resp; - resp=belle_sip_response_create_from_request(request,501); - belle_sip_server_transaction_send_response(server_transaction,resp); - return; -} - -/* - * Extract the sdp from a sip message. - * If there is no body in the message, the session_desc is set to null, 0 is returned. - * If body was present is not a SDP or parsing of SDP failed, -1 is returned and SalReason is set appropriately. - * -**/ -static int extract_sdp(SalOp *op, belle_sip_message_t* message,belle_sdp_session_description_t** session_desc, SalReason *error) { - const char *body; - belle_sip_header_content_type_t* content_type; - - if (op&&op->sdp_handling == SalOpSDPSimulateError){ - ms_error("Simulating SDP parsing error for op %p", op); - *session_desc=NULL; - *error=SalReasonNotAcceptable; - return -1; - } else if( op && op->sdp_handling == SalOpSDPSimulateRemove){ - ms_error("Simulating no SDP for op %p", op); - *session_desc = NULL; - return 0; - } - - body = belle_sip_message_get_body(message); - if(body == NULL) { - *session_desc = NULL; - return 0; - } - - content_type = belle_sip_message_get_header_by_type(message,belle_sip_header_content_type_t); - if (content_type){ - if (strcmp("application",belle_sip_header_content_type_get_type(content_type))==0 - && strcmp("sdp",belle_sip_header_content_type_get_subtype(content_type))==0) { - *session_desc=belle_sdp_session_description_parse(body); - if (*session_desc==NULL) { - ms_error("Failed to parse SDP message."); - *error=SalReasonNotAcceptable; - return -1; - } - }else{ - *error=SalReasonUnsupportedContent; - return -1; - } - }else *session_desc=NULL; - return 0; -} - -static int is_media_description_acceptable(SalMediaDescription *md){ - if (md->nb_streams==0){ - ms_warning("Media description does not define any stream."); - return FALSE; - } - return TRUE; -} - -static SalReason process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { - belle_sdp_session_description_t* sdp; - SalReason reason = SalReasonNone; - SalErrorInfo sei; - - memset(&sei, 0, sizeof(sei)); - if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) { - if (sdp){ - op->sdp_offering=FALSE; - op->base.remote_media=sal_media_description_new(); - sdp_to_media_description(sdp,op->base.remote_media); - /*make some sanity check about the SDP received*/ - if (!is_media_description_acceptable(op->base.remote_media)){ - reason=SalReasonNotAcceptable; - } - belle_sip_object_unref(sdp); - }else op->sdp_offering=TRUE; /*INVITE without SDP*/ - } - - if (reason != SalReasonNone){ - sal_error_info_set(&sei, reason,"SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(op, &sei,NULL); - sal_error_info_reset(&sei); - } - return reason; -} - -static void sal_op_reset_descriptions(SalOp *op) { - if (op->base.remote_media){ - sal_media_description_unref(op->base.remote_media); - op->base.remote_media=NULL; - } - if (op->result){ - sal_media_description_unref(op->result); - op->result=NULL; - } -} - -static bool_t is_a_pending_invite_incoming_transaction(belle_sip_transaction_t *tr){ - return BELLE_SIP_OBJECT_IS_INSTANCE_OF(tr, belle_sip_ist_t) && belle_sip_transaction_state_is_transient( - belle_sip_transaction_get_state(tr)); -} - -static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - SalReason reason; - belle_sip_server_transaction_t* server_transaction=NULL; - belle_sdp_session_description_t* sdp; - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_dialog_state_t dialog_state; - 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; - bool_t drop_op = FALSE; - - if (strcmp("ACK",method)!=0){ /*ACK doesn't create a server transaction*/ - server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); - belle_sip_object_ref(server_transaction); - belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),sal_op_ref(op)); - } - - if (strcmp("INVITE",method)==0) { - if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); - /*updating pending invite transaction*/ - op->pending_server_trans=server_transaction; - belle_sip_object_ref(op->pending_server_trans); - } - - if (strcmp("UPDATE",method)==0) { - if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans); - /*updating pending update transaction*/ - op->pending_update_server_trans=server_transaction; - belle_sip_object_ref(op->pending_update_server_trans); - } - - if (!op->dialog) { - set_or_update_dialog(op,belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(op->pending_server_trans))); - ms_message("new incoming call from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); - } - dialog_state=belle_sip_dialog_get_state(op->dialog); - switch(dialog_state) { - case BELLE_SIP_DIALOG_NULL: { - if (strcmp("INVITE",method)==0) { - if (!op->replaces && (op->replaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) { - belle_sip_object_ref(op->replaces); - } else if(op->replaces) { - ms_warning("replace header already set"); - } - - if ( (reason = process_sdp_for_invite(op,req)) == SalReasonNone) { - if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) { - if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) { - op->auto_answer_asked=TRUE; - ms_message("The caller asked to automatically answer the call(Emergency?)\n"); - } - } - op->base.root->callbacks.call_received(op); - }else{ - sal_error_info_set(&op->error_info, reason, "SIP", 0, NULL, NULL); - op->base.root->callbacks.call_rejected(op); - /*the INVITE was declined by process_sdp_for_invite(). As we are not inside an established dialog, we can drop the op immediately*/ - drop_op = TRUE; - } - break; - }BCTBX_NO_BREAK; /* else same behavior as for EARLY state, thus NO BREAK*/ - } - case BELLE_SIP_DIALOG_EARLY: { - if (strcmp("CANCEL",method)==0) { - if(belle_sip_request_event_get_server_transaction(event)) { - /*first answer 200 ok to cancel*/ - belle_sip_server_transaction_send_response(server_transaction - ,sal_op_create_response_from_request(op,req,200)); - /*terminate invite transaction*/ - call_terminated(op,op->pending_server_trans,487,req); - } else { - /*call leg does not exist*/ - belle_sip_server_transaction_send_response(server_transaction - ,sal_op_create_response_from_request(op,req,481)); - } - } else if (strcmp("PRACK",method)==0) { - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - } else if (strcmp("UPDATE",method)==0) { - sal_op_reset_descriptions(op); - if (process_sdp_for_invite(op,req)==SalReasonNone) - 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); - } - break; - } - case BELLE_SIP_DIALOG_CONFIRMED: - /*great ACK received*/ - if (strcmp("ACK",method)==0) { - if (!op->pending_client_trans || - !belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state((belle_sip_transaction_t*)op->pending_client_trans))){ - if (op->sdp_offering){ - SalReason reason; - if (extract_sdp(op,BELLE_SIP_MESSAGE(req),&sdp,&reason)==0){ - if (sdp){ - if (op->base.remote_media) - sal_media_description_unref(op->base.remote_media); - op->base.remote_media=sal_media_description_new(); - sdp_to_media_description(sdp,op->base.remote_media); - sdp_process(op); - belle_sip_object_unref(sdp); - }else{ - ms_warning("SDP expected in ACK but not found."); - } - } - } - op->base.root->callbacks.call_ack_received(op, (SalCustomHeader*)req); - }else{ - ms_message("Ignored received ack since a new client transaction has been started since."); - } - } else if(strcmp("BYE",method)==0) { - call_terminated(op,server_transaction,200,req); - /*call end not notified by dialog deletion because transaction can end before dialog*/ - } 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)==SalReasonNone) - 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")) { - /*vfu request*/ - ms_message("Receiving VFU request on op [%p]",op); - if (op->base.root->callbacks.vfu_request){ - op->base.root->callbacks.vfu_request(op); - - } - }else{ - belle_sip_message_t *msg = BELLE_SIP_MESSAGE(req); - belle_sip_body_handler_t *body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, msg)); - if (body_handler) { - belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); - if (content_type - && (strcmp(belle_sip_header_content_type_get_type(content_type), "application") == 0) - && (strcmp(belle_sip_header_content_type_get_subtype(content_type), "dtmf-relay") == 0)) { - char tmp[10]; - if (sal_lines_get_value(belle_sip_message_get_body(msg), "Signal",tmp, sizeof(tmp))){ - op->base.root->callbacks.dtmf_received(op,tmp[0]); - } - }else - op->base.root->callbacks.info_received(op, (SalBodyHandler *)body_handler); - } else { - op->base.root->callbacks.info_received(op,NULL); - } - } - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - }else if (strcmp("REFER",method)==0) { - sal_op_process_refer(op,event,server_transaction); - } else if (strcmp("NOTIFY",method)==0) { - sal_op_call_process_notify(op,event,server_transaction); - } else if (strcmp("OPTIONS",method)==0) { - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - } else if (strcmp("CANCEL",method)==0) { - belle_sip_transaction_t *last_transaction = belle_sip_dialog_get_last_transaction(op->dialog); - if (last_transaction == NULL || !is_a_pending_invite_incoming_transaction(last_transaction) ) { - /*call leg does not exist because 200ok already sent*/ - belle_sip_server_transaction_send_response(server_transaction,sal_op_create_response_from_request(op,req,481)); - } else { - /* CANCEL on re-INVITE for which a 200ok has not been sent yet */ - belle_sip_server_transaction_send_response(server_transaction, sal_op_create_response_from_request(op, req, 200)); - belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(last_transaction), - sal_op_create_response_from_request(op, belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_transaction)), 487)); - } - } else if (strcmp("MESSAGE",method)==0){ - sal_process_incoming_message(op,event); - }else{ - ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->dialog); - unsupported_method(server_transaction,req); - } - break; - default: - ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - break; - } - - if (server_transaction) belle_sip_object_unref(server_transaction); - if (drop_op) sal_op_release(op); -} - - -/*Call API*/ -int sal_call_set_local_media_description(SalOp *op, SalMediaDescription *desc){ - if (desc) - sal_media_description_ref(desc); - if (op->base.local_media) - sal_media_description_unref(op->base.local_media); - op->base.local_media=desc; - - if (op->base.remote_media){ - /*case of an incoming call where we modify the local capabilities between the time - * the call is ringing and it is accepted (for example if you want to accept without video*/ - /*reset the sdp answer so that it is computed again*/ - if (op->sdp_answer){ - belle_sip_object_unref(op->sdp_answer); - op->sdp_answer=NULL; - } - } - return 0; -} - -static belle_sip_header_allow_t *create_allow(bool_t enable_update){ - belle_sip_header_allow_t* header_allow; - char allow [256]; - snprintf(allow,sizeof(allow),"INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO%s",(enable_update?", UPDATE":"")); - header_allow = belle_sip_header_allow_create(allow); - return header_allow; -} - -static void sal_op_fill_invite(SalOp *op, belle_sip_request_t* invite) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(create_allow(op->base.root->enable_sip_update))); - - if (op->base.root->session_expires!=0){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "600;refresher=uas")); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer")); - } - if (op->base.local_media){ - op->sdp_offering=TRUE; - set_sdp_from_desc(BELLE_SIP_MESSAGE(invite),op->base.local_media); - }else op->sdp_offering=FALSE; - return; -} - -int sal_call(SalOp *op, const char *from, const char *to){ - belle_sip_request_t* invite; - op->dir=SalOpDirOutgoing; - - sal_op_set_from(op,from); - sal_op_set_to(op,to); - - ms_message("[%s] calling [%s] on op [%p]", from, to, op); - invite=sal_op_build_request(op,"INVITE"); - - if( invite == NULL ){ - /* can happen if the op has an invalid address */ - return -1; - } - - sal_op_fill_invite(op,invite); - - sal_op_call_fill_cbs(op); - if (op->replaces){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->replaces)); - } - if (op->referred_by) - belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(op->referred_by)); - - return sal_op_send_request(op,invite); -} - -static belle_sip_listener_callbacks_t call_op_callbacks={0}; - -void sal_op_call_fill_cbs(SalOp*op) { - if (call_op_callbacks.process_response_event==NULL){ - call_op_callbacks.process_io_error=call_process_io_error; - call_op_callbacks.process_response_event=call_process_response; - call_op_callbacks.process_timeout=call_process_timeout; - call_op_callbacks.process_transaction_terminated=call_process_transaction_terminated; - call_op_callbacks.process_request_event=process_request_event; - call_op_callbacks.process_dialog_terminated=process_dialog_terminated; - } - op->callbacks=&call_op_callbacks; - op->type=SalOpCall; -} - -static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* response) { - if (op->base.local_media){ - /*this is the case where we received an invite without SDP*/ - if (op->sdp_offering) { - set_sdp_from_desc(BELLE_SIP_MESSAGE(response),op->base.local_media); - }else{ - - if ( op->sdp_answer==NULL ) - { - if( op->sdp_handling == SalOpSDPSimulateRemove ){ - ms_warning("Simulating SDP removal in answer for op %p", op); - } else { - sdp_process(op); - } - } - - if (op->sdp_answer){ - set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer); - belle_sip_object_unref(op->sdp_answer); - op->sdp_answer=NULL; - } - } - }else{ - ms_error("You are accepting a call but not defined any media capabilities !"); - } -} - -int sal_call_notify_ringing(SalOp *op, bool_t early_media){ - int status_code =early_media?183:180; - belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)); - belle_sip_response_t* ringing_response = sal_op_create_response_from_request(op,req,status_code); - belle_sip_header_t *require; - const char *tags=NULL; - - if (early_media){ - handle_offer_answer_response(op,ringing_response); - } - require=belle_sip_message_get_header((belle_sip_message_t*)req,"Require"); - if (require) tags=belle_sip_header_get_unparsed_value(require); - /* if client requires 100rel, then add necessary stuff*/ - if (tags && strstr(tags,"100rel")!=0) { - belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("Require","100rel")); - belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("RSeq","1")); - } - -#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING - if (tags && strstr(tags,"100rel")!=0) -#endif - { - belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op); - belle_sip_header_contact_t* contact_header; - if (contact && (contact_header=belle_sip_header_contact_create(contact))) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header)); - } - } - belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response); - return 0; -} - - -/*accept an incoming call or, during a call accept a reINVITE*/ -int sal_call_accept(SalOp*h){ - belle_sip_response_t *response; - belle_sip_header_contact_t* contact_header; - belle_sip_server_transaction_t* transaction; - - /*first check if an UPDATE transaction need to be accepted*/ - if (h->pending_update_server_trans) { - transaction=h->pending_update_server_trans; - } else if (h->pending_server_trans) { - /*so it must be an invite/re-invite*/ - transaction=h->pending_server_trans; - } else { - ms_error("No transaction to accept for op [%p]",h); - return -1; - } - ms_message("Accepting server transaction [%p] on op [%p]", transaction, h); - - /* sends a 200 OK */ - response = sal_op_create_response_from_request(h,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(transaction)),200); - if (response==NULL){ - ms_error("Fail to build answer for call"); - return -1; - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow(h->base.root->enable_sip_update))); - if (h->base.root->session_expires!=0){ -/* if (h->supports_session_timers) {*/ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer")); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Session-expires", "600;refresher=uac")); - /*}*/ - } - - if ((contact_header=sal_op_create_contact(h))) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header)); - } - - _sal_op_add_custom_headers(h, BELLE_SIP_MESSAGE(response)); - - handle_offer_answer_response(h,response); - - belle_sip_server_transaction_send_response(transaction,response); - if (h->pending_update_server_trans) { - belle_sip_object_unref(h->pending_update_server_trans); - h->pending_update_server_trans=NULL; - } - if (h->state == SalOpStateEarly){ - h->state = SalOpStateActive; - } - return 0; -} - -static belle_sip_header_reason_t *sal_call_make_reason_header( const SalErrorInfo *info){ - if (info != NULL && info->reason != SalReasonNone){ - belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); - belle_sip_header_reason_set_text(reason, info->status_string); - belle_sip_header_reason_set_protocol(reason,info->protocol); - belle_sip_header_reason_set_cause(reason,info->protocol_code); - return reason; - } - return NULL; -} - -int sal_call_cancel_invite_with_info(SalOp* op, const SalErrorInfo *info) { - belle_sip_request_t* cancel; - - if (op->pending_client_trans == NULL){ - ms_warning("There is no transaction to cancel."); - return -1; - } - - ms_message("Cancelling INVITE request from [%s] to [%s] ",sal_op_get_from(op), sal_op_get_to(op)); - cancel = belle_sip_client_transaction_create_cancel(op->pending_client_trans); - if (cancel){ - if (info != NULL && info->reason != SalReasonNone){ - belle_sip_header_reason_t* reason = sal_call_make_reason_header(info); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(cancel),BELLE_SIP_HEADER(reason)); - } - sal_op_send_request(op,cancel); - return 0; - }else if (op->dialog){ - belle_sip_dialog_state_t state = belle_sip_dialog_get_state(op->dialog);; - /*case where the response received is invalid (could not establish a dialog), but the transaction is not cancellable - * because already terminated*/ - switch(state){ - case BELLE_SIP_DIALOG_EARLY: - case BELLE_SIP_DIALOG_NULL: - /*force kill the dialog*/ - ms_warning("op [%p]: force kill of dialog [%p]", op, op->dialog); - belle_sip_dialog_delete(op->dialog); - break; - default: - break; - } - } - return -1; -} - -int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){ - belle_sip_response_t* response; - belle_sip_header_contact_t* contact=NULL; - int status=sal_reason_to_sip_code(reason); - belle_sip_transaction_t *trans; - - if (reason==SalReasonRedirect){ - if (redirection!=NULL) { - if (strstr(redirection,"sip:")!=0) status=302; - else status=380; - contact= belle_sip_header_contact_new(); - belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); - } else { - ms_error("Cannot redirect to null"); - } - } - trans=(belle_sip_transaction_t*)op->pending_server_trans; - if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; - if (!trans){ - ms_error("sal_call_decline(): no pending transaction to decline."); - return -1; - } - response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status); - if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); - belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); - return 0; -} - -int sal_call_decline_with_error_info(SalOp *op, const SalErrorInfo *info, const char *redirection /*optional*/){ - belle_sip_response_t* response; - belle_sip_header_contact_t* contact=NULL; - int status = info->protocol_code; - belle_sip_transaction_t *trans; - - if (info->reason==SalReasonRedirect){ - if (redirection!=NULL) { - if (strstr(redirection,"sip:")!=0) status=302; - else status=380; - contact= belle_sip_header_contact_new(); - belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); - } else { - ms_error("Cannot redirect to null"); - } - } - trans=(belle_sip_transaction_t*)op->pending_server_trans; - if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; - if (!trans){ - ms_error("sal_call_decline_with_error_info(): no pending transaction to decline."); - return -1; - } - response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status); - belle_sip_header_reason_t* reason_header = sal_call_make_reason_header(info->sub_sei); - if (reason_header) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(reason_header)); - } - - if (contact) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); - } - belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); - return 0; -} - -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; - - if (op->dialog == NULL) { - /* If the dialog does not exist, this is that we are trying to recover from a connection loss - during a very early state of outgoing call initiation (the dialog has not been created yet). */ - const char *from = sal_op_get_from(op); - const char *to = sal_op_get_to(op); - return sal_call(op, from, to); - } - - state = belle_sip_dialog_get_state(op->dialog); - belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking); - - /*check for dialog state*/ - if ( state == BELLE_SIP_DIALOG_CONFIRMED) { - 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 { - ms_error("Cannot update op [%p] with dialog [%p] in state [%s]",op, op->dialog,belle_sip_dialog_state_to_string(state)); - return -1; - } - if (update){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(update),belle_sip_header_create( "Subject", subject)); - sal_op_fill_invite(op, update); - return sal_op_send_request(op,update); - } - /*it failed why ?*/ - if (belle_sip_dialog_request_pending(op->dialog)) - sal_error_info_set(&op->error_info,SalReasonRequestPending, "SIP", 491,NULL,NULL); - else - sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", 500,NULL,NULL); - return -1; -} - -SalMediaDescription * sal_call_get_remote_media_description(SalOp *h){ - return h->base.remote_media; -} - -SalMediaDescription * sal_call_get_final_media_description(SalOp *h){ - if (h->base.local_media && h->base.remote_media && !h->result){ - sdp_process(h); - } - return h->result; -} - -int sal_call_send_dtmf(SalOp *h, char dtmf){ - if (h->dialog && (belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_CONFIRMED || belle_sip_dialog_get_state(h->dialog) == BELLE_SIP_DIALOG_EARLY)){ - belle_sip_request_t *req=belle_sip_dialog_create_queued_request(h->dialog,"INFO"); - if (req){ - size_t bodylen; - char dtmf_body[128]={0}; - - snprintf(dtmf_body, sizeof(dtmf_body)-1, "Signal=%c\r\nDuration=250\r\n", dtmf); - bodylen=strlen(dtmf_body); - belle_sip_message_set_body((belle_sip_message_t*)req,dtmf_body,bodylen); - belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_length_create(bodylen)); - belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_type_create("application", "dtmf-relay")); - sal_op_send_request(h,req); - }else ms_error("sal_call_send_dtmf(): could not build request"); - }else ms_error("sal_call_send_dtmf(): no dialog"); - return 0; -} - - -int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ - SalErrorInfo sei; - const SalErrorInfo *p_sei; - belle_sip_dialog_state_t dialog_state = op->dialog ? belle_sip_dialog_get_state(op->dialog) : BELLE_SIP_DIALOG_NULL; - int ret = 0; - - memset(&sei, 0, sizeof(sei)); - if (info == NULL && dialog_state != BELLE_SIP_DIALOG_CONFIRMED && op->dir == SalOpDirIncoming){ - /*the purpose of this line is to set a default SalErrorInfo for declining an incoming call (not yet established of course) */ - sal_error_info_set(&sei,SalReasonDeclined, "SIP", 0, NULL, NULL); - p_sei = &sei; - } else{ - p_sei = info; - } - if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) { - ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state)); - ret = -1; - goto end; - } - switch(dialog_state) { - case BELLE_SIP_DIALOG_CONFIRMED: { - belle_sip_request_t * req = belle_sip_dialog_create_request(op->dialog,"BYE"); - if (info != NULL && info->reason != SalReasonNone){ - belle_sip_header_reason_t* reason = sal_call_make_reason_header(info); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(reason)); - } - sal_op_send_request(op,req); - op->state=SalOpStateTerminating; - break; - } - - case BELLE_SIP_DIALOG_NULL: { - if (op->dir == SalOpDirIncoming) { - sal_call_decline_with_error_info(op, p_sei, NULL); - op->state=SalOpStateTerminated; - } else if (op->pending_client_trans){ - if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){ - cancelling_invite(op, p_sei); - }else{ - /* Case where the CANCEL cannot be sent because no provisional response was received so far. - * The Op must be kept for the time of the transaction in case a response is received later. - * The state is passed to Terminating to remember to terminate later. - */ - op->state=SalOpStateTerminating; - /* However, even if the transaction is kept alive, we can stop sending retransmissions to avoid flowing the network with no longer - * necessary messages and avoid confusion in logs.*/ - belle_sip_client_transaction_stop_retransmissions(op->pending_client_trans); - } - } - break; - } - case BELLE_SIP_DIALOG_EARLY: { - if (op->dir == SalOpDirIncoming) { - sal_call_decline_with_error_info(op, p_sei,NULL); - op->state=SalOpStateTerminated; - } else { - cancelling_invite(op, p_sei); - } - break; - } - default: { - ms_error("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - ret = -1; - goto end; - } - } -end: - sal_error_info_reset(&sei); - return ret; -} - - -int sal_call_terminate(SalOp *op){ - return sal_call_terminate_with_error(op, NULL); -} - - -bool_t sal_call_autoanswer_asked(SalOp *op){ - return op->auto_answer_asked; -} - -void sal_call_send_vfu_request(SalOp *op){ - char info_body[] = - "" - "" - " " - " " - " " - " " - " " - ""; - size_t content_lenth = sizeof(info_body) - 1; - belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; /*no dialog = dialog in NULL state*/ - if (dialog_state == BELLE_SIP_DIALOG_CONFIRMED) { - belle_sip_request_t* info = belle_sip_dialog_create_queued_request(op->dialog,"INFO"); - int error=TRUE; - if (info) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","media_control+xml"))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_lenth))); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(info),info_body,content_lenth); - error=sal_op_send_request(op,info); - } - if (error) - ms_warning("Cannot send vfu request to [%s] ", sal_op_get_to(op)); - - } else { - ms_warning("Cannot send vfu request to [%s] because dialog [%p] in wrong state [%s]",sal_op_get_to(op) - ,op->dialog - ,belle_sip_dialog_state_to_string(dialog_state)); - } - - return ; -} - -int sal_call_is_offerer(const SalOp *h){ - return h->sdp_offering; -} - -bool_t sal_call_compare_op(const SalOp *op1, const SalOp *op2) { - if (strcmp(op1->base.call_id, op2->base.call_id) == 0) return TRUE; - return FALSE; -} - -bool_t sal_call_dialog_request_pending(const SalOp *op) { - return belle_sip_dialog_request_pending(op->dialog) ? TRUE : FALSE; -} - -const char * sal_call_get_local_tag(SalOp *op) { - return belle_sip_dialog_get_local_tag(op->dialog); -} - -const char * sal_call_get_remote_tag(SalOp *op) { - return belle_sip_dialog_get_remote_tag(op->dialog); -} - -void sal_call_set_replaces(SalOp *op, const char *call_id, const char *from_tag, const char *to_tag) { - belle_sip_header_replaces_t *replaces = belle_sip_header_replaces_create(call_id, from_tag, to_tag); - sal_op_set_replaces(op, replaces); -} diff --git a/coreapi/bellesip_sal/sal_op_call_transfer.c b/coreapi/bellesip_sal/sal_op_call_transfer.c deleted file mode 100644 index 40ff71daf..000000000 --- a/coreapi/bellesip_sal/sal_op_call_transfer.c +++ /dev/null @@ -1,273 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" -#include "offeranswer.h" - - - -/*call transfer*/ -static void sal_op_set_referred_by(SalOp* op,belle_sip_header_referred_by_t* referred_by) { - if (op->referred_by){ - belle_sip_object_unref(op->referred_by); - } - op->referred_by=referred_by; - belle_sip_object_ref(op->referred_by); -} - - -int sal_call_refer_to(SalOp *op, belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by){ - char* tmp; - belle_sip_request_t* req=op->dialog?belle_sip_dialog_create_request(op->dialog,"REFER"):sal_op_build_request(op, "REFER"); - if (!req) { - tmp=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to))); - ms_error("Cannot refer to [%s] for op [%p]",tmp,op); - belle_sip_free(tmp); - return -1; - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to)); - if (referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(referred_by)); - return sal_op_send_request(op,req); -} - -int sal_call_refer(SalOp *op, const char *refer_to){ - belle_sip_header_address_t *referred_by; - belle_sip_header_refer_to_t* refer_to_header; - if (op->dialog) { - referred_by=(belle_sip_header_address_t*)belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_dialog_get_local_party(op->dialog))); - }else{ - referred_by=BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)); - } - refer_to_header=belle_sip_header_refer_to_create(belle_sip_header_address_parse(refer_to)); - - return sal_call_refer_to(op,refer_to_header,belle_sip_header_referred_by_create(referred_by)); -} - -int sal_call_refer_with_replaces(SalOp *op, SalOp *other_call_op){ - belle_sip_dialog_state_t other_call_dialog_state=other_call_op->dialog?belle_sip_dialog_get_state(other_call_op->dialog):BELLE_SIP_DIALOG_NULL; - belle_sip_dialog_state_t op_dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; - belle_sip_header_replaces_t* replaces; - belle_sip_header_refer_to_t* refer_to; - belle_sip_header_referred_by_t* referred_by; - const char* from_tag; - const char* to_tag; - char* escaped_replaces; - /*first, build refer to*/ - if ((other_call_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) && (other_call_dialog_state!=BELLE_SIP_DIALOG_EARLY)) { - ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED or BELE_SIP_DIALOG_EARLY", - belle_sip_dialog_state_to_string(other_call_dialog_state), - other_call_op); - return -1; - } - if (op_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) { - ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED", - belle_sip_dialog_state_to_string(op_dialog_state), - op); - return -1; - } - - refer_to=belle_sip_header_refer_to_create(belle_sip_dialog_get_remote_party(other_call_op->dialog)); - belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(refer_to)); - /*rfc3891 - ... - 4. User Agent Client Behavior: Sending a Replaces Header - - A User Agent that wishes to replace a single existing early or - confirmed dialog with a new dialog of its own, MAY send the target - User Agent an INVITE request containing a Replaces header field. The - User Agent Client (UAC) places the Call-ID, to-tag, and from-tag - information for the target dialog in a single Replaces header field - and sends the new INVITE to the target.*/ - from_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog); - to_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog); - - replaces=belle_sip_header_replaces_create(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(other_call_op->dialog)) - ,from_tag,to_tag); - escaped_replaces=belle_sip_header_replaces_value_to_escaped_string(replaces); - belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)),"Replaces",escaped_replaces); - belle_sip_free(escaped_replaces); - referred_by=belle_sip_header_referred_by_create(belle_sip_dialog_get_local_party(op->dialog)); - belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(referred_by)); - return sal_call_refer_to(op,refer_to,referred_by); -} -/* -int sal_call_accept_refer(SalOp *h){ - ms_fatal("sal_call_accept_refer not implemented yet"); - return -1; -}*/ -/*informs this call is consecutive to an incoming refer */ -int sal_call_set_referer(SalOp *h, SalOp *refered_call){ - if (refered_call->replaces) - sal_op_set_replaces(h,refered_call->replaces); - if (refered_call->referred_by) - sal_op_set_referred_by(h,refered_call->referred_by); - return 0; -} -/* returns the SalOp of a call that should be replaced by h, if any */ -SalOp *sal_call_get_replaces(SalOp *op){ - if (op && op->replaces){ - /*rfc3891 - 3. User Agent Server Behavior: Receiving a Replaces Header - - The Replaces header contains information used to match an existing - SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE - with a Replaces header, the User Agent (UA) attempts to match this - information with a confirmed or early dialog. The User Agent Server - (UAS) matches the to-tag and from-tag parameters as if they were tags - present in an incoming request. In other words, the to-tag parameter - is compared to the local tag, and the from-tag parameter is compared - to the remote tag. - */ - belle_sip_dialog_t* dialog=belle_sip_provider_find_dialog(op->base.root->prov - ,belle_sip_header_replaces_get_call_id(op->replaces) - ,belle_sip_header_replaces_get_to_tag(op->replaces) - ,belle_sip_header_replaces_get_from_tag(op->replaces)); - - if (!dialog) { - /*for backward compatibility with liblinphone <= 3.10.2-243 */ - dialog=belle_sip_provider_find_dialog(op->base.root->prov - ,belle_sip_header_replaces_get_call_id(op->replaces) - ,belle_sip_header_replaces_get_from_tag(op->replaces) - ,belle_sip_header_replaces_get_to_tag(op->replaces)); - } - if (dialog) { - return (SalOp*)belle_sip_dialog_get_application_data(dialog); - } - } - return NULL; -} - -static int send_notify_for_refer(SalOp* op, int code, const char *reason){ - belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"); - char *sipfrag=belle_sip_strdup_printf("SIP/2.0 %i %s\r\n",code,reason); - size_t content_length=strlen(sipfrag); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,-1))); - - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),belle_sip_header_create("Event","refer")); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_type_create("message","sipfrag"))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); - belle_sip_message_assign_body(BELLE_SIP_MESSAGE(notify),sipfrag,content_length); - return sal_op_send_request(op,notify); -} - -static void notify_last_response(SalOp *op, SalOp *newcall){ - belle_sip_client_transaction_t *tr=newcall->pending_client_trans; - belle_sip_response_t *resp=NULL; - if (tr){ - resp=belle_sip_transaction_get_response((belle_sip_transaction_t*)tr); - } - if (resp==NULL){ - send_notify_for_refer(op, 100, "Trying"); - }else{ - send_notify_for_refer(op, belle_sip_response_get_status_code(resp), belle_sip_response_get_reason_phrase(resp)); - } -} - -int sal_call_notify_refer_state(SalOp *op, SalOp *newcall){ - belle_sip_dialog_state_t state; - if(belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_TERMINATED){ - return 0; - } - state = newcall->dialog?belle_sip_dialog_get_state(newcall->dialog):BELLE_SIP_DIALOG_NULL; - switch(state) { - case BELLE_SIP_DIALOG_EARLY: - send_notify_for_refer(op, 100, "Trying"); - break; - case BELLE_SIP_DIALOG_CONFIRMED: - send_notify_for_refer(op, 200, "Ok"); - break; - case BELLE_SIP_DIALOG_TERMINATED: - case BELLE_SIP_DIALOG_NULL: - notify_last_response(op,newcall); - break; - } - return 0; -} - - -void sal_op_process_refer(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t *server_transaction){ - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t); - belle_sip_header_referred_by_t *referred_by= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_referred_by_t); - belle_sip_response_t* resp; - belle_sip_uri_t* refer_to_uri; - char* refer_to_uri_str; - - ms_message("Receiving REFER request on op [%p]",op); - if (refer_to) { - refer_to_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)); - - if (refer_to_uri && belle_sip_uri_get_header(refer_to_uri,"Replaces")) { - sal_op_set_replaces(op,belle_sip_header_replaces_create2(belle_sip_uri_get_header(refer_to_uri,"Replaces"))); - belle_sip_uri_remove_header(refer_to_uri,"Replaces"); - } - if (referred_by){ - sal_op_set_referred_by(op,referred_by); - } - refer_to_uri_str=belle_sip_uri_to_string(refer_to_uri); - resp = sal_op_create_response_from_request(op,req,202); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.refer_received(op->base.root,op,refer_to_uri_str); - belle_sip_free(refer_to_uri_str); - } else { - ms_warning("cannot do anything with the refer without destination\n"); - resp = sal_op_create_response_from_request(op,req,400); - belle_sip_server_transaction_send_response(server_transaction,resp); - } - -} - -void sal_op_call_process_notify(SalOp *op, const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction){ - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); - belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"); - belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t); - belle_sip_response_t* resp; - - ms_message("Receiving NOTIFY request on op [%p]",op); - if (header_event - && strncasecmp(belle_sip_header_get_unparsed_value(header_event),"refer",strlen("refer"))==0 - && content_type - && strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0 - && strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0 - && body){ - belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body)); - - if (sipfrag){ - int code=belle_sip_response_get_status_code(sipfrag); - SalReferStatus status=SalReferFailed; - if (code<200){ - status=SalReferTrying; - }else if (code<300){ - status=SalReferSuccess; - }else if (code>=400){ - status=SalReferFailed; - } - belle_sip_object_unref(sipfrag); - resp = sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.notify_refer(op,status); - } - }else{ - ms_error("Notify without sipfrag or not for 'refer' event package, rejecting"); - resp = sal_op_create_response_from_request(op,req,489); - belle_sip_server_transaction_send_response(server_transaction,resp); - } -} - diff --git a/coreapi/bellesip_sal/sal_op_events.c b/coreapi/bellesip_sal/sal_op_events.c deleted file mode 100644 index d3198fde9..000000000 --- a/coreapi/bellesip_sal/sal_op_events.c +++ /dev/null @@ -1,385 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" - -SalSubscribeStatus belle_sip_message_get_subscription_state(const belle_sip_message_t *msg){ - belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t); - SalSubscribeStatus sss=SalSubscribeNone; - if (subscription_state_header){ - if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED)==0) - sss=SalSubscribeTerminated; - else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_PENDING)==0) - sss=SalSubscribePending; - else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE)==0) - sss=SalSubscribeActive; - } - return sss; -} - -static void subscribe_refresher_listener (belle_sip_refresher_t* refresher - ,void* user_pointer - ,unsigned int status_code - ,const char* reason_phrase, int will_retry) { - SalOp* op = (SalOp*)user_pointer; - belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)); - /*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/ - SalSubscribeStatus sss=SalSubscribeTerminated; - - ms_message("Subscribe refresher [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none"); - if (status_code>=200 && status_code<300){ - if (status_code==200) sss=SalSubscribeActive; - else if (status_code==202) sss=SalSubscribePending; - set_or_update_dialog(op,belle_sip_transaction_get_dialog(tr)); - op->base.root->callbacks.subscribe_response(op,sss, will_retry); - } else if (status_code >= 300) { - SalReason reason = SalReasonUnknown; - if (status_code == 503) { /*refresher returns 503 for IO error*/ - reason = SalReasonIOError; - } - sal_error_info_set(&op->error_info, reason, "SIP", status_code,reason_phrase,NULL); - op->base.root->callbacks.subscribe_response(op,sss, will_retry); - }else if (status_code==0){ - op->base.root->callbacks.on_expire(op); - } - -} - -static void subscribe_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - SalOp *op = (SalOp*)user_ctx; - belle_sip_object_t *src = belle_sip_io_error_event_get_source(event); - if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(src, belle_sip_client_transaction_t)){ - belle_sip_client_transaction_t *tr = BELLE_SIP_CLIENT_TRANSACTION(src); - belle_sip_request_t* req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); - const char *method=belle_sip_request_get_method(req); - - if (!op->dialog) { - /*this is handling outgoing out-of-dialog notifies*/ - if (strcmp(method,"NOTIFY")==0){ - SalErrorInfo *ei=&op->error_info; - sal_error_info_set(ei,SalReasonIOError, "SIP", 0,NULL,NULL); - op->base.root->callbacks.on_notify_response(op); - } - } - } -} - -static void subscribe_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) { - belle_sip_dialog_t *dialog = belle_sip_dialog_terminated_event_get_dialog(event); - SalOp* op= (SalOp*)ctx; - if (op->dialog) { - if (belle_sip_dialog_terminated_event_is_expired(event)){ - if (!belle_sip_dialog_is_server(dialog)){ - /*notify the app that our subscription is dead*/ - const char *eventname = NULL; - if (op->event){ - eventname = belle_sip_header_event_get_package_name(op->event); - } - op->base.root->callbacks.notify(op, SalSubscribeTerminated, eventname, NULL); - }else{ - op->base.root->callbacks.incoming_subscribe_closed(op); - } - } - set_or_update_dialog(op, NULL); - } -} - -static void subscribe_response_event(void *op_base, const belle_sip_response_event_t *event){ - SalOp *op = (SalOp*)op_base; - belle_sip_request_t * req; - const char *method; - belle_sip_client_transaction_t *tr = belle_sip_response_event_get_client_transaction(event); - - if (!tr) return; - req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); - method = belle_sip_request_get_method(req); - - if (!op->dialog) { - if (strcmp(method,"NOTIFY")==0){ - sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); - op->base.root->callbacks.on_notify_response(op); - } - } -} - -static void subscribe_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp *op = (SalOp*)user_ctx; - belle_sip_request_t * req; - const char *method; - belle_sip_client_transaction_t *tr = belle_sip_timeout_event_get_client_transaction(event); - - if (!tr) return; - req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); - method = belle_sip_request_get_method(req); - - if (!op->dialog) { - /*this is handling outgoing out-of-dialog notifies*/ - if (strcmp(method,"NOTIFY")==0){ - SalErrorInfo *ei=&op->error_info; - sal_error_info_set(ei,SalReasonRequestTimeout, "SIP", 0,NULL,NULL); - op->base.root->callbacks.on_notify_response(op); - } - } -} - -static void subscribe_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { -} - -static void handle_notify(SalOp *op, belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){ - SalSubscribeStatus sub_state; - belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); - belle_sip_response_t* resp; - belle_sip_server_transaction_t* server_transaction = op->pending_server_trans; - - if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { - sub_state=SalSubscribeTerminated; - ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); - } else - sub_state=SalSubscribeActive; - sal_op_ref(op); - op->base.root->callbacks.notify(op,sub_state,eventname,body_handler); - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_unref(op); -} - -static void subscribe_process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_dialog_state_t dialog_state; - belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); - belle_sip_header_event_t *event_header; - belle_sip_body_handler_t *body_handler; - belle_sip_response_t* resp; - const char *eventname=NULL; - const char *method=belle_sip_request_get_method(req); - belle_sip_dialog_t *dialog = NULL; - - 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; - - event_header=belle_sip_message_get_header_by_type(req,belle_sip_header_event_t); - body_handler = BELLE_SIP_BODY_HANDLER(sal_op_get_body_handler(op, BELLE_SIP_MESSAGE(req))); - - if (event_header==NULL){ - ms_warning("No event header in incoming SUBSCRIBE."); - resp=sal_op_create_response_from_request(op,req,400); - belle_sip_server_transaction_send_response(server_transaction,resp); - if (!op->dialog) sal_op_release(op); - return; - } - if (op->event==NULL) { - op->event=event_header; - belle_sip_object_ref(op->event); - } - eventname=belle_sip_header_event_get_package_name(event_header); - - if (!op->dialog) { - if (strcmp(method,"SUBSCRIBE")==0){ - dialog = belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction)); - if (!dialog){ - resp=sal_op_create_response_from_request(op,req,481); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_release(op); - return; - } - set_or_update_dialog(op, dialog); - ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); - }else{ /*this is a NOTIFY*/ - handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); - return; - } - } - dialog_state=belle_sip_dialog_get_state(op->dialog); - switch(dialog_state) { - - case BELLE_SIP_DIALOG_NULL: { - const char *type = NULL; - belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); - if (content_type) type = belle_sip_header_content_type_get_type(content_type); - op->base.root->callbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL); - break; - } - case BELLE_SIP_DIALOG_EARLY: - ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->dialog); - break; - - case BELLE_SIP_DIALOG_CONFIRMED: - if (strcmp("NOTIFY",method)==0) { - handle_notify(op, req, eventname, (SalBodyHandler *)body_handler); - } else if (strcmp("SUBSCRIBE",method)==0) { - /*either a refresh of an unsubscribe*/ - if (expires && belle_sip_header_expires_get_expires(expires)>0) { - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - } else if(expires) { - ms_message("Unsubscribe received from [%s]",sal_op_get_from(op)); - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - op->base.root->callbacks.incoming_subscribe_closed(op); - } - } - break; - default: { - ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - } - } -} - -static belle_sip_listener_callbacks_t op_subscribe_callbacks={ 0 }; - -/*Invoke when sal_op_release is called by upper layer*/ -static void sal_op_release_cb(struct SalOpBase* op_base) { - SalOp *op =(SalOp*)op_base; - if(op->refresher) { - belle_sip_refresher_stop(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - set_or_update_dialog(op,NULL); /*only if we have refresher. else dialog terminated event will remove association*/ - } - -} - -void sal_op_subscribe_fill_cbs(SalOp*op) { - if (op_subscribe_callbacks.process_io_error==NULL){ - op_subscribe_callbacks.process_io_error=subscribe_process_io_error; - op_subscribe_callbacks.process_response_event=subscribe_response_event; - op_subscribe_callbacks.process_timeout=subscribe_process_timeout; - op_subscribe_callbacks.process_transaction_terminated=subscribe_process_transaction_terminated; - op_subscribe_callbacks.process_request_event=subscribe_process_request_event; - op_subscribe_callbacks.process_dialog_terminated=subscribe_process_dialog_terminated; - } - op->callbacks=&op_subscribe_callbacks; - op->type=SalOpSubscribe; - op->base.release_cb=sal_op_release_cb; -} - - -int sal_subscribe(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ - belle_sip_request_t *req=NULL; - - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - - if (!op->dialog){ - sal_op_subscribe_fill_cbs(op); - req=sal_op_build_request(op,"SUBSCRIBE"); - if( req == NULL ) { - return -1; - } - sal_op_set_event(op, eventname); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(op->event)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); - return sal_op_send_and_create_refresher(op,req,expires,subscribe_refresher_listener); - }else if (op->refresher){ - const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - /* modify last request to update body*/ - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler)); - return belle_sip_refresher_refresh(op->refresher,expires); - } - ms_warning("sal_subscribe(): no dialog and no refresher ?"); - return -1; -} - -int sal_unsubscribe(SalOp *op){ - if (op->refresher){ - const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); - belle_sip_refresher_refresh(op->refresher,0); - return 0; - } - return -1; -} - -int sal_subscribe_accept(SalOp *op){ - belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)); - belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); - belle_sip_response_t* resp = sal_op_create_response_from_request(op,req,200); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires)); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; -} - -int sal_notify_pending_state(SalOp *op){ - - if (op->dialog != NULL && op->pending_server_trans) { - belle_sip_request_t* notify; - belle_sip_header_subscription_state_t* sub_state; - ms_message("Sending NOTIFY with subscription state pending for op [%p]",op); - if (!(notify=belle_sip_dialog_create_request(op->dialog,"NOTIFY"))) { - ms_error("Cannot create NOTIFY on op [%p]",op); - return -1; - } - if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event)); - sub_state=belle_sip_header_subscription_state_new(); - belle_sip_header_subscription_state_set_state(sub_state,BELLE_SIP_SUBSCRIPTION_STATE_PENDING); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify), BELLE_SIP_HEADER(sub_state)); - return sal_op_send_request(op,notify); - } else { - ms_warning("NOTIFY with subscription state pending for op [%p] not implemented in this case (either dialog pending trans does not exist",op); - } - - return 0; -} - - -int sal_subscribe_decline(SalOp *op, SalReason reason){ - belle_sip_response_t* resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)), - sal_reason_to_sip_code(reason)); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; -} - -int sal_notify(SalOp *op, const SalBodyHandler *body_handler){ - belle_sip_request_t* notify; - - if (op->dialog){ - if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1; - }else{ - sal_op_subscribe_fill_cbs(op); - notify = sal_op_build_request(op, "NOTIFY"); - } - - if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event)); - - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,op->dialog ? - BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)) : - BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,0)) - ); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler)); - return sal_op_send_request(op,notify); -} - -int sal_notify_close(SalOp *op){ - belle_sip_request_t* notify; - if (!op->dialog) return -1; - if (!(notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"))) return -1; - if (op->event) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(op->event)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); - return sal_op_send_request(op,notify); -} - diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 3f4f2e079..41190959f 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -17,488 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "sal_impl.h" - -/*create an operation */ -SalOp * sal_op_new(Sal *sal){ - SalOp *op=ms_new0(SalOp,1); - __sal_op_init(op,sal); - op->type=SalOpUnknown; - op->privacy=SalPrivacyNone; - op->manual_refresher=FALSE;/*tells that requests with expiry (SUBSCRIBE, PUBLISH) will be automatically refreshed*/ - op->sdp_handling=sal->default_sdp_handling; - sal_op_ref(op); - return op; -} - -void sal_op_kill_dialog(SalOp *op) { - ms_warning("op [%p]: force kill of dialog [%p]", op, op->dialog); - belle_sip_dialog_delete(op->dialog); -} - -void sal_op_release(SalOp *op){ - /*if in terminating state, keep this state because it means we are waiting for a response to be able to terminate the operation.*/ - if (op->state!=SalOpStateTerminating) - op->state=SalOpStateTerminated; - sal_op_set_user_pointer(op,NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/ - if (op->base.release_cb) - op->base.release_cb(&op->base); - if (op->refresher) { - belle_sip_refresher_stop(op->refresher); - } - op->op_released = TRUE; - sal_op_unref(op); -} - -void sal_op_release_impl(SalOp *op){ - ms_message("Destroying op [%p] of type [%s]",op,sal_op_type_to_string(op->type)); - if (op->pending_auth_transaction) belle_sip_object_unref(op->pending_auth_transaction); - sal_remove_pending_auth(op->base.root,op); - if (op->auth_info) { - sal_auth_info_delete(op->auth_info); - } - if (op->sdp_answer) belle_sip_object_unref(op->sdp_answer); - if (op->refresher) { - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - } - if (op->result) - sal_media_description_unref(op->result); - if(op->replaces) belle_sip_object_unref(op->replaces); - if(op->referred_by) belle_sip_object_unref(op->referred_by); - - if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans); - if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); - if (op->pending_update_server_trans) belle_sip_object_unref(op->pending_update_server_trans); - if (op->event) belle_sip_object_unref(op->event); - sal_error_info_reset(&op->error_info); - __sal_op_free(op); - return ; -} - -void sal_op_authenticate(SalOp *op, const SalAuthInfo *info){ - if (op->type == SalOpRegister) { - /*Registration authenticate is just about registering again*/ - sal_register_refresh(op,-1); - }else { - /*for sure auth info will be accessible from the provider*/ - sal_process_authentication(op); - } - return ; -} - -void sal_op_cancel_authentication(SalOp *h){ - ms_fatal("sal_op_cancel_authentication not implemented yet"); - return ; -} - -SalAuthInfo * sal_op_get_auth_requested(SalOp *op){ - return op->auth_info; -} - -belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){ - belle_sip_header_contact_t* contact_header; - belle_sip_uri_t* contact_uri; - - if (sal_op_get_contact_address(op)) { - contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_contact_address(op))); - } else { - contact_header= belle_sip_header_contact_new(); - } - - if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) { - /*no uri, just creating a new one*/ - contact_uri=belle_sip_uri_new(); - belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri); - } - - belle_sip_uri_set_user_password(contact_uri,NULL); - belle_sip_uri_set_secure(contact_uri,sal_op_is_secure(op)); - if (op->privacy!=SalPrivacyNone){ - belle_sip_uri_set_user(contact_uri,NULL); - } - - /*don't touch contact in case of gruu*/ - if (!belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header))),"gr")) { - belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts); - if (op->base.root->uuid){ - if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){ - char *instance_id=belle_sip_strdup_printf("\"\"",op->base.root->uuid); - belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id); - belle_sip_free(instance_id); - } - } - } - return contact_header; -} - - - -static void add_initial_route_set(belle_sip_request_t *request, const MSList *list){ - const MSList *elem; - for (elem=list;elem!=NULL;elem=elem->next){ - SalAddress *addr=(SalAddress*)elem->data; - belle_sip_header_route_t *route; - belle_sip_uri_t *uri; - /*Optimization: if the initial route set only contains one URI which is the same as the request URI, ommit it*/ - if (elem==list && list->next==NULL){ - belle_sip_uri_t *requri=belle_sip_request_get_uri(request); - /*skip the first route it is the same as the request uri*/ - if (strcmp(sal_address_get_domain(addr),belle_sip_uri_get_host(requri))==0 ){ - ms_message("Skipping top route of initial route-set because same as request-uri."); - 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); - belle_sip_message_add_header((belle_sip_message_t*)request,(belle_sip_header_t*)route); - } -} - -belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { - belle_sip_header_from_t* from_header; - belle_sip_header_to_t* to_header; - belle_sip_provider_t* prov=op->base.root->prov; - belle_sip_request_t *req; - belle_sip_uri_t* req_uri; - belle_sip_uri_t* to_uri; - belle_sip_header_call_id_t *call_id_header; - - const SalAddress* to_address; - const MSList *elem=sal_op_get_route_addresses(op); - char token[10]; - - /* check that the op has a correct to address */ - to_address = sal_op_get_to_address(op); - if( to_address == NULL ){ - ms_error("No To: address, cannot build request"); - return NULL; - } - - to_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to_address)); - if( to_uri == NULL ){ - ms_error("To: address is invalid, cannot build request"); - return NULL; - } - - if (strcmp("REGISTER",method)==0 || op->privacy==SalPrivacyNone) { - from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(sal_op_get_from_address(op)) - ,belle_sip_random_token(token,sizeof(token))); - } else { - from_header=belle_sip_header_from_create2("Anonymous ",belle_sip_random_token(token,sizeof(token))); - } - /*make sure to preserve components like headers or port*/ - - req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)to_uri); - belle_sip_uri_set_secure(req_uri,sal_op_is_secure(op)); - - to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(to_address),NULL); - belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to_header))), "gr"); /*remove gruu in any case*/ - call_id_header = belle_sip_provider_create_call_id(prov); - if (sal_op_get_call_id(op)) { - belle_sip_header_call_id_set_call_id(call_id_header, sal_op_get_call_id(op)); - } - - req=belle_sip_request_create( - req_uri, - method, - call_id_header, - belle_sip_header_cseq_create(20,method), - from_header, - to_header, - belle_sip_header_via_new(), - 70); - - if (op->privacy & SalPrivacyId) { - 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) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyCritical)); - if (op->privacy&SalPrivacyHeader) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyHeader)); - if (op->privacy&SalPrivacyId) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyId)); - if (op->privacy&SalPrivacyNone) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyNone)); - if (op->privacy&SalPrivacySession) - belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacySession)); - if (op->privacy&SalPrivacyUser) - 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),op->base.root->supported); - return req; -} - -belle_sip_response_t *sal_op_create_response_from_request(SalOp *op, belle_sip_request_t *req, int code){ - return sal_create_response_from_request(op->base.root,req,code); -} - -/*ping: main purpose is to obtain its own contact address behind firewalls*/ -int sal_ping(SalOp *op, const char *from, const char *to){ - sal_op_set_from(op,from); - sal_op_set_to(op,to); - return sal_op_send_request(op,sal_op_build_request(op,"OPTIONS")); -} - -void sal_op_set_replaces(SalOp* op,belle_sip_header_replaces_t* replaces) { - if (op->replaces){ - belle_sip_object_unref(op->replaces); - } - op->replaces=replaces; - belle_sip_object_ref(op->replaces); -} - -void sal_op_set_remote_ua(SalOp*op,belle_sip_message_t* message) { - belle_sip_header_user_agent_t* user_agent=belle_sip_message_get_header_by_type(message,belle_sip_header_user_agent_t); - char user_agent_string[256]; - if (user_agent && belle_sip_header_user_agent_get_products_as_string(user_agent,user_agent_string,sizeof(user_agent_string))>0) { - if (op->base.remote_ua!=NULL){ - ms_free(op->base.remote_ua); - } - op->base.remote_ua=ms_strdup(user_agent_string); - } -} - -int sal_op_send_request_with_expires(SalOp* op, belle_sip_request_t* request,int expires) { - belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES); - - if (!expires_header && expires>=0) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new())); - } - if (expires_header) belle_sip_header_expires_set_expires(expires_header,expires); - return sal_op_send_request(op,request); -} - -void sal_op_resend_request(SalOp* op, belle_sip_request_t* request) { - belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ); - belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1); - sal_op_send_request(op,request); -} - -static void add_headers(SalOp *op, belle_sip_header_t *h, belle_sip_message_t *msg){ - - if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){ - belle_sip_header_contact_t* newct; - /*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/ - sal_op_set_contact_address(op,(SalAddress*)BELLE_SIP_HEADER_ADDRESS(h)); - newct = sal_op_create_contact(op); - belle_sip_message_set_header(BELLE_SIP_MESSAGE(msg),BELLE_SIP_HEADER(newct)); - return; - } - /*if a header already exists in the message, replace it*/ - belle_sip_message_set_header(msg,h); - -} - -void _sal_op_add_custom_headers(SalOp *op, belle_sip_message_t *msg){ - if (op->base.sent_custom_headers){ - belle_sip_message_t *ch=(belle_sip_message_t*)op->base.sent_custom_headers; - belle_sip_list_t *l=belle_sip_message_get_all_headers(ch); - belle_sip_list_t *elem; - for(elem=l;elem!=NULL;elem=elem->next){ - add_headers(op,(belle_sip_header_t*)elem->data,msg); - } - belle_sip_list_free(l); - } -} - -static int _sal_op_send_request_with_contact(SalOp* op, belle_sip_request_t* request, bool_t add_contact) { - belle_sip_client_transaction_t* client_transaction; - belle_sip_provider_t* prov=op->base.root->prov; - belle_sip_uri_t* outbound_proxy=NULL; - belle_sip_header_contact_t* contact; - int result =-1; - belle_sip_uri_t *next_hop_uri=NULL; - - if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) { - contact = sal_op_create_contact(op); - belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact)); - } /*keep existing*/ - - _sal_op_add_custom_headers(op, (belle_sip_message_t*)request); - - if (!op->dialog || belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_NULL) { - /*don't put route header if dialog is in confirmed state*/ - const MSList *elem=sal_op_get_route_addresses(op); - const char *transport; - const char *method=belle_sip_request_get_method(request); - belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP"); - - if (elem) { - outbound_proxy=belle_sip_header_address_get_uri((belle_sip_header_address_t*)elem->data); - next_hop_uri=outbound_proxy; - }else{ - next_hop_uri=(belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request)); - } - transport=belle_sip_uri_get_transport_param(next_hop_uri); - if (transport==NULL){ - /*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use - * the first available transport*/ - if (!belle_sip_uri_is_secure(next_hop_uri)){ - if (udplp==NULL){ - if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){ - transport="tcp"; - }else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){ - transport="tls"; - } - } - if (transport){ - belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport); - belle_sip_uri_set_transport_param(next_hop_uri,transport); - } - } - }else{ -#ifdef TUNNEL_ENABLED - if (udplp && BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){ - /* our tunnel mode only supports UDP. Force transport to be set to UDP */ - belle_sip_uri_set_transport_param(next_hop_uri,"udp"); - } -#endif - } - /*because in case of tunnel, transport can be changed*/ - transport=belle_sip_uri_get_transport_param(next_hop_uri); - - if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport && - (strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){ - /*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/ - belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t); - belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL); - } - } - - client_transaction = belle_sip_provider_create_client_transaction(prov,request); - belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),sal_op_ref(op)); - if (op->pending_client_trans) belle_sip_object_unref(op->pending_client_trans); - op->pending_client_trans=client_transaction; /*update pending inv for being able to cancel*/ - belle_sip_object_ref(op->pending_client_trans); - - if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL) - belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(op->base.root->user_agent)); - - 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,op->base.realm); - } - result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); - - /*update call id if not set yet for this OP*/ - if (result == 0 && !op->base.call_id) { - op->base.call_id=ms_strdup(belle_sip_header_call_id_get_call_id(BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t)))); - } - - return result; - -} - -int sal_op_send_request(SalOp* op, belle_sip_request_t* request) { - bool_t need_contact=FALSE; - if (request==NULL) { - return -1; /*sanity check*/ - } - /* - Header field where proxy ACK BYE CAN INV OPT REG - ___________________________________________________________ - Contact R o - - m o o - */ - if (strcmp(belle_sip_request_get_method(request),"INVITE")==0 - ||strcmp(belle_sip_request_get_method(request),"REGISTER")==0 - ||strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0 - ||strcmp(belle_sip_request_get_method(request),"OPTIONS")==0 - ||strcmp(belle_sip_request_get_method(request),"REFER")==0) /* Despite contact seems not mandatory, call flow example show a Contact in REFER requests*/ - need_contact=TRUE; - - return _sal_op_send_request_with_contact(op, request,need_contact); -} - -int sal_reason_to_sip_code(SalReason r){ - int ret=500; - switch(r){ - case SalReasonNone: - ret=200; - break; - case SalReasonIOError: - ret=503; - break; - case SalReasonUnknown: - ret=400; - break; - case SalReasonBusy: - ret=486; - break; - case SalReasonDeclined: - ret=603; - break; - case SalReasonDoNotDisturb: - ret=600; - break; - case SalReasonForbidden: - ret=403; - break; - case SalReasonUnsupportedContent: - ret=415; - break; - case SalReasonNotFound: - ret=404; - break; - case SalReasonRedirect: - ret=302; - break; - case SalReasonTemporarilyUnavailable: - ret=480; - break; - case SalReasonServiceUnavailable: - ret=503; - break; - case SalReasonRequestPending: - ret=491; - break; - case SalReasonUnauthorized: - ret=401; - break; - case SalReasonNotAcceptable: - ret=488; /*or maybe 606 Not Acceptable ?*/ - break; - case SalReasonNoMatch: - ret=481; - break; - case SalReasonRequestTimeout: - ret=408; - break; - case SalReasonMovedPermanently: - ret=301; - break; - case SalReasonGone: - ret=410; - break; - case SalReasonAddressIncomplete: - ret=484; - break; - case SalReasonNotImplemented: - ret=501; - break; - case SalReasonServerTimeout: - ret=504; - break; - case SalReasonBadGateway: - ret=502; - break; - case SalReasonInternalError: - ret=500; - break; - } - return ret; -} +#include "sal/sal.h" SalReason _sal_reason_from_sip_code(int code) { if (code>=100 && code<300) return SalReasonNone; @@ -561,13 +80,12 @@ SalReason _sal_reason_from_sip_code(int code) { } const SalErrorInfo *sal_error_info_none(void){ - static SalErrorInfo none={ + static const SalErrorInfo none = { SalReasonNone, (char *)"Ok", 200, NULL, - NULL, - + NULL }; return &none; } @@ -601,7 +119,7 @@ void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol else{ ei->reason=reason; if (code == 0) { - code = sal_reason_to_sip_code(reason); + code = LinphonePrivate::to_sip_code(reason); } } ei->protocol_code=code; @@ -614,290 +132,3 @@ void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol else ei->full_string=ms_strdup(ei->status_string); } } - -void sal_op_set_reason_error_info(SalOp *op, belle_sip_message_t *msg){ - belle_sip_header_reason_t* reason_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_reason_t); - if (reason_header){ - SalErrorInfo *ei=&op->reason_error_info; // ?// - const char *protocol = belle_sip_header_reason_get_protocol(reason_header); - int code = belle_sip_header_reason_get_cause(reason_header); - const char *text = belle_sip_header_reason_get_text(reason_header); - sal_error_info_set(ei, SalReasonUnknown, protocol, code, text, NULL); - } -} - -void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *response){ - int code = belle_sip_response_get_status_code(response); - const char *reason_phrase=belle_sip_response_get_reason_phrase(response); - belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning"); - SalErrorInfo *ei=&op->error_info; - const char *warnings; - - warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL; - sal_error_info_set(ei,SalReasonUnknown,"SIP", code,reason_phrase,warnings); - sal_op_set_reason_error_info(op, BELLE_SIP_MESSAGE(response)); -} - -const SalErrorInfo *sal_op_get_error_info(const SalOp *op){ - return &op->error_info; -} - -const SalErrorInfo * sal_op_get_reason_error_info(const SalOp *op){ - return &op->reason_error_info; -} - - - - -static void unlink_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){ - belle_sip_dialog_set_application_data(dialog,NULL); - sal_op_unref(op); - belle_sip_object_unref(dialog); -} - -static belle_sip_dialog_t *link_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){ - belle_sip_dialog_set_application_data(dialog,sal_op_ref(op)); - belle_sip_object_ref(dialog); - return dialog; -} - -void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) { - ms_message("op [%p] : set_or_update_dialog() current=[%p] new=[%p]",op,op->dialog,dialog); - sal_op_ref(op); - if (op->dialog!=dialog){ - if (op->dialog){ - /*FIXME: shouldn't we delete unconfirmed dialogs ?*/ - unlink_op_with_dialog(op,op->dialog); - op->dialog=NULL; - } - if (dialog) { - op->dialog=link_op_with_dialog(op,dialog); - belle_sip_dialog_enable_pending_trans_checking(dialog,op->base.root->pending_trans_checking); - } - } - sal_op_unref(op); -} -/*return reffed op*/ -SalOp* sal_op_ref(SalOp* op) { - op->ref++; - return op; -} -/*return null, destroy op if ref count =0*/ -void* sal_op_unref(SalOp* op) { - op->ref--; - if (op->ref==0) { - sal_op_release_impl(op); - }else if (op->ref<0){ - ms_fatal("SalOp [%p]: too many unrefs.",op); - } - return NULL; -} - -int sal_op_send_and_create_refresher(SalOp* op,belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener ) { - if (sal_op_send_request_with_expires(op,req,expires)==0) { - if (op->refresher) { - belle_sip_refresher_stop(op->refresher); - 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 - * 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(). - Something in the design is not very good here, it makes things complicated to the belle-sip user. - Possible ideas to improve things: refresher shall not use belle_sip_transaction_set_application_data() internally, refresher should let the first transaction - 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 { - return -1; - } - } - return -1; -} - -const char* sal_op_state_to_string(const SalOpState value) { - switch(value) { - case SalOpStateEarly: return"SalOpStateEarly"; - case SalOpStateActive: return "SalOpStateActive"; - case SalOpStateTerminating: return "SalOpStateTerminating"; - case SalOpStateTerminated: return "SalOpStateTerminated"; - default: - return "Unknown"; - } -} - -/* - * Warning: this function takes owneship of the custom headers - */ -void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch){ - SalOpBase *b=(SalOpBase *)op; - if (b->sent_custom_headers){ - sal_custom_header_free(b->sent_custom_headers); - b->sent_custom_headers=NULL; - } - if (ch) belle_sip_object_ref((belle_sip_message_t*)ch); - b->sent_custom_headers=ch; -} - -void sal_op_assign_recv_headers(SalOp *op, belle_sip_message_t *incoming){ - if (incoming) belle_sip_object_ref(incoming); - if (op->base.recv_custom_headers){ - belle_sip_object_unref(op->base.recv_custom_headers); - op->base.recv_custom_headers=NULL; - } - if (incoming){ - op->base.recv_custom_headers=(SalCustomHeader*)incoming; - } -} - -const char *sal_op_get_remote_contact(const SalOp *op){ - /* - * remote contact is filled in process_response - */ - return op->base.remote_contact; -} - -SalBodyHandler * sal_op_get_body_handler(SalOp *op, belle_sip_message_t *msg) { - belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg); - if (body_handler != NULL) { - belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); - belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t); - belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding"); - if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type)); - if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length)); - if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding); - } - return (SalBodyHandler *)body_handler; -} - -void sal_op_set_privacy(SalOp* op,SalPrivacyMask privacy) { - op->privacy=privacy; -} -SalPrivacyMask sal_op_get_privacy(const SalOp* op) { - return op->privacy; -} - -bool_t sal_op_is_secure(const SalOp* op) { - const SalAddress* from = sal_op_get_from_address(op); - const SalAddress* to = sal_op_get_to_address(op); - - return from && to && strcasecmp("sips",sal_address_get_scheme(from))==0 && strcasecmp("sips",sal_address_get_scheme(to))==0; -} - -void sal_op_set_manual_refresher_mode(SalOp *op, bool_t enabled){ - op->manual_refresher=enabled; -} - -int sal_op_get_address_family(SalOp *op){ - belle_sip_transaction_t *tr=NULL; - belle_sip_header_address_t *contact; - - if (op->refresher) - tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(op->refresher); - - if (tr==NULL) - tr=(belle_sip_transaction_t *)op->pending_client_trans; - if (tr==NULL) - tr=(belle_sip_transaction_t *)op->pending_server_trans; - - if (tr==NULL){ - bctbx_error("Unable to determine IP version from signaling operation."); - return AF_UNSPEC; - } - - if (op->refresher) { - belle_sip_message_t *msg = belle_sip_transaction_get_response(tr) ? (belle_sip_message_t*) belle_sip_transaction_get_response(tr) : (belle_sip_message_t*) belle_sip_transaction_get_request(tr); - belle_sip_header_via_t *via = msg ?belle_sip_message_get_header_by_type(msg,belle_sip_header_via_t):NULL; - if (!via) { - bctbx_error("Unable to determine IP version from signaling operation, no via header found."); - return AF_UNSPEC; - } - - const char *host = belle_sip_header_via_get_host(via); - if (!host) { - bctbx_error("Unable to get host. No network?"); - return AF_UNSPEC; - } - - return strchr(host, ':') ? AF_INET6 : AF_INET; - } - - belle_sip_request_t *req = belle_sip_transaction_get_request(tr); - contact = (belle_sip_header_address_t *)belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); - if (!contact) - bctbx_error("Unable to determine IP version from signaling operation, no contact header found."); - return sal_address_is_ipv6((SalAddress*)contact) ? AF_INET6 : AF_INET; -} - -bool_t sal_op_is_idle(SalOp *op){ - if (op->dialog){ - return !belle_sip_dialog_request_pending(op->dialog); - } - return TRUE; -} - -void sal_op_stop_refreshing(SalOp *op){ - if (op->refresher){ - belle_sip_refresher_stop(op->refresher); - } -} - -void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) { - if (handling != SalOpSDPNormal) ms_message("Enabling special SDP handling for SalOp[%p]!", h); - h->sdp_handling = handling; -} -void sal_op_cnx_ip_to_0000_if_sendonly_enable(SalOp *op,bool_t yesno) { - op->cnx_ip_to_0000_if_sendonly_enabled = yesno; -} - -bool_t sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp *op) { - return op->cnx_ip_to_0000_if_sendonly_enabled; -} - -bool_t sal_op_is_forked_of(const SalOp *op1, const SalOp *op2){ - return op1->base.call_id && op2->base.call_id && strcmp(op1->base.call_id, op2->base.call_id) == 0; -} -int sal_op_refresh(SalOp *op) { - if (op->refresher) { - belle_sip_refresher_refresh(op->refresher,belle_sip_refresher_get_expires(op->refresher)); - return 0; - } - ms_warning("sal_refresh on op [%p] of type [%s] no refresher",op,sal_op_type_to_string(op->type)); - return -1; -} - -void sal_op_set_event(SalOp *op, const char *eventname){ - belle_sip_header_event_t *header = NULL; - if (op->event) belle_sip_object_unref(op->event); - if (eventname){ - header = belle_sip_header_event_create(eventname); - belle_sip_object_ref(header); - } - op->event = header; -} - -const char* sal_op_get_public_address(SalOp *op, int *port) { - if (op && op->refresher) { - return belle_sip_refresher_get_public_address(op->refresher, port); - } - return NULL; -} - -const char* sal_op_get_local_address(SalOp *op, int *port) { - if (op && op->refresher) { - return belle_sip_refresher_get_local_address(op->refresher, port); - } - return NULL; -} - -char* sal_op_get_dialog_id(const SalOp *op) { - if (op->dialog != NULL) { - return ms_strdup_printf("%s;to-tag=%s;from-tag=%s", ((SalOpBase*)op)->call_id, - belle_sip_dialog_get_remote_tag(op->dialog), belle_sip_dialog_get_local_tag(op->dialog)); - } - return NULL; -} diff --git a/coreapi/bellesip_sal/sal_op_info.c b/coreapi/bellesip_sal/sal_op_info.c deleted file mode 100644 index 7ecf8e68b..000000000 --- a/coreapi/bellesip_sal/sal_op_info.c +++ /dev/null @@ -1,34 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" - - -int sal_send_info(SalOp *op, const char *from, const char *to, const SalBodyHandler *body_handler){ - if (op->dialog && belle_sip_dialog_get_state(op->dialog) == BELLE_SIP_DIALOG_CONFIRMED){ - belle_sip_request_t *req; - belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking); - req=belle_sip_dialog_create_queued_request(op->dialog,"INFO"); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); - return sal_op_send_request(op,req); - }else{ - ms_error("Cannot send INFO message on op [%p] because dialog is not in confirmed state yet.", op); - } - return -1; -} - diff --git a/coreapi/bellesip_sal/sal_op_message.c b/coreapi/bellesip_sal/sal_op_message.c deleted file mode 100644 index cfb73763a..000000000 --- a/coreapi/bellesip_sal/sal_op_message.c +++ /dev/null @@ -1,216 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" - -#include "linphone/core.h" -#include "private.h" -#include - -static void process_error( SalOp* op) { - if (op->dir == SalOpDirOutgoing) { - op->base.root->callbacks.message_delivery_update(op, SalMessageDeliveryFailed); - } else { - ms_warning("unexpected io error for incoming message on op [%p]",op); - } - op->state=SalOpStateTerminated; - -} - -static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - SalOp* op = (SalOp*)user_ctx; - sal_error_info_set(&op->error_info,SalReasonIOError, "SIP", 503,"IO Error",NULL); - process_error(op); -} -static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp* op=(SalOp*)user_ctx; - sal_error_info_set(&op->error_info,SalReasonRequestTimeout, "SIP", 408,"Request timeout",NULL); - process_error(op); - -} -static void process_response_event(void *op_base, const belle_sip_response_event_t *event){ - SalOp* op = (SalOp*)op_base; - int code = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); - SalMessageDeliveryStatus status; - sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); - - if (code>=100 && code <200) - status=SalMessageDeliveryInProgress; - else if (code>=200 && code <300) - status=SalMessageDeliveryDone; - else - status=SalMessageDeliveryFailed; - - op->base.root->callbacks.message_delivery_update(op,status); -} - -static bool_t is_external_body(belle_sip_header_content_type_t* content_type) { - return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0 - && strcmp("external-body",belle_sip_header_content_type_get_subtype(content_type))==0; -} - -static void add_message_accept(SalOp *op, belle_sip_message_t *msg) { - bctbx_list_t *item; - const char *str; - char *old; - char *header = ms_strdup("xml/cipher, application/cipher.vnd.gsma.rcs-ft-http+xml"); - - for (item = op->base.root->supported_content_types; item != NULL; item = bctbx_list_next(item)) { - str = (const char *)bctbx_list_get_data(item); - old = header; - header = ms_strdup_printf("%s, %s", old, str); - ms_free(old); - } - - belle_sip_message_add_header(msg, belle_sip_header_create("Accept", header)); - ms_free(header); -} - -void sal_process_incoming_message(SalOp *op,const belle_sip_request_event_t *event){ - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,req); - belle_sip_header_address_t* address; - belle_sip_header_from_t* from_header; - belle_sip_header_content_type_t* content_type; - belle_sip_response_t* resp; - int errcode = 500; - belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); - belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); - belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); - char* from; - bool_t external_body=FALSE; - - from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); - content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); - - if (content_type) { - SalMessage salmsg; - char message_id[256]={0}; - - if (op->pending_server_trans) belle_sip_object_unref(op->pending_server_trans); - op->pending_server_trans=server_transaction; - belle_sip_object_ref(op->pending_server_trans); - - external_body=is_external_body(content_type); - address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) - ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); - from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); - snprintf(message_id,sizeof(message_id)-1,"%s%i" - ,belle_sip_header_call_id_get_call_id(call_id) - ,belle_sip_header_cseq_get_seq_number(cseq)); - salmsg.from=from; - /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ - salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; - salmsg.url=NULL; - salmsg.content_type = ms_strdup_printf("%s/%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type)); - if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { - size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); - salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ - ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ - } - salmsg.message_id=message_id; - salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); - op->base.root->callbacks.message_received(op,&salmsg); - - belle_sip_object_unref(address); - belle_sip_free(from); - if (salmsg.url) ms_free((char*)salmsg.url); - ms_free((char *)salmsg.content_type); - } else { - ms_error("Unsupported MESSAGE (no Content-Type)"); - resp = belle_sip_response_create_from_request(req, errcode); - add_message_accept(op, (belle_sip_message_t*)resp); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_release(op); - } -} - -static void process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - sal_process_incoming_message(op,event); -} - -int sal_message_send(SalOp *op, const char *from, const char *to, const char* content_type, const char *msg, const char *peer_uri){ - belle_sip_request_t* req; - char content_type_raw[256]; - size_t content_length = msg?strlen(msg):0; - time_t curtime = ms_time(NULL); - const char *body; - int retval; - - if (op->dialog){ - /*for SIP MESSAGE that are sent in call's dialog*/ - req=belle_sip_dialog_create_queued_request(op->dialog,"MESSAGE"); - }else{ - sal_op_message_fill_cbs(op); - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - op->dir=SalOpDirOutgoing; - - req=sal_op_build_request(op,"MESSAGE"); - if (req == NULL ){ - return -1; - } - if (sal_op_get_contact_address(op)){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); - } - } - - snprintf(content_type_raw,sizeof(content_type_raw),BELLE_SIP_CONTENT_TYPE ": %s",content_type); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_type_parse(content_type_raw))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); - body = msg; - if (body){ - /*don't call set_body() with null argument because it resets content type and content length*/ - belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), body, content_length); - } - retval = sal_op_send_request(op,req); - - return retval; -} - -int sal_message_reply(SalOp *op, SalReason reason){ - if (op->pending_server_trans){ - int code=sal_reason_to_sip_code(reason); - belle_sip_response_t *resp = belle_sip_response_create_from_request( - belle_sip_transaction_get_request((belle_sip_transaction_t*)op->pending_server_trans),code); - belle_sip_server_transaction_send_response(op->pending_server_trans,resp); - return 0; - }else ms_error("sal_message_reply(): no server transaction"); - return -1; -} - -int sal_text_send(SalOp *op, const char *from, const char *to, const char *msg) { - return sal_message_send(op,from,to,"text/plain",msg, NULL); -} - -static belle_sip_listener_callbacks_t op_message_callbacks={0}; - -void sal_op_message_fill_cbs(SalOp*op) { - if (op_message_callbacks.process_io_error==NULL){ - op_message_callbacks.process_io_error=process_io_error; - op_message_callbacks.process_response_event=process_response_event; - op_message_callbacks.process_timeout=process_timeout; - op_message_callbacks.process_request_event=process_request_event; - } - op->callbacks=&op_message_callbacks; - op->type=SalOpMessage; -} diff --git a/coreapi/bellesip_sal/sal_op_presence.c b/coreapi/bellesip_sal/sal_op_presence.c deleted file mode 100644 index ba0624bfb..000000000 --- a/coreapi/bellesip_sal/sal_op_presence.c +++ /dev/null @@ -1,441 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" - - -void sal_add_presence_info(SalOp *op, belle_sip_message_t *notify, SalPresenceModel *presence) { - char *contact_info; - char *content = NULL; - size_t content_length; - - if (presence){ - belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(notify,belle_sip_header_from_t); - contact_info=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); - op->base.root->callbacks.convert_presence_to_xml_requested(op, presence, contact_info, &content); - belle_sip_free(contact_info); - if (content == NULL) return; - } - - 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"))); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length=strlen(content)))); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),content,content_length); - ms_free(content); - } -} - -static void presence_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){ - SalOp* op = (SalOp*)user_ctx; - belle_sip_request_t* request; - belle_sip_client_transaction_t* client_transaction = NULL; - - if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event), - belle_sip_client_transaction_t)){ - client_transaction = (belle_sip_client_transaction_t*)belle_sip_io_error_event_get_source(event); - } - - if (!client_transaction) return; - - request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); - - if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ - if (op->refresher){ - ms_warning("presence_process_io_error() refresher is present, should not happen"); - return; - } - ms_message("subscription to [%s] io error",sal_op_get_to(op)); - if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ - } - } -} - -static void presence_process_dialog_terminated(void *ctx, const belle_sip_dialog_terminated_event_t *event) { - SalOp* op= (SalOp*)ctx; - if (op->dialog && belle_sip_dialog_is_server(op->dialog)) { - ms_message("Incoming subscribtion from [%s] terminated",sal_op_get_from(op)); - if (!op->op_released){ - op->base.root->callbacks.subscribe_presence_closed(op, sal_op_get_from(op)); - } - set_or_update_dialog(op, NULL); - }/* else client dialog is managed by refresher*/ -} - -static void presence_refresher_listener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry){ - SalOp* op = (SalOp*)user_pointer; - if (status_code >= 300) { - ms_message("The SUBSCRIBE dialog no longer works. Let's restart a new one."); - belle_sip_refresher_stop(op->refresher); - if (op->dialog) { /*delete previous dialog if any*/ - set_or_update_dialog(op, NULL); - } - - if (sal_op_get_contact_address(op)) { - /*contact is also probably not good*/ - SalAddress* contact=sal_address_clone(sal_op_get_contact_address(op)); - sal_address_set_port(contact,-1); - sal_address_set_domain(contact,NULL); - sal_op_set_contact_address(op,contact); - sal_address_destroy(contact); - } - /*send a new SUBSCRIBE, that will attempt to establish a new dialog*/ - sal_subscribe_presence(op,NULL,NULL,-1); - } - if (status_code == 0 || status_code == 503){ - /*timeout or io error: the remote doesn't seem reachable.*/ - if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeActive, NULL,NULL); /*NULL = offline*/ - } - } -} - - -static void presence_response_event(void *op_base, const belle_sip_response_event_t *event){ - SalOp* op = (SalOp*)op_base; - belle_sip_dialog_state_t dialog_state; - belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); - belle_sip_response_t* response=belle_sip_response_event_get_response(event); - 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) { - if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ - ms_message("subscription to [%s] rejected",sal_op_get_to(op)); - if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ - } - return; - } - } - set_or_update_dialog(reinterpret_cast(op_base),belle_sip_response_event_get_dialog(event)); - if (!op->dialog) { - ms_message("presence op [%p] receive out of dialog answer [%i]",op,code); - return; - } - dialog_state=belle_sip_dialog_get_state(op->dialog); - - switch(dialog_state) { - case BELLE_SIP_DIALOG_NULL: - case BELLE_SIP_DIALOG_EARLY: { - ms_error("presence op [%p] receive an unexpected answer [%i]",op,code); - break; - } - case BELLE_SIP_DIALOG_CONFIRMED: { - if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0) { - expires=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t); - if(op->refresher) { - belle_sip_refresher_stop(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - } - if ((expires != NULL) && (belle_sip_header_expires_get_expires(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; - } - default: { - ms_error("presence op [%p] receive answer [%i] not implemented",op,code); - } - /* no break */ - } -} - -static void presence_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) { - SalOp* op = (SalOp*)user_ctx; - belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); - belle_sip_request_t* request; - - if (!client_transaction) return; - - request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); - - if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ - ms_message("subscription to [%s] timeout",sal_op_get_to(op)); - if (!op->op_released){ - op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ - } - } -} - -static void presence_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { - ms_message("presence_process_transaction_terminated not implemented yet"); -} - -static SalPresenceModel * process_presence_notification(SalOp *op, belle_sip_request_t *req) { - belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); - belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_length_t); - const char *body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); - SalPresenceModel *result = NULL; - - if ((content_type == NULL) || (content_length == NULL)) - return NULL; - if (belle_sip_header_content_length_get_content_length(content_length) == 0) - return NULL; - - if (body==NULL) return NULL; - if (!op->op_released){ - op->base.root->callbacks.parse_presence_requested(op, - belle_sip_header_content_type_get_type(content_type), - belle_sip_header_content_type_get_subtype(content_type), - body, - &result); - } - - return result; -} - -static void handle_notify(SalOp *op, belle_sip_request_t *req, belle_sip_dialog_t *dialog){ - belle_sip_response_t* resp=NULL; - 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)); - - if (op->dialog !=NULL && dialog != op->dialog){ - ms_warning("Receiving a NOTIFY from a dialog we haven't stored (op->dialog=%p dialog=%p)", op->dialog, dialog); - } - if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { - sub_state=SalSubscribeTerminated; - ms_message("Outgoing subscription terminated by remote [%s]",sal_op_get_to(op)); - } else { - sub_state=belle_sip_message_get_subscription_state(BELLE_SIP_MESSAGE(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 */ - if (!op->op_released){ - op->base.root->callbacks.notify_presence(op, sub_state, presence_model, NULL); - } - } else if (body){ - /* Formatting error in presence notification body. */ - ms_warning("Wrongly formatted presence document."); - resp = sal_op_create_response_from_request(op, req, 488); - } - if (resp) belle_sip_server_transaction_send_response(server_transaction,resp); - } -} - -static void presence_process_request_event(void *op_base, const belle_sip_request_event_t *event) { - SalOp* op = (SalOp*)op_base; - belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event)); - belle_sip_request_t* req = belle_sip_request_event_get_request(event); - belle_sip_dialog_state_t dialog_state; - belle_sip_response_t* resp; - const char *method=belle_sip_request_get_method(req); - belle_sip_header_event_t *event_header; - 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; - event_header=belle_sip_message_get_header_by_type(req,belle_sip_header_event_t); - - if (event_header==NULL){ - ms_warning("No event header in incoming SUBSCRIBE."); - resp=sal_op_create_response_from_request(op,req,400); - belle_sip_server_transaction_send_response(server_transaction,resp); - if (!op->dialog) sal_op_release(op); - return; - } - if (op->event==NULL) { - op->event=event_header; - belle_sip_object_ref(op->event); - } - - - if (!op->dialog) { - if (strcmp(method,"SUBSCRIBE")==0){ - belle_sip_dialog_t *dialog = belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction)); - if (!dialog){ - resp=sal_op_create_response_from_request(op,req,481); - belle_sip_server_transaction_send_response(server_transaction,resp); - sal_op_release(op); - return; - } - set_or_update_dialog(op, dialog); - ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op)); - }else if (strcmp(method,"NOTIFY")==0 && belle_sip_request_event_get_dialog(event)) { - /*special case of dialog created by notify matching subscribe*/ - set_or_update_dialog(op, belle_sip_request_event_get_dialog(event)); - } else {/* this is a NOTIFY */ - ms_message("Receiving out of dialog notify"); - handle_notify(op, req, belle_sip_request_event_get_dialog(event)); - return; - } - } - dialog_state=belle_sip_dialog_get_state(op->dialog); - switch(dialog_state) { - case BELLE_SIP_DIALOG_NULL: { - if (strcmp("NOTIFY",method)==0) { - handle_notify(op, req, belle_sip_request_event_get_dialog(event)); - } else if (strcmp("SUBSCRIBE",method)==0) { - op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op)); - } - break; - } - case BELLE_SIP_DIALOG_EARLY: - ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",method,op->dialog); - break; - - case BELLE_SIP_DIALOG_CONFIRMED: - if (strcmp("NOTIFY",method)==0) { - handle_notify(op, req, belle_sip_request_event_get_dialog(event)); - } else if (strcmp("SUBSCRIBE",method)==0) { - /*either a refresh or an unsubscribe. - If it is a refresh there is nothing to notify to the app. If it is an unSUBSCRIBE, then the dialog - will be terminated shortly, and this will be notified to the app through the dialog_terminated callback.*/ - resp=sal_op_create_response_from_request(op,req,200); - belle_sip_server_transaction_send_response(server_transaction,resp); - } - break; - default: - ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); - break; - } -} - -static belle_sip_listener_callbacks_t op_presence_callbacks={0}; - -/*Invoke when sal_op_release is called by upper layer*/ -static void sal_op_release_cb(struct SalOpBase* op_base) { - SalOp *op =(SalOp*)op_base; - if(op->refresher) { - belle_sip_refresher_stop(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - set_or_update_dialog(op,NULL); /*only if we have refresher. else dialog terminated event will remove association*/ - } - -} -void sal_op_presence_fill_cbs(SalOp*op) { - if (op_presence_callbacks.process_request_event==NULL){ - op_presence_callbacks.process_io_error=presence_process_io_error; - op_presence_callbacks.process_response_event=presence_response_event; - op_presence_callbacks.process_timeout=presence_process_timeout; - op_presence_callbacks.process_transaction_terminated=presence_process_transaction_terminated; - op_presence_callbacks.process_request_event=presence_process_request_event; - op_presence_callbacks.process_dialog_terminated=presence_process_dialog_terminated; - } - op->callbacks=&op_presence_callbacks; - op->type=SalOpPresence; - op->base.release_cb=sal_op_release_cb; -} - - -/*presence Subscribe/notify*/ -int sal_subscribe_presence(SalOp *op, const char *from, const char *to, int expires){ - belle_sip_request_t *req=NULL; - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - - sal_op_presence_fill_cbs(op); - - if (expires==-1){ - if (op->refresher){ - expires=belle_sip_refresher_get_expires(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - }else{ - ms_error("sal_subscribe_presence(): cannot guess expires from previous refresher."); - return -1; - } - } - if (!op->event){ - op->event=belle_sip_header_event_create("presence"); - belle_sip_object_ref(op->event); - } - belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.from_address),"tag"); - belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(op->base.to_address),"tag"); - req=sal_op_build_request(op,"SUBSCRIBE"); - if( req ){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(op->event)); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); - } - - return sal_op_send_request(op,req); -} - - -static belle_sip_request_t *create_presence_notify(SalOp *op){ - belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(op->dialog,"NOTIFY"); - if (!notify) return NULL; - - belle_sip_message_add_header((belle_sip_message_t*)notify,belle_sip_header_create("Event","presence")); - return notify; -} - -static int sal_op_check_dialog_state(SalOp *op) { - belle_sip_dialog_state_t state=op->dialog?belle_sip_dialog_get_state(op->dialog): BELLE_SIP_DIALOG_NULL; - if (state != BELLE_SIP_DIALOG_CONFIRMED) { - ms_warning("Cannot notify presence for op [%p] because dialog in state [%s]",op, belle_sip_dialog_state_to_string(state)); - return -1; - } else - return 0; -} - -int sal_notify_presence(SalOp *op, SalPresenceModel *presence){ - belle_sip_request_t* notify=NULL; - if (sal_op_check_dialog_state(op)) { - return -1; - } - notify=create_presence_notify(op); - if (!notify) return-1; - - sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),presence); /*FIXME, what about expires ??*/ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600))); - return sal_op_send_request(op,notify); -} - -int sal_notify_presence_close(SalOp *op){ - belle_sip_request_t* notify=NULL; - int status; - if (sal_op_check_dialog_state(op)) { - return -1; - } - notify=create_presence_notify(op); - if (!notify) return-1; - - sal_add_presence_info(op,BELLE_SIP_MESSAGE(notify),NULL); /*FIXME, what about expires ??*/ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) - ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); - status = sal_op_send_request(op,notify); - set_or_update_dialog(op,NULL); /*because we may be chalanged for the notify, so we must release dialog right now*/ - return status; -} - - - diff --git a/coreapi/bellesip_sal/sal_op_publish.c b/coreapi/bellesip_sal/sal_op_publish.c deleted file mode 100644 index 2de596519..000000000 --- a/coreapi/bellesip_sal/sal_op_publish.c +++ /dev/null @@ -1,112 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" - - -static void publish_refresher_listener (belle_sip_refresher_t* refresher - ,void* user_pointer - ,unsigned int status_code - ,const char* reason_phrase, int will_retry) { - SalOp* op = (SalOp*)user_pointer; - const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); - belle_sip_response_t *response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(last_publish_trans)); - ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase?reason_phrase:"none",sal_op_get_proxy(op)); - if (status_code==0){ - op->base.root->callbacks.on_expire(op); - }else if (status_code>=200){ - belle_sip_header_t *sip_etag; - const char *sip_etag_string = NULL; - if (response && (sip_etag = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response), "SIP-ETag"))) { - sip_etag_string = belle_sip_header_get_unparsed_value(sip_etag); - } - sal_op_set_entity_tag(op, sip_etag_string); - sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", status_code,reason_phrase,NULL); - sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); - op->base.root->callbacks.on_publish_response(op); - } -} - -static void publish_response_event(void *userctx, const belle_sip_response_event_t *event){ - SalOp *op=(SalOp*)userctx; - sal_op_set_error_info_from_response(op,belle_sip_response_event_get_response(event)); - if (op->error_info.protocol_code>=200){ - op->base.root->callbacks.on_publish_response(op); - } -} - -static belle_sip_listener_callbacks_t op_publish_callbacks={0}; - -void sal_op_publish_fill_cbs(SalOp *op) { - if (op_publish_callbacks.process_response_event==NULL){ - op_publish_callbacks.process_response_event=publish_response_event; - } - op->callbacks=&op_publish_callbacks; - op->type=SalOpPublish; -} - -int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler){ - belle_sip_request_t *req=NULL; - if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) { - if (from) - sal_op_set_from(op,from); - if (to) - sal_op_set_to(op,to); - - sal_op_publish_fill_cbs(op); - req=sal_op_build_request(op,"PUBLISH"); - if( req == NULL ){ - return -1; - } - - if (sal_op_get_entity_tag(op)) { - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("SIP-If-Match", sal_op_get_entity_tag(op))); - } - - if (sal_op_get_contact_address(op)){ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op))); - } - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); - if (expires!=-1) - return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener); - else return sal_op_send_request(op,req); - } else { - /*update status*/ - const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); - /*update body*/ - if (expires == 0) { - belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_publish), NULL, 0); - } else { - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_publish), BELLE_SIP_BODY_HANDLER(body_handler)); - } - return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); - } -} - -int sal_op_unpublish(SalOp *op){ - if (op->refresher){ - const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(op->refresher); - belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); - belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); - belle_sip_refresher_refresh(op->refresher,0); - return 0; - } - return -1; -} diff --git a/coreapi/bellesip_sal/sal_sdp.c b/coreapi/bellesip_sal/sal_sdp.c index 22b8c5be1..9cd5a5ed8 100644 --- a/coreapi/bellesip_sal/sal_sdp.c +++ b/coreapi/bellesip_sal/sal_sdp.c @@ -42,7 +42,7 @@ static void add_ice_candidates(belle_sdp_media_description_t *md, const SalStrea return; } if (candidate->raddr[0] != '\0') { - nb = snprintf(buffer + nb, sizeof(buffer) - nb, " raddr %s rport %d", candidate->raddr, candidate->rport); + nb = snprintf(buffer + nb, sizeof(buffer) - (size_t)nb, " raddr %s rport %d", candidate->raddr, candidate->rport); if (nb < 0) { ms_error("Cannot add ICE candidate attribute!"); return; @@ -63,7 +63,7 @@ static void add_ice_remote_candidates(belle_sdp_media_description_t *md, const S for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; i++) { candidate = &desc->ice_remote_candidates[i]; if ((candidate->addr[0] != '\0') && (candidate->port != 0)) { - offset = snprintf(ptr, buffer + sizeof(buffer) - ptr, "%s%d %s %d", (i > 0) ? " " : "", i + 1, candidate->addr, candidate->port); + offset = snprintf(ptr, (size_t)(buffer + sizeof(buffer) - ptr), "%s%d %s %d", (i > 0) ? " " : "", i + 1, candidate->addr, candidate->port); if (offset < 0) { ms_error("Cannot add ICE remote-candidates attribute!"); return; @@ -150,25 +150,25 @@ static void add_rtcp_fb_attributes(belle_sdp_media_description_t *media_desc, co /* Add trr-int if not set generally. */ if (general_trr_int != TRUE && trr_int != 0) { - add_rtcp_fb_trr_int_attribute(media_desc, payload_type_get_number(pt), avpf_params.trr_interval); + add_rtcp_fb_trr_int_attribute(media_desc, (int8_t)payload_type_get_number(pt), avpf_params.trr_interval); } /* Add rtcp-fb attributes according to the AVPF features of the payload types. */ if (avpf_params.features & PAYLOAD_TYPE_AVPF_PLI) { - add_rtcp_fb_nack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_PLI); + add_rtcp_fb_nack_attribute(media_desc, (int8_t)payload_type_get_number(pt), BELLE_SDP_RTCP_FB_PLI); } if (avpf_params.features & PAYLOAD_TYPE_AVPF_SLI) { - add_rtcp_fb_nack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_SLI); + add_rtcp_fb_nack_attribute(media_desc, (int8_t)payload_type_get_number(pt), BELLE_SDP_RTCP_FB_SLI); } if (avpf_params.features & PAYLOAD_TYPE_AVPF_RPSI) { if (avpf_params.rpsi_compatibility == TRUE) { - add_rtcp_fb_nack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_RPSI); + add_rtcp_fb_nack_attribute(media_desc, (int8_t)payload_type_get_number(pt), BELLE_SDP_RTCP_FB_RPSI); } else { - add_rtcp_fb_ack_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_RPSI); + add_rtcp_fb_ack_attribute(media_desc, (int8_t)payload_type_get_number(pt), BELLE_SDP_RTCP_FB_RPSI); } } if (avpf_params.features & PAYLOAD_TYPE_AVPF_FIR) { - add_rtcp_fb_ccm_attribute(media_desc, payload_type_get_number(pt), BELLE_SDP_RTCP_FB_FIR); + add_rtcp_fb_ccm_attribute(media_desc, (int8_t)payload_type_get_number(pt), BELLE_SDP_RTCP_FB_FIR); } } } @@ -263,9 +263,9 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session if (ms_crypto_suite_to_name_params(stream->crypto[j].algo,&desc)==0){ if (desc.params) snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s %s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key,desc.params); - else + else snprintf ( buffer, sizeof ( buffer )-1, "%d %s inline:%s", stream->crypto[j].tag, desc.name, stream->crypto[j].master_key ); - + belle_sdp_media_description_add_attribute( media_desc,belle_sdp_attribute_create ("crypto", buffer)); }else break; } @@ -314,11 +314,11 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session break; } if ( dir ) belle_sdp_media_description_add_attribute ( media_desc,belle_sdp_attribute_create ( dir,NULL ) ); - + if (stream->rtcp_mux){ belle_sdp_media_description_add_attribute(media_desc, belle_sdp_attribute_create ("rtcp-mux",NULL ) ); } - + if (rtp_port != 0) { different_rtp_and_rtcp_addr = (rtcp_addr[0] != '\0') && (strcmp(rtp_addr, rtcp_addr) != 0); if ((rtcp_port != (rtp_port + 1)) || (different_rtp_and_rtcp_addr == TRUE)) { @@ -337,7 +337,7 @@ static void stream_description_to_sdp ( belle_sdp_session_description_t *session belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-mismatch",NULL)); } else { if (rtp_port != 0) { - if (stream->ice_pwd[0] != '\0') + if (stream->ice_pwd[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-pwd",stream->ice_pwd)); if (stream->ice_ufrag[0] != '\0') belle_sdp_media_description_add_attribute(media_desc,belle_sdp_attribute_create ("ice-ufrag",stream->ice_ufrag)); @@ -432,7 +432,7 @@ belle_sdp_session_description_t * media_description_to_sdp ( const SalMediaDescr if ( desc->bandwidth>0 ) { belle_sdp_session_description_set_bandwidth ( session_desc,"AS",desc->bandwidth ); } - + if (desc->set_nortpproxy == TRUE) belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("nortpproxy","yes")); if (desc->ice_pwd[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-pwd",desc->ice_pwd)); if (desc->ice_ufrag[0] != '\0') belle_sdp_session_description_add_attribute(session_desc, belle_sdp_attribute_create("ice-ufrag",desc->ice_ufrag)); @@ -486,7 +486,7 @@ static void sdp_parse_payload_types(belle_sdp_media_description_t *media_desc, S static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *media_desc, SalStreamDescription *stream) { belle_sip_list_t *attribute_it; belle_sdp_attribute_t *attribute; - char tmp[256], tmp2[256], parameters[256]={0}; + char tmp[257], tmp2[257], parameters[257]={0}; int valid_count = 0; int nb; @@ -501,7 +501,7 @@ static void sdp_parse_media_crypto_parameters(belle_sdp_media_description_t *med &stream->crypto[valid_count].tag, tmp, tmp2, parameters ); - + if ( nb >= 3 ) { MSCryptoSuite cs; MSCryptoSuiteNameParams np; @@ -651,7 +651,7 @@ static bool_t sdp_parse_rtcp_fb_parameters(belle_sdp_media_description_t *media_ PayloadType *pt; int8_t pt_num; bool_t retval = FALSE; - + /* Handle rtcp-fb attributes that concern all payload types. */ for (it = belle_sdp_media_description_get_attributes(media_desc); it != NULL; it = it->next) { attribute = BELLE_SDP_ATTRIBUTE(it->data); @@ -805,7 +805,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, } stream->rtcp_mux = belle_sdp_media_description_get_attribute(media_desc, "rtcp-mux") != NULL; - + /* Get media payload types */ sdp_parse_payload_types(media_desc, stream); @@ -857,7 +857,7 @@ static SalStreamDescription * sdp_to_stream_description(SalMediaDescription *md, /* Get ICE candidate attributes if any */ sdp_parse_media_ice_parameters(media_desc, stream); - + has_avpf_attributes = sdp_parse_rtcp_fb_parameters(media_desc, stream); /* Get RTCP-FB attributes if any */ @@ -892,7 +892,7 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S const char* value; SalDtlsRole session_role=SalDtlsRoleInvalid; int i; - + desc->nb_streams = 0; desc->dir = SalStreamSendRecv; @@ -902,11 +902,11 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S if ( (sname=belle_sdp_session_description_get_session_name(session_desc)) && belle_sdp_session_name_get_value(sname) ){ strncpy(desc->name,belle_sdp_session_name_get_value(sname),sizeof(desc->name) - 1); } - + if ( belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ) >0 ) { desc->bandwidth=belle_sdp_session_description_get_bandwidth ( session_desc,"AS" ); } - + /*in some very rare case, session attribute may set stream dir*/ if ( belle_sdp_session_description_get_attribute ( session_desc,"sendrecv" ) ) { desc->dir=SalStreamSendRecv; @@ -940,10 +940,10 @@ int sdp_to_media_description ( belle_sdp_session_description_t *session_desc, S /* Get ICE remote ufrag and remote pwd, and ice_lite flag */ value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-ufrag"); if (value) strncpy(desc->ice_ufrag, value, sizeof(desc->ice_ufrag) - 1); - + value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-pwd"); if (value) strncpy(desc->ice_pwd, value, sizeof(desc->ice_pwd)-1); - + value=belle_sdp_session_description_get_attribute_value(session_desc,"ice-lite"); if (value) desc->ice_lite = TRUE; diff --git a/coreapi/buffer.c b/coreapi/buffer.c index d895b1357..c3bd79270 100644 --- a/coreapi/buffer.c +++ b/coreapi/buffer.c @@ -18,10 +18,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/core.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. #include "private.h" - - static void linphone_buffer_destroy(LinphoneBuffer *buffer) { if (buffer->content) belle_sip_free(buffer->content); } diff --git a/coreapi/call_log.c b/coreapi/call_log.c index 542570cc3..a4f52c67f 100644 --- a/coreapi/call_log.c +++ b/coreapi/call_log.c @@ -16,27 +16,29 @@ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __APPLE__ + +#ifndef __APPLE__ /*XOPEN_SOURCE icompilation issue with xcode9 https://github.com/eclipse/omr/pull/1721*/ #define _XOPEN_SOURCE 700 /*required for strptime of GNU libc*/ #endif #include -#include "private.h" #ifdef SQLITE_STORAGE_ENABLED -#ifndef _WIN32 -#if !defined(__ANDROID__) && !defined(__QNXNTO__) -# include -# include -# include -#endif -#else -#include + #if !defined(_WIN32) && !defined(__ANDROID__) && !defined(__QNXNTO__) + #include + #include + #include + #endif + + #include "sqlite3.h" + + #define MAX_PATH_SIZE 1024 #endif -#define MAX_PATH_SIZE 1024 -#include "sqlite3.h" -#endif +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" typedef struct _CallLogStorageResult { LinphoneCore *core; @@ -117,7 +119,7 @@ void call_logs_write_to_config_file(LinphoneCore *lc){ } } -bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc){ +bctbx_list_t * linphone_core_read_call_logs_from_config_file(LinphoneCore *lc){ char logsection[32]; int i; const char *tmp; @@ -138,7 +140,7 @@ bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc){ continue; cl=linphone_call_log_new(static_cast(lp_config_get_int(cfg,logsection,"dir",0)),from,to); cl->status=static_cast(lp_config_get_int(cfg,logsection,"status",0)); - sec=lp_config_get_int64(cfg,logsection,"start_date_time",0); + sec=(uint64_t)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; @@ -154,7 +156,7 @@ bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc){ 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); + 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); call_logs=bctbx_list_append(call_logs,cl); @@ -189,15 +191,15 @@ const char *linphone_call_log_get_call_id(const LinphoneCallLog *cl){ return cl->call_id; } -LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl){ +LinphoneCallDir linphone_call_log_get_dir(const LinphoneCallLog *cl){ return cl->dir; } -int linphone_call_log_get_duration(LinphoneCallLog *cl){ +int linphone_call_log_get_duration(const LinphoneCallLog *cl){ return cl->duration; } -LinphoneAddress *linphone_call_log_get_from_address(LinphoneCallLog *cl){ +const LinphoneAddress *linphone_call_log_get_from_address(const LinphoneCallLog *cl){ return cl->from; } @@ -205,7 +207,7 @@ 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){ +float linphone_call_log_get_quality(const LinphoneCallLog *cl){ return cl->quality; } @@ -213,7 +215,11 @@ const char *linphone_call_log_get_ref_key(const LinphoneCallLog *cl){ return cl->refkey; } -LinphoneAddress *linphone_call_log_get_remote_address(LinphoneCallLog *cl){ +const LinphoneAddress *linphone_call_log_get_local_address(const LinphoneCallLog *cl) { + return (cl->dir == LinphoneCallIncoming) ? cl->to : cl->from; +} + +const LinphoneAddress *linphone_call_log_get_remote_address(const LinphoneCallLog *cl){ return (cl->dir == LinphoneCallIncoming) ? cl->from : cl->to; } @@ -221,15 +227,15 @@ 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){ +time_t linphone_call_log_get_start_date(const LinphoneCallLog *cl){ return cl->start_date_time; } -LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl){ +LinphoneCallStatus linphone_call_log_get_status(const LinphoneCallLog *cl){ return cl->status; } -LinphoneAddress *linphone_call_log_get_to_address(LinphoneCallLog *cl){ +const LinphoneAddress *linphone_call_log_get_to_address(const LinphoneCallLog *cl){ return cl->to; } @@ -241,32 +247,32 @@ void linphone_call_log_set_ref_key(LinphoneCallLog *cl, const char *refkey){ if (refkey) cl->refkey=ms_strdup(refkey); } -char * linphone_call_log_to_str(LinphoneCallLog *cl){ +char * linphone_call_log_to_str(const LinphoneCallLog *cl){ const 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"); + status="aborted"; break; case LinphoneCallSuccess: - status=_("completed"); + status="completed"; break; case LinphoneCallMissed: - status=_("missed"); + status="missed"; break; case LinphoneCallAcceptedElsewhere: - status=_("answered elsewhere"); + status="answered elsewhere"; break; case LinphoneCallDeclinedElsewhere: - status=_("declined elsewhere"); + status="declined elsewhere"; break; default: - status=_("unknown"); + status="unknown"; } - tmp=ms_strdup_printf(_("%s at %s\nFrom: %s\nTo: %s\nStatus: %s\nDuration: %i mn %i sec\n"), - (cl->dir==LinphoneCallIncoming) ? _("Incoming call") : _("Outgoing call"), + tmp=ms_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, @@ -278,15 +284,15 @@ char * linphone_call_log_to_str(LinphoneCallLog *cl){ return tmp; } -bool_t linphone_call_log_video_enabled(LinphoneCallLog *cl) { +bool_t linphone_call_log_video_enabled(const LinphoneCallLog *cl) { return cl->video_enabled; } -bool_t linphone_call_log_was_conference(LinphoneCallLog *cl) { +bool_t linphone_call_log_was_conference(const LinphoneCallLog *cl) { return cl->was_conference; } -const LinphoneErrorInfo *linphone_call_log_get_error_info(LinphoneCallLog *cl){ +const LinphoneErrorInfo *linphone_call_log_get_error_info(const LinphoneCallLog *cl){ return cl->error_info; } @@ -334,7 +340,7 @@ LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *fr set_call_log_date(cl,cl->start_date_time); cl->from=from; - cl->to=to; + cl->to=to; cl->status=LinphoneCallAborted; /*default status*/ cl->quality=-1; @@ -579,7 +585,7 @@ const bctbx_list_t *linphone_core_get_call_history(LinphoneCore *lc) { CallLogStorageResult clsres; if (!lc || lc->logs_db == NULL) return NULL; - if (lc->call_logs != NULL) return lc->call_logs; + if (lc->call_logs != NULL) return lc->call_logs; if (lc->max_call_logs != LINPHONE_MAX_CALL_HISTORY_UNLIMITED){ buf = sqlite3_mprintf("SELECT * FROM call_history ORDER BY id DESC LIMIT %i", lc->max_call_logs); @@ -625,7 +631,10 @@ int linphone_core_get_call_history_size(LinphoneCore *lc) { sqlite3_stmt *selectStatement; int returnValue; - if (!lc || lc->logs_db == NULL) return 0; + if (!lc) + return 0; + if (!lc->logs_db) + return (int)bctbx_list_size(lc->call_logs); buf = sqlite3_mprintf("SELECT count(*) FROM call_history"); returnValue = sqlite3_prepare_v2(lc->logs_db, buf, -1, &selectStatement, NULL); diff --git a/coreapi/call_params.c b/coreapi/call_params.c deleted file mode 100644 index b1bbf7d20..000000000 --- a/coreapi/call_params.c +++ /dev/null @@ -1,408 +0,0 @@ -/* -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone/call_params.h" -#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->media_encryption == LinphoneMediaEncryptionDTLS) && params->avpf_enabled) return SalProtoUdpTlsRtpSavpf; - if (params->media_encryption == LinphoneMediaEncryptionDTLS) return SalProtoUdpTlsRtpSavp; - if (params->avpf_enabled) return SalProtoRtpAvpf; - return SalProtoRtpAvp; -} - -SalStreamDir sal_dir_from_call_params_dir(LinphoneMediaDirection cpdir) { - switch (cpdir) { - case LinphoneMediaDirectionInactive: - return SalStreamInactive; - case LinphoneMediaDirectionSendOnly: - return SalStreamSendOnly; - case LinphoneMediaDirectionRecvOnly: - return SalStreamRecvOnly; - case LinphoneMediaDirectionSendRecv: - return SalStreamSendRecv; - case LinphoneMediaDirectionInvalid: - ms_error("LinphoneMediaDirectionInvalid shall not be used."); - return SalStreamInactive; - } - return SalStreamSendRecv; -} - -LinphoneMediaDirection media_direction_from_sal_stream_dir(SalStreamDir dir){ - switch (dir) { - case SalStreamInactive: - return LinphoneMediaDirectionInactive; - case SalStreamSendOnly: - return LinphoneMediaDirectionSendOnly; - case SalStreamRecvOnly: - return LinphoneMediaDirectionRecvOnly; - case SalStreamSendRecv: - return LinphoneMediaDirectionSendRecv; - } - return LinphoneMediaDirectionSendRecv; -} - -SalStreamDir get_audio_dir_from_call_params(const LinphoneCallParams *params) { - return sal_dir_from_call_params_dir(linphone_call_params_get_audio_direction(params)); -} - -SalStreamDir get_video_dir_from_call_params(const LinphoneCallParams *params) { - return sal_dir_from_call_params_dir(linphone_call_params_get_video_direction(params)); -} - -void linphone_call_params_set_custom_headers(LinphoneCallParams *params, const SalCustomHeader *ch){ - if (params->custom_headers){ - sal_custom_header_free(params->custom_headers); - params->custom_headers = NULL; - } - if (ch){ - params->custom_headers = sal_custom_header_clone(ch); - } -} - -void linphone_call_params_set_custom_sdp_attributes(LinphoneCallParams *params, const SalCustomSdpAttribute *csa) { - if (params->custom_sdp_attributes) { - sal_custom_sdp_attribute_free(params->custom_sdp_attributes); - params->custom_sdp_attributes = NULL; - } - if (csa) { - params->custom_sdp_attributes = sal_custom_sdp_attribute_clone(csa); - } -} - -void linphone_call_params_set_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa) { - if (params->custom_sdp_media_attributes[type]) { - sal_custom_sdp_attribute_free(params->custom_sdp_media_attributes[type]); - params->custom_sdp_media_attributes[type] = NULL; - } - if (csa) { - params->custom_sdp_media_attributes[type] = sal_custom_sdp_attribute_clone(csa); - } -} - - -/******************************************************************************* - * 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); -} - -void linphone_call_params_add_custom_sdp_attribute(LinphoneCallParams *params, const char *attribute_name, const char *attribute_value) { - params->custom_sdp_attributes = sal_custom_sdp_attribute_append(params->custom_sdp_attributes, attribute_name, attribute_value); -} - -void linphone_call_params_add_custom_sdp_media_attribute(LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name, const char *attribute_value) { - params->custom_sdp_media_attributes[type] = sal_custom_sdp_attribute_append(params->custom_sdp_media_attributes[type], attribute_name, attribute_value); -} - -void linphone_call_params_clear_custom_sdp_attributes(LinphoneCallParams *params) { - linphone_call_params_set_custom_sdp_attributes(params, NULL); -} - -void linphone_call_params_clear_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type) { - linphone_call_params_set_custom_sdp_media_attributes(params, type, NULL); -} - -LinphoneCallParams * linphone_call_params_copy(const LinphoneCallParams *cp){ - return (LinphoneCallParams *)belle_sip_object_clone((const belle_sip_object_t *)cp); -} - -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_audio(LinphoneCallParams *cp, bool_t enabled){ - cp->has_audio=enabled; - if (enabled && cp->audio_dir==LinphoneMediaDirectionInactive) - cp->audio_dir=LinphoneMediaDirectionSendRecv; -} - -LinphoneStatus linphone_call_params_enable_realtime_text(LinphoneCallParams *params, bool_t yesno) { - params->realtimetext_enabled=yesno; - return 0; -} - -void linphone_call_params_enable_video(LinphoneCallParams *cp, bool_t enabled){ - cp->has_video=enabled; - if (enabled && cp->video_dir==LinphoneMediaDirectionInactive) - cp->video_dir=LinphoneMediaDirectionSendRecv; -} - -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); -} - -const char * linphone_call_params_get_custom_sdp_attribute(const LinphoneCallParams *params, const char *attribute_name) { - return sal_custom_sdp_attribute_find(params->custom_sdp_attributes, attribute_name); -} - -const char * linphone_call_params_get_custom_sdp_media_attribute(const LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name) { - return sal_custom_sdp_attribute_find(params->custom_sdp_media_attributes[type], attribute_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 LinphoneVideoDefinition * linphone_call_params_get_received_video_definition(const LinphoneCallParams *cp) { - return cp->recv_vdef; -} - -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 LinphoneVideoDefinition * linphone_call_params_get_sent_video_definition(const LinphoneCallParams *cp) { - return cp->sent_vdef; -} - -const char *linphone_call_params_get_session_name(const LinphoneCallParams *cp){ - return cp->session_name; -} - -LinphonePayloadType *linphone_call_params_get_used_audio_payload_type(const LinphoneCallParams *cp) { - return cp->audio_codec ? linphone_payload_type_new(NULL, cp->audio_codec) : NULL; -} - -LinphonePayloadType *linphone_call_params_get_used_video_payload_type(const LinphoneCallParams *cp) { - return cp->video_codec ? linphone_payload_type_new(NULL, cp->video_codec) : NULL; -} - -LinphonePayloadType *linphone_call_params_get_used_text_payload_type(const LinphoneCallParams *cp) { - return cp->text_codec ? linphone_payload_type_new(NULL, cp->text_codec) : NULL; -} - -const OrtpPayloadType *linphone_call_params_get_used_audio_codec(const LinphoneCallParams *cp) { - return cp->audio_codec; -} - -const OrtpPayloadType *linphone_call_params_get_used_video_codec(const LinphoneCallParams *cp) { - return cp->video_codec; -} - -const OrtpPayloadType *linphone_call_params_get_used_text_codec(const LinphoneCallParams *cp) { - return cp->text_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_audio_enabled(const LinphoneCallParams *cp){ - return cp->has_audio; -} - -bool_t linphone_call_params_realtime_text_enabled(const LinphoneCallParams *params) { - return params->realtimetext_enabled; -} - -bool_t linphone_call_params_video_enabled(const LinphoneCallParams *cp){ - return cp->has_video; -} - -LinphoneMediaDirection linphone_call_params_get_audio_direction(const LinphoneCallParams *cp) { - return cp->audio_dir; -} - -LinphoneMediaDirection linphone_call_params_get_video_direction(const LinphoneCallParams *cp) { - return cp->video_dir; -} - -void linphone_call_params_set_audio_direction(LinphoneCallParams *cp,LinphoneMediaDirection dir) { - cp->audio_dir=dir; -} - -void linphone_call_params_set_video_direction(LinphoneCallParams *cp,LinphoneMediaDirection dir) { - cp->video_dir=dir; -} - - -/******************************************************************************* - * 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); -} - -void linphone_call_params_enable_audio_multicast(LinphoneCallParams *params, bool_t yesno) { - params->audio_multicast_enabled=yesno; -} - -bool_t linphone_call_params_audio_multicast_enabled(const LinphoneCallParams *params) { - return params->audio_multicast_enabled; -} - -void linphone_call_params_enable_video_multicast(LinphoneCallParams *params, bool_t yesno) { - params->video_multicast_enabled=yesno; -} -bool_t linphone_call_params_video_multicast_enabled(const LinphoneCallParams *params) { - return params->video_multicast_enabled; -} - -/******************************************************************************* - * Constructor and destructor functions * - ******************************************************************************/ - -static void _linphone_call_params_uninit(LinphoneCallParams *cp){ - unsigned int i; - if (cp->record_file) ms_free(cp->record_file); - if (cp->custom_headers) sal_custom_header_free(cp->custom_headers); - if (cp->custom_sdp_attributes) sal_custom_sdp_attribute_free(cp->custom_sdp_attributes); - for (i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) { - if (cp->custom_sdp_media_attributes[i]) sal_custom_sdp_attribute_free(cp->custom_sdp_media_attributes[i]); - } - if (cp->session_name) ms_free(cp->session_name); - if (cp->sent_vdef != NULL) linphone_video_definition_unref(cp->sent_vdef); - if (cp->recv_vdef != NULL) linphone_video_definition_unref(cp->recv_vdef); -} - -static void _linphone_call_params_clone(LinphoneCallParams *dst, const LinphoneCallParams *src) { - unsigned int i; - - /* - * Save the belle_sip_object_t part, copy the entire structure and restore the belle_sip_object_t part - */ - belle_sip_object_t tmp = dst->base; - memcpy(dst, src, sizeof(LinphoneCallParams)); - dst->base = tmp; - - if (src->sent_vdef) dst->sent_vdef = linphone_video_definition_ref(src->sent_vdef); - if (src->recv_vdef) dst->recv_vdef = linphone_video_definition_ref(src->recv_vdef); - if (src->record_file) dst->record_file=ms_strdup(src->record_file); - if (src->session_name) dst->session_name=ms_strdup(src->session_name); - /* - * The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. - */ - if (src->custom_headers) dst->custom_headers=sal_custom_header_clone(src->custom_headers); - if (src->custom_sdp_attributes) dst->custom_sdp_attributes = sal_custom_sdp_attribute_clone(src->custom_sdp_attributes); - for (i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) { - if (src->custom_sdp_media_attributes[i]) dst->custom_sdp_media_attributes[i] = sal_custom_sdp_attribute_clone(src->custom_sdp_media_attributes[i]); - } -} - -LinphoneCallParams * linphone_call_params_new(void) { - LinphoneCallParams *cp=belle_sip_object_new(LinphoneCallParams); - cp->audio_dir=LinphoneMediaDirectionSendRecv; - cp->video_dir=LinphoneMediaDirectionSendRecv; - cp->has_audio=TRUE; - cp->realtimetext_enabled = FALSE; - return cp; -} - -/* 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_uninit, - (belle_sip_object_clone_t)_linphone_call_params_clone, // clone - NULL, // marshal - FALSE -); diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 31797e722..87bc3ab80 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -17,10 +17,15 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "c-wrapper/internal/c-sal.h" +#include "sal/call-op.h" +#include "sal/message-op.h" +#include "sal/refer-op.h" -#include "sal/sal.h" - +#include "linphone/api/c-content.h" #include "linphone/core.h" +#include "linphone/utils/utils.h" + #include "private.h" #include "mediastreamer2/mediastream.h" #include "linphone/lpconfig.h" @@ -33,629 +38,194 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #endif +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-room/chat-room.h" +#include "chat/chat-room/client-group-chat-room-p.h" +#include "chat/chat-room/server-group-chat-room-p.h" +#include "conference/participant.h" +#include "conference/session/call-session-p.h" +#include "conference/session/call-session.h" +#include "conference/session/media-session-p.h" +#include "conference/session/media-session.h" +#include "core/core-p.h" + +using namespace std; + +using namespace LinphonePrivate; + static void register_failure(SalOp *op); -static int media_parameters_changed(LinphoneCall *call, SalMediaDescription *oldmd, SalMediaDescription *newmd) { - int result=0; - int otherdesc_changed; - char *tmp1=NULL; - char *tmp2=NULL; - if (call->params->in_conference != call->current_params->in_conference) return SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION; - if (call->up_bw != linphone_core_get_upload_bandwidth(call->core)) return SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION; - if (call->localdesc_changed) ms_message("Local description has changed: %s", tmp1 = sal_media_description_print_differences(call->localdesc_changed)); - otherdesc_changed = sal_media_description_equals(oldmd, newmd); - if (otherdesc_changed) ms_message("Other description has changed: %s", tmp2 = sal_media_description_print_differences(otherdesc_changed)); - result = call->localdesc_changed | otherdesc_changed; - if (tmp1) ms_free(tmp1); - if (tmp2) ms_free(tmp2); - return result; -} +static void call_received(SalCallOp *h) { + LinphoneCore *lc = reinterpret_cast(h->getSal()->getUserPointer()); -void linphone_core_update_streams_destinations(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) { - SalStreamDescription *new_audiodesc = NULL; - SalStreamDescription *new_videodesc = NULL; - char *rtp_addr, *rtcp_addr; - int i; - - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&new_md->streams[i])) continue; - if (new_md->streams[i].type == SalAudio) { - new_audiodesc = &new_md->streams[i]; - } else if (new_md->streams[i].type == SalVideo) { - new_videodesc = &new_md->streams[i]; - } - } - if (call->audiostream && new_audiodesc) { - rtp_addr = (new_audiodesc->rtp_addr[0] != '\0') ? new_audiodesc->rtp_addr : new_md->addr; - rtcp_addr = (new_audiodesc->rtcp_addr[0] != '\0') ? new_audiodesc->rtcp_addr : new_md->addr; - ms_message("Change audio stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_audiodesc->rtp_port, rtcp_addr, new_audiodesc->rtcp_port); - rtp_session_set_remote_addr_full(call->audiostream->ms.sessions.rtp_session, rtp_addr, new_audiodesc->rtp_port, rtcp_addr, new_audiodesc->rtcp_port); - } -#ifdef VIDEO_ENABLED - if (call->videostream && new_videodesc) { - rtp_addr = (new_videodesc->rtp_addr[0] != '\0') ? new_videodesc->rtp_addr : new_md->addr; - rtcp_addr = (new_videodesc->rtcp_addr[0] != '\0') ? new_videodesc->rtcp_addr : new_md->addr; - ms_message("Change video stream destination: RTP=%s:%d RTCP=%s:%d", rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port); - rtp_session_set_remote_addr_full(call->videostream->ms.sessions.rtp_session, rtp_addr, new_videodesc->rtp_port, rtcp_addr, new_videodesc->rtcp_port); - } -#else - (void)new_videodesc; -#endif -} - -static void _clear_early_media_destinations(LinphoneCall *call, MediaStream *ms){ - RtpSession *session=ms->sessions.rtp_session; - rtp_session_clear_aux_remote_addr(session); - if (!call->ice_session) rtp_session_set_symmetric_rtp(session,linphone_core_symmetric_rtp_enabled(call->core));/*restore symmetric rtp if ICE is not used*/ -} - -static void clear_early_media_destinations(LinphoneCall *call){ - if (call->audiostream){ - _clear_early_media_destinations(call,(MediaStream*)call->audiostream); - } - if (call->videostream){ - _clear_early_media_destinations(call,(MediaStream*)call->videostream); - } -} - -static void prepare_early_media_forking(LinphoneCall *call){ - /*we need to disable symmetric rtp otherwise our outgoing streams will be switching permanently between the multiple destinations*/ - if (call->audiostream){ - rtp_session_set_symmetric_rtp(call->audiostream->ms.sessions.rtp_session,FALSE); - } - if (call->videostream){ - rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,FALSE); - } -} - -void linphone_call_update_frozen_payloads(LinphoneCall *call, SalMediaDescription *result_desc){ - SalMediaDescription *local=call->localdesc; - int i; - for(i=0;inb_streams;++i){ - bctbx_list_t *elem; - for (elem=result_desc->streams[i].payloads;elem!=NULL;elem=elem->next){ - PayloadType *pt=(PayloadType*)elem->data; - if (is_payload_type_number_available(local->streams[i].already_assigned_payloads, payload_type_get_number(pt), NULL)){ - /*new codec, needs to be added to the list*/ - local->streams[i].already_assigned_payloads=bctbx_list_append(local->streams[i].already_assigned_payloads, payload_type_clone(pt)); - ms_message("LinphoneCall[%p] : payload type %i %s/%i fmtp=%s added to frozen list.", - call, payload_type_get_number(pt), pt->mime_type, pt->clock_rate, pt->recv_fmtp ? pt->recv_fmtp : ""); - } - } - } -} - -void linphone_call_update_streams(LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state) { - LinphoneCore *lc = linphone_call_get_core(call); - SalMediaDescription *oldmd = call->resultdesc; - int md_changed = 0; - - if (!((call->state == LinphoneCallIncomingEarlyMedia) && (linphone_core_get_ring_during_incoming_early_media(lc)))) { - linphone_core_stop_ringing(lc); - } - if (!new_md) { - ms_error("linphone_call_update_streams() called with null media description"); + if (linphone_core_get_global_state(lc) != LinphoneGlobalOn) { + h->decline(SalReasonServiceUnavailable, nullptr); + h->release(); return; } - linphone_call_update_biggest_desc(call, call->localdesc); - sal_media_description_ref(new_md); - call->resultdesc = new_md; - if ((call->audiostream && (call->audiostream->ms.state == MSStreamStarted)) || (call->videostream && (call->videostream->ms.state == MSStreamStarted))) { - clear_early_media_destinations(call); - - /* We already started media: check if we really need to restart it */ - if (oldmd) { - md_changed = media_parameters_changed(call, oldmd, new_md); - /*might not be mandatory to restart stream for each ice restart as it leads bad user experience, specially in video. See 0002495 for better background on this*/ - if ((md_changed & ( SAL_MEDIA_DESCRIPTION_CODEC_CHANGED - |SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED - |SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED - |SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED - |SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION ))) { - ms_message("Media descriptions are different, need to restart the streams."); - } else if (call->playing_ringbacktone) { - ms_message("Playing ringback tone, will restart the streams."); - } else { - if (call->all_muted && target_state == LinphoneCallStreamsRunning) { - ms_message("Early media finished, unmuting inputs..."); - /* We were in early media, now we want to enable real media */ - call->all_muted = FALSE; - if (call->audiostream) linphone_core_enable_mic(lc, linphone_core_mic_enabled(lc)); -#ifdef VIDEO_ENABLED - if (call->videostream && call->camera_enabled) { - linphone_call_enable_camera(call, linphone_call_camera_enabled(call)); - } -#endif - } - if (md_changed == SAL_MEDIA_DESCRIPTION_UNCHANGED) { - /*FIXME ZRTP, might be restarted in any cases ? */ - ms_message("No need to restart streams, SDP is unchanged."); - goto end; - } else { - if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) { - ms_message("Network parameters have changed, update them."); - linphone_core_update_streams_destinations(call, oldmd, new_md); - } - if (md_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) { - ms_message("Crypto parameters have changed, update them."); - linphone_call_update_crypto_parameters(call, oldmd, new_md); - } - goto end; - } - } - } - linphone_call_stop_media_streams(call); - if (md_changed & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED) { - ms_message("Media ip type has changed, destroying sessions context on call [%p]", call); - ms_media_stream_sessions_uninit(&call->sessions[call->main_audio_stream_index]); - ms_media_stream_sessions_uninit(&call->sessions[call->main_video_stream_index]); - ms_media_stream_sessions_uninit(&call->sessions[call->main_text_stream_index]); - } - 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); - } - - if (call->params->real_early_media && (call->state == LinphoneCallOutgoingEarlyMedia)) { - prepare_early_media_forking(call); - } - linphone_call_start_media_streams(call, target_state); - if ((call->state == LinphoneCallPausing) && call->paused_by_app && (bctbx_list_size(lc->calls) == 1)) { - linphone_core_play_named_tone(lc, LinphoneToneCallOnHold); - } - linphone_call_update_frozen_payloads(call, new_md); - -end: - if (oldmd) sal_media_description_unref(oldmd); - -} - -#if 0 -static bool_t is_duplicate_call(LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to){ - bctbx_list_t *elem; - 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)){ - return TRUE; - } - } - return FALSE; -} -#endif - -static bool_t already_a_call_with_remote_address(const LinphoneCore *lc, const LinphoneAddress *remote) { - bctbx_list_t *elem; - ms_message("Searching for already_a_call_with_remote_address."); - - for(elem=lc->calls;elem!=NULL;elem=elem->next){ - const LinphoneCall *call=(LinphoneCall*)elem->data; - const LinphoneAddress *cRemote=linphone_call_get_remote_address(call); - if (linphone_address_weak_equal(cRemote,remote)) { - ms_warning("already_a_call_with_remote_address found."); - return TRUE; - } - } - return FALSE; -} - - -static LinphoneCall * look_for_broken_call_to_replace(SalOp *h, LinphoneCore *lc) { - const bctbx_list_t *calls = linphone_core_get_calls(lc); - const bctbx_list_t *it = calls; - while (it != NULL) { - LinphoneCall *replaced_call = NULL; - LinphoneCall *call = (LinphoneCall *)bctbx_list_get_data(it); - SalOp *replaced_op = sal_call_get_replaces(h); - if (replaced_op) replaced_call = (LinphoneCall*)sal_op_get_user_pointer(replaced_op); - if ((call->broken && sal_call_compare_op(h, call->op)) - || ((replaced_call == call) && (strcmp(sal_op_get_from(h), sal_op_get_from(replaced_op)) == 0) && (strcmp(sal_op_get_to(h), sal_op_get_to(replaced_op)) == 0))) { - return call; - } - it = bctbx_list_next(it); - } - - return NULL; -} - -static void call_received(SalOp *h){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); - LinphoneCall *call; - LinphoneCall *replaced_call; - char *alt_contact; - LinphoneAddress *from_addr=NULL; - LinphoneAddress *to_addr=NULL; - LinphoneAddress *from_address_to_search_if_me=NULL; /*address used to know if I'm the caller*/ - SalMediaDescription *md; - const char * p_asserted_id; - LinphoneErrorInfo *ei = NULL; - LinphonePresenceActivity *activity = NULL; /* Look if this INVITE is for a call that has already been notified but broken because of network failure */ - replaced_call = look_for_broken_call_to_replace(h, lc); - if (replaced_call != NULL) { - linphone_call_replace_op(replaced_call, h); + if (L_GET_PRIVATE_FROM_C_OBJECT(lc)->inviteReplacesABrokenCall(h)) return; + + LinphoneAddress *fromAddr = nullptr; + const char *pAssertedId = sal_custom_header_find(h->getRecvCustomHeaders(), "P-Asserted-Identity"); + /* In some situation, better to trust the network rather than the UAC */ + if (lp_config_get_int(linphone_core_get_config(lc), "sip", "call_logs_use_asserted_id_instead_of_from", 0)) { + if (pAssertedId) { + LinphoneAddress *pAssertedIdAddr = linphone_address_new(pAssertedId); + if (pAssertedIdAddr) { + ms_message("Using P-Asserted-Identity [%s] instead of from [%s] for op [%p]", pAssertedId, h->getFrom().c_str(), h); + fromAddr = pAssertedIdAddr; + } else + ms_warning("Unsupported P-Asserted-Identity header for op [%p] ", h); + } else + ms_warning("No P-Asserted-Identity header found so cannot use it for op [%p] instead of from", h); } - p_asserted_id = sal_custom_header_find(sal_op_get_recv_custom_header(h),"P-Asserted-Identity"); - /*in some situation, better to trust the network rather than the UAC*/ - if (lp_config_get_int(lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0)) { - LinphoneAddress *p_asserted_id_addr; - if (!p_asserted_id) { - ms_warning("No P-Asserted-Identity header found so cannot use it for op [%p] instead of from",h); - } else { - p_asserted_id_addr = linphone_address_new(p_asserted_id); - if (!p_asserted_id_addr) { - ms_warning("Unsupported P-Asserted-Identity header for op [%p] ",h); - } else { - ms_message("Using P-Asserted-Identity [%s] instead of from [%s] for op [%p]",p_asserted_id,sal_op_get_from(h),h); - from_addr=p_asserted_id_addr; + if (!fromAddr) + fromAddr = linphone_address_new(h->getFrom().c_str()); + LinphoneAddress *toAddr = linphone_address_new(h->getTo().c_str()); + + if (_linphone_core_is_conference_creation(lc, toAddr)) { + linphone_address_unref(toAddr); + linphone_address_unref(fromAddr); + if (sal_address_has_param(h->getRemoteContactAddress(), "text")) { + bool oneToOneChatRoom = false; + const char *oneToOneChatRoomStr = sal_custom_header_find(h->getRecvCustomHeaders(), "One-To-One-Chat-Room"); + if (oneToOneChatRoomStr && (strcmp(oneToOneChatRoomStr, "true") == 0)) + oneToOneChatRoom = true; + if (oneToOneChatRoom) { + IdentityAddress from(h->getFrom()); + list identAddresses = ServerGroupChatRoom::parseResourceLists(h->getRemoteBody()); + if (identAddresses.size() != 1) { + h->decline(SalReasonNotAcceptable, nullptr); + h->release(); + return; + } + IdentityAddress confAddr = L_GET_PRIVATE_FROM_C_OBJECT(lc)->mainDb->findOneToOneConferenceChatRoomAddress(from, identAddresses.front()); + if (confAddr.isValid()) { + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(ChatRoomId(confAddr, confAddr)); + L_GET_PRIVATE(static_pointer_cast(chatRoom))->confirmRecreation(h); + return; + } } + _linphone_core_create_server_group_chat_room(lc, h); } + // TODO: handle media conference creation if the "text" feature tag is not present + return; + } else if (sal_address_has_param(h->getRemoteContactAddress(), "text")) { + linphone_address_unref(toAddr); + linphone_address_unref(fromAddr); + if (linphone_core_conference_server_enabled(lc)) { + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom( + ChatRoomId(IdentityAddress(h->getTo()), IdentityAddress(h->getTo())) + ); + if (chatRoom) { + L_GET_PRIVATE(static_pointer_cast(chatRoom))->confirmJoining(h); + } else { + //invite is for an unknown chatroom + h->decline(SalReasonNotFound, nullptr); + h->release(); + } + } else { + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom( + ChatRoomId(IdentityAddress(h->getFrom()), IdentityAddress(h->getTo())) + ); + if (!chatRoom) { + chatRoom = L_GET_PRIVATE_FROM_C_OBJECT(lc)->createClientGroupChatRoom( + h->getSubject(), h->getRemoteContact(), h->getRemoteBody(), false + ); + } + L_GET_PRIVATE(static_pointer_cast(chatRoom))->confirmJoining(h); + } + return; + } else { + // TODO: handle media conference joining if the "text" feature tag is not present } - if (!from_addr) - from_addr=linphone_address_new(sal_op_get_from(h)); - to_addr=linphone_address_new(sal_op_get_to(h)); - - /* first check if we can answer successfully to this invite */ - if (linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed + /* First check if we can answer successfully to this invite */ + LinphonePresenceActivity *activity = nullptr; + if ((linphone_presence_model_get_basic_status(lc->presence_model) == LinphonePresenceBasicStatusClosed) && (activity = linphone_presence_model_get_activity(lc->presence_model))) { + char *altContact = nullptr; switch (linphone_presence_activity_get_type(activity)) { case LinphonePresenceActivityPermanentAbsence: - alt_contact = linphone_presence_model_get_contact(lc->presence_model); - if (alt_contact != NULL) { + altContact = linphone_presence_model_get_contact(lc->presence_model); + if (altContact) { SalErrorInfo sei; memset(&sei, 0, sizeof(sei)); - sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(h, &sei,alt_contact); - ms_free(alt_contact); - ei = linphone_error_info_new(); - linphone_error_info_set(ei, NULL, LinphoneReasonMovedPermanently, 302, "Moved permanently", NULL); - linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); - sal_op_release(h); + sal_error_info_set(&sei, SalReasonRedirect, "SIP", 0, nullptr, nullptr); + SalAddress *altAddr = sal_address_new(altContact); + h->declineWithErrorInfo(&sei, altAddr); + ms_free(altContact); + sal_address_unref(altAddr); + LinphoneErrorInfo *ei = linphone_error_info_new(); + linphone_error_info_set(ei, nullptr, LinphoneReasonMovedPermanently, 302, "Moved permanently", nullptr); + linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei); + h->release(); sal_error_info_reset(&sei); return; } break; default: - /*nothing special to be done*/ + /* Nothing special to be done */ break; } } - if (!linphone_core_can_we_add_call(lc)){/*busy*/ - sal_call_decline(h,SalReasonBusy,NULL); - ei = linphone_error_info_new(); - linphone_error_info_set(ei, NULL, LinphoneReasonBusy, 486, "Busy - too many calls", NULL); - linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); - sal_op_release(h); + if (!L_GET_PRIVATE_FROM_C_OBJECT(lc)->canWeAddCall()) { /* Busy */ + h->decline(SalReasonBusy, nullptr); + LinphoneErrorInfo *ei = linphone_error_info_new(); + linphone_error_info_set(ei, nullptr, LinphoneReasonBusy, 486, "Busy - too many calls", nullptr); + linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei); + h->release(); return; } - - if (sal_op_get_privacy(h) == SalPrivacyNone) { - from_address_to_search_if_me=linphone_address_clone(from_addr); - } else if (p_asserted_id) { - from_address_to_search_if_me = linphone_address_new(p_asserted_id); - } else { - ms_warning ("Hidden from identity, don't know if it's me"); - } - - if (from_address_to_search_if_me && already_a_call_with_remote_address(lc,from_address_to_search_if_me)){ - char *addr = linphone_address_as_string(from_addr); - ms_warning("Receiving a call while one with same address [%s] is initiated, refusing this one with busy message.",addr); - sal_call_decline(h,SalReasonBusy,NULL); - ei = linphone_error_info_new(); - linphone_error_info_set(ei, NULL, LinphoneReasonBusy, 486, "Busy - duplicated call", NULL); - linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); - sal_op_release(h); - linphone_address_unref(from_address_to_search_if_me); + /* Check if I'm the caller */ + LinphoneAddress *fromAddressToSearchIfMe = nullptr; + if (h->getPrivacy() == SalPrivacyNone) + fromAddressToSearchIfMe = linphone_address_clone(fromAddr); + else if (pAssertedId) + fromAddressToSearchIfMe = linphone_address_new(pAssertedId); + else + ms_warning("Hidden from identity, don't know if it's me"); + if (fromAddressToSearchIfMe && L_GET_PRIVATE_FROM_C_OBJECT(lc)->isAlreadyInCallWithAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(fromAddressToSearchIfMe))) { + char *addr = linphone_address_as_string(fromAddr); + ms_warning("Receiving a call while one with same address [%s] is initiated, refusing this one with busy message", addr); + h->decline(SalReasonBusy, nullptr); + LinphoneErrorInfo *ei = linphone_error_info_new(); + linphone_error_info_set(ei, nullptr, LinphoneReasonBusy, 486, "Busy - duplicated call", nullptr); + linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, fromAddr, toAddr, ei); + h->release(); + linphone_address_unref(fromAddressToSearchIfMe); ms_free(addr); return; - } else if (from_address_to_search_if_me) { - linphone_address_unref(from_address_to_search_if_me); } + if (fromAddressToSearchIfMe) + linphone_address_unref(fromAddressToSearchIfMe); - call=linphone_call_new_incoming(lc,from_addr,to_addr,h); - - linphone_call_make_local_media_description(call); - sal_call_set_local_media_description(call->op,call->localdesc); - md=sal_call_get_final_media_description(call->op); - if (md){ - if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){ - ei = linphone_error_info_new(); - linphone_error_info_set(ei, NULL, LinphoneReasonNotAcceptable, 488, "Not acceptable here", NULL); - linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_ref(from_addr), linphone_address_ref(to_addr), ei); - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); - linphone_call_unref(call); - return; - } - } - - /* 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 */ - - call->bg_task_id=sal_begin_background_task("liblinphone call notification", NULL, NULL); - - if (call->defer_notify_incoming) { - /* Defer ringing until the end of the ICE candidates gathering process. */ - ms_message("Defer ringing to gather ICE candidates"); - return; - } -#ifdef BUILD_UPNP - if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) && (call->upnp_session != NULL)) { - /* Defer ringing until the end of the ICE candidates gathering process. */ - ms_message("Defer ringing to gather uPnP candidates"); - return; - } -#endif //BUILD_UPNP - - linphone_core_notify_incoming_call(lc,call); + LinphoneCall *call = linphone_call_new_incoming(lc, fromAddr, toAddr, h); + linphone_address_unref(fromAddr); + linphone_address_unref(toAddr); + L_GET_PRIVATE_FROM_C_OBJECT(call)->startIncomingNotification(); } -static void call_rejected(SalOp *h){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(h)); +static void call_rejected(SalCallOp *h){ + LinphoneCore *lc = reinterpret_cast(h->getSal()->getUserPointer()); LinphoneErrorInfo *ei = linphone_error_info_new(); linphone_error_info_from_sal_op(ei, h); - linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_new(sal_op_get_from(h)), linphone_address_new(sal_op_get_to(h)), ei); + linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_new(h->getFrom().c_str()), linphone_address_new(h->getTo().c_str()), ei); } -static void try_early_media_forking(LinphoneCall *call, SalMediaDescription *md){ - SalMediaDescription *cur_md=call->resultdesc; - 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;istreams[i])) continue; - ref_stream=&cur_md->streams[i]; - new_stream=&md->streams[i]; - if (ref_stream->type==new_stream->type && ref_stream->payloads && new_stream->payloads){ - PayloadType *refpt, *newpt; - refpt=(PayloadType*)ref_stream->payloads->data; - newpt=(PayloadType*)new_stream->payloads->data; - if (strcmp(refpt->mime_type,newpt->mime_type)==0 && refpt->clock_rate==newpt->clock_rate - && payload_type_get_number(refpt)==payload_type_get_number(newpt)){ - MediaStream *ms=NULL; - if (ref_stream->type==SalAudio){ - ms=(MediaStream*)call->audiostream; - }else if (ref_stream->type==SalVideo){ - ms=(MediaStream*)call->videostream; - } - if (ms){ - RtpSession *session=ms->sessions.rtp_session; - const char *rtp_addr=new_stream->rtp_addr[0]!='\0' ? new_stream->rtp_addr : md->addr; - const char *rtcp_addr=new_stream->rtcp_addr[0]!='\0' ? new_stream->rtcp_addr : md->addr; - if (ms_is_multicast(rtp_addr)) - ms_message("Multicast addr [%s/%i] does not need auxiliary rtp's destination for call [%p]", - rtp_addr,new_stream->rtp_port,call); - else - rtp_session_add_aux_remote_addr_full(session,rtp_addr,new_stream->rtp_port,rtcp_addr,new_stream->rtcp_port); - } - } - } - } -} - -static void start_remote_ring(LinphoneCore *lc, LinphoneCall *call) { - if (lc->sound_conf.play_sndcard!=NULL){ - MSSndCard *ringcard=lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; - if (call->localdesc->streams[0].max_rate>0) ms_snd_card_set_preferred_sample_rate(ringcard, call->localdesc->streams[0].max_rate); - /*we release sound before playing ringback tone*/ - if (call->audiostream) - audio_stream_unprepare_sound(call->audiostream); - if( lc->sound_conf.remote_ring ){ - ms_snd_card_set_stream_type(ringcard, MS_SND_CARD_STREAM_VOICE); - lc->ringstream=ring_start(lc->factory, lc->sound_conf.remote_ring,2000,ringcard); - } - } -} - -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); - - 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); - if (call->state==LinphoneCallOutgoingEarlyMedia){ - /*already doing early media */ - return; - } - if (lc->ringstream == NULL) start_remote_ring(lc, call); - ms_message("Remote ringing..."); - linphone_core_notify_display_status(lc,_("Remote ringing...")); - linphone_call_set_state(call,LinphoneCallOutgoingRinging,"Remote ringing"); - }else{ - SalMediaDescription *rmd = sal_call_get_remote_media_description(call->op); - /*initialize the remote call params by invoking linphone_call_get_remote_params(). This is useful as the SDP may not be present in the 200Ok*/ - linphone_call_get_remote_params(call); - /*accept early media */ - if ((call->audiostream && audio_stream_started(call->audiostream)) -#ifdef VIDEO_ENABLED - || (call->videostream && video_stream_started(call->videostream)) -#endif - ) { - /*streams already started */ - try_early_media_forking(call,md); - #ifdef VIDEO_ENABLED - if (call->videostream){ - /*just request for iframe*/ - video_stream_send_vfu(call->videostream); - } - #endif - return; - } - - 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..."); - if (call->ice_session != NULL && rmd) { - linphone_call_update_ice_from_remote_media_description(call, rmd, !sal_call_is_offerer(call->op)); - } - linphone_call_update_streams(call, md, call->state); - if ((linphone_call_params_get_audio_direction(linphone_call_get_current_params(call)) == LinphoneMediaDirectionInactive) && call->audiostream) { - if (lc->ringstream != NULL) return; /* Already ringing! */ - start_remote_ring(lc, call); - } - } -} - -static unsigned char start_pending_refer (void *call) { - LinphoneCall *to_refer = static_cast(call); - linphone_core_start_refered_call(to_refer->core, to_refer, NULL); - return 0; -} - -static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *op){ - SalMediaDescription *md, *rmd; - LinphoneCallState next_state = LinphoneCallIdle; - const char *next_state_str = NULL; - LinphoneTaskList tl; - - switch (call->state){/*immediately notify the connected state, even if errors occur after*/ - case LinphoneCallOutgoingProgress: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - /*immediately notify the connected state*/ - linphone_call_set_state(call,LinphoneCallConnected,"Connected"); - { - char *tmp=linphone_call_get_remote_address_as_string (call); - char *msg=ms_strdup_printf(_("Call answered by %s"),tmp); - linphone_core_notify_display_status(lc,msg); - ms_free(tmp); - ms_free(msg); - } - break; - default: - break; - } - - linphone_task_list_init(&tl); - rmd=sal_call_get_remote_media_description(op); - /*set privacy*/ - call->current_params->privacy=(LinphonePrivacyMask)sal_op_get_privacy(call->op); - /*reset the internal call update flag, so it doesn't risk to be copied and used in further re-INVITEs*/ - if (call->params->internal_call_update) - call->params->internal_call_update = FALSE; - - -#ifdef BUILD_UPNP - if (call->upnp_session != NULL && rmd) { - linphone_call_update_upnp_from_remote_media_description(call, rmd); - } -#endif //BUILD_UPNP - - md=sal_call_get_final_media_description(op); - if (md == NULL && call->prevstate == LinphoneCallOutgoingEarlyMedia && call->resultdesc != NULL){ - ms_message("Using early media SDP since none was received with the 200 OK"); - md = call->resultdesc; - } - if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ - md = NULL; - } - if (md){ /*there is a valid SDP in the response, either offer or answer, and we're able to start/update the streams*/ - - /* Handle remote ICE attributes if any. */ - if (call->ice_session != NULL && rmd) { - linphone_call_update_ice_from_remote_media_description(call, rmd, !sal_call_is_offerer(op)); - } - - switch (call->state){ - case LinphoneCallResuming: - linphone_core_notify_display_status(lc,_("Call resumed.")); - BCTBX_NO_BREAK; /*intentionally no break*/ - case LinphoneCallConnected: - if (call->referer) linphone_core_notify_refer_state(lc,call->referer,call); - BCTBX_NO_BREAK; /*intentionally no break*/ - case LinphoneCallUpdating: - case LinphoneCallUpdatedByRemote: - if (!sal_media_description_has_dir(call->localdesc, SalStreamInactive) && - (sal_media_description_has_dir(md,SalStreamRecvOnly) || - sal_media_description_has_dir(md,SalStreamInactive))){ - next_state = LinphoneCallPausedByRemote; - next_state_str = "Call paused by remote"; - }else{ - if (!call->params->in_conference) - lc->current_call=call; - next_state = LinphoneCallStreamsRunning; - next_state_str = "Streams running"; - } - break; - case LinphoneCallEarlyUpdating: - next_state_str = "Early update accepted"; - next_state = call->prevstate; - break; - case LinphoneCallPausing: - /*when we entered the pausing state, we always reach the paused state whatever the content of the remote SDP is. - Our streams are all send-only (with music), soundcard and camera are never used*/ - next_state = LinphoneCallPaused; - next_state_str = "Call paused"; - if (call->refer_pending) - linphone_task_list_add(&tl, start_pending_refer, call); - break; - default: - ms_error("call_accepted(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state)); - break; - } - - if (next_state != LinphoneCallIdle){ - linphone_call_update_remote_session_id_and_ver(call); - linphone_call_update_ice_state_in_call_stats(call); - linphone_call_update_streams(call, md, next_state); - linphone_call_fix_call_parameters(call, rmd); - linphone_call_set_state(call, next_state, next_state_str); - }else{ - ms_error("BUG: next_state is not set in call_accepted(), current state is %s", linphone_call_state_to_string(call->state)); - } - }else{ /*invalid or no SDP*/ - switch (call->prevstate){ - /*send a bye only in case of early states*/ - case LinphoneCallOutgoingInit: - case LinphoneCallOutgoingProgress: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallIncomingReceived: - case LinphoneCallIncomingEarlyMedia: - ms_error("Incompatible SDP answer received, need to abort the call"); - linphone_call_abort(call, _("Incompatible, check codecs or security settings...")); - break; - /*otherwise we are able to resume previous state*/ - default: - ms_error("Incompatible SDP answer received"); - switch(call->state) { - case LinphoneCallPausedByRemote: - break; - case LinphoneCallPaused: - break; - case LinphoneCallStreamsRunning: - break; - default: - ms_message("Incompatible SDP answer received, restoring previous state [%s]",linphone_call_state_to_string(call->prevstate)); - linphone_call_set_state(call,call->prevstate,_("Incompatible media parameters.")); - break; - } - break; - } - } - linphone_task_list_run(&tl); - linphone_task_list_free(&tl); +static void call_ringing(SalOp *h) { + LinphonePrivate::CallSession *session = reinterpret_cast(h->getUserPointer()); + if (!session) return; + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->remoteRinging(); } /* @@ -663,452 +233,90 @@ static void process_call_accepted(LinphoneCore *lc, LinphoneCall *call, SalOp *o * - when the call is accepted * - when a request is accepted (pause, resume) */ -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); - - if (call == NULL){ - ms_warning("call_accepted: call does no longer exist."); - return ; - } - process_call_accepted(lc, call, op); -} - -static void call_resumed(LinphoneCore *lc, LinphoneCall *call){ - linphone_core_notify_display_status(lc,_("We have been resumed.")); - _linphone_call_accept_update(call,NULL,LinphoneCallStreamsRunning,"Connected (streams running)"); -} - -static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){ - LinphoneCallParams *params; - - /* we are being paused */ - linphone_core_notify_display_status(lc,_("We are paused by other party.")); - params = linphone_call_params_copy(call->params); - if (lp_config_get_int(lc->config, "sip", "inactive_video_on_pause", 0)) { - linphone_call_params_set_video_direction(params, LinphoneMediaDirectionInactive); - } - _linphone_call_accept_update(call,params,LinphoneCallPausedByRemote,"Call paused by remote"); - linphone_call_params_unref(params); -} - -static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){ - linphone_core_notify_display_status(lc,_("Call is updated by remote.")); - linphone_call_set_state(call, LinphoneCallUpdatedByRemote,"Call updated by remote"); - - if (call->ice_session && check_ice_reinvite_needs_defered_response(call)){ - call->defer_update = TRUE; - ms_message("LinphoneCall [%p]: Ice reinvite received, but one or more check list are not completed. Response will be sent later, once ICE has completed.", call); - call->incoming_ice_reinvite_pending = TRUE; - } - - if (call->defer_update == FALSE){ - if (call->state == LinphoneCallUpdatedByRemote){ - linphone_call_accept_update(call, NULL); - }else{ - /*otherwise it means that the app responded by linphone_core_accept_call_update - * within the callback, so job is already done.*/ - } - }else{ - if (call->state == LinphoneCallUpdatedByRemote){ - ms_message("LinphoneCall [%p]: UpdatedByRemoted was signaled but defered. LinphoneCore expects the application to call " - "linphone_core_accept_call_update() later.", call); - } +static void call_accepted(SalOp *op) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("call_accepted: CallSession no longer exists"); + return; } + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->accepted(); } /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ -static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t is_update){ - SalErrorInfo sei; - SalMediaDescription *rmd=sal_call_get_remote_media_description(op); - - memset(&sei, 0, sizeof(sei)); - call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE); - - switch(call->state){ - case LinphoneCallPausedByRemote: - if (sal_media_description_has_dir(rmd,SalStreamSendRecv) || sal_media_description_has_dir(rmd,SalStreamRecvOnly)){ - call_resumed(lc,call); - }else{ - call_updated_by_remote(lc, call); - } - break; - /*SIP UPDATE CASE*/ - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallIncomingEarlyMedia: - if (is_update) { - linphone_call_set_state(call, LinphoneCallEarlyUpdatedByRemote, "EarlyUpdatedByRemote"); - _linphone_call_accept_update(call,NULL,call->prevstate,linphone_call_state_to_string(call->prevstate)); - } - break; - case LinphoneCallStreamsRunning: - case LinphoneCallConnected: - case LinphoneCallUpdatedByRemote: // Can happen on UAC connectivity loss - 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); - } - break; - case LinphoneCallPaused: - /*we'll remain in pause state but accept the offer anyway according to default parameters*/ - _linphone_call_accept_update(call,NULL,call->state,linphone_call_state_to_string(call->state)); - break; - case LinphoneCallUpdating: - case LinphoneCallPausing: - case LinphoneCallResuming: - sal_error_info_set(&sei,SalReasonInternalError, "SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(call->op, &sei,NULL); - BCTBX_NO_BREAK; /*no break*/ - case LinphoneCallIdle: - case LinphoneCallOutgoingInit: - case LinphoneCallEnd: - case LinphoneCallIncomingReceived: - case LinphoneCallOutgoingProgress: - case LinphoneCallRefered: - case LinphoneCallError: - case LinphoneCallReleased: - case LinphoneCallEarlyUpdatedByRemote: - case LinphoneCallEarlyUpdating: - ms_warning("Receiving reINVITE or UPDATE while in state [%s], should not happen.",linphone_call_state_to_string(call->state)); - break; - } - sal_error_info_reset(&sei); -} - -/* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ -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); - SalErrorInfo sei; - - if (!call) { - ms_error("call_updating(): call doesn't exist anymore"); - return ; - } - memset(&sei, 0, sizeof(sei)); - linphone_call_fix_call_parameters(call, rmd); - if (call->state!=LinphoneCallPaused){ - /*Refresh the local description, but in paused state, we don't change anything.*/ - if (rmd == NULL && lp_config_get_int(call->core->config,"sip","sdp_200_ack_follow_video_policy",0)) { - LinphoneCallParams *p=linphone_core_create_call_params(lc, NULL); - ms_message("Applying default policy for offering SDP on call [%p]",call); - _linphone_call_set_new_params(call, p); - linphone_call_params_unref(p); - } - linphone_call_make_local_media_description(call); - sal_call_set_local_media_description(call->op,call->localdesc); - } - if (rmd == NULL){ - /* case of a reINVITE or UPDATE without SDP */ - call->expect_media_in_ack = TRUE; - sal_call_accept(op); /*respond with an offer*/ - /*don't do anything else in this case, wait for the ACK to receive to notify the app*/ - }else { - SalMediaDescription *md; - SalMediaDescription *prev_result_desc=call->resultdesc; - - call->expect_media_in_ack = FALSE; - - md=sal_call_get_final_media_description(call->op); - if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ - sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(call->op, &sei,NULL); - sal_error_info_reset(&sei); - return; - } - if (is_update && prev_result_desc && md){ - int diff=sal_media_description_equals(prev_result_desc,md); - if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ - ms_warning("Cannot accept this update, it is changing parameters that require user approval"); - sal_error_info_set(&sei,SalReasonUnknown, "SIP", 504, "Cannot change the session parameters without prompting the user", NULL); - sal_call_decline_with_error_info(call->op, &sei,NULL); - sal_error_info_reset(&sei); - return; - } - } - call_updated(lc, call, op, is_update); - } -} - - -static void call_ack_received(SalOp *op, SalCustomHeader *ack){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - - if (call == NULL){ - ms_warning("call_ack(): no call for which an ack is expected"); +static void call_updating(SalOp *op, bool_t is_update) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("call_updating: CallSession no longer exists"); return; } - linphone_call_notify_ack_processing(call, reinterpret_cast(ack), TRUE); - if (call->expect_media_in_ack){ - switch(call->state){ - case LinphoneCallStreamsRunning: - case LinphoneCallPausedByRemote: - linphone_call_set_state(call, LinphoneCallUpdatedByRemote, "UpdatedByRemote"); - break; - default: - break; - } - process_call_accepted(lc, call, op); - } + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->updating(!!is_update); } -static void call_ack_being_sent(SalOp *op, SalCustomHeader *ack){ - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - - if (call == NULL){ - ms_warning("call_ack(): no call for which an ack is supposed to be sent"); +static void call_ack_received(SalOp *op, SalCustomHeader *ack) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("call_ack_received(): no CallSession for which an ack is expected"); return; } - linphone_call_notify_ack_processing(call, reinterpret_cast(ack), FALSE); + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->ackReceived(reinterpret_cast(ack)); } -static void call_terminated(SalOp *op, const char *from){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - if (call==NULL) return; - - switch(linphone_call_get_state(call)){ - case LinphoneCallEnd: - case LinphoneCallError: - ms_warning("call_terminated: already terminated, ignoring."); - return; - break; - case LinphoneCallIncomingReceived: - case LinphoneCallIncomingEarlyMedia: - if(!sal_op_get_reason_error_info(op)->protocol || strcmp(sal_op_get_reason_error_info(op)->protocol, "") == 0) { - linphone_error_info_set(call->ei,NULL, LinphoneReasonNotAnswered, 0, "Incoming call cancelled", NULL); - call->non_op_error = TRUE; - } - break; - default: - break; +static void call_ack_being_sent(SalOp *op, SalCustomHeader *ack) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("call_ack_being_sent(): no CallSession for which an ack is supposed to be sent"); + return; } - ms_message("Current call terminated..."); - if (call->refer_pending){ - linphone_core_start_refered_call(lc,call,NULL); - } - //we stop the call only if we have this current call or if we are in call - if ((bctbx_list_size(lc->calls) == 1) || linphone_core_in_call(lc)) { - linphone_core_stop_ringing(lc); - } - linphone_call_stop_media_streams(call); - linphone_core_notify_show_interface(lc); - linphone_core_notify_display_status(lc,_("Call terminated.")); - -#ifdef BUILD_UPNP - linphone_call_delete_upnp_session(call); -#endif //BUILD_UPNP - - linphone_call_set_state(call, LinphoneCallEnd,"Call ended"); + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->ackBeingSent(reinterpret_cast(ack)); } -static int resume_call_after_failed_transfer (void *call, unsigned int) { - LinphoneCall *to_resume = static_cast(call); - if (to_resume->was_automatically_paused && to_resume->state==LinphoneCallPausing) - return BELLE_SIP_CONTINUE; /*was still in pausing state*/ - - if (to_resume->was_automatically_paused && to_resume->state==LinphoneCallPaused){ - if (sal_op_is_idle(to_resume->op)){ - linphone_call_resume(to_resume); - }else { - ms_message("resume_call_after_failed_transfer(), salop was busy"); - return BELLE_SIP_CONTINUE; - } - } - linphone_call_unref(to_resume); - return BELLE_SIP_STOP; +static void call_terminated(SalOp *op, const char *from) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) + return; + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->terminated(); } -static void call_failure(SalOp *op){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - const SalErrorInfo *ei=sal_op_get_error_info(op); - const char *msg486=_("User is busy."); - const char *msg480=_("User is temporarily unavailable."); - /*const char *retrymsg=_("%s. Retry after %i minute(s).");*/ - const char *msg600=_("User does not want to be disturbed."); - const char *msg603=_("Call declined."); - const char *msg=ei->full_string; - LinphoneCall *referer; - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - bool_t stop_ringing = TRUE; - bctbx_list_t *calls = lc->calls; - - if (call==NULL){ - ms_warning("Call faillure reported on already terminated call."); - return ; - } - - referer=call->referer; - - linphone_core_notify_show_interface(lc); - switch(ei->reason){ - case SalReasonNone: - break; - case SalReasonRequestTimeout: - msg=_("Request timeout."); - linphone_core_notify_display_status(lc,msg); - break; - case SalReasonDeclined: - msg=msg603; - linphone_core_notify_display_status(lc,msg603); - break; - case SalReasonBusy: - msg=msg486; - linphone_core_notify_display_status(lc,msg486); - break; - case SalReasonRedirect: - { - linphone_call_stop_media_streams(call); - if ( call->state==LinphoneCallOutgoingInit - || call->state==LinphoneCallOutgoingProgress - || call->state==LinphoneCallOutgoingRinging /*push case*/ - || call->state==LinphoneCallOutgoingEarlyMedia){ - LinphoneAddress* redirection_to = (LinphoneAddress*)sal_op_get_remote_contact_address(call->op); - if( redirection_to ){ - char* url = linphone_address_as_string(redirection_to); - ms_warning("Redirecting call [%p] to %s",call, url); - ms_free(url); - if( call->log->to != NULL ) { - linphone_address_unref(call->log->to); - } - call->log->to = linphone_address_ref(redirection_to); - linphone_call_restart_invite(call); - return; - } - } - msg=_("Redirected"); - linphone_core_notify_display_status(lc,msg); - } - break; - case SalReasonTemporarilyUnavailable: - msg=msg480; - linphone_core_notify_display_status(lc,msg480); - break; - case SalReasonNotFound: - linphone_core_notify_display_status(lc,msg); - break; - case SalReasonDoNotDisturb: - msg=msg600; - linphone_core_notify_display_status(lc,msg600); - break; - case SalReasonUnsupportedContent: /*state == LinphoneCallOutgoingInit) - || (call->state == LinphoneCallOutgoingProgress) - || (call->state == LinphoneCallOutgoingRinging) /* Push notification case */ - || (call->state == LinphoneCallOutgoingEarlyMedia)) { - int i; - for (i = 0; i < call->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 (i == 0) ms_message("Retrying call [%p] with SAVP", call); - call->params->avpf_enabled = FALSE; - linphone_call_restart_invite(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; - memset(call->localdesc->streams[i].crypto, 0, sizeof(call->localdesc->streams[i].crypto)); - linphone_call_restart_invite(call); - return; - } - } else if (call->params->avpf_enabled == TRUE) { - if (i == 0) ms_message("Retrying call [%p] with AVP", call); - call->params->avpf_enabled = FALSE; - linphone_call_restart_invite(call); - return; - } - } - } - msg=_("Incompatible media parameters."); - linphone_core_notify_display_status(lc,msg); - break; - default: - linphone_core_notify_display_status(lc,_("Call failed.")); - } - - /*some call errors are not fatal*/ - switch (call->state) { - case LinphoneCallUpdating: - case LinphoneCallPausing: - case LinphoneCallResuming: - if (ei->reason != SalReasonNoMatch){ - ms_message("Call error on state [%s], restoring previous state",linphone_call_state_to_string(call->prevstate)); - linphone_call_set_state(call, call->prevstate,ei->full_string); - return; - } - default: - break; /*nothing to do*/ - } - - /* Stop ringing */ - bool_t ring_during_early_media = linphone_core_get_ring_during_incoming_early_media(lc); - while(calls) { - if (((LinphoneCall *)calls->data)->state == LinphoneCallIncomingReceived || (ring_during_early_media && ((LinphoneCall *)calls->data)->state == LinphoneCallIncomingEarlyMedia)) { - stop_ringing = FALSE; - break; - } - calls = calls->next; - } - if(stop_ringing) { - linphone_core_stop_ringing(lc); - } - linphone_call_stop_media_streams(call); - -#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."); - }else{ - if (linphone_call_state_is_early(call->state)){ - linphone_call_set_state(call,LinphoneCallError,ei->full_string); - }else{ - linphone_call_set_state(call, LinphoneCallEnd, ei->full_string); - } - } - 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); - /*schedule automatic resume of the call. This must be done only after the notifications are completed due to dialog serialization of requests.*/ - linphone_core_queue_task(lc, resume_call_after_failed_transfer,linphone_call_ref(referer),"Automatic call resuming after failed transfer"); +static void call_failure(SalOp *op) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("Failure reported on already terminated CallSession"); + return; } + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->failure(); } -static void call_released(SalOp *op){ - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - if (call!=NULL){ - linphone_call_set_state(call,LinphoneCallReleased,"Call released"); - }else{ - /*we can arrive here when the core manages call at Sal level without creating a LinphoneCall object. Typicially: - * - when declining an incoming call with busy because maximum number of calls is reached. - */ +static void call_released(SalOp *op) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + /* We can get here when the core manages call at Sal level without creating a Call object. Typicially, + * when declining an incoming call with busy because maximum number of calls is reached. */ + return; } + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->setState(LinphonePrivate::CallSession::State::Released, "Call released"); } static void call_cancel_done(SalOp *op) { - LinphoneCall *call = (LinphoneCall *)sal_op_get_user_pointer(op); - if (call->reinvite_on_cancel_response_requested == TRUE) { - call->reinvite_on_cancel_response_requested = FALSE; - linphone_call_reinvite_to_recover_from_connection_loss(call); + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("Cancel done reported on already terminated CallSession"); + return; } + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->cancelDone(); } static void auth_failure(SalOp *op, SalAuthInfo* info) { - LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCore *lc = reinterpret_cast(op->getSal()->getUserPointer()); LinphoneAuthInfo *ai = NULL; if (info != NULL) { @@ -1127,29 +335,18 @@ static void auth_failure(SalOp *op, SalAuthInfo* info) { } 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; - + LinphoneProxyConfig *cfg=(LinphoneProxyConfig *)op->getUserPointer(); 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 (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)); - linphone_core_notify_display_status(lc,msg); - ms_free(msg); - } - } static void register_failure(SalOp *op){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)sal_op_get_user_pointer(op); - const SalErrorInfo *ei=sal_op_get_error_info(op); + LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)op->getUserPointer(); + const SalErrorInfo *ei=op->getErrorInfo(); const char *details=ei->full_string; if (cfg==NULL){ @@ -1157,17 +354,11 @@ static void register_failure(SalOp *op){ return ; } if (details==NULL) - details=_("no response timeout"); - - { - char *msg=ortp_strdup_printf(_("Registration on %s failed: %s"),sal_op_get_proxy(op), details); - linphone_core_notify_display_status(lc,msg); - ms_free(msg); - } + details="no response timeout"; if ((ei->reason == SalReasonServiceUnavailable || ei->reason == SalReasonIOError) && linphone_proxy_config_get_state(cfg) == LinphoneRegistrationOk) { - linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,_("Service unavailable, retrying")); + linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress,"Service unavailable, retrying"); } else { linphone_proxy_config_set_state(cfg,LinphoneRegistrationFailed,details); } @@ -1179,62 +370,65 @@ static void register_failure(SalOp *op){ } } -static void vfu_request(SalOp *op){ -#ifdef VIDEO_ENABLED - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer (op); - if (call==NULL){ - ms_warning("VFU request but no call !"); - return ; +static void vfu_request(SalOp *op) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) + return; + auto sessionRef = session->getSharedFromThis(); + auto mediaSessionRef = dynamic_pointer_cast(sessionRef); + if (!mediaSessionRef) { + ms_warning("VFU request but no MediaSession!"); + return; } - if (call->videostream) - video_stream_send_vfu(call->videostream); -#endif + L_GET_PRIVATE(mediaSessionRef)->sendVfu(); } -static void dtmf_received(SalOp *op, char dtmf){ - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - if (!call) return; - linphone_call_notify_dtmf_received(call, dtmf); +static void dtmf_received(SalOp *op, char dtmf) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) + return; + auto sessionRef = session->getSharedFromThis(); + auto mediaSessionRef = dynamic_pointer_cast(sessionRef); + if (!mediaSessionRef) { + ms_warning("DTMF received but no MediaSession!"); + return; + } + L_GET_PRIVATE(mediaSessionRef)->dtmfReceived(dtmf); } -static void refer_received(Sal *sal, SalOp *op, const char *referto){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - LinphoneAddress *refer_to_addr = linphone_address_new(referto); - char method[20] = ""; - - if(refer_to_addr) { - const char *tmp = linphone_address_get_method_param(refer_to_addr); - if(tmp) strncpy(method, tmp, sizeof(method)); - linphone_address_unref(refer_to_addr); - } - if (call && (strlen(method) == 0 || strcmp(method, "INVITE") == 0)) { - if (call->refer_to!=NULL){ - ms_free(call->refer_to); - } - call->refer_to=ms_strdup(referto); - call->refer_pending=TRUE; - linphone_call_set_state(call,LinphoneCallRefered,"Refered"); - { - char *msg=ms_strdup_printf(_("We are transferred to %s"),referto); - linphone_core_notify_display_status(lc,msg); - ms_free(msg); - } - if (call->refer_pending) linphone_core_start_refered_call(lc,call,NULL); - }else { - linphone_core_notify_refer_received(lc,referto); +static void call_refer_received(SalOp *op, const SalAddress *referTo) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + char *addrStr = sal_address_as_string_uri_only(referTo); + Address referToAddr(addrStr); + string method; + if (referToAddr.isValid()) + method = referToAddr.getMethodParam(); + if (session && (method.empty() || (method == "INVITE"))) { + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->referred(referToAddr); + } else { + LinphoneCore *lc = reinterpret_cast(op->getSal()->getUserPointer()); + linphone_core_notify_refer_received(lc, addrStr); } + bctbx_free(addrStr); } static void message_received(SalOp *op, const SalMessage *msg){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + LinphoneCore *lc=(LinphoneCore *)op->getSal()->getUserPointer(); + + if (linphone_core_get_global_state(lc) != LinphoneGlobalOn) { + static_cast(op)->reply(SalReasonServiceUnavailable); + return; + } + + LinphoneCall *call=(LinphoneCall*)op->getUserPointer(); LinphoneReason reason = lc->chat_deny_code; if (reason == LinphoneReasonNone) { linphone_core_message_received(lc, op, msg); } - sal_message_reply(op, linphone_reason_to_sal(reason)); - if (!call) sal_op_release(op); + auto messageOp = dynamic_cast(op); + messageOp->reply(linphone_reason_to_sal(reason)); + if (!call) op->release(); } static void parse_presence_requested(SalOp *op, const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result) { @@ -1253,33 +447,32 @@ static void convert_presence_to_xml_requested(SalOp *op, SalPresenceModel *prese } static void notify_presence(SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); + LinphoneCore *lc=(LinphoneCore *)op->getSal()->getUserPointer(); linphone_notify_recv(lc,op,ss,model); } -static void subscribe_presence_received(SalOp *op, const char *from){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void subscribe_presence_received(SalPresenceOp *op, const char *from){ + LinphoneCore *lc=(LinphoneCore *)op->getSal()->getUserPointer(); + if (linphone_core_get_global_state(lc) != LinphoneGlobalOn) { + op->decline(SalReasonServiceUnavailable); + return; + } linphone_subscription_new(lc,op,from); } -static void subscribe_presence_closed(SalOp *op, const char *from){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void subscribe_presence_closed(SalPresenceOp *op, const char *from){ + LinphoneCore *lc=(LinphoneCore *)op->getSal()->getUserPointer(); linphone_subscription_closed(lc,op); } -static void ping_reply(SalOp *op){ - LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op); - ms_message("ping reply !"); - if (call){ - if (call->state==LinphoneCallOutgoingInit){ - call->ping_replied=TRUE; - linphone_call_proceed_with_invite_if_ready(call, NULL); - } - } - else - { - ms_warning("ping reply without call attached..."); +static void ping_reply(SalOp *op) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("Ping reply without CallSession attached..."); + return; } + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->pingReply(); } static bool_t fill_auth_info_with_client_certificate(LinphoneCore *lc, SalAuthInfo* sai) { @@ -1317,6 +510,19 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) { } if (ai) { if (sai->mode == SalAuthModeHttpDigest) { + /* + * Compare algorithm of server(sai) with algorithm of client(ai), if they are not correspondant, + * exit. The default algorithm is MD5 if it's NULL. + */ + if (sai->algorithm && ai->algorithm) { + if (strcasecmp(ai->algorithm, sai->algorithm)) + return TRUE; + } else if ( + (ai->algorithm && strcasecmp(ai->algorithm, "MD5")) || + (sai->algorithm && strcasecmp(sai->algorithm, "MD5")) + ) + return TRUE; + sai->userid = ms_strdup(ai->userid ? ai->userid : ai->username); sai->password = ai->passwd?ms_strdup(ai->passwd) : NULL; sai->ha1 = ai->ha1 ? ms_strdup(ai->ha1) : NULL; @@ -1346,7 +552,7 @@ static bool_t fill_auth_info(LinphoneCore *lc, SalAuthInfo* sai) { } } static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) { - LinphoneCore *lc = (LinphoneCore *)sal_get_user_pointer(sal); + LinphoneCore *lc = (LinphoneCore *)sal->getUserPointer(); if (fill_auth_info(lc,sai)) { return TRUE; } else { @@ -1363,31 +569,29 @@ static bool_t auth_requested(Sal* sal, SalAuthInfo* sai) { } } -static void notify_refer(SalOp *op, SalReferStatus status){ - LinphoneCall *call=(LinphoneCall*) sal_op_get_user_pointer(op); - LinphoneCallState cstate; - if (call==NULL) { - ms_warning("Receiving notify_refer for unknown call."); - return ; +static void notify_refer(SalOp *op, SalReferStatus status) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) { + ms_warning("Receiving notify_refer for unknown CallSession"); + return; } - switch(status){ + auto sessionRef = session->getSharedFromThis(); + LinphonePrivate::CallSession::State cstate; + switch (status) { case SalReferTrying: - cstate=LinphoneCallOutgoingProgress; - break; + cstate = LinphonePrivate::CallSession::State::OutgoingProgress; + break; case SalReferSuccess: - cstate=LinphoneCallConnected; - break; + cstate = LinphonePrivate::CallSession::State::Connected; + break; case SalReferFailed: - cstate=LinphoneCallError; - break; default: - cstate=LinphoneCallError; - } - linphone_call_set_transfer_state(call, cstate); - if (cstate==LinphoneCallConnected){ - /*automatically terminate the call as the transfer is complete.*/ - linphone_call_terminate(call); + cstate = LinphonePrivate::CallSession::State::Error; + break; } + L_GET_PRIVATE(sessionRef)->setTransferState(cstate); + if (cstate == LinphonePrivate::CallSession::State::Connected) + sessionRef->terminate(); // Automatically terminate the call as the transfer is complete } static LinphoneChatMessageState chatStatusSal2Linphone(SalMessageDeliveryStatus status){ @@ -1402,29 +606,32 @@ static LinphoneChatMessageState chatStatusSal2Linphone(SalMessageDeliveryStatus return LinphoneChatMessageStateIdle; } -static void message_delivery_update(SalOp *op, SalMessageDeliveryStatus status){ - LinphoneChatMessage *chat_msg=(LinphoneChatMessage* )sal_op_get_user_pointer(op); - - if (chat_msg == NULL) { - // Do not handle delivery status for isComposing messages. +static void message_delivery_update(SalOp *op, SalMessageDeliveryStatus status) { + auto lc = reinterpret_cast(op->getSal()->getUserPointer()); + if (linphone_core_get_global_state(lc) != LinphoneGlobalOn) { + static_cast(op)->reply(SalReasonDeclined); return; } - // check that the message does not belong to an already destroyed chat room - if so, do not invoke callbacks - if (chat_msg->chat_room != NULL) { - linphone_chat_message_update_state(chat_msg, chatStatusSal2Linphone(status)); - } - if (status != SalMessageDeliveryInProgress) { /*only release op if not in progress*/ - linphone_chat_message_destroy(chat_msg); - } + + LinphonePrivate::ChatMessage *msg = reinterpret_cast(op->getUserPointer()); + if (!msg) + return; // Do not handle delivery status for isComposing messages. + + // Check that the message does not belong to an already destroyed chat room - if so, do not invoke callbacks + if (msg->getChatRoom()) + L_GET_PRIVATE(msg)->setState((LinphonePrivate::ChatMessage::State)chatStatusSal2Linphone(status)); } -static void info_received(SalOp *op, SalBodyHandler *body_handler){ - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); - linphone_core_notify_info_message(lc,op,body_handler); +static void info_received(SalOp *op, SalBodyHandler *body_handler) { + LinphonePrivate::CallSession *session = reinterpret_cast(op->getUserPointer()); + if (!session) + return; + auto sessionRef = session->getSharedFromThis(); + L_GET_PRIVATE(sessionRef)->infoReceived(body_handler); } static void subscribe_response(SalOp *op, SalSubscribeStatus status, int will_retry){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->getUserPointer(); if (lev==NULL) return; @@ -1440,16 +647,16 @@ static void subscribe_response(SalOp *op, SalSubscribeStatus status, int will_re } } -static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalBodyHandler *body_handler){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void notify(SalSubscribeOp *op, SalSubscribeStatus st, const char *eventname, SalBodyHandler *body_handler){ + LinphoneEvent *lev=(LinphoneEvent*)op->getUserPointer(); + LinphoneCore *lc=(LinphoneCore *)op->getSal()->getUserPointer(); bool_t out_of_dialog = (lev==NULL); if (out_of_dialog) { /*out of dialog notify */ lev = linphone_event_new_with_out_of_dialog_op(lc,op,LinphoneSubscriptionOutgoing,eventname); } { - LinphoneContent *ct=linphone_content_from_sal_body_handler(body_handler); + LinphoneContent *ct = linphone_content_from_sal_body_handler(body_handler); if (ct) { linphone_core_notify_notify_received(lc,lev,eventname,ct); linphone_content_unref(ct); @@ -1463,28 +670,37 @@ static void notify(SalOp *op, SalSubscribeStatus st, const char *eventname, SalB } } -static void subscribe_received(SalOp *op, const char *eventname, const SalBodyHandler *body_handler){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); - LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); +static void subscribe_received(SalSubscribeOp *op, const char *eventname, const SalBodyHandler *body_handler){ + LinphoneEvent *lev=(LinphoneEvent*)op->getUserPointer(); + LinphoneCore *lc=(LinphoneCore *)op->getSal()->getUserPointer(); + + if (linphone_core_get_global_state(lc) != LinphoneGlobalOn) { + op->decline(SalReasonServiceUnavailable); + return; + } if (lev==NULL) { lev=linphone_event_new_with_op(lc,op,LinphoneSubscriptionIncoming,eventname); linphone_event_set_state(lev,LinphoneSubscriptionIncomingReceived); - }else{ + LinphoneContent *ct = linphone_content_from_sal_body_handler(body_handler); + linphone_core_notify_subscribe_received(lc,lev,eventname,ct); + if (ct) + linphone_content_unref(ct); + } else { /*subscribe refresh, unhandled*/ } } static void incoming_subscribe_closed(SalOp *op){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->getUserPointer(); 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); + LinphoneEvent *lev=(LinphoneEvent*)op->getUserPointer(); + const SalErrorInfo *ei=op->getErrorInfo(); if (lev==NULL) return; if (ei->reason==SalReasonNone){ @@ -1503,7 +719,7 @@ static void on_publish_response(SalOp* op){ static void on_expire(SalOp *op){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->getUserPointer(); if (lev==NULL) return; @@ -1515,25 +731,124 @@ static void on_expire(SalOp *op){ } static void on_notify_response(SalOp *op){ - LinphoneEvent *lev=(LinphoneEvent*)sal_op_get_user_pointer(op); + LinphoneEvent *lev=(LinphoneEvent*)op->getUserPointer(); + if (!lev) + return; - if (lev==NULL) return; - /*this is actually handling out of dialogs notify - for the moment*/ - if (!lev->is_out_of_dialog_op) return; - switch (linphone_event_get_subscription_state(lev)){ - case LinphoneSubscriptionIncomingReceived: - if (sal_op_get_error_info(op)->reason == SalReasonNone){ - linphone_event_set_state(lev, LinphoneSubscriptionTerminated); - }else{ - linphone_event_set_state(lev, LinphoneSubscriptionError); - } - break; - default: - ms_warning("Unhandled on_notify_response() case %s", linphone_subscription_state_to_string(linphone_event_get_subscription_state(lev))); + if (lev->is_out_of_dialog_op) { + switch (linphone_event_get_subscription_state(lev)) { + case LinphoneSubscriptionIncomingReceived: + if (op->getErrorInfo()->reason == SalReasonNone) + linphone_event_set_state(lev, LinphoneSubscriptionTerminated); + else + linphone_event_set_state(lev, LinphoneSubscriptionError); + break; + default: + ms_warning("Unhandled on_notify_response() case %s", + linphone_subscription_state_to_string(linphone_event_get_subscription_state(lev))); + break; + } + } else { + ms_warning("on_notify_response in dialog"); + _linphone_event_notify_notify_response(lev); } } -SalCallbacks linphone_sal_callbacks={ +static void refer_received(SalOp *op, const SalAddress *refer_to){ + if (sal_address_has_param(refer_to, "text")) { + char *refer_uri = sal_address_as_string(refer_to); + LinphonePrivate::Address addr(refer_uri); + bctbx_free(refer_uri); + if (addr.isValid()) { + LinphoneCore *lc = reinterpret_cast(op->getSal()->getUserPointer()); + + if (linphone_core_get_global_state(lc) != LinphoneGlobalOn) { + static_cast(op)->reply(SalReasonDeclined); + return; + } + + if (addr.hasUriParam("method") && (addr.getUriParamValue("method") == "BYE")) { + if (linphone_core_conference_server_enabled(lc)) { + // Removal of a participant at the server side + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom( + ChatRoomId(IdentityAddress(op->getTo()), IdentityAddress(op->getTo())) + ); + if (chatRoom) { + std::shared_ptr participant = chatRoom->findParticipant(IdentityAddress(op->getFrom())); + if (!participant || !participant->isAdmin()) { + static_cast(op)->reply(SalReasonDeclined); + return; + } + participant = chatRoom->findParticipant(addr); + if (participant) + chatRoom->removeParticipant(participant); + static_cast(op)->reply(SalReasonNone); + return; + } + } else { + // The server asks a participant to leave a chat room + LinphoneChatRoom *cr = L_GET_C_BACK_PTR( + L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(ChatRoomId(addr, IdentityAddress(op->getTo()))) + ); + if (cr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->leave(); + static_cast(op)->reply(SalReasonNone); + return; + } + static_cast(op)->reply(SalReasonDeclined); + } + } else { + if (linphone_core_conference_server_enabled(lc)) { + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom( + ChatRoomId(IdentityAddress(op->getTo()), IdentityAddress(op->getTo())) + ); + LinphoneChatRoom *cr = L_GET_C_BACK_PTR(chatRoom); + if (cr) { + Address fromAddr(op->getFrom()); + shared_ptr participant = chatRoom->findParticipant(fromAddr); + if (!participant || !participant->isAdmin()) { + static_cast(op)->reply(SalReasonDeclined); + return; + } + if (addr.hasParam("admin")) { + participant = chatRoom->findParticipant(addr); + if (participant) { + bool value = Utils::stob(addr.getParamValue("admin")); + chatRoom->setParticipantAdminStatus(participant, value); + static_cast(op)->reply(SalReasonNone); + return; + } + } else { + participant = L_GET_PRIVATE(static_pointer_cast(chatRoom))->findFilteredParticipant(addr); + if (!participant) { + list identAddresses; + identAddresses.push_back(addr); + L_GET_PRIVATE(static_pointer_cast(chatRoom))->checkCompatibleParticipants( + IdentityAddress(op->getRemoteContact()), + identAddresses + ); + static_cast(op)->reply(SalReasonNone); + return; + } + } + } + } else { + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom( + ChatRoomId(addr, IdentityAddress(op->getTo())) + ); + if (!chatRoom) + chatRoom = L_GET_PRIVATE_FROM_C_OBJECT(lc)->createClientGroupChatRoom("", addr.asString(), Content(), false); + chatRoom->join(); + static_cast(op)->reply(SalReasonNone); + return; + } + } + } + } + static_cast(op)->reply(SalReasonDeclined); +} + +Sal::Callbacks linphone_sal_callbacks={ call_received, call_rejected, call_ringing, @@ -1545,12 +860,12 @@ SalCallbacks linphone_sal_callbacks={ call_failure, call_released, call_cancel_done, + call_refer_received, auth_failure, register_success, register_failure, vfu_request, dtmf_received, - refer_received, message_received, message_delivery_update, notify_refer, @@ -1568,5 +883,6 @@ SalCallbacks linphone_sal_callbacks={ info_received, on_publish_response, on_expire, - on_notify_response + on_notify_response, + refer_received, }; diff --git a/coreapi/carddav.c b/coreapi/carddav.c index 75dc7afd5..912da2b87 100644 --- a/coreapi/carddav.c +++ b/coreapi/carddav.c @@ -67,7 +67,7 @@ static void linphone_carddav_client_to_server_sync_done(LinphoneCardDavContext * if (!success) { ms_error("[carddav] CardDAV client to server sync failure: %s", msg); } - + if (cdc->sync_done_cb) { cdc->sync_done_cb(cdc, success, msg); } @@ -80,7 +80,7 @@ static void linphone_carddav_server_to_client_sync_done(LinphoneCardDavContext * } else { ms_error("[carddav] CardDAV server to client sync failure: %s", msg); } - + if (cdc->sync_done_cb) { cdc->sync_done_cb(cdc, success, msg); } @@ -118,7 +118,7 @@ static void linphone_carddav_vcards_pulled(LinphoneCardDavContext *cdc, bctbx_li LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(cdc->friend_list->lc->vcard_context, vCard->vcard); LinphoneFriend *lf = NULL; bctbx_list_t *local_friend = NULL; - + if (lvc) { // Compute downloaded vCards' URL and save it (+ eTag) char *vCard_name = strrchr(vCard->url, '/'); @@ -132,7 +132,7 @@ static void linphone_carddav_vcards_pulled(LinphoneCardDavContext *cdc, bctbx_li linphone_vcard_unref(lvc); /*ref is now owned by friend*/ if (lf) { local_friend = bctbx_list_find_custom(friends, (int (*)(const void*, const void*))find_matching_friend, lf); - + if (local_friend) { LinphoneFriend *lf2 = (LinphoneFriend *)local_friend->data; lf->storage_id = lf2->storage_id; @@ -142,7 +142,7 @@ static void linphone_carddav_vcards_pulled(LinphoneCardDavContext *cdc, bctbx_li lf->presence_received = lf2->presence_received; lf->lc = lf2->lc; lf->friend_list = lf2->friend_list; - + if (cdc->contact_updated_cb) { ms_debug("Contact updated: %s", linphone_friend_get_name(lf)); cdc->contact_updated_cb(cdc, lf, lf2); @@ -222,7 +222,7 @@ static void linphone_carddav_vcards_fetched(LinphoneCardDavContext *cdc, bctbx_l bctbx_list_t *friends = cdc->friend_list->friends; bctbx_list_t *friends_to_remove = NULL; bctbx_list_t *temp_list = NULL; - + while (friends) { LinphoneFriend *lf = (LinphoneFriend *)friends->data; if (lf) { @@ -258,7 +258,7 @@ static void linphone_carddav_vcards_fetched(LinphoneCardDavContext *cdc, bctbx_l friends_to_remove = bctbx_list_next(friends_to_remove); } temp_list = bctbx_list_free_with_data(temp_list, (void (*)(void *))linphone_friend_unref); - + linphone_carddav_pull_vcards(cdc, vCards); bctbx_list_free_with_data(vCards, (void (*)(void *))linphone_carddav_response_free); } @@ -338,22 +338,22 @@ static void linphone_carddav_query_free(LinphoneCardDavQuery *query) { if (!query) { return; } - + if (query->http_request_listener) { belle_sip_object_unref(query->http_request_listener); query->http_request_listener = NULL; } - + // Context will be freed later (in sync_done) query->context = NULL; - + if (query->url) { ms_free(query->url); } if (query->body) { ms_free(query->body); } - + ms_free(query); } @@ -378,7 +378,7 @@ static bool_t is_query_client_to_server_sync(LinphoneCardDavQuery *query) { static void process_response_from_carddav_request(void *data, const belle_http_response_event_t *event) { LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)data; - + if (event->response) { int code = belle_http_response_get_status_code(event->response); if (code == 207 || code == 200 || code == 201 || code == 204) { @@ -469,7 +469,7 @@ static void process_auth_requested_from_carddav_request(void *data, belle_sip_au const char *realm = belle_sip_auth_event_get_realm(event); belle_generic_uri_t *uri = belle_generic_uri_parse(query->url); const char *domain = belle_generic_uri_get_host(uri); - + if (cdc->auth_info) { belle_sip_auth_event_set_username(event, cdc->auth_info->username); belle_sip_auth_event_set_passwd(event, cdc->auth_info->passwd); @@ -477,7 +477,7 @@ static void process_auth_requested_from_carddav_request(void *data, belle_sip_au } else { LinphoneCore *lc = cdc->friend_list->lc; const bctbx_list_t *auth_infos = linphone_core_get_auth_info_list(lc); - + ms_debug("Looking for auth info for domain %s and realm %s", domain, realm); while (auth_infos) { LinphoneAuthInfo *auth_info = (LinphoneAuthInfo *)auth_infos->data; @@ -492,7 +492,7 @@ static void process_auth_requested_from_carddav_request(void *data, belle_sip_au } auth_infos = bctbx_list_next(auth_infos); } - + if (!auth_infos) { ms_error("[carddav] Authentication requested during CardDAV request sending, and username/password weren't provided"); if (is_query_client_to_server_sync(query)) { @@ -523,7 +523,7 @@ static void linphone_carddav_send_query(LinphoneCardDavQuery *query) { return; } req = belle_http_request_create(query->method, uri, belle_sip_header_content_type_create("application", "xml; charset=utf-8"), NULL); - + if (!req) { if (cdc && cdc->sync_done_cb) { cdc->sync_done_cb(cdc, FALSE, "Could not create belle_http_request_t"); @@ -533,7 +533,7 @@ static void linphone_carddav_send_query(LinphoneCardDavQuery *query) { linphone_carddav_query_free(query); return; } - + ua = ms_strdup_printf("%s/%s", linphone_core_get_user_agent(cdc->friend_list->lc), linphone_core_get_version()); belle_sip_message_add_header((belle_sip_message_t *)req, belle_sip_header_create("User-Agent", ua)); ms_free(ua); @@ -544,12 +544,12 @@ static void linphone_carddav_send_query(LinphoneCardDavQuery *query) { } else if (strcmp(query->method, "PUT")) { belle_sip_message_add_header((belle_sip_message_t *)req, belle_sip_header_create("If-None-Match", "*")); } - + if (query->body) { bh = belle_sip_memory_body_handler_new_copy_from_buffer(query->body, strlen(query->body), NULL, NULL); belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), bh ? BELLE_SIP_BODY_HANDLER(bh) : NULL); } - + cbs.process_response = process_response_from_carddav_request; cbs.process_io_error = process_io_error_from_carddav_request; cbs.process_auth_requested = process_auth_requested_from_carddav_request; @@ -573,7 +573,7 @@ static char* generate_url_from_server_address_and_uid(const char *server_url) { char *result = NULL; if (server_url) { char *uuid = reinterpret_cast(ms_malloc(64)); - if (sal_generate_uuid(uuid, 64) == 0) { + if (LinphonePrivate::Sal::generateUuid(uuid, 64) == 0) { char *url = reinterpret_cast(ms_malloc(300)); snprintf(url, 300, "%s/linphone-%s.vcf", server_url, uuid); ms_debug("Generated url is %s", url); @@ -592,7 +592,7 @@ void linphone_carddav_put_vcard(LinphoneCardDavContext *cdc, LinphoneFriend *lf) if (!linphone_vcard_get_uid(lvc)) { linphone_vcard_generate_unique_id(lvc); } - + if (!linphone_vcard_get_url(lvc)) { char *url = generate_url_from_server_address_and_uid(cdc->friend_list->uri); if (url) { @@ -607,7 +607,7 @@ void linphone_carddav_put_vcard(LinphoneCardDavContext *cdc, LinphoneFriend *lf) return; } } - + query = linphone_carddav_create_put_query(cdc, lvc); query->user_data = linphone_friend_ref(lf); linphone_carddav_send_query(query); @@ -618,11 +618,11 @@ void linphone_carddav_put_vcard(LinphoneCardDavContext *cdc, LinphoneFriend *lf) } else { msg = "Unknown error"; } - + if (msg) { ms_error("[carddav] %s", msg); } - + if (cdc && cdc->sync_done_cb) { cdc->sync_done_cb(cdc, FALSE, msg); } @@ -645,7 +645,7 @@ void linphone_carddav_delete_vcard(LinphoneCardDavContext *cdc, LinphoneFriend * LinphoneVcard *lvc = linphone_friend_get_vcard(lf); if (lvc && linphone_vcard_get_uid(lvc) && linphone_vcard_get_etag(lvc)) { LinphoneCardDavQuery *query = NULL; - + if (!linphone_vcard_get_url(lvc)) { char *url = generate_url_from_server_address_and_uid(cdc->friend_list->uri); if (url) { @@ -660,7 +660,7 @@ void linphone_carddav_delete_vcard(LinphoneCardDavContext *cdc, LinphoneFriend * return; } } - + query = linphone_carddav_create_delete_query(cdc, lvc); linphone_carddav_send_query(query); } else { @@ -672,11 +672,11 @@ void linphone_carddav_delete_vcard(LinphoneCardDavContext *cdc, LinphoneFriend * } else if (!linphone_vcard_get_etag(lvc)) { msg = "LinphoneVcard doesn't have an eTag"; } - + if (msg) { ms_error("[carddav] %s", msg); } - + if (cdc && cdc->sync_done_cb) { cdc->sync_done_cb(cdc, FALSE, msg); } @@ -737,7 +737,7 @@ static LinphoneCardDavQuery* linphone_carddav_create_addressbook_multiget_query( LinphoneCardDavQuery *query = (LinphoneCardDavQuery *)ms_new0(LinphoneCardDavQuery, 1); char *body = (char *)ms_malloc((bctbx_list_size(vcards) + 1) * 300 * sizeof(char)); bctbx_list_t *iterator = vcards; - + query->context = cdc; query->depth = "1"; query->ifmatch = NULL; @@ -758,7 +758,7 @@ static LinphoneCardDavQuery* linphone_carddav_create_addressbook_multiget_query( strcat(body, ""); query->body = ms_strdup(body); ms_free(body); - + return query; } diff --git a/coreapi/chat.c b/coreapi/chat.c index 362a7213e..df42841ee 100644 --- a/coreapi/chat.c +++ b/coreapi/chat.c @@ -22,151 +22,30 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include +#include +#include + +#include + #include "linphone/core.h" #include "private.h" #include "linphone/lpconfig.h" #include "belle-sip/belle-sip.h" #include "ortp/b64.h" #include "linphone/wrapper_utils.h" -#include "bctoolbox/charconv.h" -#include -#include -#include +#include "c-wrapper/c-wrapper.h" +#include "call/call.h" +#include "chat/chat-room/basic-chat-room.h" +#include "chat/chat-room/client-group-chat-room.h" +#include "chat/chat-room/client-group-to-basic-chat-room.h" +#include "chat/chat-room/real-time-text-chat-room-p.h" +#include "chat/chat-room/real-time-text-chat-room.h" +#include "content/content-type.h" +#include "core/core-p.h" -#define COMPOSING_DEFAULT_IDLE_TIMEOUT 15 -#define COMPOSING_DEFAULT_REFRESH_TIMEOUT 60 -#define COMPOSING_DEFAULT_REMOTE_REFRESH_TIMEOUT 120 - -static void linphone_chat_message_release(LinphoneChatMessage *msg); -static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr); -static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr); -static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr); -static void _linphone_chat_message_destroy(LinphoneChatMessage *msg); -static void linphone_chat_room_notify_is_composing(LinphoneChatRoom *cr, const char *text); -static void linphone_chat_room_notify_imdn(LinphoneChatRoom *cr, const char *text); -static void linphone_chat_message_deactivate(LinphoneChatMessage *msg); - -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatMessageCbs); - -BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatMessageCbs, belle_sip_object_t, - NULL, // destroy - NULL, // clone - NULL, // marshal - FALSE); - -LinphoneChatMessageCbs *linphone_chat_message_cbs_new(void) { - return belle_sip_object_new(LinphoneChatMessageCbs); -} - -LinphoneChatMessageCbs *linphone_chat_message_cbs_ref(LinphoneChatMessageCbs *cbs) { - belle_sip_object_ref(cbs); - return cbs; -} - -void linphone_chat_message_cbs_unref(LinphoneChatMessageCbs *cbs) { - belle_sip_object_unref(cbs); -} - -void *linphone_chat_message_cbs_get_user_data(const LinphoneChatMessageCbs *cbs) { - return cbs->user_data; -} - -void linphone_chat_message_cbs_set_user_data(LinphoneChatMessageCbs *cbs, void *ud) { - cbs->user_data = ud; -} - -LinphoneChatMessageCbsMsgStateChangedCb -linphone_chat_message_cbs_get_msg_state_changed(const LinphoneChatMessageCbs *cbs) { - return cbs->msg_state_changed; -} - -void linphone_chat_message_cbs_set_msg_state_changed(LinphoneChatMessageCbs *cbs, - LinphoneChatMessageCbsMsgStateChangedCb cb) { - cbs->msg_state_changed = cb; -} - -LinphoneChatMessageCbsFileTransferRecvCb linphone_chat_message_cbs_get_file_transfer_recv(const LinphoneChatMessageCbs *cbs) { - return cbs->file_transfer_recv; -} - -void linphone_chat_message_cbs_set_file_transfer_recv(LinphoneChatMessageCbs *cbs, - LinphoneChatMessageCbsFileTransferRecvCb cb) { - cbs->file_transfer_recv = cb; -} - -LinphoneChatMessageCbsFileTransferSendCb linphone_chat_message_cbs_get_file_transfer_send(const LinphoneChatMessageCbs *cbs) { - return cbs->file_transfer_send; -} - -void linphone_chat_message_cbs_set_file_transfer_send(LinphoneChatMessageCbs *cbs, - LinphoneChatMessageCbsFileTransferSendCb cb) { - cbs->file_transfer_send = cb; -} - -LinphoneChatMessageCbsFileTransferProgressIndicationCb -linphone_chat_message_cbs_get_file_transfer_progress_indication(const LinphoneChatMessageCbs *cbs) { - return cbs->file_transfer_progress_indication; -} - -void linphone_chat_message_cbs_set_file_transfer_progress_indication( - LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsFileTransferProgressIndicationCb cb) { - cbs->file_transfer_progress_indication = cb; -} - - -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatMessage); - -static void _linphone_chat_room_destroy(LinphoneChatRoom *cr) { - 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); - bctbx_list_free_with_data(cr->transient_messages, (bctbx_list_free_func)linphone_chat_message_release); - if (cr->weak_messages != NULL) bctbx_list_free(cr->weak_messages); - if (cr->received_rtt_characters) { - cr->received_rtt_characters = bctbx_list_free_with_data(cr->received_rtt_characters, (bctbx_list_free_func)ms_free); - } - if (cr->lc != NULL) { - if (bctbx_list_find(cr->lc->chatrooms, cr)) { - ms_error("LinphoneChatRoom[%p] is destroyed while still being used by the LinphoneCore. This is abnormal." - " linphone_core_get_chat_room() doesn't give a reference, there is no need to call " - "linphone_chat_room_unref(). " - "In order to remove a chat room from the core, use linphone_core_delete_chat_room().", - cr); - cr->lc->chatrooms = bctbx_list_remove(cr->lc->chatrooms, cr); - } - } - linphone_address_unref(cr->peer_url); - if (cr->pending_message) - linphone_chat_message_destroy(cr->pending_message); - ms_free(cr->peer); -} - -void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state) { - /* do not invoke callbacks on orphan messages */ - if (state != msg->state && msg->chat_room != NULL) { - if (((msg->state == LinphoneChatMessageStateDisplayed) || (msg->state == LinphoneChatMessageStateDeliveredToUser)) - && ((state == LinphoneChatMessageStateDeliveredToUser) || (state == LinphoneChatMessageStateDelivered) || (state == LinphoneChatMessageStateNotDelivered))) { - /* If the message has been displayed or delivered to user we must not go back to the delivered or not delivered state. */ - return; - } - ms_message("Chat message %p: moving from state %s to %s", msg, linphone_chat_message_state_to_string(msg->state), - linphone_chat_message_state_to_string(state)); - msg->state = state; - if (msg->message_state_changed_cb) { - msg->message_state_changed_cb(msg, msg->state, msg->message_state_changed_user_data); - } - if (linphone_chat_message_cbs_get_msg_state_changed(msg->callbacks)) { - linphone_chat_message_cbs_get_msg_state_changed(msg->callbacks)(msg, msg->state); - } - } -} - -BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatMessage, belle_sip_object_t, - (belle_sip_object_destroy_t)_linphone_chat_message_destroy, - NULL, // clone - NULL, // marshal - FALSE); +using namespace std; void linphone_core_disable_chat(LinphoneCore *lc, LinphoneReason deny_reason) { lc->chat_deny_code = deny_reason; @@ -180,1606 +59,103 @@ bool_t linphone_core_chat_enabled(const LinphoneCore *lc) { return lc->chat_deny_code != LinphoneReasonNone; } -const bctbx_list_t *linphone_core_get_chat_rooms(LinphoneCore *lc) { - return lc->chatrooms; +const bctbx_list_t *linphone_core_get_chat_rooms (LinphoneCore *lc) { + if (lc->chat_rooms) + bctbx_list_free_with_data(lc->chat_rooms, (bctbx_list_free_func)linphone_chat_room_unref); + lc->chat_rooms = L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getChatRooms()); + return lc->chat_rooms; } -static bool_t linphone_chat_room_matches(LinphoneChatRoom *cr, const LinphoneAddress *from) { - return linphone_address_weak_equal(cr->peer_url, from); -} - -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_base(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; - cr->unread_count = -1; - cr->received_rtt_characters = NULL; - return cr; -} - -static LinphoneChatRoom *_linphone_core_create_chat_room(LinphoneCore *lc, LinphoneAddress *addr) { - LinphoneChatRoom *cr = _linphone_core_create_chat_room_base(lc, addr); - lc->chatrooms = bctbx_list_append(lc->chatrooms, (void *)cr); - return cr; +static LinphoneChatRoom *linphone_chat_room_new (LinphoneCore *core, const LinphoneAddress *addr) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(core)->getOrCreateBasicChatRoom( + *L_GET_CPP_PTR_FROM_C_OBJECT(addr), + !!linphone_core_realtime_text_enabled(core) + )); } LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call){ - LinphoneChatRoom *cr = _linphone_core_create_chat_room_base(call->core, + LinphoneChatRoom *cr = linphone_chat_room_new(linphone_call_get_core(call), linphone_address_clone(linphone_call_get_remote_address(call))); - cr->call = call; + linphone_chat_room_set_call(cr, call); 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; +LinphoneChatRoom *linphone_core_get_chat_room (LinphoneCore *lc, const LinphoneAddress *addr) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getOrCreateBasicChatRoom(*L_GET_CPP_PTR_FROM_C_OBJECT(addr))); } -LinphoneChatRoom *_linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr) { - LinphoneChatRoom *cr = NULL; - bctbx_list_t *elem; - for (elem = lc->chatrooms; elem != NULL; elem = bctbx_list_next(elem)) { - cr = (LinphoneChatRoom *)elem->data; - if (linphone_chat_room_matches(cr, addr)) { - break; - } - cr = NULL; - } - return cr; +LinphoneChatRoom *linphone_core_create_client_group_chat_room (LinphoneCore *lc, const char *subject, bool_t fallback) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->createClientGroupChatRoom(L_C_TO_STRING(subject), !!fallback)); } -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; - - if (to_addr == NULL) { - 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); - linphone_address_unref(to_addr); - if (!ret) { - ret = _linphone_core_create_chat_room_from_url(lc, to); - } - return ret; +LinphoneChatRoom *_linphone_core_create_server_group_chat_room (LinphoneCore *lc, LinphonePrivate::SalCallOp *op) { + return _linphone_server_group_chat_room_new(lc, op); } -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; -} - -void linphone_core_delete_chat_room(LinphoneCore *lc, LinphoneChatRoom *cr) { - if (bctbx_list_find(lc->chatrooms, cr)) { - lc->chatrooms = bctbx_list_remove(cr->lc->chatrooms, cr); - linphone_chat_room_delete_history(cr); - linphone_chat_room_unref(cr); - } else { - ms_error("linphone_core_delete_chat_room(): chatroom [%p] isn't part of LinphoneCore.", cr); - } +void linphone_core_delete_chat_room (LinphoneCore *, LinphoneChatRoom *cr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->deleteFromDb(); } LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to) { - return _linphone_core_get_or_create_chat_room(lc, to); + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getOrCreateBasicChatRoomFromUri(L_C_TO_STRING(to))); } -static void linphone_chat_room_delete_composing_idle_timer(LinphoneChatRoom *cr) { - if (cr->composing_idle_timer) { - if (cr->lc && 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; - } +LinphoneChatRoom *linphone_core_find_chat_room( + const LinphoneCore *lc, + const LinphoneAddress *peer_addr, + const LinphoneAddress *local_addr +) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(LinphonePrivate::ChatRoomId( + LinphonePrivate::IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(peer_addr)), + LinphonePrivate::IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(local_addr)) + ))); } -static void linphone_chat_room_delete_composing_refresh_timer(LinphoneChatRoom *cr) { - if (cr->composing_refresh_timer) { - if (cr->lc && 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; - } +LinphoneChatRoom *linphone_core_find_one_to_one_chat_room ( + const LinphoneCore *lc, + const LinphoneAddress *local_addr, + const LinphoneAddress *participant_addr +) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findOneToOneChatRoom( + LinphonePrivate::IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(local_addr)), + LinphonePrivate::IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(participant_addr)) + )); } -static void linphone_chat_room_delete_remote_composing_refresh_timer(LinphoneChatRoom *cr) { - if (cr->remote_composing_refresh_timer) { - if (cr->lc && 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; - } -} - -void linphone_chat_room_destroy(LinphoneChatRoom *cr) { - linphone_chat_room_unref(cr); -} - -void linphone_chat_room_release(LinphoneChatRoom *cr) { - 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); - bctbx_list_for_each(cr->weak_messages, (bctbx_list_iterate_func)linphone_chat_message_deactivate); - bctbx_list_for_each(cr->transient_messages, (bctbx_list_iterate_func)linphone_chat_message_deactivate); - cr->lc = NULL; - linphone_chat_room_unref(cr); -} - -static void on_weak_message_destroy(void *obj, belle_sip_object_t *message_being_destroyed) { - LinphoneChatRoom *cr = (LinphoneChatRoom *)obj; - cr->weak_messages = bctbx_list_remove(cr->weak_messages, message_being_destroyed); -} - -void linphone_chat_room_add_weak_message(LinphoneChatRoom *cr, LinphoneChatMessage *cm) { - bctbx_list_t *item = bctbx_list_find(cr->weak_messages, cm); - if (item == NULL) { - cr->weak_messages = bctbx_list_append(cr->weak_messages, belle_sip_object_weak_ref(cm, on_weak_message_destroy, 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; -} - -void linphone_chat_room_add_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - if (bctbx_list_find(msg->chat_room->transient_messages, msg) == NULL) { - cr->transient_messages = bctbx_list_append(cr->transient_messages, linphone_chat_message_ref(msg)); - } -} - -void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - if (bctbx_list_find(msg->chat_room->transient_messages, msg) != NULL) { - cr->transient_messages = bctbx_list_remove(cr->transient_messages, msg); - linphone_chat_message_unref(msg); - } -} - -static void store_or_update_chat_message(LinphoneChatMessage *msg) { - if (msg->storage_id != 0) { - /* The message has already been stored (probably because of file transfer), update it */ - linphone_chat_message_store_update(msg); +int linphone_core_message_received(LinphoneCore *lc, LinphonePrivate::SalOp *op, const SalMessage *sal_msg) { + LinphoneReason reason = LinphoneReasonNotAcceptable; + std::string peerAddress; + std::string localAddress; + if (linphone_core_conference_server_enabled(lc)) { + localAddress = peerAddress = op->getTo(); } else { - /* Store the new message */ - msg->storage_id = linphone_chat_message_store(msg); - } -} - -void _linphone_chat_message_convert_to_utf8(LinphoneChatMessage *msg) { - if (msg && msg->message) { - if (msg->locale_message) - ms_free(msg->locale_message); - - msg->locale_message = msg->message; - msg->message = bctbx_locale_to_utf8(msg->locale_message); - } -} - -void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - int retval = -1; - LinphoneCore *lc = cr->lc; - LinphoneImEncryptionEngine *imee = lc->im_encryption_engine; - - /*stubed rtt text*/ - if (cr->call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(cr->call))) { - uint32_t new_line = 0x2028; - linphone_chat_message_put_char(msg, new_line); // New Line - linphone_chat_message_unref(msg); - return; + peerAddress = op->getFrom(); + localAddress = op->getTo(); } - msg->dir = LinphoneChatMessageOutgoing; - - /* Check if we shall upload a file to a server */ - 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) */ - if (linphone_chat_room_upload_file(msg) == 0) { - /* Add to transient list only if message is going out */ - linphone_chat_room_add_transient_message(cr, msg); - /* Store the message so that even if the upload is stopped, it can be done again */ - msg->storage_id = linphone_chat_message_store(msg); - } else { - linphone_chat_message_unref(msg); - return; - } - } else { - SalOp *op = msg->op; - LinphoneCall *call=NULL; - char *content_type; - const char *identity = NULL; - char *clear_text_message = NULL; - char *clear_text_content_type = NULL; - - if (msg->message) { - clear_text_message = ms_strdup(msg->message); - } - if (msg->content_type) { - clear_text_content_type = ms_strdup(msg->content_type); - } - - /* Add to transient list */ - linphone_chat_room_add_transient_message(cr, msg); - msg->time = ms_time(0); - if (lp_config_get_int(cr->lc->config, "sip", "chat_use_call_dialogs", 0) != 0) { - if ((call = linphone_core_get_call_by_remote_address(cr->lc, cr->peer)) != NULL) { - if (call->state == LinphoneCallConnected || call->state == LinphoneCallStreamsRunning || - call->state == LinphoneCallPaused || call->state == LinphoneCallPausing || - call->state == LinphoneCallPausedByRemote) { - ms_message("send SIP msg through the existing call."); - op = call->op; - identity = linphone_core_find_best_identity(cr->lc, linphone_call_get_remote_address(call)); - } - } - } - - if (!identity) { - LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cr->lc, cr->peer_url); - if (proxy) { - identity = linphone_proxy_config_get_identity(proxy); - } else { - identity = linphone_core_get_primary_contact(cr->lc); - } - } - if (msg->from){ - /* - * BUG - * the file transfer message constructor sets the from, but doesn't do it as well as here. - */ - linphone_address_unref(msg->from); - } - msg->from = linphone_address_new(identity); - - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs); - if (cb_process_outgoing_message) { - retval = cb_process_outgoing_message(imee, cr, msg); - if(retval == 0) { - msg->is_secured = TRUE; - } - } - } - - if (op == NULL) { - /*sending out of calls*/ - msg->op = op = sal_op_new(cr->lc->sal); - linphone_configure_op(cr->lc, op, cr->peer_url, msg->custom_headers, - lp_config_get_int(cr->lc->config, "sip", "chat_msg_with_contact", 0)); - sal_op_set_user_pointer(op, msg); /*if out of call, directly store msg*/ - } - - if (retval > 0) { - sal_error_info_set((SalErrorInfo *)sal_op_get_error_info(op), SalReasonNotAcceptable, "SIP", retval, "Unable to encrypt IM", NULL); - store_or_update_chat_message(msg); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); - linphone_chat_message_unref(msg); - return; - } - - if (msg->external_body_url) { - content_type = ms_strdup_printf("message/external-body; access-type=URL; URL=\"%s\"", msg->external_body_url); - sal_message_send(op, identity, cr->peer, content_type, NULL, NULL); - ms_free(content_type); - } else { - char *peer_uri = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - const char *content_type = msg->content_type; - if (content_type == NULL) { - sal_text_send(op, identity, cr->peer, msg->message); - } else { - sal_message_send(op, identity, cr->peer, content_type, msg->message, peer_uri); - } - ms_free(peer_uri); - } - - if (msg->message && clear_text_message && strcmp(msg->message, clear_text_message) != 0) { - // We replace the encrypted message by the original one so it can be correctly stored and displayed by the application - ms_free(msg->message); - msg->message = ms_strdup(clear_text_message); - } - if (msg->content_type && clear_text_content_type && (strcmp(msg->content_type, clear_text_content_type) != 0)) { - /* We replace the encrypted content type by the original one */ - ms_free(msg->content_type); - msg->content_type = ms_strdup(clear_text_content_type); - } - msg->message_id = ms_strdup(sal_op_get_call_id(op)); /* must be known at that time */ - store_or_update_chat_message(msg); - - if (cr->is_composing == LinphoneIsComposingActive) { - cr->is_composing = LinphoneIsComposingIdle; - } - linphone_chat_room_delete_composing_idle_timer(cr); - linphone_chat_room_delete_composing_refresh_timer(cr); - - if (clear_text_message) { - ms_free(clear_text_message); - } - if (clear_text_content_type) { - ms_free(clear_text_content_type); - } - - if (call && call->op == op) { - /*In this case, chat delivery status is not notified, so unrefing chat message right now*/ - /*Might be better fixed by delivering status, but too costly for now*/ - linphone_chat_room_remove_transient_message(msg->chat_room, msg); - linphone_chat_message_unref(msg); - return; - } + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom( + LinphonePrivate::ChatRoomId(LinphonePrivate::IdentityAddress(peerAddress), LinphonePrivate::IdentityAddress(localAddress)) + ); + if (chatRoom) + reason = L_GET_PRIVATE(chatRoom)->onSipMessageReceived(op, sal_msg); + else if (!linphone_core_conference_server_enabled(lc)) { + LinphoneAddress *addr = linphone_address_new(sal_msg->from); + linphone_address_clean(addr); + LinphoneChatRoom *cr = linphone_core_get_chat_room(lc, addr); + if (cr) + reason = L_GET_PRIVATE_FROM_C_OBJECT(cr)->onSipMessageReceived(op, sal_msg); + linphone_address_unref(addr); } - // if operation failed, we should not change message state - if (msg->dir == LinphoneChatMessageOutgoing) { - linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress); - } -} - -void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state) { - linphone_chat_message_set_state(msg, new_state); - linphone_chat_message_store_state(msg); - - if (msg->state == LinphoneChatMessageStateDelivered || msg->state == LinphoneChatMessageStateNotDelivered) { - if (bctbx_list_find(msg->chat_room->transient_messages, msg) != NULL) { - // msg is not transient anymore, we can remove it from our transient list and unref it - linphone_chat_room_add_weak_message(msg->chat_room, msg); - linphone_chat_room_remove_transient_message(msg->chat_room, msg); - } else { - // msg has already been removed from the transient messages, do nothing. */ - } - } -} - -void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg) { - _linphone_chat_room_send_message(cr, linphone_chat_room_create_message(cr, msg)); -} - -static bool_t is_file_transfer(const char *content_type) { - return (strcmp("application/vnd.gsma.rcs-ft-http+xml", content_type) == 0); -} - -static bool_t is_im_iscomposing(const char* content_type) { - return (strcmp("application/im-iscomposing+xml", content_type) == 0); -} - -static bool_t is_imdn(const char *content_type) { - return (strcmp("message/imdn+xml", content_type) == 0); -} - -static bool_t is_text(const char *content_type) { - return (strcmp("text/plain", content_type) == 0); -} - -void linphone_chat_room_message_received(LinphoneChatRoom *cr, LinphoneCore *lc, LinphoneChatMessage *msg) { - if (msg->message) { - /*legacy API*/ - linphone_core_notify_text_message_received(lc, cr, msg->from, msg->message); - } - linphone_core_notify_message_received(lc, cr, msg); - if(!is_imdn(msg->content_type) && !is_im_iscomposing(msg->content_type)) { - cr->remote_is_composing = LinphoneIsComposingIdle; - linphone_core_notify_is_composing_received(cr->lc, cr); - linphone_chat_message_send_delivery_notification(msg, LinphoneReasonNone); - } -} - -static void create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(LinphoneChatMessage *msg) { - xmlChar *file_url = NULL; - xmlDocPtr xmlMessageBody; - xmlNodePtr cur; - /* parse the msg body to get all informations from it */ - xmlMessageBody = xmlParseDoc((const xmlChar *)msg->message); - msg->file_transfer_information = linphone_content_new(); - - cur = xmlDocGetRootElement(xmlMessageBody); - if (cur != NULL) { - cur = cur->xmlChildrenNode; - while (cur != NULL) { - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { - /* we found a file info node, check if it has a type="file" attribute */ - xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); - if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */ - cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */ - while (cur != NULL) { - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) { - xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - linphone_content_set_size(msg->file_transfer_information, strtol((const char *)fileSizeString, NULL, 10)); - xmlFree(fileSizeString); - } - - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-name")) { - xmlChar *filename = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - linphone_content_set_name(msg->file_transfer_information, (char *)filename); - xmlFree(filename); - } - if (!xmlStrcmp(cur->name, (const xmlChar *)"content-type")) { - xmlChar *contentType = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - int contentTypeIndex = 0; - char *type; - char *subtype; - while (contentType[contentTypeIndex] != '/' && contentType[contentTypeIndex] != '\0') { - contentTypeIndex++; - } - type = ms_strndup((char *)contentType, contentTypeIndex); - subtype = ms_strdup(((char *)contentType + contentTypeIndex + 1)); - linphone_content_set_type(msg->file_transfer_information, type); - linphone_content_set_subtype(msg->file_transfer_information, subtype); - ms_free(subtype); - ms_free(type); - xmlFree(contentType); - } - if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) { - file_url = xmlGetProp(cur, (const xmlChar *)"url"); - } - - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { - /* there is a key in the msg: file has been encrypted */ - /* convert the key from base 64 */ - xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); - size_t keyLength = b64::b64_decode((char *)keyb64, strlen((char *)keyb64), NULL, 0); - uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); - /* decode the key into local key buffer */ - b64::b64_decode((char *)keyb64, strlen((char *)keyb64), keyBuffer, keyLength); - linphone_content_set_key(msg->file_transfer_information, (char *)keyBuffer, keyLength); - /* duplicate key value into the linphone content private structure */ - xmlFree(keyb64); - free(keyBuffer); - } - - cur = cur->next; - } - xmlFree(typeAttribute); - break; - } - xmlFree(typeAttribute); - } - cur = cur->next; - } - } - xmlFreeDoc(xmlMessageBody); - - linphone_chat_message_set_external_body_url(msg, (const char *)file_url); - xmlFree(file_url); -} - -LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *sal_msg) { - LinphoneChatRoom *cr = NULL; - LinphoneAddress *addr; - LinphoneAddress *to; - LinphoneChatMessage *msg = NULL; - LinphoneImEncryptionEngine *imee = lc->im_encryption_engine; - const SalCustomHeader *ch; - LinphoneReason reason = LinphoneReasonNone; - int retval = -1; - bool_t increase_msg_count = TRUE; - - addr = linphone_address_new(sal_msg->from); - linphone_address_clean(addr); - cr = linphone_core_get_chat_room(lc, addr); - - /* Check if this is a duplicate message */ - if ((msg = linphone_chat_room_find_message_with_dir(cr, sal_op_get_call_id(op), LinphoneChatMessageIncoming))) { - reason = lc->chat_deny_code; - goto end; - } - - msg = linphone_chat_room_create_message_without_conversion(cr, sal_msg->text); - linphone_chat_message_set_content_type(msg, sal_msg->content_type); - linphone_chat_message_set_from(msg, cr->peer_url); - - to = sal_op_get_to(op) ? linphone_address_new(sal_op_get_to(op)) : linphone_address_new(linphone_core_get_identity(lc)); - msg->to = to; - - msg->time = sal_msg->time; - msg->state = LinphoneChatMessageStateDelivered; - msg->dir = LinphoneChatMessageIncoming; - msg->message_id = ms_strdup(sal_op_get_call_id(op)); - - ch = sal_op_get_recv_custom_header(op); - if (ch) { - msg->custom_headers = sal_custom_header_clone(ch); - } - - if (sal_msg->url) { - linphone_chat_message_set_external_body_url(msg, sal_msg->url); - } - - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsIncomingMessageCb cb_process_incoming_message = linphone_im_encryption_engine_cbs_get_process_incoming_message(imee_cbs); - if (cb_process_incoming_message) { - retval = cb_process_incoming_message(imee, cr, msg); - ms_debug("Decryption done, result is %i", retval); - if (retval == 0) { - msg->is_secured = TRUE; - } else if(retval > 0) { - // Unable to decrypt message - linphone_core_notify_message_received_unable_decrypt(cr->lc, cr, msg); - reason = linphone_error_code_to_reason(retval); - linphone_chat_message_send_delivery_notification(msg, reason); - // return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt - reason = LinphoneReasonNone; - goto end; - } - } else { - ms_warning("IM Encryption Engine found but there is no process incoming messsage callback set..."); - } - } else { - ms_debug("No IM Encryption Engine found"); - } - - if ((retval <= 0) && (linphone_core_is_content_type_supported(lc, msg->content_type) == FALSE)) { - retval = 415; - ms_error("Unsupported MESSAGE (content-type %s not recognized)", msg->content_type); - } - - if (retval > 0) { - reason = linphone_error_code_to_reason(retval); - linphone_chat_message_send_delivery_notification(msg, reason); - goto end; - } - - if (is_file_transfer(msg->content_type)) { - create_file_transfer_information_from_vnd_gsma_rcs_ft_http_xml(msg); - linphone_chat_message_set_to_be_stored(msg, TRUE); - } else if (is_im_iscomposing(msg->content_type)) { - linphone_chat_room_notify_is_composing(cr, msg->message); - linphone_chat_message_set_to_be_stored(msg, FALSE); - increase_msg_count = FALSE; - if(lp_config_get_int(cr->lc->config, "sip", "deliver_imdn", 0) != 1) { - goto end; - } - } else if (is_imdn(msg->content_type)) { - linphone_chat_room_notify_imdn(cr, msg->message); - linphone_chat_message_set_to_be_stored(msg, FALSE); - increase_msg_count = FALSE; - if(lp_config_get_int(cr->lc->config, "sip", "deliver_imdn", 0) != 1) { - goto end; - } - } else if (is_text(msg->content_type)) { - linphone_chat_message_set_to_be_stored(msg, TRUE); - } - - if (increase_msg_count == TRUE) { - if (cr->unread_count < 0) - cr->unread_count = 1; - else - cr->unread_count++; - /* Mark the message as pending so that if linphone_core_chat_room_mark_as_read() is called - in the linphone_chat_room_message_received() callback, it will effectively be marked as - being read before being stored. */ - cr->pending_message = msg; - } - - linphone_chat_room_message_received(cr, lc, msg); - - if(linphone_chat_message_get_to_be_stored(msg)) { - msg->storage_id = linphone_chat_message_store(msg); - } - - cr->pending_message = NULL; - -end: - linphone_address_unref(addr); - if (msg != NULL) linphone_chat_message_unref(msg); return reason; } -static int linphone_chat_room_remote_refresh_composing_expired(void *data, unsigned int revents) { - LinphoneChatRoom *cr = (LinphoneChatRoom *)data; - belle_sip_object_unref(cr->remote_composing_refresh_timer); - cr->remote_composing_refresh_timer = NULL; - cr->remote_is_composing = LinphoneIsComposingIdle; - linphone_core_notify_is_composing_received(cr->lc, cr); - return BELLE_SIP_STOP; -} - -static const char *iscomposing_prefix = "/xsi:isComposing"; - -static void process_im_is_composing_notification(LinphoneChatRoom *cr, xmlparsing_context_t *xml_ctx) { - char xpath_str[MAX_XPATH_LENGTH]; - xmlXPathObjectPtr iscomposing_object; - char *state_str = NULL; - char *refresh_str = NULL; - int refresh_duration = lp_config_get_int(cr->lc->config, "sip", "composing_remote_refresh_timeout", - COMPOSING_DEFAULT_REMOTE_REFRESH_TIMEOUT); - int i; - LinphoneIsComposingState state = LinphoneIsComposingIdle; - - if (linphone_create_xml_xpath_context(xml_ctx) < 0) - return; - - xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"xsi", - (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing"); - iscomposing_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, iscomposing_prefix); - if (iscomposing_object != NULL) { - if (iscomposing_object->nodesetval != NULL) { - for (i = 1; i <= iscomposing_object->nodesetval->nodeNr; i++) { - snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/xsi:state", iscomposing_prefix, i); - state_str = linphone_get_xml_text_content(xml_ctx, xpath_str); - if (state_str == NULL) - continue; - snprintf(xpath_str, sizeof(xpath_str), "%s[%i]/xsi:refresh", iscomposing_prefix, i); - refresh_str = linphone_get_xml_text_content(xml_ctx, xpath_str); - } - } - xmlXPathFreeObject(iscomposing_object); - } - - if (state_str != NULL) { - if (strcmp(state_str, "active") == 0) { - state = LinphoneIsComposingActive; - if (refresh_str != NULL) { - refresh_duration = atoi(refresh_str); - } - if (!cr->remote_composing_refresh_timer) { - cr->remote_composing_refresh_timer = - sal_create_timer(cr->lc->sal, linphone_chat_room_remote_refresh_composing_expired, cr, - refresh_duration * 1000, "composing remote refresh timeout"); - } else { - belle_sip_source_set_timeout(cr->remote_composing_refresh_timer, refresh_duration * 1000); - } - } else { - linphone_chat_room_delete_remote_composing_refresh_timer(cr); - } - - cr->remote_is_composing = state; - linphone_core_notify_is_composing_received(cr->lc, cr); - linphone_free_xml_text_content(state_str); - } - if (refresh_str != NULL) { - linphone_free_xml_text_content(refresh_str); - } -} - -static void linphone_chat_room_notify_is_composing(LinphoneChatRoom *cr, const char *text) { - xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); - xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); - xml_ctx->doc = xmlReadDoc((const unsigned char *)text, 0, NULL, 0); - if (xml_ctx->doc != NULL) { - process_im_is_composing_notification(cr, xml_ctx); - } else { - ms_warning("Wrongly formatted presence XML: %s", xml_ctx->errorBuffer); - } - linphone_xmlparsing_context_destroy(xml_ctx); -} - -bool_t linphone_chat_room_is_remote_composing(const LinphoneChatRoom *cr) { - return (cr->remote_is_composing == LinphoneIsComposingActive) ? TRUE : FALSE; -} - -static const char *imdn_prefix = "/imdn:imdn"; - -static void process_imdn(LinphoneChatRoom *cr, xmlparsing_context_t *xml_ctx) { - char xpath_str[MAX_XPATH_LENGTH]; - xmlXPathObjectPtr imdn_object; - xmlXPathObjectPtr delivery_status_object; - xmlXPathObjectPtr display_status_object; - char *message_id_str = NULL; - char *datetime_str = NULL; - LinphoneCore *lc = linphone_chat_room_get_core(cr); - LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); - - if (linphone_create_xml_xpath_context(xml_ctx) < 0) - return; - - xmlXPathRegisterNs(xml_ctx->xpath_ctx, (const xmlChar *)"imdn", - (const xmlChar *)"urn:ietf:params:xml:ns:imdn"); - imdn_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, imdn_prefix); - if (imdn_object != NULL) { - if ((imdn_object->nodesetval != NULL) && (imdn_object->nodesetval->nodeNr >= 1)) { - snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:message-id", imdn_prefix); - message_id_str = linphone_get_xml_text_content(xml_ctx, xpath_str); - snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:datetime", imdn_prefix); - datetime_str = linphone_get_xml_text_content(xml_ctx, xpath_str); - } - xmlXPathFreeObject(imdn_object); - } - - if ((message_id_str != NULL) && (datetime_str != NULL)) { - LinphoneChatMessage *cm = linphone_chat_room_find_message_with_dir(cr, message_id_str, LinphoneChatMessageOutgoing); - if (cm == NULL) { - ms_warning("Received IMDN for unknown message %s", message_id_str); - } else { - snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:delivery-notification/imdn:status", imdn_prefix); - delivery_status_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str); - snprintf(xpath_str, sizeof(xpath_str), "%s[1]/imdn:display-notification/imdn:status", imdn_prefix); - display_status_object = linphone_get_xml_xpath_object_for_node_list(xml_ctx, xpath_str); - if ((delivery_status_object != NULL) && (linphone_im_notif_policy_get_recv_imdn_delivered(policy) == TRUE)) { - if ((delivery_status_object->nodesetval != NULL) && (delivery_status_object->nodesetval->nodeNr >= 1)) { - xmlNodePtr node = delivery_status_object->nodesetval->nodeTab[0]; - if ((node->children != NULL) && (node->children->name != NULL)) { - if (strcmp((const char *)node->children->name, "delivered") == 0) { - linphone_chat_message_update_state(cm, LinphoneChatMessageStateDeliveredToUser); - } else if (strcmp((const char *)node->children->name, "error") == 0) { - linphone_chat_message_update_state(cm, LinphoneChatMessageStateNotDelivered); - } - } - } - xmlXPathFreeObject(delivery_status_object); - } - if ((display_status_object != NULL) && (linphone_im_notif_policy_get_recv_imdn_displayed(policy) == TRUE)) { - if ((display_status_object->nodesetval != NULL) && (display_status_object->nodesetval->nodeNr >= 1)) { - xmlNodePtr node = display_status_object->nodesetval->nodeTab[0]; - if ((node->children != NULL) && (node->children->name != NULL)) { - if (strcmp((const char *)node->children->name, "displayed") == 0) { - linphone_chat_message_update_state(cm, LinphoneChatMessageStateDisplayed); - } - } - } - xmlXPathFreeObject(display_status_object); - } - linphone_chat_message_unref(cm); - } - } - if (message_id_str != NULL) linphone_free_xml_text_content(message_id_str); - if (datetime_str != NULL) linphone_free_xml_text_content(datetime_str); -} - -static void linphone_chat_room_notify_imdn(LinphoneChatRoom *cr, const char *text) { - xmlparsing_context_t *xml_ctx = linphone_xmlparsing_context_new(); - xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); - xml_ctx->doc = xmlReadDoc((const unsigned char *)text, 0, NULL, 0); - if (xml_ctx->doc != NULL) { - process_imdn(cr, xml_ctx); - } else { - ms_warning("Wrongly formatted IMDN XML: %s", xml_ctx->errorBuffer); - } - linphone_xmlparsing_context_destroy(xml_ctx); -} - -LinphoneCore *linphone_chat_room_get_lc(LinphoneChatRoom *cr) { - return linphone_chat_room_get_core(cr); -} - -LinphoneCore *linphone_chat_room_get_core(LinphoneChatRoom *cr) { - return cr->lc; -} - -const LinphoneAddress *linphone_chat_room_get_peer_address(LinphoneChatRoom *cr) { - return cr->peer_url; -} - -static LinphoneChatMessage *_linphone_chat_room_create_message(LinphoneChatRoom *cr, const char *message) { - LinphoneChatMessage *msg = belle_sip_object_new(LinphoneChatMessage); - msg->state = LinphoneChatMessageStateIdle; - msg->callbacks = linphone_chat_message_cbs_new(); - msg->chat_room = (LinphoneChatRoom *)cr; - msg->message = message ? ms_strdup(message) : NULL; - msg->locale_message = NULL; - msg->content_type = ms_strdup("text/plain"); - msg->file_transfer_information = NULL; /* this property is used only when transfering file */ - msg->http_request = NULL; - msg->time = ms_time(0); - msg->is_secured = FALSE; - return msg; -} - -LinphoneChatMessage *linphone_chat_room_create_message_without_conversion(LinphoneChatRoom *cr, const char *message) { - return _linphone_chat_room_create_message(cr, message); -} - -LinphoneChatMessage *linphone_chat_room_create_message(LinphoneChatRoom *cr, const char *message) { - LinphoneChatMessage *msg = _linphone_chat_room_create_message(cr, message); - _linphone_chat_message_convert_to_utf8(msg); - return msg; -} - -LinphoneChatMessage *linphone_chat_room_create_message_2(LinphoneChatRoom *cr, const char *message, - const char *external_body_url, LinphoneChatMessageState state, - time_t time, bool_t is_read, bool_t is_incoming) { - LinphoneChatMessage *msg = linphone_chat_room_create_message(cr, message); - LinphoneCore *lc = linphone_chat_room_get_core(cr); - msg->external_body_url = external_body_url ? ms_strdup(external_body_url) : NULL; - msg->time = time; - msg->is_secured = FALSE; - linphone_chat_message_set_state(msg, state); - if (is_incoming) { - msg->dir = LinphoneChatMessageIncoming; - linphone_chat_message_set_from(msg, linphone_chat_room_get_peer_address(cr)); - msg->to = linphone_address_new(linphone_core_get_identity(lc)); /*direct assignment*/ - } else { - msg->dir = LinphoneChatMessageOutgoing; - linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr)); - msg->from = linphone_address_new(linphone_core_get_identity(lc));/*direct assignment*/ - } - return msg; -} - -void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage *msg, - LinphoneChatMessageStateChangedCb status_cb, void *ud) { - msg->message_state_changed_cb = status_cb; - msg->message_state_changed_user_data = ud; - _linphone_chat_room_send_message(cr, msg); -} - -void linphone_chat_room_send_chat_message_2(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - linphone_chat_message_ref(msg); - _linphone_chat_room_send_message(cr, msg); -} - -void linphone_chat_room_send_chat_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - _linphone_chat_room_send_message(cr, msg); -} - -void _linphone_chat_message_resend(LinphoneChatMessage *msg, bool_t ref_msg) { - LinphoneChatMessageState state = linphone_chat_message_get_state(msg); - LinphoneChatRoom *cr; - - if (state != LinphoneChatMessageStateNotDelivered) { - ms_warning("Cannot resend chat message in state %s", linphone_chat_message_state_to_string(state)); - return; - } - - cr = linphone_chat_message_get_chat_room(msg); - if (ref_msg) linphone_chat_message_ref(msg); - _linphone_chat_room_send_message(cr, msg); -} - -void linphone_chat_message_resend(LinphoneChatMessage *msg) { - _linphone_chat_message_resend(msg, FALSE); -} - -void linphone_chat_message_resend_2(LinphoneChatMessage *msg) { - _linphone_chat_message_resend(msg, TRUE); -} - -static char *linphone_chat_room_create_is_composing_xml(LinphoneChatRoom *cr) { - xmlBufferPtr buf; - xmlTextWriterPtr writer; - int err; - char *content = NULL; - - buf = xmlBufferCreate(); - if (buf == NULL) { - ms_error("Error creating the XML buffer"); - return content; - } - writer = xmlNewTextWriterMemory(buf, 0); - if (writer == NULL) { - ms_error("Error creating the XML writer"); - return content; - } - - err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); - if (err >= 0) { - err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"isComposing", - (const xmlChar *)"urn:ietf:params:xml:ns:im-iscomposing"); - } - if (err >= 0) { - err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"xsi", NULL, - (const xmlChar *)"http://www.w3.org/2001/XMLSchema-instance"); - } - if (err >= 0) { - err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xsi", (const xmlChar *)"schemaLocation", NULL, - (const xmlChar *)"urn:ietf:params:xml:ns:im-composing iscomposing.xsd"); - } - if (err >= 0) { - err = xmlTextWriterWriteElement(writer, (const xmlChar *)"state", - (cr->is_composing == LinphoneIsComposingActive) ? (const xmlChar *)"active" - : (const xmlChar *)"idle"); - } - if ((err >= 0) && (cr->is_composing == LinphoneIsComposingActive)) { - char refresh_str[4] = {0}; - int refresh_timeout = - lp_config_get_int(cr->lc->config, "sip", "composing_refresh_timeout", COMPOSING_DEFAULT_REFRESH_TIMEOUT); - snprintf(refresh_str, sizeof(refresh_str), "%u", refresh_timeout); - err = xmlTextWriterWriteElement(writer, (const xmlChar *)"refresh", (const xmlChar *)refresh_str); - } - if (err >= 0) { - /* Close the "isComposing" element. */ - err = xmlTextWriterEndElement(writer); - } - if (err >= 0) { - err = xmlTextWriterEndDocument(writer); - } - if (err > 0) { - /* xmlTextWriterEndDocument returns the size of the content. */ - content = ms_strdup((char *)buf->content); - } - xmlFreeTextWriter(writer); - xmlBufferFree(buf); - return content; -} - -static void linphone_chat_room_send_is_composing_notification(LinphoneChatRoom *cr) { - SalOp *op = NULL; - const char *identity = NULL; - char *content = NULL; - LinphoneCore *lc = linphone_chat_room_get_core(cr); - LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); - if (linphone_im_notif_policy_get_send_is_composing(policy) == TRUE) { - LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(lc, cr->peer_url); - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc); - LinphoneChatMessage *msg = NULL; - - if (proxy) - identity = linphone_proxy_config_get_identity(proxy); - else - identity = linphone_core_get_primary_contact(lc); - /*sending out of calls*/ - op = sal_op_new(lc->sal); - linphone_configure_op(lc, op, cr->peer_url, NULL, - lp_config_get_int(lc->config, "sip", "chat_msg_with_contact", 0)); - - content = linphone_chat_room_create_is_composing_xml(cr); - if (content != NULL) { - int retval = -1; - LinphoneAddress *from_addr = linphone_address_new(identity); - LinphoneAddress *to_addr = linphone_address_new(cr->peer); - msg = linphone_chat_room_create_message(cr, content); - linphone_chat_message_set_from_address(msg, from_addr); - linphone_chat_message_set_to_address(msg, to_addr); - linphone_chat_message_set_content_type(msg, "application/im-iscomposing+xml"); - - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs); - if (cb_process_outgoing_message) { - retval = cb_process_outgoing_message(imee, cr, msg); - } - } - - if (retval <= 0) { - sal_message_send(op, identity, cr->peer, msg->content_type, msg->message, NULL); - } - - linphone_chat_message_unref(msg); - linphone_address_unref(from_addr); - linphone_address_unref(to_addr); - ms_free(content); - sal_op_unref(op); - } - } -} - -enum ImdnType { - ImdnTypeDelivery, - ImdnTypeDisplay -}; - -static char *linphone_chat_message_create_imdn_xml(LinphoneChatMessage *cm, enum ImdnType imdn_type, LinphoneReason reason) { - xmlBufferPtr buf; - xmlTextWriterPtr writer; - int err; - char *content = NULL; - char *datetime = NULL; - const char *message_id; - - /* Check that the chat message has a message id */ - message_id = linphone_chat_message_get_message_id(cm); - if (message_id == NULL) return NULL; - - buf = xmlBufferCreate(); - if (buf == NULL) { - ms_error("Error creating the XML buffer"); - return content; - } - writer = xmlNewTextWriterMemory(buf, 0); - if (writer == NULL) { - ms_error("Error creating the XML writer"); - return content; - } - - datetime = linphone_timestamp_to_rfc3339_string(linphone_chat_message_get_time(cm)); - err = xmlTextWriterStartDocument(writer, "1.0", "UTF-8", NULL); - if (err >= 0) { - err = xmlTextWriterStartElementNS(writer, NULL, (const xmlChar *)"imdn", - (const xmlChar *)"urn:ietf:params:xml:ns:imdn"); - } - if ((err >= 0) && (reason != LinphoneReasonNone)) { - err = xmlTextWriterWriteAttributeNS(writer, (const xmlChar *)"xmlns", (const xmlChar *)"linphoneimdn", NULL, (const xmlChar *)"http://www.linphone.org/xsds/imdn.xsd"); - } - if (err >= 0) { - err = xmlTextWriterWriteElement(writer, (const xmlChar *)"message-id", (const xmlChar *)message_id); - } - if (err >= 0) { - err = xmlTextWriterWriteElement(writer, (const xmlChar *)"datetime", (const xmlChar *)datetime); - } - if (err >= 0) { - if (imdn_type == ImdnTypeDelivery) { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"delivery-notification"); - } else { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"display-notification"); - } - } - if (err >= 0) { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"status"); - } - if (err >= 0) { - if (reason == LinphoneReasonNone) { - if (imdn_type == ImdnTypeDelivery) { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"delivered"); - } else { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"displayed"); - } - } else { - err = xmlTextWriterStartElement(writer, (const xmlChar *)"error"); - } - } - if (err >= 0) { - /* Close the "delivered", "displayed" or "error" element. */ - err = xmlTextWriterEndElement(writer); - } - if ((err >= 0) && (reason != LinphoneReasonNone)) { - err = xmlTextWriterStartElementNS(writer, (const xmlChar *)"linphoneimdn", (const xmlChar *)"reason", NULL); - if (err >= 0) { - char codestr[16]; - snprintf(codestr, 16, "%d", linphone_reason_to_error_code(reason)); - err = xmlTextWriterWriteAttribute(writer, (const xmlChar *)"code", (const xmlChar *)codestr); - } - if (err >= 0) { - err = xmlTextWriterWriteString(writer, (const xmlChar *)linphone_reason_to_string(reason)); - } - if (err >= 0) { - err = xmlTextWriterEndElement(writer); - } - } - if (err >= 0) { - /* Close the "status" element. */ - err = xmlTextWriterEndElement(writer); - } - if (err >= 0) { - /* Close the "delivery-notification" or "display-notification" element. */ - err = xmlTextWriterEndElement(writer); - } - if (err >= 0) { - /* Close the "imdn" element. */ - err = xmlTextWriterEndElement(writer); - } - if (err >= 0) { - err = xmlTextWriterEndDocument(writer); - } - if (err > 0) { - /* xmlTextWriterEndDocument returns the size of the content. */ - content = ms_strdup((char *)buf->content); - } - xmlFreeTextWriter(writer); - xmlBufferFree(buf); - ms_free(datetime); - return content; -} - -static void linphone_chat_message_send_imdn(LinphoneChatMessage *cm, enum ImdnType imdn_type, LinphoneReason reason) { - SalOp *op = NULL; - const char *identity = NULL; - char *content = NULL; - LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(cm); - LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cr->lc, cr->peer_url); - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(cr->lc); - LinphoneChatMessage *msg; - - if (proxy) - identity = linphone_proxy_config_get_identity(proxy); - else - identity = linphone_core_get_primary_contact(cr->lc); - /* Sending out of calls */ - op = sal_op_new(cr->lc->sal); - linphone_configure_op(cr->lc, op, cr->peer_url, NULL, - lp_config_get_int(cr->lc->config, "sip", "chat_msg_with_contact", 0)); - - content = linphone_chat_message_create_imdn_xml(cm, imdn_type, reason); - if (content != NULL) { - int retval = -1; - LinphoneAddress *from_addr = linphone_address_new(identity); - LinphoneAddress *to_addr = linphone_address_new(cr->peer); - msg = linphone_chat_room_create_message(cr, content); - linphone_chat_message_set_from_address(msg, from_addr); - linphone_chat_message_set_to_address(msg, to_addr); - linphone_chat_message_set_content_type(msg, "message/imdn+xml"); - - /* Do not try to encrypt the notification when it is reporting an error (maybe it should be bypassed only for some reasons). */ - if (imee && (reason == LinphoneReasonNone)) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsOutgoingMessageCb cb_process_outgoing_message = linphone_im_encryption_engine_cbs_get_process_outgoing_message(imee_cbs); - if (cb_process_outgoing_message) { - retval = cb_process_outgoing_message(imee, cr, msg); - } - } - - if (retval <= 0) { - sal_message_send(op, identity, cr->peer, msg->content_type, msg->message, NULL); - } - - linphone_chat_message_unref(msg); - linphone_address_unref(from_addr); - linphone_address_unref(to_addr); - ms_free(content); - } - sal_op_unref(op); -} - -void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason) { - LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(cm); - LinphoneCore *lc = linphone_chat_room_get_core(cr); - LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); - if (linphone_im_notif_policy_get_send_imdn_delivered(policy) == TRUE) { - linphone_chat_message_send_imdn(cm, ImdnTypeDelivery, reason); - } -} - -void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm) { - LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(cm); - LinphoneCore *lc = linphone_chat_room_get_core(cr); - LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); - if (linphone_im_notif_policy_get_send_imdn_displayed(policy) == TRUE) { - linphone_chat_message_send_imdn(cm, ImdnTypeDisplay, LinphoneReasonNone); - } -} - -static char* utf8_to_char(uint32_t ic) { - char *result = reinterpret_cast(ms_malloc(sizeof(char) * 5)); - int size = 0; - if (ic < 0x80) { - result[0] = ic; - size = 1; - } else if (ic < 0x800) { - result[1] = 0x80 + ((ic & 0x3F)); - result[0] = 0xC0 + ((ic >> 6) & 0x1F); - size = 2; - } else if (ic < 0x100000) { - result[2] = 0x80 + (ic & 0x3F); - result[1] = 0x80 + ((ic >> 6) & 0x3F); - result[0] = 0xE0 + ((ic >> 12) & 0xF); - size = 3; - } else if (ic < 0x110000) { - result[3] = 0x80 + (ic & 0x3F); - result[2] = 0x80 + ((ic >> 6) & 0x3F); - result[1] = 0x80 + ((ic >> 12) & 0x3F); - result[0] = 0xF0 + ((ic >> 18) & 0x7); - size = 4; - } - result[size] = '\0'; - return result; -} - void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call) { - uint32_t new_line = 0x2028; - uint32_t crlf = 0x0D0A; - uint32_t lf = 0x0A; - - if (call && linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) { - LinphoneChatMessageCharacter *cmc = ms_new0(LinphoneChatMessageCharacter, 1); - - if (cr->pending_message == NULL) { - cr->pending_message = linphone_chat_room_create_message(cr, ""); - } - - cmc->value = character; - cmc->has_been_read = FALSE; - cr->received_rtt_characters = bctbx_list_append(cr->received_rtt_characters, (void *)cmc); - - cr->remote_is_composing = LinphoneIsComposingActive; - linphone_core_notify_is_composing_received(cr->lc, cr); - - if (character == new_line || character == crlf || character == lf) { - // End of message - LinphoneChatMessage *msg = cr->pending_message; - ms_debug("New line received, forge a message with content %s", cr->pending_message->message); - - linphone_chat_message_set_from(msg, cr->peer_url); - if (msg->to) - linphone_address_unref(msg->to); - msg->to = call->dest_proxy ? linphone_address_clone(call->dest_proxy->identity_address) : - linphone_address_new(linphone_core_get_identity(lc)); - msg->time = ms_time(0); - msg->state = LinphoneChatMessageStateDelivered; - msg->dir = LinphoneChatMessageIncoming; - - if (lp_config_get_int(lc->config, "misc", "store_rtt_messages", 1) == 1) { - msg->storage_id = linphone_chat_message_store(msg); - } - - if (cr->unread_count < 0) cr->unread_count = 1; - else cr->unread_count++; - - linphone_chat_room_message_received(cr, lc, msg); - linphone_chat_message_unref(msg); - cr->pending_message = NULL; - cr->received_rtt_characters = bctbx_list_free_with_data(cr->received_rtt_characters, (void (*)(void *))ms_free); - } else { - char *value = utf8_to_char(character); - cr->pending_message->message = ms_strcat_printf(cr->pending_message->message, value); - ms_debug("Received RTT character: %s (%lu), pending text is %s", value, (unsigned long)character, cr->pending_message->message); - ms_free(value); - } - } + if (!(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities() & LinphonePrivate::ChatRoom::Capabilities::RealTimeText)) + return; + L_GET_PRIVATE_FROM_C_OBJECT(cr, RealTimeTextChatRoom)->realtimeTextReceived(character, L_GET_CPP_PTR_FROM_C_OBJECT(call)); } -uint32_t linphone_chat_room_get_char(const LinphoneChatRoom *cr) { - if (cr && cr->received_rtt_characters) { - bctbx_list_t *characters = cr->received_rtt_characters; - while (characters != NULL) { - LinphoneChatMessageCharacter *cmc = (LinphoneChatMessageCharacter *)characters->data; - if (!cmc->has_been_read) { - cmc->has_been_read = TRUE; - return cmc->value; - } - characters = bctbx_list_next(characters); - } - } - return 0; -} - -LinphoneStatus linphone_chat_message_put_char(LinphoneChatMessage *msg, uint32_t character) { - LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg); - LinphoneCall *call = cr->call; - LinphoneCore *lc = cr->lc; - uint32_t new_line = 0x2028; - uint32_t crlf = 0x0D0A; - uint32_t lf = 0x0A; - - if (!call || !call->textstream) { - return -1; - } - - if (character == new_line || character == crlf || character == lf) { - if (lc && lp_config_get_int(lc->config, "misc", "store_rtt_messages", 1) == 1) { - ms_debug("New line sent, forge a message with content %s", msg->message); - msg->time = ms_time(0); - msg->state = LinphoneChatMessageStateDisplayed; - msg->dir = LinphoneChatMessageOutgoing; - if (msg->from) linphone_address_unref(msg->from); - msg->from = linphone_address_new(linphone_core_get_identity(lc)); - msg->storage_id = linphone_chat_message_store(msg); - ms_free(msg->message); - msg->message = NULL; - } - } else { - char *value = utf8_to_char(character); - msg->message = ms_strcat_printf(msg->message, value); - ms_debug("Sent RTT character: %s (%lu), pending text is %s", value, (unsigned long)character, msg->message); - ms_free(value); - } - - text_stream_putchar32(call->textstream, character); - return 0; -} - -const char* linphone_chat_message_get_message_id(const LinphoneChatMessage *cm) { - return cm->message_id; -} - -static int linphone_chat_room_stop_composing(void *data, unsigned int revents) { - LinphoneChatRoom *cr = (LinphoneChatRoom *)data; - cr->is_composing = LinphoneIsComposingIdle; - linphone_chat_room_send_is_composing_notification(cr); - linphone_chat_room_delete_composing_refresh_timer(cr); - belle_sip_object_unref(cr->composing_idle_timer); - cr->composing_idle_timer = NULL; - return BELLE_SIP_STOP; -} - -static int linphone_chat_room_refresh_composing(void *data, unsigned int revents) { - LinphoneChatRoom *cr = (LinphoneChatRoom *)data; - linphone_chat_room_send_is_composing_notification(cr); - return BELLE_SIP_CONTINUE; -} - -void linphone_chat_room_compose(LinphoneChatRoom *cr) { - int idle_timeout = - lp_config_get_int(cr->lc->config, "sip", "composing_idle_timeout", COMPOSING_DEFAULT_IDLE_TIMEOUT); - int refresh_timeout = - lp_config_get_int(cr->lc->config, "sip", "composing_refresh_timeout", COMPOSING_DEFAULT_REFRESH_TIMEOUT); - if (cr->is_composing == LinphoneIsComposingIdle) { - cr->is_composing = LinphoneIsComposingActive; - linphone_chat_room_send_is_composing_notification(cr); - if (!cr->composing_refresh_timer) { - cr->composing_refresh_timer = sal_create_timer(cr->lc->sal, linphone_chat_room_refresh_composing, cr, - refresh_timeout * 1000, "composing refresh timeout"); - } else { - belle_sip_source_set_timeout(cr->composing_refresh_timer, refresh_timeout * 1000); - } - if (!cr->composing_idle_timer) { - cr->composing_idle_timer = sal_create_timer(cr->lc->sal, linphone_chat_room_stop_composing, cr, - idle_timeout * 1000, "composing idle timeout"); - } - } - belle_sip_source_set_timeout(cr->composing_idle_timer, idle_timeout * 1000); -} - -const char *linphone_chat_message_state_to_string(const LinphoneChatMessageState state) { - switch (state) { - case LinphoneChatMessageStateIdle: - return "LinphoneChatMessageStateIdle"; - case LinphoneChatMessageStateInProgress: - return "LinphoneChatMessageStateInProgress"; - case LinphoneChatMessageStateDelivered: - return "LinphoneChatMessageStateDelivered"; - case LinphoneChatMessageStateNotDelivered: - return "LinphoneChatMessageStateNotDelivered"; - case LinphoneChatMessageStateFileTransferError: - return "LinphoneChatMessageStateFileTransferError"; - case LinphoneChatMessageStateFileTransferDone: - return "LinphoneChatMessageStateFileTransferDone "; - case LinphoneChatMessageStateDeliveredToUser: - return "LinphoneChatMessageStateDeliveredToUser"; - case LinphoneChatMessageStateDisplayed: - return "LinphoneChatMessageStateDisplayed"; - } - return NULL; -} - -LinphoneChatRoom *linphone_chat_message_get_chat_room(LinphoneChatMessage *msg) { - return msg->chat_room; -} - -const LinphoneAddress *linphone_chat_message_get_peer_address(LinphoneChatMessage *msg) { - return linphone_chat_room_get_peer_address(msg->chat_room); -} - -void linphone_chat_message_set_user_data(LinphoneChatMessage *msg, void *ud) { - msg->message_userdata = ud; -} - -void *linphone_chat_message_get_user_data(const LinphoneChatMessage *msg) { - return msg->message_userdata; -} - -const char *linphone_chat_message_get_external_body_url(const LinphoneChatMessage *msg) { - return msg->external_body_url; -} - -void linphone_chat_message_set_external_body_url(LinphoneChatMessage *msg, const char *url) { - if (msg->external_body_url) { - ms_free(msg->external_body_url); - } - msg->external_body_url = url ? ms_strdup(url) : NULL; -} - -const char * linphone_chat_message_get_content_type(const LinphoneChatMessage *msg) { - return msg->content_type; -} - -void linphone_chat_message_set_content_type(LinphoneChatMessage *msg, const char *content_type) { - if (msg->content_type) { - ms_free(msg->content_type); - } - msg->content_type = content_type ? ms_strdup(content_type) : NULL; -} - -bool_t linphone_chat_message_is_file_transfer(const LinphoneChatMessage *msg) { - return is_file_transfer(msg->content_type); -} - -bool_t linphone_chat_message_is_text(const LinphoneChatMessage *msg) { - return is_text(msg->content_type); -} - -bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *msg) { - return msg->to_be_stored; -} - -void linphone_chat_message_set_to_be_stored(LinphoneChatMessage *msg, bool_t to_be_stored) { - msg->to_be_stored = to_be_stored; -} - -const char *linphone_chat_message_get_appdata(const LinphoneChatMessage *msg) { - return msg->appdata; -} - -void linphone_chat_message_set_appdata(LinphoneChatMessage *msg, const char *data) { - if (msg->appdata) { - ms_free(msg->appdata); - } - msg->appdata = data ? ms_strdup(data) : NULL; - linphone_chat_message_store_appdata(msg); -} - -void linphone_chat_message_set_from_address(LinphoneChatMessage *msg, const LinphoneAddress *from) { - if (msg->from) - linphone_address_unref(msg->from); - msg->from = linphone_address_clone(from); -} - -const LinphoneAddress *linphone_chat_message_get_from_address(const LinphoneChatMessage *msg) { - return msg->from; -} - -void linphone_chat_message_set_to_address(LinphoneChatMessage *msg, const LinphoneAddress *to) { - if (msg->to) - linphone_address_unref(msg->to); - msg->to = linphone_address_clone(to); -} - -const LinphoneAddress *linphone_chat_message_get_to_address(const LinphoneChatMessage *msg) { - if (msg->to) - return msg->to; - if (msg->dir == LinphoneChatMessageOutgoing) { - return msg->chat_room->peer_url; - } - return NULL; -} - -void linphone_chat_message_set_is_secured(LinphoneChatMessage *msg, bool_t secured) { - msg->is_secured = secured; -} - -bool_t linphone_chat_message_is_secured(LinphoneChatMessage *msg) { - return msg->is_secured; -} - -LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage *msg) { - return msg->dir == LinphoneChatMessageOutgoing ? msg->from : msg->to; -} - -time_t linphone_chat_message_get_time(const LinphoneChatMessage *msg) { - return msg->time; -} - -LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage *msg) { - return msg->state; -} - -const char *linphone_chat_message_get_text(LinphoneChatMessage *msg) { - if (msg->message && !msg->locale_message) { - msg->locale_message = bctbx_utf8_to_locale(msg->message); - } - return msg->locale_message; -} - -int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text) { - if (msg->message) - ms_free(msg->message); - if (msg->locale_message) { - ms_free(msg->locale_message); - } - - if (text) { - msg->message = bctbx_locale_to_utf8(text); - msg->locale_message = ms_strdup(text); - } else { - msg->message = NULL; - msg->locale_message = NULL; - } - - return 0; -} - -void linphone_chat_message_add_custom_header(LinphoneChatMessage *msg, const char *header_name, - const char *header_value) { - msg->custom_headers = sal_custom_header_append(msg->custom_headers, header_name, header_value); -} - -const char *linphone_chat_message_get_custom_header(LinphoneChatMessage *msg, const char *header_name) { - return sal_custom_header_find(msg->custom_headers, header_name); -} - -void linphone_chat_message_remove_custom_header(LinphoneChatMessage *msg, const char *header_name) { - msg->custom_headers = sal_custom_header_remove(msg->custom_headers, header_name); -} - -bool_t linphone_chat_message_is_read(LinphoneChatMessage *msg) { - LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg); - LinphoneCore *lc = linphone_chat_room_get_core(cr); - LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(lc); - if ((linphone_im_notif_policy_get_recv_imdn_displayed(policy) == TRUE) && (msg->state == LinphoneChatMessageStateDisplayed)) return TRUE; - if ((linphone_im_notif_policy_get_recv_imdn_delivered(policy) == TRUE) && (msg->state == LinphoneChatMessageStateDeliveredToUser || msg->state == LinphoneChatMessageStateDisplayed)) return TRUE; - return (msg->state == LinphoneChatMessageStateDelivered || msg->state == LinphoneChatMessageStateDisplayed || msg->state == LinphoneChatMessageStateDeliveredToUser); -} - -bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage *msg) { - return msg->dir == LinphoneChatMessageOutgoing; -} - -unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage *msg) { - return msg->storage_id; -} - -LinphoneChatMessage *linphone_chat_message_clone(const LinphoneChatMessage *msg) { - LinphoneChatMessage *new_message = linphone_chat_room_create_message(msg->chat_room, msg->message); - if (msg->external_body_url) - new_message->external_body_url = ms_strdup(msg->external_body_url); - if (msg->appdata) - new_message->appdata = ms_strdup(msg->appdata); - new_message->message_state_changed_cb = msg->message_state_changed_cb; - new_message->message_state_changed_user_data = msg->message_state_changed_user_data; - new_message->message_userdata = msg->message_userdata; - new_message->time = msg->time; - new_message->state = msg->state; - new_message->storage_id = msg->storage_id; - if (msg->from) - new_message->from = linphone_address_clone(msg->from); - if (msg->file_transfer_filepath) - new_message->file_transfer_filepath = ms_strdup(msg->file_transfer_filepath); - if (msg->file_transfer_information) - new_message->file_transfer_information = linphone_content_copy(msg->file_transfer_information); - return new_message; -} - -void linphone_chat_message_destroy(LinphoneChatMessage *msg) { - belle_sip_object_unref(msg); -} - -#define strfree0(str) \ - if (str) { \ - memset(str, 0, strlen(str)); \ - ms_free(str); \ - } - -static void _linphone_chat_message_destroy(LinphoneChatMessage *msg) { - if (msg->op) - sal_op_release(msg->op); - if (msg->ei) - linphone_error_info_unref(msg->ei); - strfree0(msg->message); - strfree0(msg->external_body_url); - strfree0(msg->appdata); - if (msg->from) - linphone_address_unref(msg->from); - if (msg->to) - linphone_address_unref(msg->to); - strfree0(msg->message_id); - if (msg->custom_headers) - sal_custom_header_free(msg->custom_headers); - strfree0(msg->content_type); - if (msg->file_transfer_information) { - linphone_content_unref(msg->file_transfer_information); - } - strfree0(msg->file_transfer_filepath); - if (msg->callbacks) { - linphone_chat_message_cbs_unref(msg->callbacks); - } -} - -LinphoneChatMessage *linphone_chat_message_ref(LinphoneChatMessage *msg) { - belle_sip_object_ref(msg); - return msg; -} - -void linphone_chat_message_unref(LinphoneChatMessage *msg) { - belle_sip_object_unref(msg); -} - -static void linphone_chat_message_deactivate(LinphoneChatMessage *msg){ - if (msg->file_transfer_information != NULL) { - _linphone_chat_message_cancel_file_transfer(msg, FALSE); - } - /*mark the chat msg as orphan (it has no chat room anymore)*/ - msg->chat_room = NULL; -} - -static void linphone_chat_message_release(LinphoneChatMessage *msg) { - linphone_chat_message_deactivate(msg); - linphone_chat_message_unref(msg); -} - -const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg) { - if (!msg->ei) ((LinphoneChatMessage*)msg)->ei = linphone_error_info_new(); /*let's do it mutable*/ - linphone_error_info_from_sal_op(msg->ei, msg->op); - return msg->ei; -} - -LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage *msg) { - return linphone_error_info_get_reason(linphone_chat_message_get_error_info(msg)); -} - -LinphoneChatMessageCbs *linphone_chat_message_get_callbacks(const LinphoneChatMessage *msg) { - return msg->callbacks; -} - -LinphoneCall *linphone_chat_room_get_call(const LinphoneChatRoom *room) { - return room->call; +unsigned int linphone_chat_message_store(LinphoneChatMessage *msg) { + // DO nothing, just for old JNI compat... + return 1; } diff --git a/coreapi/chat_file_transfer.c b/coreapi/chat_file_transfer.c deleted file mode 100644 index 5fb2ae4b5..000000000 --- a/coreapi/chat_file_transfer.c +++ /dev/null @@ -1,679 +0,0 @@ -/*************************************************************************** - * chat_file_transfer.c - * - * Sun Jun 5 19:34:18 2005 - * Copyright 2005 Simon Morlat - * Email simon dot morlat at linphone dot org - ****************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "linphone/core.h" -#include "private.h" -#include "ortp/b64.h" - -static bool_t file_transfer_in_progress_and_valid(LinphoneChatMessage* msg) { - return (msg->chat_room && msg->chat_room->lc && msg->http_request && !belle_http_request_is_cancelled(msg->http_request)); -} - -static void _release_http_request(LinphoneChatMessage* msg) { - if (msg->http_request) { - belle_sip_object_unref(msg->http_request); - msg->http_request = NULL; - if (msg->http_listener){ - belle_sip_object_unref(msg->http_listener); - msg->http_listener = NULL; - // unhold the reference that the listener was holding on the message - linphone_chat_message_unref(msg); - } - } -} - -static void linphone_chat_message_process_io_error_upload(void *data, const belle_sip_io_error_event_t *event) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - ms_error("I/O Error during file upload of msg [%p]", msg); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); - _release_http_request(msg); - linphone_chat_room_remove_transient_message(msg->chat_room, msg); - linphone_chat_message_unref(msg); -} - -static void linphone_chat_message_process_auth_requested_upload(void *data, belle_sip_auth_event_t *event) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - ms_error("Error during file upload: auth requested for msg [%p]", msg); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); - _release_http_request(msg); - linphone_chat_room_remove_transient_message(msg->chat_room, msg); - linphone_chat_message_unref(msg); -} - -static void linphone_chat_message_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 msg [%p]", msg); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateFileTransferError); - _release_http_request(msg); -} - -static void linphone_chat_message_process_auth_requested_download(void *data, belle_sip_auth_event_t *event) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - ms_error("Error during file download : auth requested for msg [%p]", msg); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateFileTransferError); - _release_http_request(msg); -} - -static void linphone_chat_message_file_transfer_on_progress(belle_sip_body_handler_t *bh, belle_sip_message_t *m, - void *data, size_t offset, size_t total) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - if (!file_transfer_in_progress_and_valid(msg)) { - ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__); - _release_http_request(msg); - return; - } - if (linphone_chat_message_cbs_get_file_transfer_progress_indication(msg->callbacks)) { - linphone_chat_message_cbs_get_file_transfer_progress_indication(msg->callbacks)( - msg, msg->file_transfer_information, offset, total); - } else { - /* Legacy: call back given by application level */ - linphone_core_notify_file_transfer_progress_indication(msg->chat_room->lc, msg, msg->file_transfer_information, - offset, total); - } -} - -static int on_send_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, - void *data, size_t offset, uint8_t *buffer, size_t *size) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - LinphoneCore *lc = NULL; - LinphoneImEncryptionEngine *imee = NULL; - int retval = -1; - - if (!file_transfer_in_progress_and_valid(msg)) { - if (msg->http_request) { - ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__); - _release_http_request(msg); - } - return BELLE_SIP_STOP; - } - - lc = msg->chat_room->lc; - /* if we've not reach the end of file yet, ask for more data */ - /* in case of file body handler, won't be called */ - if (msg->file_transfer_filepath == NULL && offset < linphone_content_get_size(msg->file_transfer_information)) { - /* get data from call back */ - LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb = linphone_chat_message_cbs_get_file_transfer_send(msg->callbacks); - if (file_transfer_send_cb) { - LinphoneBuffer *lb = file_transfer_send_cb(msg, msg->file_transfer_information, offset, *size); - if (lb == NULL) { - *size = 0; - } else { - *size = linphone_buffer_get_size(lb); - memcpy(buffer, linphone_buffer_get_content(lb), *size); - linphone_buffer_unref(lb); - } - } else { - /* Legacy */ - linphone_core_notify_file_transfer_send(lc, msg, msg->file_transfer_information, (char *)buffer, size); - } - } - - imee = linphone_core_get_im_encryption_engine(lc); - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsUploadingFileCb cb_process_uploading_file = linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs); - if (cb_process_uploading_file) { - size_t max_size = *size; - uint8_t *encrypted_buffer = (uint8_t *)ms_malloc0(max_size); - retval = cb_process_uploading_file(imee, msg, offset, (const uint8_t *)buffer, size, encrypted_buffer); - if (retval == 0) { - if (*size > max_size) { - ms_error("IM encryption engine process upload file callback returned a size bigger than the size of the buffer, so it will be truncated !"); - *size = max_size; - } - memcpy(buffer, encrypted_buffer, *size); - } - ms_free(encrypted_buffer); - } - } - - return retval <= 0 ? BELLE_SIP_CONTINUE : BELLE_SIP_STOP; -} - -static void on_send_end(belle_sip_user_body_handler_t *bh, void *data) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - LinphoneCore *lc = msg->chat_room->lc; - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc); - - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsUploadingFileCb cb_process_uploading_file = linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs); - if (cb_process_uploading_file) { - cb_process_uploading_file(imee, msg, 0, NULL, NULL, NULL); - } - } -} - -static void file_upload_end_background_task(LinphoneChatMessage *obj){ - if (obj->bg_task_id){ - ms_message("channel [%p]: ending file upload background task with id=[%lx].",obj,obj->bg_task_id); - sal_end_background_task(obj->bg_task_id); - obj->bg_task_id=0; - } -} - -static void file_upload_background_task_ended(LinphoneChatMessage *obj){ - ms_warning("channel [%p]: file upload background task has to be ended now, but work isn't finished.",obj); - file_upload_end_background_task(obj); -} - -static void file_upload_begin_background_task(LinphoneChatMessage *obj){ - if (obj->bg_task_id==0){ - obj->bg_task_id=sal_begin_background_task("file transfer upload",(void (*)(void*))file_upload_background_task_ended, obj); - if (obj->bg_task_id) ms_message("channel [%p]: starting file upload background task with id=[%lx].",obj,obj->bg_task_id); - } -} - -static void linphone_chat_message_process_response_from_post_file(void *data, - const belle_http_response_event_t *event) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - - if (msg->http_request && !file_transfer_in_progress_and_valid(msg)) { - ms_warning("Cancelled request for %s msg [%p], ignoring %s", msg->chat_room?"":"ORPHAN", msg, __FUNCTION__); - _release_http_request(msg); - return; - } - - /* check the answer code */ - if (event->response) { - int code = belle_http_response_get_status_code(event->response); - if (code == 204) { /* this is the reply to the first post to the server - an empty msg */ - /* start uploading the file */ - belle_sip_multipart_body_handler_t *bh; - char *first_part_header; - belle_sip_body_handler_t *first_part_bh; - - bool_t is_file_encryption_enabled = FALSE; - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(msg->chat_room->lc); - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb = - linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(imee_cbs); - if (is_encryption_enabled_for_file_transfer_cb) { - is_file_encryption_enabled = is_encryption_enabled_for_file_transfer_cb(imee, msg->chat_room); - } - } - /* shall we encrypt the file */ - if (is_file_encryption_enabled) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = - linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); - if (generate_file_transfer_key_cb) { - generate_file_transfer_key_cb(imee, msg->chat_room, msg); - } - /* temporary storage for the Content-disposition header value : use a generic filename to not leak it - * Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg - * sended to the */ - first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"filename.txt\""); - } else { - /* temporary storage for the Content-disposition header value */ - first_part_header = belle_sip_strdup_printf("form-data; name=\"File\"; filename=\"%s\"", - linphone_content_get_name(msg->file_transfer_information)); - } - - /* 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_body_handler_t *)belle_sip_user_body_handler_new( - linphone_content_get_size(msg->file_transfer_information), - linphone_chat_message_file_transfer_on_progress, NULL, NULL, - on_send_body, on_send_end, msg); - if (msg->file_transfer_filepath != NULL) { - belle_sip_user_body_handler_t *body_handler = (belle_sip_user_body_handler_t *)first_part_bh; - first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(msg->file_transfer_filepath, - NULL, msg); // No need to add again the callback for progression, otherwise it will be called twice - linphone_content_set_size(msg->file_transfer_information, belle_sip_file_body_handler_get_file_size((belle_sip_file_body_handler_t *)first_part_bh)); - belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)first_part_bh, body_handler); - } else if (linphone_content_get_buffer(msg->file_transfer_information) != NULL) { - first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer( - linphone_content_get_buffer(msg->file_transfer_information), - linphone_content_get_size(msg->file_transfer_information), linphone_chat_message_file_transfer_on_progress, msg); - } - - belle_sip_body_handler_add_header(first_part_bh, - belle_sip_header_create("Content-disposition", first_part_header)); - belle_sip_free(first_part_header); - belle_sip_body_handler_add_header(first_part_bh, - (belle_sip_header_t *)belle_sip_header_content_type_create( - linphone_content_get_type(msg->file_transfer_information), - linphone_content_get_subtype(msg->file_transfer_information))); - - /* insert it in a multipart body handler which will manage the boundaries of multipart msg */ - bh = belle_sip_multipart_body_handler_new(linphone_chat_message_file_transfer_on_progress, msg, first_part_bh, NULL); - - linphone_chat_message_ref(msg); - _release_http_request(msg); - file_upload_begin_background_task(msg); - linphone_chat_room_upload_file(msg); - belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(msg->http_request), BELLE_SIP_BODY_HANDLER(bh)); - linphone_chat_message_unref(msg); - } else if (code == 200) { /* file has been uploaded correctly, get server reply and send it */ - const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); - if (body && strlen(body) > 0) { - /* if we have an encryption key for the file, we must insert it into the msg and restore the correct - * filename */ - const char *content_key = linphone_content_get_key(msg->file_transfer_information); - size_t content_key_size = linphone_content_get_key_size(msg->file_transfer_information); - if (content_key != NULL) { - /* parse the msg body */ - xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body); - - xmlNodePtr cur = xmlDocGetRootElement(xmlMessageBody); - if (cur != NULL) { - cur = cur->xmlChildrenNode; - while (cur != NULL) { - if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { /* we found a file info node, check - it has a type="file" attribute */ - xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); - if (!xmlStrcmp(typeAttribute, - (const xmlChar *)"file")) { /* this is the node we are looking for : add a - file-key children node */ - xmlNodePtr fileInfoNodeChildren = - cur - ->xmlChildrenNode; /* need to parse the children node to update the file-name - one */ - /* convert key to base64 */ - size_t b64Size = b64::b64_encode(NULL, content_key_size, NULL, 0); - char *keyb64 = (char *)ms_malloc0(b64Size + 1); - int xmlStringLength; - - b64Size = b64::b64_encode(content_key, content_key_size, keyb64, b64Size); - keyb64[b64Size] = '\0'; /* libxml need a null terminated string */ - - /* add the node containing the key to the file-info node */ - xmlNewTextChild(cur, NULL, (const xmlChar *)"file-key", (const xmlChar *)keyb64); - xmlFree(typeAttribute); - ms_free(keyb64); - - /* look for the file-name node and update its content */ - while (fileInfoNodeChildren != NULL) { - if (!xmlStrcmp( - fileInfoNodeChildren->name, - (const xmlChar *)"file-name")) { /* we found a the file-name node, update - its content with the real filename */ - /* update node content */ - xmlNodeSetContent(fileInfoNodeChildren, - (const xmlChar *)(linphone_content_get_name( - msg->file_transfer_information))); - break; - } - fileInfoNodeChildren = fileInfoNodeChildren->next; - } - - /* dump the xml into msg->message */ - xmlDocDumpFormatMemoryEnc(xmlMessageBody, (xmlChar **)&msg->message, &xmlStringLength, - "UTF-8", 0); - - break; - } - xmlFree(typeAttribute); - } - cur = cur->next; - } - } - xmlFreeDoc(xmlMessageBody); - } else { /* no encryption key, transfer in plain, just copy the msg sent by server */ - msg->message = ms_strdup(body); - } - linphone_chat_message_set_content_type(msg, "application/vnd.gsma.rcs-ft-http+xml"); - linphone_chat_message_ref(msg); - linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone); - _release_http_request(msg); - _linphone_chat_room_send_message(msg->chat_room, msg); - file_upload_end_background_task(msg); - linphone_chat_message_unref(msg); - } else { - ms_warning("Received empty response from server, file transfer failed"); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); - _release_http_request(msg); - file_upload_end_background_task(msg); - linphone_chat_message_unref(msg); - } - } else if (code == 400) { - ms_warning("Received HTTP code response %d for file transfer, probably meaning file is too large", code); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateFileTransferError); - _release_http_request(msg); - file_upload_end_background_task(msg); - linphone_chat_message_unref(msg); - } else { - ms_warning("Unhandled HTTP code response %d for file transfer", code); - linphone_chat_message_update_state(msg, LinphoneChatMessageStateNotDelivered); - _release_http_request(msg); - file_upload_end_background_task(msg); - linphone_chat_message_unref(msg); - } - } -} - -const LinphoneContent *linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage *msg) { - return msg->file_transfer_information; -} - -static void on_recv_body(belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, void *data, size_t offset, uint8_t *buffer, size_t size) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - LinphoneCore *lc = NULL; - LinphoneImEncryptionEngine *imee = NULL; - int retval = -1; - uint8_t *decrypted_buffer = NULL; - - if (!msg->chat_room) { - linphone_chat_message_cancel_file_transfer(msg); - return; - } - lc = msg->chat_room->lc; - - if (lc == NULL){ - return; /*might happen during linphone_core_destroy()*/ - } - - if (!msg->http_request || belle_http_request_is_cancelled(msg->http_request)) { - ms_warning("Cancelled request for msg [%p], ignoring %s", msg, __FUNCTION__); - return; - } - - /* first call may be with a zero size, ignore it */ - if (size == 0) { - return; - } - - decrypted_buffer = (uint8_t *)ms_malloc0(size); - imee = linphone_core_get_im_encryption_engine(lc); - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs); - if (cb_process_downloading_file) { - retval = cb_process_downloading_file(imee, msg, offset, (const uint8_t *)buffer, size, decrypted_buffer); - if (retval == 0) { - memcpy(buffer, decrypted_buffer, size); - } - } - } - ms_free(decrypted_buffer); - - if (retval <= 0) { - if (msg->file_transfer_filepath == NULL) { - if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) { - LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size); - linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb); - linphone_buffer_unref(lb); - } else { - /* Legacy: call back given by application level */ - linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, (const char *)buffer, size); - } - } - } else { - ms_warning("File transfer decrypt failed with code %d", (int)retval); - linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError); - } - - return; -} - -static void on_recv_end(belle_sip_user_body_handler_t *bh, void *data) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - LinphoneCore *lc = msg->chat_room->lc; - LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(lc); - int retval = -1; - - if (imee) { - LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); - LinphoneImEncryptionEngineCbsDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs); - if (cb_process_downloading_file) { - retval = cb_process_downloading_file(imee, msg, 0, NULL, 0, NULL); - } - } - - if (retval <= 0) { - if (msg->file_transfer_filepath == NULL) { - if (linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)) { - LinphoneBuffer *lb = linphone_buffer_new(); - linphone_chat_message_cbs_get_file_transfer_recv(msg->callbacks)(msg, msg->file_transfer_information, lb); - linphone_buffer_unref(lb); - } else { - /* Legacy: call back given by application level */ - linphone_core_notify_file_transfer_recv(lc, msg, msg->file_transfer_information, NULL, 0); - } - } - } - - if (retval <= 0 && linphone_chat_message_get_state(msg) != LinphoneChatMessageStateFileTransferError) { - linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferDone); - } -} - -static LinphoneContent *linphone_chat_create_file_transfer_information_from_headers(const belle_sip_message_t *m) { - LinphoneContent *content = linphone_content_new(); - - belle_sip_header_content_length_t *content_length_hdr = - BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(m, "Content-Length")); - belle_sip_header_content_type_t *content_type_hdr = - BELLE_SIP_HEADER_CONTENT_TYPE(belle_sip_message_get_header(m, "Content-Type")); - const char *type = NULL, *subtype = NULL; - - linphone_content_set_name(content, ""); - - if (content_type_hdr) { - type = belle_sip_header_content_type_get_type(content_type_hdr); - subtype = belle_sip_header_content_type_get_subtype(content_type_hdr); - ms_message("Extracted content type %s / %s from header", type ? type : "", subtype ? subtype : ""); - if (type) - linphone_content_set_type(content, type); - if (subtype) - linphone_content_set_subtype(content, subtype); - } - - if (content_length_hdr) { - linphone_content_set_size(content, belle_sip_header_content_length_get_content_length(content_length_hdr)); - ms_message("Extracted content length %i from header", (int)linphone_content_get_size(content)); - } - - return content; -} - -static void linphone_chat_process_response_headers_from_get_file(void *data, const belle_http_response_event_t *event) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - if (event->response) { - /*we are receiving a response, set a specific body handler to acquire the response. - * if not done, belle-sip will create a memory body handler, the default*/ - belle_sip_message_t *response = BELLE_SIP_MESSAGE(event->response); - belle_sip_body_handler_t *body_handler = NULL; - size_t body_size = 0; - - if (msg->file_transfer_information == NULL) { - ms_warning("No file transfer information for msg %p: creating...", msg); - msg->file_transfer_information = linphone_chat_create_file_transfer_information_from_headers(response); - } - - if (msg->file_transfer_information) { - body_size = linphone_content_get_size(msg->file_transfer_information); - } - - - body_handler = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new(body_size, linphone_chat_message_file_transfer_on_progress, NULL, on_recv_body, NULL, on_recv_end, msg); - if (msg->file_transfer_filepath != NULL) { - belle_sip_user_body_handler_t *bh = (belle_sip_user_body_handler_t *)body_handler; - body_handler = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new( - msg->file_transfer_filepath, linphone_chat_message_file_transfer_on_progress, msg); - if (belle_sip_body_handler_get_size((belle_sip_body_handler_t *)body_handler) == 0) { - /* If the size of the body has not been initialized from the file stat, use the one from the - * file_transfer_information. */ - belle_sip_body_handler_set_size((belle_sip_body_handler_t *)body_handler, body_size); - } - belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)body_handler, bh); - } - belle_sip_message_set_body_handler((belle_sip_message_t *)event->response, body_handler); - } -} - -static void linphone_chat_process_response_from_get_file(void *data, const belle_http_response_event_t *event) { - LinphoneChatMessage *msg = (LinphoneChatMessage *)data; - /* check the answer code */ - if (event->response) { - int code = belle_http_response_get_status_code(event->response); - if (code >= 400 && code < 500) { - ms_warning("File transfer failed with code %d", code); - linphone_chat_message_set_state(msg, LinphoneChatMessageStateFileTransferError); - } else if (code != 200) { - ms_warning("Unhandled HTTP code response %d for file transfer", code); - } - _release_http_request(msg); - } -} - -int _linphone_chat_room_start_http_transfer(LinphoneChatMessage *msg, const char* url, const char* action, const belle_http_request_listener_callbacks_t *cbs) { - belle_generic_uri_t *uri = NULL; - const char* ua = linphone_core_get_user_agent(msg->chat_room->lc); - - if (url == NULL) { - ms_warning("Cannot process file transfer msg: no file remote URI configured."); - goto error; - } - uri = belle_generic_uri_parse(url); - if (uri == NULL || belle_generic_uri_get_host(uri)==NULL) { - ms_warning("Cannot process file transfer msg: incorrect file remote URI configured '%s'.", url); - goto error; - } - - msg->http_request = belle_http_request_create(action, uri, belle_sip_header_create("User-Agent", ua), NULL); - - if (msg->http_request == NULL) { - ms_warning("Could not create http request for uri %s", url); - goto error; - } - /* keep a reference to the http request to be able to cancel it during upload */ - belle_sip_object_ref(msg->http_request); - - /* give msg to listener to be able to start the actual file upload when server answer a 204 No content */ - msg->http_listener = belle_http_request_listener_create_from_callbacks(cbs, linphone_chat_message_ref(msg)); - belle_http_provider_send_request(msg->chat_room->lc->http_provider, msg->http_request, msg->http_listener); - return 0; -error: - if (uri) { - belle_sip_object_unref(uri); - } - return -1; -} - -int linphone_chat_room_upload_file(LinphoneChatMessage *msg) { - belle_http_request_listener_callbacks_t cbs = {0}; - int err; - - if (msg->http_request){ - ms_error("linphone_chat_room_upload_file(): there is already an upload in progress."); - return -1; - } - - cbs.process_response = linphone_chat_message_process_response_from_post_file; - cbs.process_io_error = linphone_chat_message_process_io_error_upload; - cbs.process_auth_requested = linphone_chat_message_process_auth_requested_upload; - err = _linphone_chat_room_start_http_transfer(msg, linphone_core_get_file_transfer_server(msg->chat_room->lc), "POST", &cbs); - if (err == -1){ - linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered); - } - return err; -} - -LinphoneStatus linphone_chat_message_download_file(LinphoneChatMessage *msg) { - belle_http_request_listener_callbacks_t cbs = {0}; - int err; - - if (msg->http_request){ - ms_error("linphone_chat_message_download_file(): there is already a download in progress"); - return -1; - } - 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 = linphone_chat_message_process_io_error_download; - cbs.process_auth_requested = linphone_chat_message_process_auth_requested_download; - err = _linphone_chat_room_start_http_transfer(msg, msg->external_body_url, "GET", &cbs); - if (err == -1) return -1; - /* start the download, status is In Progress */ - linphone_chat_message_set_state(msg, LinphoneChatMessageStateInProgress); - return 0; -} - -void linphone_chat_message_start_file_download(LinphoneChatMessage *msg, - LinphoneChatMessageStateChangedCb status_cb, void *ud) { - msg->message_state_changed_cb = status_cb; - msg->message_state_changed_user_data = ud; - linphone_chat_message_download_file(msg); -} - -void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_t unref) { - if (msg->http_request) { - if (msg->state == LinphoneChatMessageStateInProgress) { - linphone_chat_message_set_state(msg, LinphoneChatMessageStateNotDelivered); - } - if (!belle_http_request_is_cancelled(msg->http_request)) { - if (msg->chat_room) { - ms_message("Canceling file transfer %s - msg [%p] chat room[%p]" - , (msg->external_body_url == NULL) ? linphone_core_get_file_transfer_server(msg->chat_room->lc) : msg->external_body_url - , msg - , msg->chat_room); - belle_http_provider_cancel_request(msg->chat_room->lc->http_provider, msg->http_request); - if ((msg->dir == LinphoneChatMessageOutgoing) && unref) { - // must release it - linphone_chat_message_unref(msg); - } - } else { - ms_message("Warning: http request still running for ORPHAN msg [%p]: this is a memory leak", msg); - } - } - _release_http_request(msg); - } else { - ms_message("No existing file transfer - nothing to cancel"); - } -} - -void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg) { - _linphone_chat_message_cancel_file_transfer(msg, TRUE); -} - -void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath) { - if (msg->file_transfer_filepath != NULL) { - ms_free(msg->file_transfer_filepath); - } - msg->file_transfer_filepath = ms_strdup(filepath); -} - -const char *linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg) { - return msg->file_transfer_filepath; -} - -LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, - const LinphoneContent *initial_content) { - LinphoneChatMessage *msg = belle_sip_object_new(LinphoneChatMessage); - msg->callbacks = linphone_chat_message_cbs_new(); - msg->chat_room = (LinphoneChatRoom *)cr; - msg->message = NULL; - msg->file_transfer_information = linphone_content_copy(initial_content); - msg->dir = LinphoneChatMessageOutgoing; - linphone_chat_message_set_to(msg, linphone_chat_room_get_peer_address(cr)); - msg->from = linphone_address_new(linphone_core_get_identity(cr->lc)); /*direct assignment*/ - /* 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->content_type = NULL; - /* this will store the http request during file upload to the server */ - msg->http_request = NULL; - msg->time = ms_time(0); - return msg; -} diff --git a/coreapi/conference.cc b/coreapi/conference.cc index d743cd280..06b35378a 100644 --- a/coreapi/conference.cc +++ b/coreapi/conference.cc @@ -23,20 +23,32 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "linphone/core.h" -#include "private.h" -#include "conference_private.h" -#include -#include -#include #include +#include #include +#include + +#include + +#include "linphone/core.h" + +#include "conference_private.h" + +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "conference/params/media-session-params-p.h" +#include "core/core-p.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" + +using namespace std; namespace Linphone { template -inline std::list<_type> toStd(const bctbx_list_t *l){ - std::list<_type> ret; +inline list<_type> toStd(const bctbx_list_t *l){ + list<_type> ret; for(; l != NULL; l = l->next){ ret.push_back(static_cast<_type>(l->data)); } @@ -54,8 +66,8 @@ public: ~Participant() { linphone_address_unref(m_uri); - if(m_call) m_call->conf_ref = NULL; - + if(m_call) + _linphone_call_set_conf_ref(m_call, nullptr); } const LinphoneAddress *getUri() const { @@ -107,7 +119,7 @@ public: const Params &getCurrentParams() const {return m_currentParams;} - virtual int inviteAddresses(const std::list &addresses, const LinphoneCallParams *params) = 0; + virtual int inviteAddresses(const list &addresses, const LinphoneCallParams *params) = 0; virtual int addParticipant(LinphoneCall *call) = 0; virtual int removeParticipant(LinphoneCall *call) = 0; virtual int removeParticipant(const LinphoneAddress *uri) = 0; @@ -123,7 +135,7 @@ public: float getInputVolume() const; virtual int getSize() const {return (int)m_participants.size() + (isIn()?1:0);} - const std::list &getParticipants() const {return m_participants;} + const list &getParticipants() const {return m_participants;} virtual int startRecording(const char *path) = 0; virtual int stopRecording() = 0; @@ -151,11 +163,11 @@ protected: Participant *findParticipant(const LinphoneAddress *uri) const; protected: - std::string m_conferenceID; + string m_conferenceID; LinphoneCore *m_core; AudioStream *m_localParticipantStream; bool m_isMuted; - std::list m_participants; + list m_participants; Params m_currentParams; LinphoneConferenceState m_state; LinphoneConference *m_conference; @@ -166,23 +178,25 @@ public: LocalConference(LinphoneCore *core, LinphoneConference *conf, const Params *params = NULL); virtual ~LocalConference(); - virtual int inviteAddresses(const std::list &addresses, const LinphoneCallParams *params); - virtual int addParticipant(LinphoneCall *call); - virtual int removeParticipant(LinphoneCall *call); - virtual int removeParticipant(const LinphoneAddress *uri); - virtual int terminate(); + virtual int inviteAddresses(const list &addresses, const LinphoneCallParams *params) override; + virtual int addParticipant(LinphoneCall *call) override; + virtual int removeParticipant(LinphoneCall *call) override; + virtual int removeParticipant(const LinphoneAddress *uri) override; + virtual int terminate() override; - virtual int enter(); - virtual int leave(); - virtual bool isIn() const {return m_localParticipantStream!=NULL;} - virtual int getSize() const; + virtual int enter() override; + virtual int leave() override; + virtual bool isIn() const override { + return m_localParticipantStream!=NULL; + } + virtual int getSize() const override; - virtual int startRecording(const char *path); - virtual int stopRecording(); + virtual int startRecording(const char *path) override; + virtual int stopRecording() override; - virtual void onCallStreamStarting(LinphoneCall *call, bool isPausedByRemote); - virtual void onCallStreamStopping(LinphoneCall *call); - virtual void onCallTerminating(LinphoneCall *call); + virtual void onCallStreamStarting(LinphoneCall *call, bool isPausedByRemote) override; + virtual void onCallStreamStopping(LinphoneCall *call) override; + virtual void onCallTerminating(LinphoneCall *call) override; private: void addLocalEndpoint(); @@ -204,18 +218,24 @@ public: RemoteConference(LinphoneCore *core, LinphoneConference *conf, const Params *params = NULL); virtual ~RemoteConference(); - virtual int inviteAddresses(const std::list &addresses, const LinphoneCallParams *params); - virtual int addParticipant(LinphoneCall *call); - virtual int removeParticipant(LinphoneCall *call) {return -1;} - virtual int removeParticipant(const LinphoneAddress *uri); - virtual int terminate(); + virtual int inviteAddresses(const list &addresses, const LinphoneCallParams *params) override; + virtual int addParticipant(LinphoneCall *call) override; + virtual int removeParticipant(LinphoneCall *call) override { + return -1; + } + virtual int removeParticipant(const LinphoneAddress *uri) override; + virtual int terminate() override; - virtual int enter(); - virtual int leave(); - virtual bool isIn() const; + virtual int enter() override; + virtual int leave() override; + virtual bool isIn() const override; - virtual int startRecording(const char *path) {return 0;} - virtual int stopRecording() {return 0;} + virtual int startRecording (const char *path) override { + return 0; + } + virtual int stopRecording() override { + return 0; + } private: bool focusIsReady() const; @@ -233,8 +253,8 @@ private: char *m_focusContact; LinphoneCall *m_focusCall; LinphoneCoreCbs *m_coreCbs; - std::list m_pendingCalls; - std::list m_transferingCalls; + list m_pendingCalls; + list m_transferingCalls; }; }; @@ -244,122 +264,126 @@ using namespace Linphone; using namespace std; -Conference::Conference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params): +Conference::Conference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params) : m_core(core), - m_localParticipantStream(NULL), + m_localParticipantStream(nullptr), m_isMuted(false), m_currentParams(), m_state(LinphoneConferenceStopped), m_conference(conf) { - if(params) m_currentParams = *params; + if (params) + m_currentParams = *params; } -int Conference::addParticipant(LinphoneCall *call) { - Participant *p =new Participant(call); +int Conference::addParticipant (LinphoneCall *call) { + Participant *p = new Participant(call); m_participants.push_back(p); - call->conf_ref = m_conference; + _linphone_call_set_conf_ref(call, m_conference); return 0; } -int Conference::removeParticipant(LinphoneCall *call) { +int Conference::removeParticipant (LinphoneCall *call) { Participant *p = findParticipant(call); - if(p == NULL) return -1; + if (!p) + return -1; delete p; m_participants.remove(p); return 0; } -int Conference::removeParticipant(const LinphoneAddress *uri) { +int Conference::removeParticipant (const LinphoneAddress *uri) { Participant *p = findParticipant(uri); - if(p == NULL) return -1; + if (!p) + return -1; delete p; m_participants.remove(p); return 0; } -int Conference::terminate() { - for(list::iterator it = m_participants.begin(); it!=m_participants.end(); it++) { +int Conference::terminate () { + for (auto it = m_participants.begin(); it != m_participants.end(); it++) delete *it; - } m_participants.clear(); return 0; } -int Conference::muteMicrophone(bool val) { - if (val) { +int Conference::muteMicrophone (bool val) { + if (val) audio_stream_set_mic_gain(m_localParticipantStream, 0); - } else { + else audio_stream_set_mic_gain_db(m_localParticipantStream, m_core->sound_conf.soft_mic_lev); - } - if ( linphone_core_get_rtp_no_xmit_on_audio_mute(m_core) ){ + if (linphone_core_get_rtp_no_xmit_on_audio_mute(m_core)) audio_stream_mute_rtp(m_localParticipantStream, val); - } - m_isMuted=val; + m_isMuted = val; return 0; } -float Conference::getInputVolume() const { - AudioStream *st=m_localParticipantStream; - if (st && st->volsend && !m_isMuted){ - float vol=0; - ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); +float Conference::getInputVolume () const { + AudioStream *st = m_localParticipantStream; + if (st && st->volsend && !m_isMuted) { + float vol = 0; + ms_filter_call_method(st->volsend, MS_VOLUME_GET, &vol); return vol; - } return LINPHONE_VOLUME_DB_LOWEST; } -const char *Conference::stateToString(LinphoneConferenceState state) { +const char *Conference::stateToString (LinphoneConferenceState state) { switch(state) { - case LinphoneConferenceStopped: return "Stopped"; - case LinphoneConferenceStarting: return "Starting"; - case LinphoneConferenceRunning: return "Ready"; - case LinphoneConferenceStartingFailed: return "Startig failed"; - default: return "Invalid state"; + case LinphoneConferenceStopped: + return "Stopped"; + case LinphoneConferenceStarting: + return "Starting"; + case LinphoneConferenceRunning: + return "Ready"; + case LinphoneConferenceStartingFailed: + return "Starting failed"; + default: + return "Invalid state"; } } -void Conference::setState(LinphoneConferenceState state) { - if(m_state != state) { +void Conference::setState (LinphoneConferenceState state) { + if (m_state != state) { ms_message("Switching conference [%p] into state '%s'", this, stateToString(state)); m_state = state; - if(m_currentParams.m_stateChangedCb) { + if (m_currentParams.m_stateChangedCb) m_currentParams.m_stateChangedCb(m_conference, state, m_currentParams.m_userData); - } } } -Conference::Participant *Conference::findParticipant(const LinphoneCall *call) const { - for(list::const_iterator it=m_participants.begin(); it!=m_participants.end(); it++) { - if((*it)->getCall() == call) return *it; +Conference::Participant *Conference::findParticipant (const LinphoneCall *call) const { + for (auto it = m_participants.begin(); it != m_participants.end(); it++) { + if ((*it)->getCall() == call) + return *it; } - return NULL; + return nullptr; } -Conference::Participant *Conference::findParticipant(const LinphoneAddress *uri) const { - for(list::const_iterator it=m_participants.begin(); it!=m_participants.end(); it++) { - if(linphone_address_equal((*it)->getUri(), uri)) return *it; +Conference::Participant *Conference::findParticipant (const LinphoneAddress *uri) const { + for (auto it = m_participants.begin(); it != m_participants.end(); it++) { + if (linphone_address_equal((*it)->getUri(), uri)) + return *it; } - return NULL; + return nullptr; } -LocalConference::LocalConference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params): +LocalConference::LocalConference (LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params) : Conference(core, conf, params), - m_conf(NULL), - m_localEndpoint(NULL), - m_recordEndpoint(NULL), - m_localDummyProfile(NULL), + m_conf(nullptr), + m_localEndpoint(nullptr), + m_recordEndpoint(nullptr), + m_localDummyProfile(nullptr), m_terminating(FALSE) { - MSAudioConferenceParams ms_conf_params; - ms_conf_params.samplerate = lp_config_get_int(m_core->config, "sound","conference_rate",16000); - m_conf=ms_audio_conference_new(&ms_conf_params, core->factory); - m_state= LinphoneConferenceRunning; + ms_conf_params.samplerate = lp_config_get_int(m_core->config, "sound", "conference_rate", 16000); + m_conf = ms_audio_conference_new(&ms_conf_params, core->factory); + m_state = LinphoneConferenceRunning; } LocalConference::~LocalConference() { @@ -367,24 +391,24 @@ LocalConference::~LocalConference() { ms_audio_conference_destroy(m_conf); } -RtpProfile *LocalConference::sMakeDummyProfile(int samplerate){ - RtpProfile *prof=rtp_profile_new("dummy"); - PayloadType *pt=payload_type_clone(&payload_type_l16_mono); - pt->clock_rate=samplerate; - rtp_profile_set_payload(prof,0,pt); +RtpProfile *LocalConference::sMakeDummyProfile (int samplerate) { + RtpProfile *prof = rtp_profile_new("dummy"); + PayloadType *pt = payload_type_clone(&payload_type_l16_mono); + pt->clock_rate = samplerate; + rtp_profile_set_payload(prof, 0, pt); return prof; } -void LocalConference::addLocalEndpoint() { - /*create a dummy audiostream in order to extract the local part of it */ +void LocalConference::addLocalEndpoint () { + /* Create a dummy audiostream in order to extract the local part of it */ /* network address and ports have no meaning and are not used here. */ - AudioStream *st=audio_stream_new(m_core->factory, 65000,65001,FALSE); - MSSndCard *playcard=m_core->sound_conf.lsd_card ? - m_core->sound_conf.lsd_card : m_core->sound_conf.play_sndcard; - MSSndCard *captcard=m_core->sound_conf.capt_sndcard; - const MSAudioConferenceParams *params=ms_audio_conference_get_params(m_conf); - m_localDummyProfile=sMakeDummyProfile(params->samplerate); - + AudioStream *st = audio_stream_new(m_core->factory, 65000, 65001, FALSE); + MSSndCard *playcard = m_core->sound_conf.lsd_card + ? m_core->sound_conf.lsd_card + : m_core->sound_conf.play_sndcard; + MSSndCard *captcard = m_core->sound_conf.capt_sndcard; + const MSAudioConferenceParams *params = ms_audio_conference_get_params(m_conf); + m_localDummyProfile = sMakeDummyProfile(params->samplerate); audio_stream_start_full(st, m_localDummyProfile, "127.0.0.1", 65000, @@ -392,283 +416,282 @@ void LocalConference::addLocalEndpoint() { 65001, 0, 40, - NULL, - NULL, + nullptr, + nullptr, playcard, captcard, linphone_core_echo_cancellation_enabled(m_core) ); - _post_configure_audio_stream(st,m_core,FALSE); - m_localParticipantStream=st; - m_localEndpoint=ms_audio_endpoint_get_from_stream(st,FALSE); - ms_message("conference: adding local endpoint"); - ms_audio_conference_add_member(m_conf,m_localEndpoint); + _post_configure_audio_stream(st, m_core, FALSE); + m_localParticipantStream = st; + m_localEndpoint = ms_audio_endpoint_get_from_stream(st, FALSE); + ms_message("Conference: adding local endpoint"); + ms_audio_conference_add_member(m_conf, m_localEndpoint); } -int LocalConference::inviteAddresses(const std::list &addresses, const LinphoneCallParams *params){ - - for (std::list::const_iterator it = addresses.begin(); it != addresses.end(); ++it){ - const LinphoneAddress *addr = *it; - LinphoneCall * call = linphone_core_get_call_by_remote_address2(m_core, addr); - if (!call){ - /*start a new call by indicating that it has to be put into the conference directlly*/ - LinphoneCallParams * new_params = params ? linphone_call_params_copy(params) : linphone_core_create_call_params(m_core, NULL); - LinphoneCall *call; - /*toggle this flag so the call is immediately added to the conference upon acceptance*/ - new_params->in_conference = TRUE; - linphone_call_params_enable_video(new_params, FALSE); /*turn off video as it is not supported for conferencing at this time*/ - call = linphone_core_invite_address_with_params(m_core, addr, new_params); - if (!call){ +int LocalConference::inviteAddresses (const list &addresses, const LinphoneCallParams *params) { + for (const auto &address : addresses) { + LinphoneCall *call = linphone_core_get_call_by_remote_address2(m_core, address); + if (!call) { + /* Start a new call by indicating that it has to be put into the conference directly */ + LinphoneCallParams *new_params = params + ? linphone_call_params_copy(params) + : linphone_core_create_call_params(m_core, nullptr); + /* Toggle this flag so the call is immediately added to the conference upon acceptance */ + linphone_call_params_set_in_conference(new_params, TRUE); + /* Turn off video as it is not supported for conferencing at this time */ + linphone_call_params_enable_video(new_params, FALSE); + call = linphone_core_invite_address_with_params(m_core, address, new_params); + if (!call) ms_error("LocalConference::inviteAddresses(): could not invite participant"); - } linphone_call_params_unref(new_params); - }else{ - /*there is already a call to this address, so simply join it to the local conference if not already done*/ - if (!call->current_params->in_conference) + } else { + /* There is already a call to this address, so simply join it to the local conference if not already done */ + if (!linphone_call_params_get_in_conference(linphone_call_get_current_params(call))) addParticipant(call); } - /*if the local participant is not yet created, created it and it to the conference */ - if (!m_localEndpoint) addLocalEndpoint(); + /* If the local participant is not yet created, created it and it to the conference */ + if (!m_localEndpoint) + addLocalEndpoint(); } return 0; } -int LocalConference::addParticipant(LinphoneCall *call) { - if (call->current_params->in_conference){ +int LocalConference::addParticipant (LinphoneCall *call) { + if (linphone_call_params_get_in_conference(linphone_call_get_current_params(call))) { ms_error("Already in conference"); return -1; } - if (call->state==LinphoneCallPaused){ - call->params->in_conference=TRUE; - call->params->has_video=FALSE; + if (linphone_call_get_state(call) == LinphoneCallPaused) { + const_cast( + L_GET_PRIVATE(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams()))->setInConference(true); + const_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams())->enableVideo(false); linphone_call_resume(call); - }else if (call->state==LinphoneCallStreamsRunning){ + } else if (linphone_call_get_state(call) == LinphoneCallStreamsRunning) { LinphoneCallParams *params = linphone_core_create_call_params(m_core, call); - params->in_conference=TRUE; - params->has_video=FALSE; + linphone_call_params_set_in_conference(params, TRUE); + linphone_call_params_enable_video(params, FALSE); - if (call->audiostream || call->videostream){ - linphone_call_stop_media_streams(call); /*free the audio & video local resources*/ + if (L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio) + || L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeVideo)) { + linphone_call_stop_media_streams(call); /* Free the audio & video local resources */ linphone_call_init_media_streams(call); } - if (call==m_core->current_call){ - m_core->current_call=NULL; - } - /*this will trigger a reINVITE that will later redraw the streams */ - /*FIXME probably a bit too much to just redraw streams !*/ - linphone_call_update(call,params); + if (call == linphone_core_get_current_call(m_core)) + L_GET_PRIVATE_FROM_C_OBJECT(m_core)->setCurrentCall(nullptr); + /* This will trigger a reINVITE that will later redraw the streams */ + /* FIXME: probably a bit too much to just redraw streams! */ + linphone_call_update(call, params); linphone_call_params_unref(params); addLocalEndpoint(); - }else{ - ms_error("Call is in state %s, it cannot be added to the conference.",linphone_call_state_to_string(call->state)); + } else { + ms_error("Call is in state %s, it cannot be added to the conference", + linphone_call_state_to_string(linphone_call_get_state(call))); return -1; } return 0; } -int LocalConference::removeFromConference(LinphoneCall *call, bool_t active){ - int err=0; - char *str; - - if (!call->current_params->in_conference){ - if (call->params->in_conference){ +int LocalConference::removeFromConference (LinphoneCall *call, bool_t active) { + if (!linphone_call_params_get_in_conference(linphone_call_get_current_params(call))) { + if (linphone_call_params_get_in_conference(linphone_call_get_params(call))) { ms_warning("Not (yet) in conference, be patient"); return -1; - }else{ - ms_error("Not in a conference."); + } else { + ms_error("Not in a conference"); return -1; } } - call->params->in_conference=FALSE; + const_cast( + L_GET_PRIVATE(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams()))->setInConference(false); - str=linphone_call_get_remote_address_as_string(call); + char *str = linphone_call_get_remote_address_as_string(call); ms_message("%s will be removed from conference", str); ms_free(str); - if (active){ - LinphoneCallParams *params=linphone_call_params_copy(linphone_call_get_current_params(call)); - params->in_conference=FALSE; - // reconnect local audio with this call + int err = 0; + if (active) { + LinphoneCallParams *params = linphone_call_params_copy(linphone_call_get_current_params(call)); + linphone_call_params_set_in_conference(params, FALSE); + // Reconnect local audio with this call if (isIn()){ - ms_message("Leaving conference for reconnecting with unique call."); + ms_message("Leaving conference for reconnecting with unique call"); leave(); } ms_message("Updating call to actually remove from conference"); - err=linphone_call_update(call,params); + err = linphone_call_update(call, params); linphone_call_params_unref(params); - } else{ + } else { ms_message("Pausing call to actually remove from conference"); - err=_linphone_call_pause(call); + err = _linphone_call_pause(call); } return err; } -int LocalConference::remoteParticipantsCount() { - int count=getSize(); - if (count==0) return 0; - if (!m_localParticipantStream) return count; - return count -1; +int LocalConference::remoteParticipantsCount () { + int count = getSize(); + if (count == 0) + return 0; + if (!m_localParticipantStream) + return count; + return count - 1; } -int LocalConference::convertConferenceToCall(){ - int err=0; - bctbx_list_t *calls=m_core->calls; - - if (remoteParticipantsCount()!=1){ - ms_error("No unique call remaining in conference."); +int LocalConference::convertConferenceToCall () { + if (remoteParticipantsCount() != 1) { + ms_error("No unique call remaining in conference"); return -1; } - while (calls) { - LinphoneCall *rc=(LinphoneCall*)calls->data; - calls=calls->next; - if (rc->params->in_conference) { // not using current_param - bool_t active_after_removed=isIn(); - err=removeFromConference(rc, active_after_removed); - break; + list> calls = L_GET_CPP_PTR_FROM_C_OBJECT(m_core)->getCalls(); + for (auto it = calls.begin(); it != calls.end(); it++) { + shared_ptr call(*it); + if (L_GET_PRIVATE(call->getParams())->getInConference()) { + bool_t active_after_removed = isIn(); + return removeFromConference(L_GET_C_BACK_PTR(call), active_after_removed); } } - return err; + return 0; } -int LocalConference::removeParticipant(LinphoneCall *call) { - int err; - char * str=linphone_call_get_remote_address_as_string(call); +int LocalConference::removeParticipant (LinphoneCall *call) { + char *str = linphone_call_get_remote_address_as_string(call); ms_message("Removing call %s from the conference", str); ms_free(str); - err=removeFromConference(call, FALSE); - if (err){ - ms_error("Error removing participant from conference."); + int err = removeFromConference(call, FALSE); + if (err) { + ms_error("Error removing participant from conference"); return err; } - if (remoteParticipantsCount()==1){ - ms_message("conference size is 1: need to be converted to plain call"); - err=convertConferenceToCall(); - } else { - ms_message("the conference need not to be converted as size is %i", remoteParticipantsCount()); - } + if (remoteParticipantsCount() == 1) { + ms_message("Conference size is 1: need to be converted to plain call"); + err = convertConferenceToCall(); + } else + ms_message("The conference need not to be converted as size is %i", remoteParticipantsCount()); return err; } -int LocalConference::removeParticipant(const LinphoneAddress *uri) { +int LocalConference::removeParticipant (const LinphoneAddress *uri) { const Participant *participant = findParticipant(uri); - if(participant == NULL) return -1; + if (!participant) + return -1; LinphoneCall *call = participant->getCall(); - if(call == NULL) return -1; + if (!call) + return -1; return removeParticipant(call); } -int LocalConference::terminate() { - bctbx_list_t *calls=m_core->calls; - m_terminating =TRUE; +int LocalConference::terminate () { + m_terminating = TRUE; - while (calls) { - LinphoneCall *call=(LinphoneCall*)calls->data; - calls=calls->next; - if (call->current_params->in_conference) { - linphone_call_terminate(call); - } + list> calls = L_GET_CPP_PTR_FROM_C_OBJECT(m_core)->getCalls(); + for (auto it = calls.begin(); it != calls.end(); it++) { + shared_ptr call(*it); + if (L_GET_PRIVATE(call->getCurrentParams())->getInConference()) + call->terminate(); } Conference::terminate(); m_terminating = FALSE; - return 0; } -int LocalConference::enter() { - if (linphone_core_sound_resources_locked(m_core)) { +int LocalConference::enter () { + if (linphone_core_sound_resources_locked(m_core)) return -1; - } - if (m_core->current_call != NULL) { - _linphone_call_pause(m_core->current_call); - } - if (m_localParticipantStream==NULL) addLocalEndpoint(); + if (linphone_core_get_current_call(m_core)) + _linphone_call_pause(linphone_core_get_current_call(m_core)); + if (!m_localParticipantStream) + addLocalEndpoint(); return 0; } -void LocalConference::removeLocalEndpoint(){ - if (m_localEndpoint){ - ms_audio_conference_remove_member(m_conf,m_localEndpoint); +void LocalConference::removeLocalEndpoint () { + if (m_localEndpoint) { + ms_audio_conference_remove_member(m_conf, m_localEndpoint); ms_audio_endpoint_release_from_stream(m_localEndpoint); - m_localEndpoint=NULL; + m_localEndpoint = nullptr; audio_stream_stop(m_localParticipantStream); - m_localParticipantStream=NULL; + m_localParticipantStream = nullptr; rtp_profile_destroy(m_localDummyProfile); } } -int LocalConference::leave() { +int LocalConference::leave () { if (isIn()) removeLocalEndpoint(); return 0; } -int LocalConference::getSize() const { - if (m_conf == NULL) { +int LocalConference::getSize () const { + if (!m_conf) return 0; - } return ms_audio_conference_get_size(m_conf) - (m_recordEndpoint ? 1 : 0); } -int LocalConference::startRecording(const char *path) { - if (m_conf == NULL) { - ms_warning("linphone_core_start_conference_recording(): no conference now."); +int LocalConference::startRecording (const char *path) { + if (!m_conf) { + ms_warning("linphone_core_start_conference_recording(): no conference now"); return -1; } - if (m_recordEndpoint==NULL){ - m_recordEndpoint=ms_audio_endpoint_new_recorder(m_core->factory); - ms_audio_conference_add_member(m_conf,m_recordEndpoint); + if (!m_recordEndpoint) { + m_recordEndpoint = ms_audio_endpoint_new_recorder(m_core->factory); + ms_audio_conference_add_member(m_conf, m_recordEndpoint); } - ms_audio_recorder_endpoint_start(m_recordEndpoint,path); + ms_audio_recorder_endpoint_start(m_recordEndpoint, path); return 0; } -int LocalConference::stopRecording() { - if (m_conf == NULL) { - ms_warning("linphone_core_stop_conference_recording(): no conference now."); +int LocalConference::stopRecording () { + if (!m_conf) { + ms_warning("linphone_core_stop_conference_recording(): no conference now"); return -1; } - if (m_recordEndpoint==NULL){ - ms_warning("linphone_core_stop_conference_recording(): no record active."); + if (!m_recordEndpoint) { + ms_warning("linphone_core_stop_conference_recording(): no record active"); return -1; } ms_audio_recorder_endpoint_stop(m_recordEndpoint); return 0; } -void LocalConference::onCallStreamStarting(LinphoneCall *call, bool isPausedByRemote) { - call->params->has_video = FALSE; - call->camera_enabled = FALSE; - ms_message("LocalConference::onCallStreamStarting(): joining AudioStream [%p] of call [%p] into conference.", call->audiostream, call); - MSAudioEndpoint *ep=ms_audio_endpoint_get_from_stream(call->audiostream,TRUE); - ms_audio_conference_add_member(m_conf,ep); - ms_audio_conference_mute_member(m_conf,ep,isPausedByRemote); - call->endpoint=ep; +void LocalConference::onCallStreamStarting (LinphoneCall *call, bool isPausedByRemote) { + const_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams())->enableVideo(false); + L_GET_CPP_PTR_FROM_C_OBJECT(call)->enableCamera(false); + ms_message("LocalConference::onCallStreamStarting(): joining AudioStream [%p] of call [%p] into conference", + L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio), call); + MSAudioEndpoint *ep = ms_audio_endpoint_get_from_stream( + reinterpret_cast(L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio)), + TRUE); + ms_audio_conference_add_member(m_conf, ep); + ms_audio_conference_mute_member(m_conf, ep, isPausedByRemote); + _linphone_call_set_endpoint(call, ep); setState(LinphoneConferenceRunning); Conference::addParticipant(call); } -void LocalConference::onCallStreamStopping(LinphoneCall *call) { - ms_audio_conference_remove_member(m_conf,call->endpoint); - ms_audio_endpoint_release_from_stream(call->endpoint); - call->endpoint=NULL; +void LocalConference::onCallStreamStopping (LinphoneCall *call) { + ms_audio_conference_remove_member(m_conf, _linphone_call_get_endpoint(call)); + ms_audio_endpoint_release_from_stream(_linphone_call_get_endpoint(call)); + _linphone_call_set_endpoint(call, nullptr); Conference::removeParticipant(call); } -void LocalConference::onCallTerminating(LinphoneCall *call) { - int remote_count=remoteParticipantsCount(); +void LocalConference::onCallTerminating (LinphoneCall *call) { + int remote_count = remoteParticipantsCount(); ms_message("conference_check_uninit(): size=%i", getSize()); - if (remote_count==1 && !m_terminating){ + if ((remote_count == 1) && !m_terminating) convertConferenceToCall(); - } - if (remote_count==0){ + + if (remote_count == 0) { if (m_localParticipantStream){ removeLocalEndpoint(); linphone_core_soundcard_hint_check(m_core); } - if (m_recordEndpoint){ + if (m_recordEndpoint) { ms_audio_conference_remove_member(m_conf, m_recordEndpoint); ms_audio_endpoint_destroy(m_recordEndpoint); } @@ -678,11 +701,12 @@ void LocalConference::onCallTerminating(LinphoneCall *call) { -RemoteConference::RemoteConference(LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params): Conference(core, conf, params) { - m_focusAddr = NULL; - m_focusContact = NULL; - m_focusCall = NULL; - m_coreCbs = NULL; +RemoteConference::RemoteConference (LinphoneCore *core, LinphoneConference *conf, const Conference::Params *params) : + Conference(core, conf, params) { + m_focusAddr = nullptr; + m_focusContact = nullptr; + m_focusCall = nullptr; + m_coreCbs = nullptr; m_focusAddr = lp_config_get_string(m_core->config, "misc", "conference_focus_addr", ""); m_coreCbs = linphone_factory_create_core_cbs(linphone_factory_get()); linphone_core_cbs_set_call_state_changed(m_coreCbs, callStateChangedCb); @@ -691,160 +715,161 @@ RemoteConference::RemoteConference(LinphoneCore *core, LinphoneConference *conf, _linphone_core_add_callbacks(m_core, m_coreCbs, TRUE); } -RemoteConference::~RemoteConference() { +RemoteConference::~RemoteConference () { terminate(); linphone_core_remove_callbacks(m_core, m_coreCbs); linphone_core_cbs_unref(m_coreCbs); } -int RemoteConference::inviteAddresses(const std::list &addresses, const LinphoneCallParams *params){ +int RemoteConference::inviteAddresses (const list &addresses, const LinphoneCallParams *params) { ms_error("RemoteConference::inviteAddresses() not implemented"); return -1; } -int RemoteConference::addParticipant(LinphoneCall *call) { +int RemoteConference::addParticipant (LinphoneCall *call) { LinphoneAddress *addr; LinphoneCallParams *params; - - switch(m_state) { + LinphoneCallLog *callLog; + switch (m_state) { case LinphoneConferenceStopped: case LinphoneConferenceStartingFailed: Conference::addParticipant(call); ms_message("Calling the conference focus (%s)", m_focusAddr); addr = linphone_address_new(m_focusAddr); - if(addr) { - params = linphone_core_create_call_params(m_core, NULL); - linphone_call_params_enable_video(params, m_currentParams.videoRequested()); - m_focusCall = linphone_core_invite_address_with_params(m_core, addr, params); - m_localParticipantStream = m_focusCall->audiostream; - m_pendingCalls.push_back(call); - LinphoneCallLog *callLog = linphone_call_get_call_log(m_focusCall); - callLog->was_conference = TRUE; - linphone_address_unref(addr); - linphone_call_params_unref(params); - setState(LinphoneConferenceStarting); - return 0; - } else return -1; - + if (!addr) + return -1; + params = linphone_core_create_call_params(m_core, nullptr); + linphone_call_params_enable_video(params, m_currentParams.videoRequested()); + m_focusCall = linphone_core_invite_address_with_params(m_core, addr, params); + m_localParticipantStream = reinterpret_cast( + L_GET_PRIVATE_FROM_C_OBJECT(m_focusCall)->getMediaStream(LinphoneStreamTypeAudio)); + m_pendingCalls.push_back(call); + callLog = linphone_call_get_call_log(m_focusCall); + callLog->was_conference = TRUE; + linphone_address_unref(addr); + linphone_call_params_unref(params); + setState(LinphoneConferenceStarting); + return 0; case LinphoneConferenceStarting: Conference::addParticipant(call); - if(focusIsReady()) { + if(focusIsReady()) transferToFocus(call); - } else { + else m_pendingCalls.push_back(call); - } return 0; - case LinphoneConferenceRunning: Conference::addParticipant(call); transferToFocus(call); return 0; - default: ms_error("Could not add call %p to the conference. Bad conference state (%s)", call, stateToString(m_state)); return -1; } } -int RemoteConference::removeParticipant(const LinphoneAddress *uri) { +int RemoteConference::removeParticipant (const LinphoneAddress *uri) { char *refer_to; LinphoneAddress *refer_to_addr; int res; - switch(m_state) { + switch (m_state) { case LinphoneConferenceRunning: - if(findParticipant(uri) == NULL) { + if(!findParticipant(uri)) { char *tmp = linphone_address_as_string(uri); ms_error("Conference: could not remove participant '%s': not in the participants list", tmp); ms_free(tmp); return -1; } - refer_to_addr = linphone_address_clone(uri); linphone_address_set_method_param(refer_to_addr, "BYE"); refer_to = linphone_address_as_string(refer_to_addr); linphone_address_unref(refer_to_addr); - res = sal_call_refer(m_focusCall->op, refer_to); + res = linphone_call_get_op(m_focusCall)->refer(refer_to); ms_free(refer_to); - - if(res == 0) { + if (res == 0) return Conference::removeParticipant(uri); - } else { + else { char *tmp = linphone_address_as_string(uri); ms_error("Conference: could not remove participant '%s': REFER with BYE has failed", tmp); ms_free(tmp); return -1; } - default: - ms_error("Cannot remove %s from conference: Bad conference state (%s)", linphone_address_as_string(uri), stateToString(m_state)); + ms_error("Cannot remove %s from conference: Bad conference state (%s)", + linphone_address_as_string(uri), stateToString(m_state)); return -1; } } -int RemoteConference::terminate() { - switch(m_state) { +int RemoteConference::terminate () { + switch (m_state) { case LinphoneConferenceRunning: case LinphoneConferenceStarting: linphone_call_terminate(m_focusCall); break; - - default: break; + default: + break; } return 0; } -int RemoteConference::enter() { - if(m_state != LinphoneConferenceRunning) { +int RemoteConference::enter () { + if (m_state != LinphoneConferenceRunning) { ms_error("Could not enter in the conference: bad conference state (%s)", stateToString(m_state)); return -1; } LinphoneCallState callState = linphone_call_get_state(m_focusCall); - switch(callState) { - case LinphoneCallStreamsRunning: break; + switch (callState) { + case LinphoneCallStreamsRunning: + break; case LinphoneCallPaused: linphone_call_resume(m_focusCall); break; default: - ms_error("Could not join the conference: bad focus call state (%s)", linphone_call_state_to_string(callState)); + ms_error("Could not join the conference: bad focus call state (%s)", + linphone_call_state_to_string(callState)); return -1; } return 0; } -int RemoteConference::leave() { - if(m_state != LinphoneConferenceRunning) { +int RemoteConference::leave () { + if (m_state != LinphoneConferenceRunning) { ms_error("Could not leave the conference: bad conference state (%s)", stateToString(m_state)); return -1; } LinphoneCallState callState = linphone_call_get_state(m_focusCall); - switch(callState) { - case LinphoneCallPaused: break; + switch (callState) { + case LinphoneCallPaused: + break; case LinphoneCallStreamsRunning: linphone_call_pause(m_focusCall); break; default: - ms_error("Could not leave the conference: bad focus call state (%s)", linphone_call_state_to_string(callState)); + ms_error("Could not leave the conference: bad focus call state (%s)", + linphone_call_state_to_string(callState)); return -1; } return 0; } -bool RemoteConference::isIn() const { - if(m_state != LinphoneConferenceRunning) return false; +bool RemoteConference::isIn () const { + if (m_state != LinphoneConferenceRunning) + return false; LinphoneCallState callState = linphone_call_get_state(m_focusCall); return callState == LinphoneCallStreamsRunning; } -bool RemoteConference::focusIsReady() const { +bool RemoteConference::focusIsReady () const { LinphoneCallState focusState; - if(m_focusCall == NULL) return false; + if (!m_focusCall) + return false; focusState = linphone_call_get_state(m_focusCall); - return focusState == LinphoneCallStreamsRunning || focusState == LinphoneCallPaused; + return (focusState == LinphoneCallStreamsRunning) || (focusState == LinphoneCallPaused); } -bool RemoteConference::transferToFocus(LinphoneCall *call) { - if(linphone_call_transfer(call, m_focusContact) == 0) { +bool RemoteConference::transferToFocus (LinphoneCall *call) { + if (linphone_call_transfer(call, m_focusContact) == 0) { m_transferingCalls.push_back(call); return true; } else { @@ -853,21 +878,20 @@ bool RemoteConference::transferToFocus(LinphoneCall *call) { } } -void RemoteConference::reset() { - m_localParticipantStream = NULL; - m_focusAddr = NULL; +void RemoteConference::reset () { + m_localParticipantStream = nullptr; + m_focusAddr = nullptr; if(m_focusContact) { ms_free(m_focusContact); - m_focusContact = NULL; + m_focusContact = nullptr; } - m_focusCall = NULL; + m_focusCall = nullptr; m_pendingCalls.clear(); m_transferingCalls.clear(); } -void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) { +void RemoteConference::onFocusCallSateChanged (LinphoneCallState state) { list::iterator it; - switch (state) { case LinphoneCallConnected: m_focusContact = ms_strdup(linphone_call_get_remote_contact(m_focusCall)); @@ -875,101 +899,91 @@ void RemoteConference::onFocusCallSateChanged(LinphoneCallState state) { while (it != m_pendingCalls.end()) { LinphoneCall *pendingCall = *it; LinphoneCallState pendingCallState = linphone_call_get_state(pendingCall); - if(pendingCallState == LinphoneCallStreamsRunning || pendingCallState == LinphoneCallPaused) { + if ((pendingCallState == LinphoneCallStreamsRunning) || (pendingCallState == LinphoneCallPaused)) { it = m_pendingCalls.erase(it); transferToFocus(pendingCall); - } else { + } else it++; - } } setState(LinphoneConferenceRunning); break; - case LinphoneCallError: reset(); Conference::terminate(); setState(LinphoneConferenceStartingFailed); break; - case LinphoneCallEnd: reset(); Conference::terminate(); setState(LinphoneConferenceStopped); break; - - default: break; - } -} - -void RemoteConference::onPendingCallStateChanged(LinphoneCall *call, LinphoneCallState state) { - switch(state) { - case LinphoneCallStreamsRunning: - case LinphoneCallPaused: - if(m_state == LinphoneConferenceRunning) { - m_pendingCalls.remove(call); - m_transferingCalls.push_back(call); - linphone_call_transfer(call, m_focusContact); - } - break; - - case LinphoneCallError: - case LinphoneCallEnd: - m_pendingCalls.remove(call); - Conference::removeParticipant(call); - if(m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size() == 0) { - terminate(); - } - break; - - default: break; - } -} - -void RemoteConference::onTransferingCallStateChanged(LinphoneCall* transfered, LinphoneCallState newCallState) { - switch (newCallState) { - case LinphoneCallConnected: - m_transferingCalls.push_back(transfered); - findParticipant(transfered)->m_call = NULL; - break; - - case LinphoneCallError: - m_transferingCalls.remove(transfered); - Conference::removeParticipant(transfered); - if(m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size() == 0) { - terminate(); - } - break; - default: break; } } -void RemoteConference::callStateChangedCb(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { - LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc); - RemoteConference *conf = (RemoteConference *)linphone_core_v_table_get_user_data(vtable); - if (call == conf->m_focusCall) { - conf->onFocusCallSateChanged(cstate); - } else { - list::iterator it = find(conf->m_pendingCalls.begin(), conf->m_pendingCalls.end(), call); - if(it != conf->m_pendingCalls.end()) { - conf->onPendingCallStateChanged(call, cstate); - } +void RemoteConference::onPendingCallStateChanged (LinphoneCall *call, LinphoneCallState state) { + switch (state) { + case LinphoneCallStreamsRunning: + case LinphoneCallPaused: + if (m_state == LinphoneConferenceRunning) { + m_pendingCalls.remove(call); + m_transferingCalls.push_back(call); + linphone_call_transfer(call, m_focusContact); + } + break; + case LinphoneCallError: + case LinphoneCallEnd: + m_pendingCalls.remove(call); + Conference::removeParticipant(call); + if ((m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size()) == 0) + terminate(); + break; + default: + break; } } -void RemoteConference::transferStateChanged(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { +void RemoteConference::onTransferingCallStateChanged (LinphoneCall* transfered, LinphoneCallState newCallState) { + switch (newCallState) { + case LinphoneCallConnected: + m_transferingCalls.push_back(transfered); + findParticipant(transfered)->m_call = nullptr; + break; + case LinphoneCallError: + m_transferingCalls.remove(transfered); + Conference::removeParticipant(transfered); + if ((m_participants.size() + m_pendingCalls.size() + m_transferingCalls.size()) == 0) + terminate(); + break; + default: + break; + } +} + +void RemoteConference::callStateChangedCb (LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { + LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc); + RemoteConference *conf = (RemoteConference *)linphone_core_v_table_get_user_data(vtable); + if (call == conf->m_focusCall) + conf->onFocusCallSateChanged(cstate); + else { + list::iterator it = find(conf->m_pendingCalls.begin(), conf->m_pendingCalls.end(), call); + if (it != conf->m_pendingCalls.end()) + conf->onPendingCallStateChanged(call, cstate); + } +} + +void RemoteConference::transferStateChanged (LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { LinphoneCoreVTable *vtable = linphone_core_get_current_vtable(lc); RemoteConference *conf = (RemoteConference *)linphone_core_v_table_get_user_data(vtable); list::iterator it = find(conf->m_transferingCalls.begin(), conf->m_transferingCalls.end(), transfered); - if (it != conf->m_transferingCalls.end()) { + if (it != conf->m_transferingCalls.end()) conf->onTransferingCallStateChanged(transfered, new_call_state); - } } -const char *linphone_conference_state_to_string(LinphoneConferenceState state) { +const char *linphone_conference_state_to_string (LinphoneConferenceState state) { return Conference::stateToString(state); } @@ -991,45 +1005,45 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneConferenceParams, belle_sip_object_t, FALSE // unown ); -LinphoneConferenceParams *linphone_conference_params_new(const LinphoneCore *core) { +LinphoneConferenceParams *linphone_conference_params_new (const LinphoneCore *core) { LinphoneConferenceParams *obj = belle_sip_object_new(LinphoneConferenceParams); obj->params = new Conference::Params(core); return obj; } -static void _linphone_conference_params_uninit(LinphoneConferenceParams *params) { +static void _linphone_conference_params_uninit (LinphoneConferenceParams *params) { delete params->params; } -LinphoneConferenceParams *linphone_conference_params_ref(LinphoneConferenceParams *params) { +LinphoneConferenceParams *linphone_conference_params_ref (LinphoneConferenceParams *params) { return (LinphoneConferenceParams *)belle_sip_object_ref(params); } -void linphone_conference_params_unref(LinphoneConferenceParams *params) { +void linphone_conference_params_unref (LinphoneConferenceParams *params) { belle_sip_object_unref(params); } -void linphone_conference_params_free(LinphoneConferenceParams *params) { +void linphone_conference_params_free (LinphoneConferenceParams *params) { linphone_conference_params_unref(params); } -static void _linphone_conference_params_clone(LinphoneConferenceParams *params, const LinphoneConferenceParams *orig) { +static void _linphone_conference_params_clone (LinphoneConferenceParams *params, const LinphoneConferenceParams *orig) { params->params = new Conference::Params(*orig->params); } -LinphoneConferenceParams *linphone_conference_params_clone(const LinphoneConferenceParams *params) { +LinphoneConferenceParams *linphone_conference_params_clone (const LinphoneConferenceParams *params) { return (LinphoneConferenceParams *)belle_sip_object_clone((const belle_sip_object_t *)params); } -void linphone_conference_params_enable_video(LinphoneConferenceParams *params, bool_t enable) { +void linphone_conference_params_enable_video (LinphoneConferenceParams *params, bool_t enable) { params->params->enableVideo(enable ? true : false); } -bool_t linphone_conference_params_video_requested(const LinphoneConferenceParams *params) { +bool_t linphone_conference_params_video_requested (const LinphoneConferenceParams *params) { return params->params->videoRequested() ? TRUE : FALSE; } -void linphone_conference_params_set_state_changed_callback(LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data) { +void linphone_conference_params_set_state_changed_callback (LinphoneConferenceParams *params, LinphoneConferenceStateChangedCb cb, void *user_data) { params->params->setStateChangedCallback(cb, user_data); } @@ -1039,7 +1053,7 @@ struct _LinphoneConference { Conference *conf; }; -static void _linphone_conference_uninit(LinphoneConference *conf); +static void _linphone_conference_uninit (LinphoneConference *conf); BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneConference); BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneConference); @@ -1050,140 +1064,143 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneConference, belle_sip_object_t, FALSE // unown ); -LinphoneConference *linphone_local_conference_new(LinphoneCore *core) { +LinphoneConference *linphone_local_conference_new (LinphoneCore *core) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new LocalConference(core, conf); return conf; } -LinphoneConference *linphone_local_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params) { +LinphoneConference *linphone_local_conference_new_with_params (LinphoneCore *core, const LinphoneConferenceParams *params) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new LocalConference(core, conf, params->params); return conf; } -LinphoneConference *linphone_remote_conference_new(LinphoneCore *core) { +LinphoneConference *linphone_remote_conference_new (LinphoneCore *core) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new RemoteConference(core, conf); return conf; } -LinphoneConference *linphone_remote_conference_new_with_params(LinphoneCore *core, const LinphoneConferenceParams *params) { +LinphoneConference *linphone_remote_conference_new_with_params (LinphoneCore *core, const LinphoneConferenceParams *params) { LinphoneConference *conf = belle_sip_object_new(LinphoneConference); conf->conf = new RemoteConference(core, conf, params->params); return conf; } -static void _linphone_conference_uninit(LinphoneConference *conf) { +static void _linphone_conference_uninit (LinphoneConference *conf) { delete conf->conf; } -LinphoneConference *linphone_conference_ref(LinphoneConference *conf) { +LinphoneConference *linphone_conference_ref (LinphoneConference *conf) { return (LinphoneConference *)belle_sip_object_ref(conf); } -void linphone_conference_unref(LinphoneConference *conf) { +void linphone_conference_unref (LinphoneConference *conf) { belle_sip_object_unref(conf); } -LinphoneConferenceState linphone_conference_get_state(const LinphoneConference *obj) { +LinphoneConferenceState linphone_conference_get_state (const LinphoneConference *obj) { return obj->conf->getState(); } -int linphone_conference_add_participant(LinphoneConference *obj, LinphoneCall *call) { +int linphone_conference_add_participant (LinphoneConference *obj, LinphoneCall *call) { return obj->conf->addParticipant(call); } -LinphoneStatus linphone_conference_remove_participant(LinphoneConference *obj, const LinphoneAddress *uri) { +LinphoneStatus linphone_conference_remove_participant (LinphoneConference *obj, const LinphoneAddress *uri) { return obj->conf->removeParticipant(uri); } -int linphone_conference_remove_participant_with_call(LinphoneConference *obj, LinphoneCall *call) { +int linphone_conference_remove_participant_with_call (LinphoneConference *obj, LinphoneCall *call) { return obj->conf->removeParticipant(call); } -int linphone_conference_terminate(LinphoneConference *obj) { +int linphone_conference_terminate (LinphoneConference *obj) { return obj->conf->terminate(); } -int linphone_conference_enter(LinphoneConference *obj) { +int linphone_conference_enter (LinphoneConference *obj) { return obj->conf->enter(); } -int linphone_conference_leave(LinphoneConference *obj) { +int linphone_conference_leave (LinphoneConference *obj) { return obj->conf->leave(); } -bool_t linphone_conference_is_in(const LinphoneConference *obj) { +bool_t linphone_conference_is_in (const LinphoneConference *obj) { return obj->conf->isIn(); } -AudioStream *linphone_conference_get_audio_stream(const LinphoneConference *obj) { +AudioStream *linphone_conference_get_audio_stream (const LinphoneConference *obj) { return obj->conf->getAudioStream(); } -int linphone_conference_mute_microphone(LinphoneConference *obj, bool_t val) { +int linphone_conference_mute_microphone (LinphoneConference *obj, bool_t val) { return obj->conf->muteMicrophone(val ? true : false); } -bool_t linphone_conference_microphone_is_muted(const LinphoneConference *obj) { +bool_t linphone_conference_microphone_is_muted (const LinphoneConference *obj) { return obj->conf->microphoneIsMuted() ? TRUE : FALSE; } -float linphone_conference_get_input_volume(const LinphoneConference *obj) { +float linphone_conference_get_input_volume (const LinphoneConference *obj) { return obj->conf->getInputVolume(); } -int linphone_conference_get_size(const LinphoneConference *obj) { +int linphone_conference_get_size (const LinphoneConference *obj) { return obj->conf->getSize(); } -bctbx_list_t *linphone_conference_get_participants(const LinphoneConference *obj) { +bctbx_list_t *linphone_conference_get_participants (const LinphoneConference *obj) { const list &participants = obj->conf->getParticipants(); - bctbx_list_t *participants_list = NULL; - for(list::const_iterator it=participants.begin();it!=participants.end();it++) { + bctbx_list_t *participants_list = nullptr; + for (auto it = participants.begin(); it != participants.end(); it++) { LinphoneAddress *uri = linphone_address_clone((*it)->getUri()); participants_list = bctbx_list_append(participants_list, uri); } return participants_list; } -int linphone_conference_start_recording(LinphoneConference *obj, const char *path) { +int linphone_conference_start_recording (LinphoneConference *obj, const char *path) { return obj->conf->startRecording(path); } -int linphone_conference_stop_recording(LinphoneConference *obj) { +int linphone_conference_stop_recording (LinphoneConference *obj) { return obj->conf->stopRecording(); } -void linphone_conference_on_call_stream_starting(LinphoneConference *obj, LinphoneCall *call, bool_t is_paused_by_remote) { +void linphone_conference_on_call_stream_starting (LinphoneConference *obj, LinphoneCall *call, bool_t is_paused_by_remote) { obj->conf->onCallStreamStarting(call, is_paused_by_remote ? true : false); } -void linphone_conference_on_call_stream_stopping(LinphoneConference *obj, LinphoneCall *call) { +void linphone_conference_on_call_stream_stopping (LinphoneConference *obj, LinphoneCall *call) { obj->conf->onCallStreamStopping(call); } -void linphone_conference_on_call_terminating(LinphoneConference *obj, LinphoneCall *call) { +void linphone_conference_on_call_terminating (LinphoneConference *obj, LinphoneCall *call) { obj->conf->onCallTerminating(call); } -bool_t linphone_conference_check_class(LinphoneConference *obj, LinphoneConferenceClass _class) { +bool_t linphone_conference_check_class (LinphoneConference *obj, LinphoneConferenceClass _class) { switch(_class) { - case LinphoneConferenceClassLocal: return typeid(obj->conf) == typeid(LocalConference); - case LinphoneConferenceClassRemote: return typeid(obj->conf) == typeid(RemoteConference); - default: return FALSE; + case LinphoneConferenceClassLocal: + return typeid(obj->conf) == typeid(LocalConference); + case LinphoneConferenceClassRemote: + return typeid(obj->conf) == typeid(RemoteConference); + default: + return FALSE; } } -LinphoneStatus linphone_conference_invite_participants(LinphoneConference *obj, const bctbx_list_t *addresses, const LinphoneCallParams *params){ +LinphoneStatus linphone_conference_invite_participants (LinphoneConference *obj, const bctbx_list_t *addresses, const LinphoneCallParams *params){ return obj->conf->inviteAddresses(toStd(addresses), params); } -const char * linphone_conference_get_ID(const LinphoneConference *obj) { +const char *linphone_conference_get_ID (const LinphoneConference *obj) { return obj->conf->getID(); } -void linphone_conference_set_ID(const LinphoneConference *obj, const char *conferenceID) { +void linphone_conference_set_ID (const LinphoneConference *obj, const char *conferenceID) { obj->conf->setID(conferenceID); } diff --git a/coreapi/contact_providers_priv.h b/coreapi/contact_providers_priv.h index 6f24a18b0..5170ad7c9 100644 --- a/coreapi/contact_providers_priv.h +++ b/coreapi/contact_providers_priv.h @@ -17,9 +17,10 @@ #ifndef CONTACT_PROVIDERS_PRIV_H #define CONTACT_PROVIDERS_PRIV_H -#include "private.h" #include "linphone/core.h" +#include "c-wrapper/c-wrapper.h" + /* Base for contact search and contact provider */ struct _LinphoneContactSearch{ diff --git a/coreapi/contactprovider.c b/coreapi/contactprovider.c index 5c1a36b75..cad4875b8 100644 --- a/coreapi/contactprovider.c +++ b/coreapi/contactprovider.c @@ -14,9 +14,10 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "contact_providers_priv.h" #include "linphone/contactprovider.h" -#include +#include "linphone/core.h" + +#include "contact_providers_priv.h" /* ############################ * * LinphoneContactSearchRequest * diff --git a/coreapi/content.c b/coreapi/content.c deleted file mode 100644 index 7637b1c54..000000000 --- a/coreapi/content.c +++ /dev/null @@ -1,241 +0,0 @@ -/* -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone/core.h" -#include "private.h" - - - -static void linphone_content_set_sal_body_handler(LinphoneContent *content, SalBodyHandler *body_handler) { - if (content->body_handler != NULL) { - sal_body_handler_unref(content->body_handler); - content->body_handler = NULL; - } - content->body_handler = sal_body_handler_ref(body_handler); -} - -static LinphoneContent * linphone_content_new_with_body_handler(SalBodyHandler *body_handler) { - LinphoneContent *content = belle_sip_object_new(LinphoneContent); - belle_sip_object_ref(content); - content->owned_fields = TRUE; - content->cryptoContext = NULL; /* this field is managed externally by encryption/decryption functions so be careful to initialise it to NULL */ - if (body_handler == NULL) { - linphone_content_set_sal_body_handler(content, sal_body_handler_new()); - } else { - linphone_content_set_sal_body_handler(content, body_handler); - } - return content; -} - -static void linphone_content_destroy(LinphoneContent *content) { - if (content->owned_fields == TRUE) { - if (content->body_handler) sal_body_handler_unref(content->body_handler); - if (content->name) belle_sip_free(content->name); - if (content->key) belle_sip_free(content->key); - /* note : crypto context is allocated/destroyed by the encryption function */ - } -} - -static void linphone_content_clone(LinphoneContent *obj, const LinphoneContent *ref) { - obj->owned_fields = TRUE; - linphone_content_set_sal_body_handler(obj, sal_body_handler_new()); - if ((linphone_content_get_type(ref) != NULL) || (linphone_content_get_subtype(ref) != NULL)) { - linphone_content_set_type(obj, linphone_content_get_type(ref)); - linphone_content_set_subtype(obj, linphone_content_get_subtype(ref)); - } - if (linphone_content_get_encoding(ref) != NULL) { - linphone_content_set_encoding(obj, linphone_content_get_encoding(ref)); - } - linphone_content_set_name(obj, linphone_content_get_name(ref)); - linphone_content_set_key(obj, linphone_content_get_key(ref), linphone_content_get_key_size(ref)); - if (linphone_content_get_buffer(ref) != NULL) { - linphone_content_set_buffer(obj, linphone_content_get_buffer(ref), linphone_content_get_size(ref)); - } else { - linphone_content_set_size(obj, linphone_content_get_size(ref)); - } -} - - -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneContent); - -BELLE_SIP_INSTANCIATE_VPTR(LinphoneContent, belle_sip_object_t, - (belle_sip_object_destroy_t)linphone_content_destroy, - (belle_sip_object_clone_t)linphone_content_clone, - NULL, // marshal - TRUE -); - - -LinphoneContent * linphone_core_create_content(LinphoneCore *lc) { - return linphone_content_new(); -} - -LinphoneContent * linphone_content_ref(LinphoneContent *content) { - belle_sip_object_ref(content); - return content; -} - -void linphone_content_unref(LinphoneContent *content) { - belle_sip_object_unref(content); -} - -void *linphone_content_get_user_data(const LinphoneContent *content) { - return content->user_data; -} - -void linphone_content_set_user_data(LinphoneContent *content, void *ud) { - content->user_data = ud; -} - -const char * linphone_content_get_type(const LinphoneContent *content) { - return sal_body_handler_get_type(content->body_handler); -} - -void linphone_content_set_type(LinphoneContent *content, const char *type) { - sal_body_handler_set_type(content->body_handler, type); -} - -const char * linphone_content_get_subtype(const LinphoneContent *content) { - return sal_body_handler_get_subtype(content->body_handler); -} - -void linphone_content_set_subtype(LinphoneContent *content, const char *subtype) { - sal_body_handler_set_subtype(content->body_handler, subtype); -} - -void * linphone_content_get_buffer(const LinphoneContent *content) { - return sal_body_handler_get_data(content->body_handler); -} - -void linphone_content_set_buffer(LinphoneContent *content, const void *buffer, size_t size) { - void *data; - sal_body_handler_set_size(content->body_handler, size); - data = belle_sip_malloc(size + 1); - memcpy(data, buffer, size); - ((char *)data)[size] = '\0'; - sal_body_handler_set_data(content->body_handler, data); -} - -const char * linphone_content_get_string_buffer(const LinphoneContent *content) { - return (const char *)linphone_content_get_buffer(content); -} - -void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer) { - sal_body_handler_set_size(content->body_handler, strlen(buffer)); - sal_body_handler_set_data(content->body_handler, belle_sip_strdup(buffer)); -} - -size_t linphone_content_get_size(const LinphoneContent *content) { - return sal_body_handler_get_size(content->body_handler); -} - -void linphone_content_set_size(LinphoneContent *content, size_t size) { - sal_body_handler_set_size(content->body_handler, size); -} - -const char * linphone_content_get_encoding(const LinphoneContent *content) { - return sal_body_handler_get_encoding(content->body_handler); -} - -void linphone_content_set_encoding(LinphoneContent *content, const char *encoding) { - sal_body_handler_set_encoding(content->body_handler, encoding); -} - -const char * linphone_content_get_name(const LinphoneContent *content) { - return content->name; -} - -void linphone_content_set_name(LinphoneContent *content, const char *name) { - if (content->name != NULL) { - belle_sip_free(content->name); - content->name = NULL; - } - if (name != NULL) { - content->name = belle_sip_strdup(name); - } -} - -size_t linphone_content_get_key_size(const LinphoneContent *content) { - return content->keyLength; -} - -const char * linphone_content_get_key(const LinphoneContent *content) { - return content->key; -} - -void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength) { - if (content->key != NULL) { - belle_sip_free(content->key); - content->key = NULL; - } - if (key != NULL) { - content->key = reinterpret_cast(belle_sip_malloc(keyLength + 1)); - memcpy(content->key, key, keyLength); - content->key[keyLength] = '\0'; - content->keyLength = keyLength; - } -} - -/* crypto context is managed(allocated/freed) by the encryption function, so provide the address of field in the private structure */ -void ** linphone_content_get_cryptoContext_address(LinphoneContent *content) { - return &(content->cryptoContext); -} - -bool_t linphone_content_is_multipart(const LinphoneContent *content) { - return sal_body_handler_is_multipart(content->body_handler); -} - -LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx) { - SalBodyHandler *part_body_handler; - if (!linphone_content_is_multipart(content)) return NULL; - part_body_handler = sal_body_handler_get_part(content->body_handler, idx); - return linphone_content_from_sal_body_handler(part_body_handler); -} - -LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value) { - SalBodyHandler *part_body_handler; - if (!linphone_content_is_multipart(content)) return NULL; - part_body_handler = sal_body_handler_find_part_by_header(content->body_handler, header_name, header_value); - return linphone_content_from_sal_body_handler(part_body_handler); -} - -const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name) { - return sal_body_handler_get_header(content->body_handler, header_name); -} - - -LinphoneContent * linphone_content_new(void) { - return linphone_content_new_with_body_handler(NULL); -} - -LinphoneContent * linphone_content_copy(const LinphoneContent *ref) { - return (LinphoneContent *)belle_sip_object_ref(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); -} - -LinphoneContent * linphone_content_from_sal_body_handler(SalBodyHandler *body_handler) { - if (body_handler) { - return linphone_content_new_with_body_handler(body_handler); - } - return NULL; -} - -SalBodyHandler * sal_body_handler_from_content(const LinphoneContent *content) { - if (content == NULL) return NULL; - return content->body_handler; -} diff --git a/coreapi/core_private.h b/coreapi/core_private.h new file mode 100644 index 000000000..395e5dfba --- /dev/null +++ b/coreapi/core_private.h @@ -0,0 +1,35 @@ +/* + * core_private.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CORE_PRIVATE_H_ +#define _CORE_PRIVATE_H_ + +#include "linphone/types.h" +#include "private_structs.h" +#include "private_types.h" + +struct _LinphoneCore { + belle_sip_object_t base; + std::shared_ptr cppPtr; + std::weak_ptr weakCppPtr; + int owner; + LINPHONE_CORE_STRUCT_FIELDS +}; + +#endif /* _CORE_PRIVATE_H_ */ diff --git a/coreapi/dial_plan.c b/coreapi/dial_plan.c index 7e3714fae..1688fde3b 100644 --- a/coreapi/dial_plan.c +++ b/coreapi/dial_plan.c @@ -19,314 +19,3 @@ Copyright (C) 2000 Simon MORLAT (simon.morlat@linphone.org) */ #include "linphone/core_utils.h" - -/* - * http://en.wikipedia.org/wiki/Telephone_numbering_plan - * http://en.wikipedia.org/wiki/Telephone_numbers_in_Europe - * imported from https://en.wikipedia.org/wiki/List_of_mobile_phone_number_series_by_country - */ -static LinphoneDialPlan const dial_plans[]={ - //Country , iso country code, e164 country calling code, number length, international usual prefix - {"Afghanistan" ,"AF" , "93" , 9 , "00" }, - {"Albania" ,"AL" , "355" , 9 , "00" }, - {"Algeria" ,"DZ" , "213" , 9 , "00" }, - {"American Samoa" ,"AS" , "1" , 10 , "011" }, - {"Andorra" ,"AD" , "376" , 6 , "00" }, - {"Angola" ,"AO" , "244" , 9 , "00" }, - {"Anguilla" ,"AI" , "1" , 10 , "011" }, - {"Antigua and Barbuda" ,"AG" , "1" , 10 , "011" }, - {"Argentina" ,"AR" , "54" , 10 , "00" }, - {"Armenia" ,"AM" , "374" , 8 , "00" }, - {"Aruba" ,"AW" , "297" , 7 , "011" }, - {"Australia" ,"AU" , "61" , 9 , "0011"}, - {"Austria" ,"AT" , "43" , 11 , "00" }, /*11 digits are possible, most numbers have 10 digits*/ - {"Azerbaijan" ,"AZ" , "994" , 9 , "00" }, - {"Bahamas" ,"BS" , "1" , 10 , "011" }, - {"Bahrain" ,"BH" , "973" , 8 , "00" }, - {"Bangladesh" ,"BD" , "880" , 10 , "00" }, - {"Barbados" ,"BB" , "1" , 10 , "011" }, - {"Belarus" ,"BY" , "375" , 9 , "00" }, - {"Belgium" ,"BE" , "32" , 9 , "00" }, - {"Belize" ,"BZ" , "501" , 7 , "00" }, - {"Benin" ,"BJ" , "229" , 8 , "00" }, - {"Bermuda" ,"BM" , "1" , 10 , "011" }, - {"Bhutan" ,"BT" , "975" , 8 , "00" }, - {"Bolivia" ,"BO" , "591" , 8 , "00" }, - {"Bosnia and Herzegovina" ,"BA" , "387" , 8 , "00" }, - {"Botswana" ,"BW" , "267" , 8 , "00" }, - {"Brazil" ,"BR" , "55" , 11 , "00" }, - {"Brunei Darussalam" ,"BN" , "673" , 7 , "00" }, - {"Bulgaria" ,"BG" , "359" , 9 , "00" }, - {"Burkina Faso" ,"BF" , "226" , 8 , "00" }, - {"Burundi" ,"BI" , "257" , 8 , "011" }, - {"Cambodia" ,"KH" , "855" , 9 , "00" }, - {"Cameroon" ,"CM" , "237" , 9 , "00" }, - {"Canada" ,"CA" , "1" , 10 , "011" }, - {"Cape Verde" ,"CV" , "238" , 7 , "00" }, - {"Cayman Islands" ,"KY" , "1" , 10 , "011" }, - {"Central African Republic" ,"CF" , "236" , 8 , "00" }, - {"Chad" ,"TD" , "235" , 8 , "00" }, - {"Chile" ,"CL" , "56" , 9 , "00" }, - {"China" ,"CN" , "86" , 11 , "00" }, - {"Colombia" ,"CO" , "57" , 10 , "00" }, - {"Comoros" ,"KM" , "269" , 7 , "00" }, - {"Congo" ,"CG" , "242" , 9 , "00" }, - {"Congo Democratic Republic" ,"CD" , "243" , 9 , "00" }, - {"Cook Islands" ,"CK" , "682" , 5 , "00" }, - {"Costa Rica" ,"CR" , "506" , 8 , "00" }, - {"Cote d'Ivoire" ,"AD" , "225" , 8 , "00" }, - {"Croatia" ,"HR" , "385" , 9 , "00" }, - {"Cuba" ,"CU" , "53" , 8 , "119" }, - {"Cyprus" ,"CY" , "357" , 8 , "00" }, - {"Czech Republic" ,"CZ" , "420" , 9 , "00" }, - {"Denmark" ,"DK" , "45" , 8 , "00" }, - {"Djibouti" ,"DJ" , "253" , 8 , "00" }, - {"Dominica" ,"DM" , "1" , 10 , "011" }, - {"Dominican Republic" ,"DO" , "1" , 10 , "011" }, - {"Ecuador" ,"EC" , "593" , 9 , "00" }, - {"Egypt" ,"EG" , "20" , 10 , "00" }, - {"El Salvador" ,"SV" , "503" , 8 , "00" }, - {"Equatorial Guinea" ,"GQ" , "240" , 9 , "00" }, - {"Eritrea" ,"ER" , "291" , 7 , "00" }, - {"Estonia" ,"EE" , "372" , 8 , "00" }, - {"Ethiopia" ,"ET" , "251" , 9 , "00" }, - {"Falkland Islands" ,"FK" , "500" , 5 , "00" }, - {"Faroe Islands" ,"FO" , "298" , 6 , "00" }, - {"Fiji" ,"FJ" , "679" , 7 , "00" }, - {"Finland" ,"FI" , "358" , 9 , "00" }, - {"France" ,"FR" , "33" , 9 , "00" }, - {"French Guiana" ,"GF" , "594" , 9 , "00" }, - {"French Polynesia" ,"PF" , "689" , 6 , "00" }, - {"Gabon" ,"GA" , "241" , 8 , "00" }, - {"Gambia" ,"GM" , "220" , 7 , "00" }, - {"Georgia" ,"GE" , "995" , 9 , "00" }, - {"Germany" ,"DE" , "49" , 11 , "00" }, - {"Ghana" ,"GH" , "233" , 9 , "00" }, - {"Gibraltar" ,"GI" , "350" , 8 , "00" }, - {"Greece" ,"GR" , "30" ,10 , "00" }, - {"Greenland" ,"GL" , "299" , 6 , "00" }, - {"Grenada" ,"GD" , "1" , 10 , "011" }, - {"Guadeloupe" ,"GP" , "590" , 9 , "00" }, - {"Guam" ,"GU" , "1" , 10 , "011" }, - {"Guatemala" ,"GT" , "502" , 8 , "00" }, - {"Guinea" ,"GN" , "224" , 8 , "00" }, - {"Guinea-Bissau" ,"GW" , "245" , 7 , "00" }, - {"Guyana" ,"GY" , "592" , 7 , "001" }, - {"Haiti" ,"HT" , "509" , 8 , "00" }, - {"Honduras" ,"HN" , "504" , 8 , "00" }, - {"Hong Kong" ,"HK" , "852" , 8 , "001" }, - {"Hungary" ,"HU" , "36" , 9 , "00" }, - {"Iceland" ,"IS" , "354" , 9 , "00" }, - {"India" ,"IN" , "91" , 10 , "00" }, - {"Indonesia" ,"ID" , "62" , 12 , "001" }, - {"Iran" ,"IR" , "98" , 10 , "00" }, - {"Iraq" ,"IQ" , "964" , 10 , "00" }, - {"Ireland" ,"IE" , "353" , 9 , "00" }, - {"Israel" ,"IL" , "972" , 9 , "00" }, - {"Italy" ,"IT" , "39" , 10 , "00" }, -/* {"Jersey" ,"JE" , "44" , 10 , "00" },*/ - {"Jamaica" ,"JM" , "1" , 10 , "011" }, - {"Japan" ,"JP" , "81" , 10 , "010" }, - {"Jordan" ,"JO" , "962" , 9 , "00" }, - {"Kazakhstan" ,"KZ" , "7" , 10 , "00" }, - {"Kenya" ,"KE" , "254" , 9 , "000" }, - {"Kiribati" ,"KI" , "686" , 5 , "00" }, - {"Korea, North" ,"KP" , "850" , 12 , "99" }, - {"Korea, South" ,"KR" , "82" , 12 , "001" }, - {"Kuwait" ,"KW" , "965" , 8 , "00" }, - {"Kyrgyzstan" ,"KG" , "996" , 9 , "00" }, - {"Laos" ,"LA" , "856" , 10 , "00" }, - {"Latvia" ,"LV" , "371" , 8 , "00" }, - {"Lebanon" ,"LB" , "961" , 7 , "00" }, - {"Lesotho" ,"LS" , "266" , 8 , "00" }, - {"Liberia" ,"LR" , "231" , 8 , "00" }, - {"Libya" ,"LY" , "218" , 8 , "00" }, - {"Liechtenstein" ,"LI" , "423" , 7 , "00" }, - {"Lithuania" ,"LT" , "370" , 8 , "00" }, - {"Luxembourg" ,"LU" , "352" , 9 , "00" }, - {"Macau" ,"MO" , "853" , 8 , "00" }, - {"Macedonia" ,"MK" , "389" , 8 , "00" }, - {"Madagascar" ,"MG" , "261" , 9 , "00" }, - {"Malawi" ,"MW" , "265" , 9 , "00" }, - {"Malaysia" ,"MY" , "60" , 9 , "00" }, - {"Maldives" ,"MV" , "960" , 7 , "00" }, - {"Mali" ,"ML" , "223" , 8 , "00" }, - {"Malta" ,"MT" , "356" , 8 , "00" }, - {"Marshall Islands" ,"MH" , "692" , 7 , "011" }, - {"Martinique" ,"MQ" , "596" , 9 , "00" }, - {"Mauritania" ,"MR" , "222" , 8 , "00" }, - {"Mauritius" ,"MU" , "230" , 7 , "00" }, - {"Mayotte Island" ,"YT" , "262" , 9 , "00" }, - {"Mexico" ,"MX" , "52" , 10 , "00" }, - /*The following is a pseudo dial plan for Mexican mobile phones. See https://en.wikipedia.org/wiki/Telephone_numbers_in_Mexico*/ - {"Mexico" ,"MX" , "521" , 10 , "00" }, - {"Micronesia" ,"FM" , "691" , 7 , "011" }, - {"Moldova" ,"MD" , "373" , 8 , "00" }, - {"Monaco" ,"MC" , "377" , 8 , "00" }, - {"Mongolia" ,"MN" , "976" , 8 , "001" }, - {"Montenegro" ,"ME" , "382" , 8 , "00" }, - {"Montserrat" ,"MS" , "664" , 10 , "011" }, - {"Morocco" ,"MA" , "212" , 9 , "00" }, - {"Mozambique" ,"MZ" , "258" , 9 , "00" }, - {"Myanmar" ,"MM" , "95" , 10 , "00" }, - {"Namibia" ,"NA" , "264" , 9 , "00" }, - {"Nauru" ,"NR" , "674" , 7 , "00" }, - {"Nepal" ,"NP" , "43" , 10 , "00" }, - {"Netherlands" ,"NL" , "31" , 9 , "00" }, - {"New Caledonia" ,"NC" , "687" , 6 , "00" }, - {"New Zealand" ,"NZ" , "64" , 8 , "00" }, - {"Nicaragua" ,"NI" , "505" , 8 , "00" }, - {"Niger" ,"NE" , "227" , 8 , "00" }, - {"Nigeria" ,"NG" , "234" , 10 , "009" }, - {"Niue" ,"NU" , "683" , 4 , "00" }, - {"Norfolk Island" ,"NF" , "672" , 5 , "00" }, - {"Northern Mariana Islands" ,"MP" , "1" , 10 , "011" }, - {"Norway" ,"NO" , "47" , 8 , "00" }, - {"Oman" ,"OM" , "968" , 8 , "00" }, - {"Pakistan" ,"PK" , "92" , 10 , "00" }, - {"Palau" ,"PW" , "680" , 7 , "011" }, - {"Palestine" ,"PS" , "970" , 9 , "00" }, - {"Panama" ,"PA" , "507" , 8 , "00" }, - {"Papua New Guinea" ,"PG" , "675" , 8 , "00" }, - {"Paraguay" ,"PY" , "595" , 9 , "00" }, - {"Peru" ,"PE" , "51" , 9 , "00" }, - {"Philippines" ,"PH" , "63" , 10 , "00" }, - {"Poland" ,"PL" , "48" , 9 , "00" }, - {"Portugal" ,"PT" , "351" , 9 , "00" }, - {"Puerto Rico" ,"PR" , "1" , 10 , "011" }, - {"Qatar" ,"QA" , "974" , 8 , "00" }, - {"R�union Island" ,"RE" , "262" , 9 , "011" }, - {"Romania" ,"RO" , "40" , 9 , "00" }, - {"Russian Federation" ,"RU" , "7" , 10 , "8" }, - {"Rwanda" ,"RW" , "250" , 9 , "00" }, - {"Saint Helena" ,"SH" , "290" , 4 , "00" }, - {"Saint Kitts and Nevis" ,"KN" , "1" , 10 , "011" }, - {"Saint Lucia" ,"LC" , "1" , 10 , "011" }, - {"Saint Pierre and Miquelon" ,"PM" , "508" , 6 , "00" }, - {"Saint Vincent and the Grenadines","VC" , "1" , 10 , "011" }, - {"Samoa" ,"WS" , "685" , 7 , "0" }, - {"San Marino" ,"SM" , "378" , 10 , "00" }, - {"Sao Tome and Principe" ,"ST" , "239" , 7 , "00" }, - {"Saudi Arabia" ,"SA" , "966" , 9 , "00" }, - {"Senegal" ,"SN" , "221" , 9 , "00" }, - {"Serbia" ,"RS" , "381" , 9 , "00" }, - {"Seychelles" ,"SC" , "248" , 7 , "00" }, - {"Sierra Leone" ,"SL" , "232" , 8 , "00" }, - {"Singapore" ,"SG" , "65" , 8 , "001" }, - {"Slovakia" ,"SK" , "421" , 9 , "00" }, - {"Slovenia" ,"SI" , "386" , 8 , "00" }, - {"Solomon Islands" ,"SB" , "677" , 7 , "00" }, - {"Somalia" ,"SO" , "252" , 8 , "00" }, - {"South Africa" ,"ZA" , "27" , 9 , "00" }, - {"Spain" ,"ES" , "34" , 9 , "00" }, - {"Sri Lanka" ,"LK" , "94" , 9 , "00" }, - {"Sudan" ,"SD" , "249" , 9 , "00" }, - {"Suriname" ,"SR" , "597" , 7 , "00" }, - {"Swaziland" ,"SZ" , "268" , 8 , "00" }, - {"Sweden" ,"SE" , "46" , 9 , "00" }, - {"Switzerland" ,"XK" , "41" , 9 , "00" }, - {"Syria" ,"SY" , "963" , 9 , "00" }, - {"Taiwan" ,"TW" , "886" , 9 , "810" }, - {"Tajikistan" ,"TJ" , "992" , 9 , "002" }, - {"Tanzania" ,"TZ" , "255" , 9 , "000" }, - {"Thailand" ,"TH" , "66" , 9 , "001" }, - {"Togo" ,"TG" , "228" , 8 , "00" }, - {"Tokelau" ,"TK" , "690" , 4 , "00" }, - {"Tonga" ,"TO" , "676" , 5 , "00" }, - {"Trinidad and Tobago" ,"TT" , "1" , 10 , "011" }, - {"Tunisia" ,"TN" , "216" , 8 , "00" }, - {"Turkey" ,"TR" , "90" , 10 , "00" }, - {"Turkmenistan" ,"TM" , "993" , 8 , "00" }, - {"Turks and Caicos Islands" ,"TC" , "1" , 7 , "0" }, - {"Tuvalu" ,"TV" , "688" , 5 , "00" }, - {"Uganda" ,"UG" , "256" , 9 , "000" }, - {"Ukraine" ,"UA" , "380" , 9 , "00" }, - {"United Arab Emirates" ,"AE" , "971" , 9 , "00" }, - {"United Kingdom" ,"GB" , "44" , 10 , "00" }, -/* {"United Kingdom" ,"UK" , "44" , 10 , "00" },*/ - {"United States" ,"US" , "1" , 10 , "011" }, - {"Uruguay" ,"UY" , "598" , 8 , "00" }, - {"Uzbekistan" ,"UZ" , "998" , 9 , "8" }, - {"Vanuatu" ,"VU" , "678" , 7 , "00" }, - {"Venezuela" ,"VE" , "58" , 10 , "00" }, - {"Vietnam" ,"VN" , "84" , 9 , "00" }, - {"Wallis and Futuna" ,"WF" , "681" , 5 , "00" }, - {"Yemen" ,"YE" , "967" , 9 , "00" }, - {"Zambia" ,"ZM" , "260" , 9 , "00" }, - {"Zimbabwe" ,"ZW" , "263" , 9 , "00" }, - {NULL ,NULL , "" , 0 , NULL } -}; -static LinphoneDialPlan most_common_dialplan={ "generic" ,"", "", 10, "00"}; - -int linphone_dial_plan_lookup_ccc_from_e164(const char* e164) { - LinphoneDialPlan* dial_plan; - LinphoneDialPlan* elected_dial_plan=NULL; - unsigned int found; - unsigned int i=0; - - if (e164[0]!='+') { - return -1;/*not an e164 number*/ - } - if (e164[1]=='1') { - /*USA case*/ - return 1; - } - do { - found=0; - i++; - for (dial_plan=(LinphoneDialPlan*)dial_plans; dial_plan->country!=NULL; dial_plan++) { - if (strncmp(dial_plan->ccc,&e164[1],i) == 0) { - elected_dial_plan=dial_plan; - found++; - } - } - } while ((found>1 || found==0) && i < sizeof(dial_plan->ccc)); - if (found==1) { - return atoi(elected_dial_plan->ccc); - } else { - return -1; /*not found */ - } - -} -int linphone_dial_plan_lookup_ccc_from_iso(const char* iso) { - LinphoneDialPlan* dial_plan; - for (dial_plan=(LinphoneDialPlan*)dial_plans; dial_plan->country!=NULL; dial_plan++) { - if (strcmp(iso, dial_plan->iso_country_code)==0) { - return atoi(dial_plan->ccc); - } - } - return -1; -} - -const LinphoneDialPlan* linphone_dial_plan_by_ccc_as_int(int ccc) { - int i; - char ccc_as_char[16] = {0}; - snprintf(ccc_as_char,sizeof(ccc_as_char)-1,"%i",ccc); - - for(i=0;dial_plans[i].country!=NULL;++i){ - if (strcmp(ccc_as_char,dial_plans[i].ccc)==0){ - return &dial_plans[i]; - } - } - /*else return a generic "most common" dial plan*/ - return &most_common_dialplan; -} - - -const LinphoneDialPlan* linphone_dial_plan_by_ccc(const char *ccc) { - if (!ccc) { - return &most_common_dialplan; - } - - return linphone_dial_plan_by_ccc_as_int((int)strtol(ccc,NULL,10)); -} - -const LinphoneDialPlan* linphone_dial_plan_get_all() { - return dial_plans; -} - -bool_t linphone_dial_plan_is_generic(const LinphoneDialPlan *ccc) { - if (strcmp(ccc->country, most_common_dialplan.country) == 0) - return TRUE; - return FALSE; -} diff --git a/coreapi/ec-calibrator.c b/coreapi/ec-calibrator.c index 7c7ddcf54..f82e597c1 100644 --- a/coreapi/ec-calibrator.c +++ b/coreapi/ec-calibrator.c @@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/dtmfgen.h" #include "linphone/lpconfig.h" - +#include "c-wrapper/c-wrapper.h" static void ecc_init_filters(EcCalibrator *ecc){ @@ -47,8 +47,8 @@ static void ecc_init_filters(EcCalibrator *ecc){ ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_OUTPUT_SAMPLE_RATE,&ecc->rate); ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_NCHANNELS,&channels); ms_filter_call_method(ecc->read_resampler,MS_FILTER_SET_OUTPUT_NCHANNELS,&ecc_channels); - - + + ecc->det=ms_factory_create_filter(ecc->factory, MS_TONE_DETECTOR_ID); ms_filter_call_method(ecc->det,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate); ecc->rec=ms_factory_create_filter(ecc->factory, MS_VOID_SINK_ID); @@ -62,7 +62,7 @@ static void ecc_init_filters(EcCalibrator *ecc){ ms_filter_call_method(ecc->gen,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate); ecc->write_resampler=ms_factory_create_filter(ecc->factory, MS_RESAMPLE_ID); ecc->sndwrite=ms_snd_card_create_writer(ecc->play_card); - + ms_filter_call_method(ecc->sndwrite,MS_FILTER_SET_SAMPLE_RATE,&ecc->rate); ms_filter_call_method(ecc->sndwrite,MS_FILTER_GET_SAMPLE_RATE,&rate); ms_filter_call_method(ecc->sndwrite,MS_FILTER_SET_NCHANNELS,&ecc_channels); @@ -153,37 +153,37 @@ static void on_tone_received(void *data, MSFilter *f, unsigned int event_id, voi static void ecc_play_tones(EcCalibrator *ecc){ MSDtmfGenCustomTone tone; MSToneDetectorDef expected_tone; - + memset(&tone,0,sizeof(tone)); memset(&expected_tone,0,sizeof(expected_tone)); ms_filter_add_notify_callback(ecc->det,on_tone_received,ecc,TRUE); /* configure the tones to be scanned */ - + strncpy(expected_tone.tone_name,"freq1",sizeof(expected_tone.tone_name)); expected_tone.frequency=(int)2349.32; expected_tone.min_duration=40; expected_tone.min_amplitude=0.1f; ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone); - + strncpy(expected_tone.tone_name,"freq2",sizeof(expected_tone.tone_name)); expected_tone.frequency=(int)2637.02; expected_tone.min_duration=40; expected_tone.min_amplitude=0.1f; ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone); - + strncpy(expected_tone.tone_name,"freq3",sizeof(expected_tone.tone_name)); expected_tone.frequency=(int)2093; expected_tone.min_duration=40; expected_tone.min_amplitude=0.1f; ms_filter_call_method (ecc->det,MS_TONE_DETECTOR_ADD_SCAN,&expected_tone); - + /*play an initial tone to startup the audio playback/capture*/ - + tone.frequencies[0]=140; tone.duration=1000; tone.amplitude=0.5; @@ -192,23 +192,23 @@ static void ecc_play_tones(EcCalibrator *ecc){ ms_sleep(2); ms_filter_add_notify_callback(ecc->gen,on_tone_sent,ecc,TRUE); - + /* play the three tones*/ - - + + if (ecc->play_cool_tones){ strncpy(tone.tone_name, "D", sizeof(tone.tone_name)); tone.frequencies[0]=(int)2349.32; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); - + strncpy(tone.tone_name, "E", sizeof(tone.tone_name)); tone.frequencies[0]=(int)2637.02; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); - + strncpy(tone.tone_name, "C", sizeof(tone.tone_name)); tone.frequencies[0]=(int)2093; tone.duration=100; @@ -220,20 +220,20 @@ static void ecc_play_tones(EcCalibrator *ecc){ tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); - + strncpy(tone.tone_name, "D", sizeof(tone.tone_name)); tone.frequencies[0]=(int)2349.32; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); - + strncpy(tone.tone_name, "E", sizeof(tone.tone_name)); tone.frequencies[0]=(int)2637.02; tone.duration=100; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); } - + /*these two next ones are for lyrism*/ if (ecc->play_cool_tones){ tone.tone_name[0]='\0'; @@ -241,15 +241,15 @@ static void ecc_play_tones(EcCalibrator *ecc){ tone.duration=400; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); ms_usleep(300000); - + tone.tone_name[0]='\0'; tone.frequencies[0]=(int)1567.98; tone.duration=400; ms_filter_call_method(ecc->gen,MS_DTMF_GEN_PLAY_CUSTOM,&tone); } - + ms_sleep(1); - + if (ecc->freq1 && ecc->freq2 && ecc->freq3) { int delay=(int)(ecc->acc/3); if (delay<0){ @@ -274,7 +274,7 @@ static void ecc_play_tones(EcCalibrator *ecc){ static void * ecc_thread(void *p){ EcCalibrator *ecc=(EcCalibrator*)p; - + ecc_init_filters(ecc); ecc_play_tones(ecc); ecc_deinit_filters(ecc); @@ -318,10 +318,59 @@ int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibration ms_error("Echo calibration is still on going !"); return -1; } - rate = lp_config_get_int(lc->config,"sound","echo_cancellation_rate",8000); + rate = (unsigned int)lp_config_get_int(lc->config,"sound","echo_cancellation_rate",8000); lc->ecc=ec_calibrator_new(lc->factory, lc->sound_conf.play_sndcard,lc->sound_conf.capt_sndcard,rate,cb,audio_init_cb,audio_uninit_cb,cb_data); - lc->ecc->play_cool_tones = lp_config_get_int(lc->config, "sound", "ec_calibrator_cool_tones", 0); + lc->ecc->play_cool_tones = !!lp_config_get_int(lc->config, "sound", "ec_calibrator_cool_tones", 0); ec_calibrator_start(lc->ecc); return 0; } +static void _ec_calibration_result_cb(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *user_data) { + linphone_core_notify_ec_calibration_result(lc, status, delay_ms); +} + +static void _ec_calibration_audio_init_cb(void *user_data) { + LinphoneCore *lc = (LinphoneCore *)user_data; + linphone_core_notify_ec_calibration_audio_init(lc); +} + +static void _ec_calibration_audio_uninit_cb(void *user_data) { + LinphoneCore *lc = (LinphoneCore *)user_data; + linphone_core_notify_ec_calibration_audio_uninit(lc); +} + +LinphoneStatus linphone_core_start_echo_canceller_calibration(LinphoneCore *lc) { + unsigned int rate; + + if (lc->ecc!=NULL){ + ms_error("Echo calibration is still on going !"); + return -1; + } + rate = (unsigned int)lp_config_get_int(lc->config,"sound","echo_cancellation_rate",8000); + lc->ecc=ec_calibrator_new(lc->factory, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard, rate, + _ec_calibration_result_cb, + _ec_calibration_audio_init_cb, + _ec_calibration_audio_uninit_cb, lc); + lc->ecc->play_cool_tones = !!lp_config_get_int(lc->config, "sound", "ec_calibrator_cool_tones", 0); + ec_calibrator_start(lc->ecc); + return 0; +} + +bool_t linphone_core_has_builtin_echo_canceller(LinphoneCore *lc) { + MSFactory * factory = linphone_core_get_ms_factory(lc); + MSDevicesInfo *devices = ms_factory_get_devices_info(factory); + SoundDeviceDescription *sound_description = ms_devices_info_get_sound_device_description(devices); + if (sound_description == NULL) return FALSE; + if (sound_description->flags & DEVICE_HAS_BUILTIN_AEC) return TRUE; + return FALSE; +} + +bool_t linphone_core_is_echo_canceller_calibration_required(LinphoneCore *lc) { + MSFactory * factory = linphone_core_get_ms_factory(lc); + MSDevicesInfo *devices = ms_factory_get_devices_info(factory); + SoundDeviceDescription *sound_description = ms_devices_info_get_sound_device_description(devices); + if (sound_description == NULL) return TRUE; + if (sound_description->flags & DEVICE_HAS_BUILTIN_AEC) return FALSE; + if (sound_description->delay != 0) return FALSE; + return TRUE; +} diff --git a/coreapi/enum.c b/coreapi/enum.c index 9b18bc1a0..3444efbba 100644 --- a/coreapi/enum.c +++ b/coreapi/enum.c @@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. static char *create_enum_domain(const char *number){ long len=(long)strlen(number); - char *domain=reinterpret_cast(ms_malloc((len*2)+10)); + char *domain=reinterpret_cast(ms_malloc((size_t)(len*2)+10)); long i,j; for (i=0,j=len-1;j>=0;j--){ diff --git a/coreapi/error_info.c b/coreapi/error_info.c index ffe29fed7..fe619e4df 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -18,12 +18,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/core.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. #include "private.h" BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneErrorInfo); - - static void linphone_error_info_reset(LinphoneErrorInfo *ei); static void error_info_destroy(LinphoneErrorInfo *ei){ @@ -182,7 +184,7 @@ void linphone_error_info_from_sal_reason_ei(LinphoneErrorInfo *ei, const SalErro linphone_error_info_from_sal(ei, reason_ei); return; } - + if (ei->sub_ei){ if (reason_ei->reason == SalReasonNone){ linphone_error_info_unref(ei->sub_ei); @@ -198,16 +200,16 @@ void linphone_error_info_from_sal_reason_ei(LinphoneErrorInfo *ei, const SalErro } } -void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op){ +void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const LinphonePrivate::SalOp *op){ if (op==NULL) { /*leave previous values in LinphoneErrorInfo, the op may have been released already.*/ return; }else{ const SalErrorInfo *sei; linphone_error_info_reset(ei); - sei = sal_op_get_error_info(op); + sei = op->getErrorInfo(); linphone_error_info_from_sal(ei, sei); - sei = sal_op_get_reason_error_info(op); + sei = op->getReasonErrorInfo(); linphone_error_info_from_sal_reason_ei(ei, sei); } } @@ -220,12 +222,12 @@ void linphone_error_info_fields_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo sei->protocol_code = ei->protocol_code; sei->protocol = bctbx_strdup(ei->protocol); } - + void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ - + linphone_error_info_fields_to_sal(ei, sei); if (ei->sub_ei !=NULL) { - + linphone_error_info_to_sal(ei->sub_ei, sei->sub_sei); } } diff --git a/coreapi/event.c b/coreapi/event.c index dd5e677c4..ade697ab0 100644 --- a/coreapi/event.c +++ b/coreapi/event.c @@ -18,8 +18,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/event.h" -#include "private.h" #include "linphone/lpconfig.h" +#include "sal/event-op.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" + +using namespace LinphonePrivate; const char * linphone_subscription_dir_to_string(LinphoneSubscriptionDir dir){ switch(dir){ @@ -69,41 +76,84 @@ LINPHONE_PUBLIC const char *linphone_publish_state_to_string(LinphonePublishStat return NULL; } + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneEventCbs); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneEventCbs, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +static LinphoneEventCbs *linphone_event_cbs_new(void) { + return belle_sip_object_new(LinphoneEventCbs); +} + +LinphoneEventCbs *linphone_event_cbs_ref(LinphoneEventCbs *cbs) { + belle_sip_object_ref(cbs); + return cbs; +} + +void linphone_event_cbs_unref(LinphoneEventCbs *cbs) { + belle_sip_object_unref(cbs); +} + +void *linphone_event_cbs_get_user_data(const LinphoneEventCbs *cbs) { + return cbs->user_data; +} + +void linphone_event_cbs_set_user_data(LinphoneEventCbs *cbs, void *ud) { + cbs->user_data = ud; +} + +LinphoneEventCbsNotifyResponseCb linphone_event_cbs_get_notify_response(const LinphoneEventCbs *cbs) { + return cbs->notify_response_cb; +} + +void linphone_event_cbs_set_notify_response(LinphoneEventCbs *cbs, LinphoneEventCbsNotifyResponseCb cb) { + cbs->notify_response_cb = cb; +} + + static void linphone_event_release(LinphoneEvent *lev){ if (lev->op) { /*this will stop the refresher*/ - sal_op_stop_refreshing(lev->op); + lev->op->stopRefreshing(); } linphone_event_unref(lev); } -static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, SalOp *op){ +static LinphoneEvent * linphone_event_new_base(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, LinphonePrivate::SalEventOp *op){ LinphoneEvent *lev=belle_sip_object_new(LinphoneEvent); + lev->callbacks = linphone_event_cbs_new(); lev->lc=lc; lev->dir=dir; lev->op=op; lev->name=ms_strdup(name); - sal_op_set_user_pointer(lev->op,lev); + if (strcmp(lev->name, "conference") == 0) + lev->internal = TRUE; + lev->op->setUserPointer(lev); return lev; } LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires){ - LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, sal_op_new(lc->sal)); + LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, new SalSubscribeOp(lc->sal)); lev->expires=expires; return lev; } -static LinphoneEvent *linphone_event_new_with_op_base(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name, bool_t is_out_of_dialog){ +static LinphoneEvent *linphone_event_new_with_op_base(LinphoneCore *lc, SalEventOp *op, LinphoneSubscriptionDir dir, const char *name, bool_t is_out_of_dialog){ LinphoneEvent *lev=linphone_event_new_base(lc, dir, name, op); lev->is_out_of_dialog_op=is_out_of_dialog; return lev; } -LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) { +LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalEventOp *op, LinphoneSubscriptionDir dir, const char *name) { return linphone_event_new_with_op_base(lc,op,dir,name,FALSE); } -LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name) { +LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalEventOp *op, LinphoneSubscriptionDir dir, const char *name) { return linphone_event_new_with_op_base(lc,op,dir,name,TRUE); } @@ -171,7 +221,7 @@ LinphoneReason linphone_event_get_reason(const LinphoneEvent *lev){ LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){ LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionOutgoing, event, expires); linphone_configure_op(lc,lev->op,resource,NULL,TRUE); - sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_subscribe",1)); + lev->op->setManualRefresherMode(!lp_config_get_int(lc->config,"sip","refresh_generic_subscribe",1)); return lev; } @@ -179,7 +229,7 @@ LinphoneEvent *linphone_core_create_notify(LinphoneCore *lc, const LinphoneAddre LinphoneEvent *lev=linphone_event_new(lc, LinphoneSubscriptionIncoming, event, -1); linphone_configure_op(lc,lev->op,resource,NULL,TRUE); lev->subscription_state = LinphoneSubscriptionIncomingReceived; - sal_op_set_event(lev->op, event); + lev->op->setEvent(event); lev->is_out_of_dialog_op = TRUE; return lev; } @@ -215,13 +265,14 @@ LinphoneStatus linphone_event_send_subscribe(LinphoneEvent *lev, const LinphoneC } if (lev->send_custom_headers){ - sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers); + lev->op->setSentCustomHeaders(lev->send_custom_headers); sal_custom_header_free(lev->send_custom_headers); lev->send_custom_headers=NULL; - }else sal_op_set_sent_custom_header(lev->op,NULL); + }else lev->op->setSentCustomHeaders(NULL); body_handler = sal_body_handler_from_content(body); - err=sal_subscribe(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); + auto subscribeOp = dynamic_cast(lev->op); + err=subscribeOp->subscribe(NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ if (lev->subscription_state==LinphoneSubscriptionNone) linphone_event_set_state(lev,LinphoneSubscriptionOutgoingProgress); @@ -234,7 +285,7 @@ LinphoneStatus linphone_event_update_subscribe(LinphoneEvent *lev, const Linphon } LinphoneStatus linphone_event_refresh_subscribe(LinphoneEvent *lev) { - return sal_op_refresh(lev->op); + return lev->op->refresh(); } LinphoneStatus linphone_event_accept_subscription(LinphoneEvent *lev){ @@ -243,7 +294,8 @@ LinphoneStatus linphone_event_accept_subscription(LinphoneEvent *lev){ ms_error("linphone_event_accept_subscription(): cannot accept subscription if subscription wasn't just received."); return -1; } - err=sal_subscribe_accept(lev->op); + auto subscribeOp = dynamic_cast(lev->op); + err=subscribeOp->accept(); if (err==0){ linphone_event_set_state(lev,LinphoneSubscriptionActive); } @@ -256,7 +308,8 @@ LinphoneStatus linphone_event_deny_subscription(LinphoneEvent *lev, LinphoneReas ms_error("linphone_event_deny_subscription(): cannot deny subscription if subscription wasn't just received."); return -1; } - err=sal_subscribe_decline(lev->op,linphone_reason_to_sal(reason)); + auto subscribeOp = dynamic_cast(lev->op); + err=subscribeOp->decline(linphone_reason_to_sal(reason)); linphone_event_set_state(lev,LinphoneSubscriptionTerminated); return err; } @@ -271,14 +324,15 @@ LinphoneStatus linphone_event_notify(LinphoneEvent *lev, const LinphoneContent * ms_error("linphone_event_notify(): cannot notify if not an incoming subscription."); return -1; } - body_handler = sal_body_handler_from_content(body); - return sal_notify(lev->op, body_handler); + body_handler = sal_body_handler_from_content(body, false); + auto subscribeOp = dynamic_cast(lev->op); + return subscribeOp->notify(body_handler); } static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, LinphoneProxyConfig *cfg, const LinphoneAddress *resource, const char *event, int expires){ LinphoneCore *lc = core; LinphoneEvent *lev; - + if (!lc && cfg) { if (cfg->lc) lc = cfg->lc; @@ -289,20 +343,21 @@ static LinphoneEvent *_linphone_core_create_publish(LinphoneCore *core, Linphone } if (!resource && cfg) resource = linphone_proxy_config_get_identity_address(cfg); - - lev = linphone_event_new(lc,LinphoneSubscriptionInvalidDir, event,expires); - linphone_configure_op_with_proxy(lc,lev->op,resource,NULL,lp_config_get_int(lc->config,"sip","publish_msg_with_contact",0),cfg); - sal_op_set_manual_refresher_mode(lev->op,!lp_config_get_int(lc->config,"sip","refresh_generic_publish",1)); + + lev = linphone_event_new_with_op(lc, new SalPublishOp(lc->sal), LinphoneSubscriptionInvalidDir, event); + lev->expires = expires; + linphone_configure_op_with_proxy(lc,lev->op,resource,NULL, !!lp_config_get_int(lc->config,"sip","publish_msg_with_contact",0),cfg); + lev->op->setManualRefresherMode(!lp_config_get_int(lc->config,"sip","refresh_generic_publish",1)); return lev; } LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires){ return _linphone_core_create_publish(lc, NULL, resource, event, expires); } LinphoneEvent *linphone_proxy_config_create_publish(LinphoneProxyConfig *cfg, const char *event, int expires) { - + return _linphone_core_create_publish(NULL, cfg,NULL, event, expires); - - + + } LinphoneEvent *linphone_core_create_one_shot_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event){ LinphoneEvent *lev = linphone_core_create_publish(lc, resource, event, -1); @@ -319,12 +374,13 @@ static int _linphone_event_send_publish(LinphoneEvent *lev, const LinphoneConten return -1; } if (lev->send_custom_headers){ - sal_op_set_sent_custom_header(lev->op,lev->send_custom_headers); + lev->op->setSentCustomHeaders(lev->send_custom_headers); sal_custom_header_free(lev->send_custom_headers); lev->send_custom_headers=NULL; - }else sal_op_set_sent_custom_header(lev->op,NULL); + }else lev->op->setSentCustomHeaders(NULL); body_handler = sal_body_handler_from_content(body); - err=sal_publish(lev->op,NULL,NULL,lev->name,lev->expires,body_handler); + auto publishOp = dynamic_cast(lev->op); + err=publishOp->publish(NULL,NULL,lev->name,lev->expires,body_handler); if (err==0){ linphone_event_set_publish_state(lev,LinphonePublishProgress); }else if (notify_err){ @@ -354,14 +410,17 @@ LinphoneStatus linphone_event_update_publish(LinphoneEvent* lev, const LinphoneC } LinphoneStatus linphone_event_refresh_publish(LinphoneEvent *lev) { - return sal_op_refresh(lev->op); + return lev->op->refresh(); } void linphone_event_pause_publish(LinphoneEvent *lev) { - if (lev->op) sal_op_stop_refreshing(lev->op); + if (lev->op) lev->op->stopRefreshing(); } void linphone_event_unpublish(LinphoneEvent *lev) { lev->terminating = TRUE; /* needed to get clear event*/ - if (lev->op) sal_op_unpublish(lev->op); + if (lev->op) { + auto op = dynamic_cast(lev->op); + op->unpublish(); + } } void linphone_event_set_user_data(LinphoneEvent *ev, void *up){ ev->userdata=up; @@ -376,7 +435,7 @@ void linphone_event_add_custom_header(LinphoneEvent *ev, const char *name, const } const char* linphone_event_get_custom_header(LinphoneEvent* ev, const char* name){ - const SalCustomHeader *ch=sal_op_get_recv_custom_header(ev->op); + const SalCustomHeader *ch=ev->op->getRecvCustomHeaders(); return sal_custom_header_find(ch,name); } @@ -392,16 +451,18 @@ void linphone_event_terminate(LinphoneEvent *lev){ } lev->terminating=TRUE; - if (lev->dir==LinphoneSubscriptionIncoming){ - sal_notify_close(lev->op); + auto op = dynamic_cast(lev->op); + op->closeNotify(); }else if (lev->dir==LinphoneSubscriptionOutgoing){ - sal_unsubscribe(lev->op); + auto op = dynamic_cast(lev->op); + op->unsubscribe(); } if (lev->publish_state!=LinphonePublishNone){ if (lev->publish_state==LinphonePublishOk && lev->expires!=-1){ - sal_op_unpublish(lev->op); + auto op = dynamic_cast(lev->op); + op->unpublish(); } linphone_event_set_publish_state(lev,LinphonePublishCleared); return; @@ -421,8 +482,13 @@ LinphoneEvent *linphone_event_ref(LinphoneEvent *lev){ static void linphone_event_destroy(LinphoneEvent *lev){ if (lev->ei) linphone_error_info_unref(lev->ei); - if (lev->op) sal_op_release(lev->op); + if (lev->op) lev->op->release(); if (lev->send_custom_headers) sal_custom_header_free(lev->send_custom_headers); + if (lev->to_address) linphone_address_unref(lev->to_address); + if (lev->from_address) linphone_address_unref(lev->from_address); + if (lev->remote_contact_address) linphone_address_unref(lev->remote_contact_address); + linphone_event_cbs_unref(lev->callbacks); + ms_free(lev->name); } @@ -442,20 +508,47 @@ const char *linphone_event_get_name(const LinphoneEvent *lev){ return lev->name; } -const LinphoneAddress *linphone_event_get_from(const LinphoneEvent *lev){ - if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){ - return (LinphoneAddress*)sal_op_get_to_address(lev->op); - }else{ - return (LinphoneAddress*)sal_op_get_from_address(lev->op); - } +static const LinphoneAddress *_linphone_event_cache_to (const LinphoneEvent *lev) { + if (lev->to_address) + linphone_address_unref(lev->to_address); + char *buf = sal_address_as_string(lev->op->getToAddress()); + ((LinphoneEvent *)lev)->to_address = linphone_address_new(buf); + ms_free(buf); + return lev->to_address; +} + +static const LinphoneAddress *_linphone_event_cache_from (const LinphoneEvent *lev) { + if (lev->from_address) + linphone_address_unref(lev->from_address); + char *buf = sal_address_as_string(lev->op->getFromAddress()); + ((LinphoneEvent *)lev)->from_address = linphone_address_new(buf); + ms_free(buf); + return lev->from_address; +} + +static const LinphoneAddress *_linphone_event_cache_remote_contact (const LinphoneEvent *lev) { + if (lev->remote_contact_address) + linphone_address_unref(lev->remote_contact_address); + char *buf = sal_address_as_string(lev->op->getRemoteContactAddress()); + ((LinphoneEvent *)lev)->remote_contact_address = linphone_address_new(buf); + ms_free(buf); + return lev->remote_contact_address; +} + +const LinphoneAddress *linphone_event_get_from (const LinphoneEvent *lev) { + if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing) + return _linphone_event_cache_to(lev); + return _linphone_event_cache_from(lev); } const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev){ - if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing){ - return (LinphoneAddress*)sal_op_get_from_address(lev->op); - }else{ - return (LinphoneAddress*)sal_op_get_to_address(lev->op); - } + if (lev->is_out_of_dialog_op && lev->dir == LinphoneSubscriptionOutgoing) + return _linphone_event_cache_from(lev); + return _linphone_event_cache_to(lev); +} + +const LinphoneAddress *linphone_event_get_remote_contact (const LinphoneEvent *lev) { + return _linphone_event_cache_remote_contact(lev); } LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev){ @@ -472,6 +565,16 @@ static belle_sip_error_code _linphone_event_marshall(belle_sip_object_t *obj, ch return err; } +void _linphone_event_notify_notify_response(const LinphoneEvent *lev) { + LinphoneEventCbsNotifyResponseCb cb = linphone_event_cbs_get_notify_response(lev->callbacks); + if (cb) + cb(lev); +} + +LinphoneEventCbs *linphone_event_get_callbacks(const LinphoneEvent *ev) { + return ev->callbacks; +} + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneEvent); BELLE_SIP_INSTANCIATE_VPTR(LinphoneEvent, belle_sip_object_t, @@ -480,4 +583,3 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneEvent, belle_sip_object_t, _linphone_event_marshall, FALSE ); - diff --git a/coreapi/factory.c b/coreapi/factory.c index a141e3134..a9434159b 100644 --- a/coreapi/factory.c +++ b/coreapi/factory.c @@ -18,17 +18,23 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/factory.h" + +#include "c-wrapper/c-wrapper.h" + +#include "address/address-p.h" + +// TODO: From coreapi. Remove me later. #include "private.h" #ifndef PACKAGE_SOUND_DIR -#define PACKAGE_SOUND_DIR "." + #define PACKAGE_SOUND_DIR "." #endif #ifndef PACKAGE_RING_DIR -#define PACKAGE_RING_DIR "." + #define PACKAGE_RING_DIR "." #endif #ifndef PACKAGE_DATA_DIR -#define PACKAGE_DATA_DIR "." + #define PACKAGE_DATA_DIR "." #endif extern LinphoneAddress *_linphone_address_new(const char *addr); @@ -55,6 +61,8 @@ struct _LinphoneFactory { char *cached_image_resources_dir; char *cached_msplugins_dir; LinphoneErrorInfo* ei; + + void *user_data; }; static void linphone_factory_uninit(LinphoneFactory *obj){ @@ -139,33 +147,83 @@ LinphoneFactory *linphone_factory_get(void) { } void linphone_factory_clean(void){ + LinphonePrivate::AddressPrivate::clearSipAddressesCache(); if (_factory){ belle_sip_object_unref(_factory); _factory = NULL; } } -LinphoneCore *linphone_factory_create_core_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, - const char *config_path, const char *factory_config_path, void *user_data, void *system_context) { +static LinphoneCore *_linphone_factory_create_core ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + const char *config_path, + const char *factory_config_path, + void *user_data, + void *system_context, + bool_t automatically_start +) { bctbx_init_logger(FALSE); LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path); - LinphoneCore *lc = _linphone_core_new_with_config(cbs, config, user_data, system_context); + LinphoneCore *lc = _linphone_core_new_with_config(cbs, config, user_data, system_context, automatically_start); lp_config_unref(config); bctbx_uninit_logger(); return lc; } -LinphoneCore *linphone_factory_create_core(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, - const char *config_path, const char *factory_config_path){ - return linphone_factory_create_core_2(factory, cbs, config_path, factory_config_path, NULL, NULL); +LinphoneCore *linphone_factory_create_core ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + const char *config_path, + const char *factory_config_path +) { + return _linphone_factory_create_core(factory, cbs, config_path, factory_config_path, NULL, NULL, TRUE); } -LinphoneCore *linphone_factory_create_core_with_config(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config) { - return _linphone_core_new_with_config(cbs, config, NULL, NULL); +LinphoneCore *linphone_factory_create_core_2 ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + const char *config_path, + const char *factory_config_path, + void *user_data, + void *system_context +) { + return _linphone_factory_create_core(factory, cbs, config_path, factory_config_path, user_data, system_context, TRUE); } -LinphoneCore *linphone_factory_create_core_with_config_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config, void *user_data, void *system_context) { - return _linphone_core_new_with_config(cbs, config, user_data, system_context); +LinphoneCore *linphone_factory_create_core_3 ( + const LinphoneFactory *factory, + const char *config_path, + const char *factory_config_path, + void *system_context +) { + return _linphone_factory_create_core(factory, NULL, config_path, factory_config_path, NULL, system_context, FALSE); +} + +LinphoneCore *linphone_factory_create_core_with_config ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + LinphoneConfig *config +) { + return _linphone_core_new_with_config(cbs, config, NULL, NULL, TRUE); +} + +LinphoneCore *linphone_factory_create_core_with_config_2 ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + LinphoneConfig *config, + void *user_data, + void *system_context +) { + return _linphone_core_new_with_config(cbs, config, user_data, system_context, TRUE); +} + +LinphoneCore *linphone_factory_create_core_with_config_3 ( + const LinphoneFactory *factory, + LinphoneConfig *config, + void *system_context +) { + return _linphone_core_new_with_config(NULL, config, NULL, system_context, FALSE); } LinphoneCoreCbs *linphone_factory_create_core_cbs(const LinphoneFactory *factory) { @@ -173,7 +231,7 @@ LinphoneCoreCbs *linphone_factory_create_core_cbs(const LinphoneFactory *factory } LinphoneAddress *linphone_factory_create_address(const LinphoneFactory *factory, const char *addr) { - return _linphone_address_new(addr); + return linphone_address_new(addr); } LinphoneAuthInfo *linphone_factory_create_auth_info(const LinphoneFactory *factory, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain) { @@ -184,6 +242,10 @@ LinphoneCallCbs * linphone_factory_create_call_cbs(const LinphoneFactory *factor return _linphone_call_cbs_new(); } +LinphoneChatRoomCbs * linphone_factory_create_chat_room_cbs(const LinphoneFactory *factory) { + return _linphone_chat_room_cbs_new(); +} + LinphoneVcard *linphone_factory_create_vcard(LinphoneFactory *factory) { return _linphone_vcard_new(); } @@ -329,3 +391,55 @@ LinphoneTransports *linphone_factory_create_transports(LinphoneFactory *factory) LinphoneVideoActivationPolicy *linphone_factory_create_video_activation_policy(LinphoneFactory *factory) { return linphone_video_activation_policy_new(); } + +LinphoneContent *linphone_factory_create_content(LinphoneFactory *factory) { + return linphone_content_new(); +} + +LinphoneBuffer *linphone_factory_create_buffer(LinphoneFactory *factory) { + return linphone_buffer_new(); +} + +LinphoneBuffer *linphone_factory_create_buffer_from_data(LinphoneFactory *factory, const uint8_t *data, size_t size) { + return linphone_buffer_new_from_data(data, size); +} + +LinphoneBuffer *linphone_factory_create_buffer_from_string(LinphoneFactory *factory, const char *data) { + return linphone_buffer_new_from_string(data); +} + +LinphoneConfig *linphone_factory_create_config(LinphoneFactory *factory, const char *path) { + return linphone_config_new(path); +} + +LinphoneConfig *linphone_factory_create_config_with_factory(LinphoneFactory *factory, const char *path, const char *factory_path) { + return linphone_config_new_with_factory(path, factory_path); +} + +LinphoneConfig *linphone_factory_create_config_from_string(LinphoneFactory *factory, const char *data) { + return linphone_config_new_from_buffer(data); +} + +const bctbx_list_t * linphone_factory_get_dial_plans(const LinphoneFactory *factory) { + return linphone_dial_plan_get_all_list(); +} + +void *linphone_factory_get_user_data(const LinphoneFactory *factory) { + return factory->user_data; +} + +void linphone_factory_set_user_data(LinphoneFactory *factory, void *data) { + factory->user_data = data; +} + +void linphone_factory_set_log_collection_path(LinphoneFactory *factory, const char *path) { + linphone_core_set_log_collection_path(path); +} + +void linphone_factory_enable_log_collection(LinphoneFactory *factory, LinphoneLogCollectionState state) { + linphone_core_enable_log_collection(state); +} + +LinphoneTunnelConfig *linphone_factory_create_tunnel_config(LinphoneFactory *factory) { + return linphone_tunnel_config_new(); +} diff --git a/coreapi/friend.c b/coreapi/friend.c index debd7c248..6b3b175ff 100644 --- a/coreapi/friend.c +++ b/coreapi/friend.c @@ -23,65 +23,75 @@ */ #include "linphone/core.h" -#include "private.h" #include "linphone/lpconfig.h" #ifdef SQLITE_STORAGE_ENABLED -#ifndef _WIN32 -#if !defined(__ANDROID__) && !defined(__QNXNTO__) -# include -# include -# include -#endif + #ifndef _WIN32 + #if !defined(__ANDROID__) && !defined(__QNXNTO__) + #include + #include + #include + #endif #else -#include + #include #endif #define MAX_PATH_SIZE 1024 -#include "sqlite3.h" + #include "sqlite3.h" #endif +#include "c-wrapper/c-wrapper.h" +#include "core/core-p.h" +#include "db/main-db.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" + +using namespace std; + +using namespace LinphonePrivate; + const char *linphone_online_status_to_string(LinphoneOnlineStatus ss){ const char *str=NULL; switch(ss){ case LinphoneStatusOnline: - str=_("Online"); + str="Online"; break; case LinphoneStatusBusy: - str=_("Busy"); + str="Busy"; break; case LinphoneStatusBeRightBack: - str=_("Be right back"); + str="Be right back"; break; case LinphoneStatusAway: - str=_("Away"); + str="Away"; break; case LinphoneStatusOnThePhone: - str=_("On the phone"); + str="On the phone"; break; case LinphoneStatusOutToLunch: - str=_("Out to lunch"); + str="Out to lunch"; break; case LinphoneStatusDoNotDisturb: - str=_("Do not disturb"); + str="Do not disturb"; break; case LinphoneStatusMoved: - str=_("Moved"); + str="Moved"; break; case LinphoneStatusAltService: - str=_("Using another messaging service"); + str="Using another messaging service"; break; case LinphoneStatusOffline: - str=_("Offline"); + str="Offline"; break; case LinphoneStatusPending: - str=_("Pending"); + str="Pending"; break; case LinphoneStatusVacation: - str=_("Vacation"); + str="Vacation"; break; default: - str=_("Unknown status"); + str="Unknown status"; } return str; } @@ -184,12 +194,12 @@ void __linphone_friend_do_subscribe(LinphoneFriend *fr){ fr->lc->vtable.notify_recv(fr->lc,(LinphoneFriend*)fr); */ }else{ - sal_op_release(fr->outsub); + fr->outsub->release(); fr->outsub=NULL; } - fr->outsub=sal_op_new(lc->sal); + fr->outsub=new SalPresenceOp(lc->sal); linphone_configure_op(lc,fr->outsub,addr,NULL,TRUE); - sal_subscribe_presence(fr->outsub,NULL,NULL,lp_config_get_int(lc->config,"sip","subscribe_expires",600)); + fr->outsub->subscribe(NULL,NULL,lp_config_get_int(lc->config,"sip","subscribe_expires",600)); fr->subscribe_active=TRUE; } } @@ -403,7 +413,7 @@ void linphone_friend_add_phone_number(LinphoneFriend *lf, const char *phone) { } } -bctbx_list_t* linphone_friend_get_phone_numbers(LinphoneFriend *lf) { +bctbx_list_t* linphone_friend_get_phone_numbers(const LinphoneFriend *lf) { if (!lf || !lf->vcard) return NULL; if (linphone_core_vcard_supported()) { @@ -467,8 +477,8 @@ void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence) } } for(elem=lf->insubs; elem!=NULL; elem=bctbx_list_next(elem)){ - SalOp *op = (SalOp*)bctbx_list_get_data(elem); - sal_notify_presence(op,(SalPresenceModel *)presence); + auto op = reinterpret_cast(bctbx_list_get_data(elem)); + op->notifyPresence((SalPresenceModel *)presence); } } @@ -479,14 +489,14 @@ void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, SalOp *op){ void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, SalOp *op){ if (bctbx_list_find(lf->insubs, op)){ - sal_op_release(op); + op->release(); lf->insubs = bctbx_list_remove(lf->insubs, op); } } static void linphone_friend_unsubscribe(LinphoneFriend *lf){ if (lf->outsub!=NULL) { - sal_unsubscribe(lf->outsub); + lf->outsub->unsubscribe(); } /* for friend list there is no necessary outsub*/ lf->subscribe_active=FALSE; @@ -497,7 +507,7 @@ void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ LinphoneCore *lc=lf->lc; if (lf->outsub!=NULL) { - sal_op_release(lf->outsub); + lf->outsub->release(); lf->outsub=NULL; } @@ -520,13 +530,17 @@ void linphone_friend_invalidate_subscription(LinphoneFriend *lf){ lf->initial_subscribes_sent=FALSE; } -static void sal_notify_presence_close_cb (void *op) { - sal_notify_presence_close(static_cast(op)); +static void close_presence_notification(SalPresenceOp *op) { + op->notifyPresenceClose(); +} + +static void release_sal_op(SalOp *op) { + op->release(); } static void linphone_friend_close_incoming_subscriptions(LinphoneFriend *lf) { - bctbx_list_for_each(lf->insubs, sal_notify_presence_close_cb); - lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc)sal_op_release); + bctbx_list_for_each(lf->insubs, (MSIterateFunc) close_presence_notification); + lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc)release_sal_op); } void linphone_friend_close_subscriptions(LinphoneFriend *lf){ @@ -535,9 +549,9 @@ void linphone_friend_close_subscriptions(LinphoneFriend *lf){ } static void _linphone_friend_release_ops(LinphoneFriend *lf){ - lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc) sal_op_release); + lf->insubs = bctbx_list_free_with_data(lf->insubs, (MSIterateFunc) release_sal_op); if (lf->outsub){ - sal_op_release(lf->outsub); + lf->outsub->release(); lf->outsub=NULL; } } @@ -759,7 +773,7 @@ void linphone_friend_update_subscribes(LinphoneFriend *fr, bool_t only_when_regi linphone_friend_unsubscribe(fr); }else if (!can_subscribe && fr->outsub){ fr->subscribe_active=FALSE; - sal_op_stop_refreshing(fr->outsub); + fr->outsub->stopRefreshing(); } } @@ -893,7 +907,7 @@ void linphone_core_update_friends_subscriptions(LinphoneCore *lc) { } bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc){ - return lp_config_get_int(lc->config,"sip","subscribe_presence_only_when_registered",1); + return !!lp_config_get_int(lc->config,"sip","subscribe_presence_only_when_registered",1); } void linphone_core_send_initial_subscribes(LinphoneCore *lc) { @@ -1034,7 +1048,7 @@ LinphoneFriend * linphone_friend_new_from_config_file(LinphoneCore *lc, int inde linphone_friend_set_inc_subscribe_policy(lf,__policy_str_to_enum(tmp)); } a=lp_config_get_int(config,item,"subscribe",0); - linphone_friend_send_subscribe(lf,a); + linphone_friend_send_subscribe(lf,!!a); a = lp_config_get_int(config, item, "presence_received", 0); lf->presence_received = (bool_t)a; @@ -1120,7 +1134,7 @@ void linphone_friend_destroy(LinphoneFriend *lf) { linphone_friend_unref(lf); } -LinphoneVcard* linphone_friend_get_vcard(LinphoneFriend *fr) { +LinphoneVcard* linphone_friend_get_vcard(const LinphoneFriend *fr) { if (fr && linphone_core_vcard_supported()) return fr->vcard; return NULL; } @@ -1160,7 +1174,7 @@ bool_t linphone_friend_create_vcard(LinphoneFriend *fr, const char *name) { lc = fr->friend_list->lc; } if (lc) { - skip = 1 - lp_config_get_int(fr->lc->config, "misc", "store_friends", 1); + skip = !lp_config_get_int(fr->lc->config, "misc", "store_friends", 1); linphone_vcard_set_skip_validation(vcard, skip); } linphone_vcard_set_full_name(vcard, name); @@ -1262,13 +1276,13 @@ static bool_t linphone_update_friends_table(sqlite3* db) { int database_user_version = -1; char *errmsg = NULL; - if (sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &stmt_version, NULL) == SQLITE_OK) { - while(sqlite3_step(stmt_version) == SQLITE_ROW) { - database_user_version = sqlite3_column_int(stmt_version, 0); + if (sqlite3_prepare_v2(db, "PRAGMA user_version;", -1, &stmt_version, NULL) == SQLITE_OK) { + while(sqlite3_step(stmt_version) == SQLITE_ROW) { + database_user_version = sqlite3_column_int(stmt_version, 0); ms_debug("friends database user version = %i", database_user_version); } } - sqlite3_finalize(stmt_version); + sqlite3_finalize(stmt_version); if (database_user_version != 3100) { // Linphone 3.10.0 int ret = sqlite3_exec(db, @@ -1414,9 +1428,9 @@ static int create_friend(void *data, int argc, char **argv, char **colName) { } } linphone_friend_set_inc_subscribe_policy(lf, static_cast(atoi(argv[3]))); - linphone_friend_send_subscribe(lf, atoi(argv[4])); + linphone_friend_send_subscribe(lf, !!atoi(argv[4])); linphone_friend_set_ref_key(lf, ms_strdup(argv[5])); - lf->presence_received = atoi(argv[9]); + lf->presence_received = !!atoi(argv[9]); lf->storage_id = storage_id; *list = bctbx_list_append(*list, linphone_friend_ref(lf)); @@ -1710,6 +1724,10 @@ bctbx_list_t* linphone_core_fetch_friends_lists_from_db(LinphoneCore *lc) { #endif void linphone_core_set_friends_database_path(LinphoneCore *lc, const char *path) { + if (!linphone_core_conference_server_enabled(lc)) + L_GET_PRIVATE(lc->cppPtr)->mainDb->import(LinphonePrivate::MainDb::Sqlite3, path); + + // TODO: Remove me later. if (lc->friends_db_file){ ms_free(lc->friends_db_file); lc->friends_db_file = NULL; @@ -1717,8 +1735,6 @@ void linphone_core_set_friends_database_path(LinphoneCore *lc, const char *path) if (path) { lc->friends_db_file = ms_strdup(path); linphone_core_friends_storage_init(lc); - - linphone_core_migrate_friends_from_rc_to_db(lc); } } @@ -1726,69 +1742,6 @@ const char* linphone_core_get_friends_database_path(LinphoneCore *lc) { return lc->friends_db_file; } -void linphone_core_migrate_friends_from_rc_to_db(LinphoneCore *lc) { - LpConfig *lpc = NULL; - LinphoneFriend *lf = NULL; - LinphoneFriendList *lfl = linphone_core_get_default_friend_list(lc); - int i; -#ifndef SQLITE_STORAGE_ENABLED - ms_warning("linphone has been compiled without sqlite, can't migrate friends"); - return; -#endif - if (!lc) { - return; - } - - lpc = linphone_core_get_config(lc); - if (!lpc) { - ms_warning("this core has been started without a rc file, nothing to migrate"); - return; - } - if (lp_config_get_int(lpc, "misc", "friends_migration_done", 0) == 1) { - ms_warning("the friends migration has already been done, skipping..."); - return; - } - - if (bctbx_list_size(linphone_friend_list_get_friends(lfl)) > 0 && lfl->storage_id == 0) { - linphone_core_remove_friend_list(lc, lfl); - lfl = linphone_core_create_friend_list(lc); - linphone_core_add_friend_list(lc, lfl); - linphone_friend_list_unref(lfl); - } - - for (i = 0; (lf = linphone_friend_new_from_config_file(lc, i)) != NULL; i++) { - char friend_section[32]; - - const LinphoneAddress *addr = linphone_friend_get_address(lf); - if (addr) { - char *address = NULL; - const char *displayName = linphone_address_get_display_name(addr); - if (!displayName) displayName = linphone_address_get_username(addr); - - address = linphone_address_as_string(addr); - if (linphone_core_vcard_supported()) { - if (!linphone_friend_create_vcard(lf, displayName)) { - ms_warning("Couldn't create vCard for friend %s", address); - } else { - linphone_vcard_add_sip_address(linphone_friend_get_vcard(lf), address); - linphone_address_unref(lf->uri); - lf->uri = NULL; - } - } - ms_free(address); - - linphone_friend_list_add_friend(lfl, lf); - linphone_friend_unref(lf); - - snprintf(friend_section, sizeof(friend_section), "friend_%i", i); - lp_config_clean_section(lpc, friend_section); - } - } - - ms_debug("friends migration successful: %i friends migrated", i); - lp_config_set_int(lpc, "misc", "friends_migration_done", 1); -} - LinphoneSubscriptionState linphone_friend_get_subscription_state(const LinphoneFriend *lf) { return lf->out_sub_state; } @@ -1826,11 +1779,13 @@ const char * linphone_friend_phone_number_to_sip_uri(LinphoneFriend *lf, const c if(strcmp(normalized_number, phone_number) != 0) { char *old_uri = ms_strdup_printf("sip:%s@%s;user=phone", phone_number, linphone_proxy_config_get_domain(proxy_config)); bctbx_iterator_t *it = bctbx_map_cchar_find_key(lf->friend_list->friends_map_uri, old_uri); - if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(lf->friend_list->friends_map_uri))){ + bctbx_iterator_t *end = bctbx_map_cchar_end(lf->friend_list->friends_map_uri); + if (!bctbx_iterator_cchar_equals(it, end)){ linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it))); bctbx_map_cchar_erase(lf->friend_list->friends_map_uri, it); } bctbx_iterator_cchar_delete(it); + bctbx_iterator_cchar_delete(end); ms_free(old_uri); } diff --git a/coreapi/friendlist.c b/coreapi/friendlist.c index f29b626ff..e55892a21 100644 --- a/coreapi/friendlist.c +++ b/coreapi/friendlist.c @@ -17,11 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/core.h" -#include "private.h" - #include +#include "linphone/api/c-content.h" +#include "linphone/core.h" + +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneFriendListCbs); BELLE_SIP_INSTANCIATE_VPTR(LinphoneFriendListCbs, belle_sip_object_t, @@ -461,14 +466,14 @@ const LinphoneAddress * _linphone_friend_list_get_rls_address(const LinphoneFrie const char* rls_uri = lp_config_get_string(list->lc->config, "sip", "rls_uri", NULL); if (list->lc->default_rls_addr) linphone_address_unref(list->lc->default_rls_addr); - + list->lc->default_rls_addr=NULL; - + if (rls_uri) { /*to make sure changes in config are used if any*/ list->lc->default_rls_addr = linphone_address_new(rls_uri); } - + return list->lc->default_rls_addr; } else @@ -476,7 +481,7 @@ const LinphoneAddress * _linphone_friend_list_get_rls_address(const LinphoneFrie } void linphone_friend_list_set_rls_address(LinphoneFriendList *list, const LinphoneAddress *rls_addr){ LinphoneAddress *new_rls_addr = rls_addr ? linphone_address_clone(rls_addr) : NULL; - + if (list->rls_addr){ linphone_address_unref(list->rls_addr); } @@ -572,6 +577,7 @@ LinphoneFriendListStatus linphone_friend_list_import_friend(LinphoneFriendList * } iterator = bctbx_list_next(iterator); } + bctbx_list_free(phone_numbers); addresses = linphone_friend_get_addresses(lf); iterator = (bctbx_list_t *)addresses; @@ -630,10 +636,13 @@ static LinphoneFriendListStatus _linphone_friend_list_remove_friend(LinphoneFrie list->friends = bctbx_list_erase_link(list->friends, elem); if(lf->refkey) { bctbx_iterator_t * it = bctbx_map_cchar_find_key(list->friends_map, lf->refkey); - if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(list->friends_map))){ + bctbx_iterator_t * end = bctbx_map_cchar_end(list->friends_map); + if (!bctbx_iterator_cchar_equals(it, end)){ linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it))); bctbx_map_cchar_erase(list->friends_map, it); } + if (it) bctbx_iterator_cchar_delete(it); + if (end) bctbx_iterator_cchar_delete(end); } phone_numbers = linphone_friend_get_phone_numbers(lf); @@ -643,14 +652,17 @@ static LinphoneFriendListStatus _linphone_friend_list_remove_friend(LinphoneFrie const char *uri = linphone_friend_phone_number_to_sip_uri(lf, number); if(uri) { bctbx_iterator_t * it = bctbx_map_cchar_find_key(list->friends_map_uri, uri); - if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(list->friends_map_uri))){ + bctbx_iterator_t * end = bctbx_map_cchar_end(list->friends_map_uri); + if (!bctbx_iterator_cchar_equals(it, end)){ linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it))); bctbx_map_cchar_erase(list->friends_map_uri, it); } - bctbx_iterator_cchar_delete(it); + if (it) bctbx_iterator_cchar_delete(it); + if (end) bctbx_iterator_cchar_delete(end); } iterator = bctbx_list_next(iterator); } + if (phone_numbers) bctbx_list_free(phone_numbers); addresses = linphone_friend_get_addresses(lf); iterator = (bctbx_list_t *)addresses; @@ -659,13 +671,16 @@ static LinphoneFriendListStatus _linphone_friend_list_remove_friend(LinphoneFrie char *uri = linphone_address_as_string_uri_only(lfaddr); if(uri) { bctbx_iterator_t * it = bctbx_map_cchar_find_key(list->friends_map_uri, uri); - if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(list->friends_map_uri))){ + bctbx_iterator_t * end = bctbx_map_cchar_end(list->friends_map_uri); + if (!bctbx_iterator_cchar_equals(it, end)){ linphone_friend_unref((LinphoneFriend*)bctbx_pair_cchar_get_second(bctbx_iterator_cchar_get_pair(it))); bctbx_map_cchar_erase(list->friends_map_uri, it); } - bctbx_iterator_cchar_delete(it); + if (it) bctbx_iterator_cchar_delete(it); + if (end) bctbx_iterator_cchar_delete(end); ms_free(uri); } + iterator = bctbx_list_next(iterator); } @@ -760,40 +775,50 @@ void linphone_friend_list_synchronize_friends_from_server(LinphoneFriendList *li } LinphoneFriend * linphone_friend_list_find_friend_by_address(const LinphoneFriendList *list, const LinphoneAddress *address) { - LinphoneFriend *result = NULL; - char *uri = linphone_address_as_string_uri_only(address); - bctbx_iterator_t* it = bctbx_map_cchar_find_key(list->friends_map_uri, uri); - if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(list->friends_map_uri))) { - bctbx_pair_t *pair = bctbx_iterator_cchar_get_pair(it); - result = (LinphoneFriend *)bctbx_pair_cchar_get_second(pair); + LinphoneAddress *clean_addr = linphone_address_clone(address); + LinphoneFriend *lf; + if (linphone_address_has_uri_param(clean_addr, "gr")) { + linphone_address_remove_uri_param(clean_addr, "gr"); } - bctbx_iterator_cchar_delete(it); - ms_free(uri); - return result; + char *uri = linphone_address_as_string_uri_only(clean_addr); + lf = linphone_friend_list_find_friend_by_uri(list, uri); + bctbx_free(uri); + linphone_address_unref(clean_addr); + return lf; } LinphoneFriend * linphone_friend_list_find_friend_by_uri(const LinphoneFriendList *list, const char *uri) { LinphoneFriend *result = NULL; - LinphoneAddress *address = linphone_address_new(uri); - if(address) { - result = linphone_friend_list_find_friend_by_address(list, address); - linphone_address_unref(address); + bctbx_iterator_t *it = bctbx_map_cchar_find_key(list->friends_map_uri, uri); + bctbx_iterator_t *end = bctbx_map_cchar_end(list->friends_map_uri); + if (!bctbx_iterator_cchar_equals(it, end)) { + bctbx_pair_t *pair = bctbx_iterator_cchar_get_pair(it); + result = (LinphoneFriend *)bctbx_pair_cchar_get_second(pair); + } + bctbx_iterator_cchar_delete(end); + bctbx_iterator_cchar_delete(it); + return result; +} + +LinphoneFriend *linphone_friend_list_find_friend_by_ref_key (const LinphoneFriendList *list, const char *ref_key) { + LinphoneFriend *result = NULL; + if (list) { + bctbx_iterator_t *it = bctbx_map_cchar_find_key(list->friends_map, ref_key); + bctbx_iterator_t *end = bctbx_map_cchar_end(list->friends_map); + if (!bctbx_iterator_cchar_equals(it, end)) { + bctbx_pair_t *pair = bctbx_iterator_cchar_get_pair(it); + result = (LinphoneFriend *)bctbx_pair_cchar_get_second(pair); + } + bctbx_iterator_cchar_delete(end); + bctbx_iterator_cchar_delete(it); } return result; } -LinphoneFriend * linphone_friend_list_find_friend_by_ref_key(const LinphoneFriendList *list, const char *ref_key) { - if(list) { - bctbx_iterator_t* it = bctbx_map_cchar_find_key(list->friends_map, ref_key); - if (!bctbx_iterator_cchar_equals(it, bctbx_map_cchar_end(list->friends_map))) { - bctbx_pair_t *pair = bctbx_iterator_cchar_get_pair(it); - return (LinphoneFriend *)bctbx_pair_cchar_get_second(pair); - } - } - return NULL; -} - -LinphoneFriend * linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, SalOp *op) { +LinphoneFriend * linphone_friend_list_find_friend_by_inc_subscribe ( + const LinphoneFriendList *list, + LinphonePrivate::SalOp *op +) { const bctbx_list_t *elem; for (elem = list->friends; elem != NULL; elem = bctbx_list_next(elem)) { LinphoneFriend *lf = (LinphoneFriend *)bctbx_list_get_data(elem); @@ -802,11 +827,14 @@ LinphoneFriend * linphone_friend_list_find_friend_by_inc_subscribe(const Linphon return NULL; } -LinphoneFriend * linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, SalOp *op) { +LinphoneFriend * linphone_friend_list_find_friend_by_out_subscribe ( + const LinphoneFriendList *list, + LinphonePrivate::SalOp *op +) { const bctbx_list_t *elem; for (elem = list->friends; elem != NULL; elem = bctbx_list_next(elem)) { LinphoneFriend *lf = (LinphoneFriend *)bctbx_list_get_data(elem); - if (lf->outsub && ((lf->outsub == op) || sal_op_is_forked_of(lf->outsub, op))) return lf; + if (lf->outsub && ((lf->outsub == op) || lf->outsub->isForkedOf(op))) return lf; } return NULL; } @@ -874,14 +902,14 @@ void linphone_friend_list_update_subscriptions(LinphoneFriendList *list){ const LinphoneAddress *address = _linphone_friend_list_get_rls_address(list); bool_t only_when_registered = FALSE; bool_t should_send_list_subscribe = FALSE; - + if (list->lc){ if (address) cfg = linphone_core_lookup_known_proxy(list->lc, address); only_when_registered = linphone_core_should_subscribe_friends_only_when_registered(list->lc); should_send_list_subscribe = (!only_when_registered || !cfg || cfg->state == LinphoneRegistrationOk); } - + if (address != NULL) { if (list->enable_subscriptions) { if (should_send_list_subscribe){ @@ -939,7 +967,7 @@ void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, Lin const char *subtype = linphone_content_get_subtype(body); if ((strcmp(type, "multipart") != 0) || (strcmp(subtype, "related") != 0)) { - ms_warning("multipart presence notified but it is not 'multipart/related'"); + ms_warning("multipart presence notified but it is not 'multipart/related', instead is '%s/%s'", type, subtype); return; } @@ -1008,7 +1036,7 @@ LinphoneCore* linphone_friend_list_get_core(const LinphoneFriendList *list) { static LinphoneStatus linphone_friend_list_import_friends_from_vcard4(LinphoneFriendList *list, bctbx_list_t *vcards) { bctbx_list_t *vcards_iterator = NULL; int count = 0; - + if (!linphone_core_vcard_supported()) { ms_error("vCard support wasn't enabled at compilation time"); return -1; @@ -1017,9 +1045,9 @@ static LinphoneStatus linphone_friend_list_import_friends_from_vcard4(LinphoneFr ms_error("Can't import into a NULL list"); return -1; } - + vcards_iterator = vcards; - + while (vcards_iterator != NULL && bctbx_list_get_data(vcards_iterator) != NULL) { LinphoneVcard *vcard = (LinphoneVcard *)bctbx_list_get_data(vcards_iterator); LinphoneFriend *lf = linphone_friend_new_from_vcard(vcard); @@ -1036,7 +1064,7 @@ static LinphoneStatus linphone_friend_list_import_friends_from_vcard4(LinphoneFr bctbx_list_free(vcards); linphone_core_store_friends_list_in_db(list->lc, list); return count; - + } LinphoneStatus linphone_friend_list_import_friends_from_vcard4_file(LinphoneFriendList *list, const char *vcard_file) { bctbx_list_t *vcards = NULL; @@ -1115,7 +1143,7 @@ void linphone_friend_list_enable_subscriptions(LinphoneFriendList *list, bool_t } else { linphone_friend_list_close_subscriptions(list); } - + } } diff --git a/coreapi/help/doc/doxygen/CMakeLists.txt b/coreapi/help/doc/doxygen/CMakeLists.txt index 94eddc998..57dd6b574 100644 --- a/coreapi/help/doc/doxygen/CMakeLists.txt +++ b/coreapi/help/doc/doxygen/CMakeLists.txt @@ -1,8 +1,8 @@ -############################################################################ +################################################################################ # CMakeLists.txt # Copyright (C) 2017 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 @@ -18,37 +18,39 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -############################################################################ +################################################################################ -if (ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER) - find_package(Doxygen) - if(DOXYGEN_FOUND) - if(DOXYGEN_DOT_FOUND) - set(top_srcdir "${PROJECT_SOURCE_DIR}") - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) - set(DOC_INPUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile - ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.dox - ${LINPHONE_HEADER_FILES} - ) - set(XML_DIR "${CMAKE_CURRENT_BINARY_DIR}/xml") - set(LINPHONE_DOXYGEN_XML_DIR ${XML_DIR} PARENT_SCOPE) - add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${XML_DIR}/index.xml" - COMMAND ${CMAKE_COMMAND} -E remove -f html/* xml/* - COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile - DEPENDS ${DOC_INPUT_FILES} - ) - add_custom_target(linphone-doc ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/html/index.html" "${XML_DIR}/index.xml") - if(ENABLE_DOC) - install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/html" "${XML_DIR}" - DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/linphone-${LINPHONE_VERSION}" - ) - endif() - else() - if (ENABLE_CXX_WRAPPER) - message(FATAL_ERROR "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") - else() - message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") - endif() - endif() +if (ENABLE_DOC OR ENABLE_CXX_WRAPPER OR ENABLE_CSHARP_WRAPPER OR ENABLE_JAVA_WRAPPER) + find_package(Doxygen) + if(DOXYGEN_FOUND) + if(DOXYGEN_DOT_FOUND) + set(top_srcdir "${PROJECT_SOURCE_DIR}") + set(DOXYGEN_INPUT "") + foreach (HEADER_FILE ${LINPHONE_HEADER_FILES}) + string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${HEADER_FILE}\"") + endforeach () + string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${CMAKE_CURRENT_SOURCE_DIR}\"") + string(CONCAT DOXYGEN_INPUT ${DOXYGEN_INPUT} " \"${PROJECT_SOURCE_DIR}/coreapi/help/examples/C\"") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile) + set(DOC_INPUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + ${CMAKE_CURRENT_SOURCE_DIR}/doxygen.dox + ${LINPHONE_HEADER_FILES} + ) + set(XML_DIR "${CMAKE_CURRENT_BINARY_DIR}/xml") + set(LINPHONE_DOXYGEN_XML_DIR ${XML_DIR} PARENT_SCOPE) + add_custom_command(OUTPUT "${XML_DIR}/index.xml" + COMMAND ${CMAKE_COMMAND} -E remove -f xml/* + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + DEPENDS ${DOC_INPUT_FILES} + ) + add_custom_target(linphone-doc ALL DEPENDS "${XML_DIR}/index.xml") + else() + if (ENABLE_CXX_WRAPPER) + message(FATAL_ERROR "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") + else() + message(WARNING "The dot program is needed to generate the linphone documentation. You can get it from http://www.graphviz.org/.") + endif() endif() + endif() endif() + diff --git a/coreapi/help/doc/doxygen/Doxyfile.in b/coreapi/help/doc/doxygen/Doxyfile.in index 9aeb18d6f..651017491 100644 --- a/coreapi/help/doc/doxygen/Doxyfile.in +++ b/coreapi/help/doc/doxygen/Doxyfile.in @@ -772,9 +772,7 @@ WARN_LOGFILE = # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. -INPUT = @top_srcdir@/include/linphone \ - @top_srcdir@/coreapi/help/doc/doxygen \ - @top_srcdir@/coreapi/help/examples/C +INPUT = @DOXYGEN_INPUT@ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -1047,7 +1045,7 @@ IGNORE_PREFIX = # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. -GENERATE_HTML = YES +GENERATE_HTML = NO # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -1591,7 +1589,7 @@ EXTRA_SEARCH_MAPPINGS = # If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # The default value is: YES. -GENERATE_LATEX = YES +GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -1827,7 +1825,7 @@ RTF_SOURCE_CODE = NO # classes and files. # The default value is: NO. -GENERATE_MAN = YES +GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of @@ -2006,7 +2004,8 @@ SEARCH_INCLUDES = YES # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = . +INCLUDE_PATH = . \ + @LINPHONE_HEADER_ROOT_DIR@ # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the diff --git a/coreapi/help/doc/sphinx/CMakeLists.txt b/coreapi/help/doc/sphinx/CMakeLists.txt index 15abb7480..5e1e890c5 100644 --- a/coreapi/help/doc/sphinx/CMakeLists.txt +++ b/coreapi/help/doc/sphinx/CMakeLists.txt @@ -20,42 +20,40 @@ # ############################################################################ -if (ENABLE_SPHINX_DOC) - set(GENERATED_LANGUAGES c cpp csharp) - set(DOCUMENTATION_DIRS ) - set(GENERATED_SPHINX_SOURCES ) - foreach(LANGUAGE_ ${GENERATED_LANGUAGES}) - set(DOCUMENTATION_DIR ${CMAKE_CURRENT_BINARY_DIR}/source/${LANGUAGE_}) - list(APPEND DOCUMENTATION_DIRS ${DOCUMENTATION_DIR}) - list(APPEND GENERATED_SPHINX_SOURCES ${DOCUMENTATION_DIR}/index.rst) - endforeach(LANGUAGE_) - - set(PYTHON_SCRIPTS gendoc.py - ${linphone_SOURCE_DIR}/tools/abstractapi.py - ${linphone_SOURCE_DIR}/tools/genapixml.py - ${linphone_SOURCE_DIR}/tools/metadoc.py - ${linphone_SOURCE_DIR}/tools/metaname.py +if (ENABLE_DOC) + set(doc_source_dir ${CMAKE_CURRENT_BINARY_DIR}/source) + set(doc_output_dir ${CMAKE_CURRENT_BINARY_DIR}/build) + set(reference_doc_source_dir ${doc_source_dir}/reference) + set(static_documentation_files + guides/authentication.rst + guides/buddy_list.rst + guides/call_control.rst + guides/call_logs.rst + guides/call_misc.rst + guides/chatroom.rst + guides/conferencing.rst + guides/event_api.rst + guides/initializing.rst + guides/ios_portability.rst + guides/linphone_address.rst + guides/media_parameters.rst + guides/misc.rst + guides/network_parameters.rst + guides/proxies.rst + index.rst + logo.png + samples/samples.rst ) - set(MUSTACHE_TEMPLATES class_page.mustache - enums_page.mustache - index_page.mustache - ) - configure_file(conf.py.in source/conf.py) - configure_file(source/index.rst source/index.rst COPYONLY) - add_custom_command(OUTPUT ${GENERATED_SPHINX_SOURCES} - COMMAND ${CMAKE_COMMAND} -E remove -f ${DOCUMENTATION_DIRS} - COMMAND ${PYTHON_EXECUTABLE} '${CMAKE_CURRENT_SOURCE_DIR}/gendoc.py' '${LINPHONE_DOXYGEN_XML_DIR}' -o 'source' - DEPENDS ${PYTHON_SCRIPTS} - ${MUSTACHE_TEMPLATES} - ${LINPHONE_DOXYGEN_XML_DIR}/index.xml - linphone-doc - ) - add_custom_command(OUTPUT build/html/index.html - COMMAND ${CMAKE_COMMAND} -E remove_directory build - COMMAND ${PYTHON_EXECUTABLE} -msphinx -M html 'source' 'build' - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/source/conf.py - ${CMAKE_CURRENT_BINARY_DIR}/source/index.rst - ${GENERATED_SPHINX_SOURCES} - ) - add_custom_target(sphinx-doc ALL DEPENDS build/html/index.html) + configure_file(conf.py.in ${doc_source_dir}/conf.py) + foreach(file ${static_documentation_files}) + configure_file(${file} ${doc_source_dir}/${file} COPYONLY) + endforeach(file) + foreach(source ${LINPHONE_C_EXAMPLES_SOURCE}) + configure_file(${source} ${doc_source_dir}/samples/ COPYONLY) + endforeach(source) + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${doc_source_dir}/_static ${reference_doc_source_dir}) + add_custom_target(sphinx-doc ALL ${PYTHON_EXECUTABLE} '${CMAKE_CURRENT_SOURCE_DIR}/gendoc.py' '${LINPHONE_DOXYGEN_XML_DIR}' -o '${reference_doc_source_dir}' + COMMAND ${PYTHON_EXECUTABLE} -msphinx -M html '${doc_source_dir}' '${doc_output_dir}' + DEPENDS linphone-doc) + install(DIRECTORY ${doc_output_dir}/html/ DESTINATION ${CMAKE_INSTALL_DOCDIR}/${LINPHONE_VERSION}) endif() diff --git a/coreapi/help/doc/sphinx/class_page.mustache b/coreapi/help/doc/sphinx/class_page.mustache index f835c5c3e..947336994 100644 --- a/coreapi/help/doc/sphinx/class_page.mustache +++ b/coreapi/help/doc/sphinx/class_page.mustache @@ -1,6 +1,13 @@ +{{#hasNamespaceDeclarator}} +.. {{#write_declarator}}namespace{{/write_declarator}}:: {{{namespace}}} + {{#isJava}} + :noindex: + {{/isJava}} +{{/hasNamespaceDeclarator}} + {{#make_chapter}}{{{className}}} class{{/make_chapter}} -.. {{#write_declarator}}class{{/write_declarator}}:: {{{fullClassName}}} +.. {{#write_declarator}}class{{/write_declarator}}:: {{{classDeclaration}}} {{#briefDoc}} {{#lines}} @@ -17,9 +24,24 @@ {{{selector}}} +{{#hasNamespaceDeclarator}} +.. {{#write_declarator}}namespace{{/write_declarator}}:: {{{fullClassName}}} + {{#isJava}} + :noindex: + {{/isJava}} +{{/hasNamespaceDeclarator}} + + Summary ======= +{{#hasEnums}} +Enums +----- + +{{{enumsSummary}}} +{{/hasEnums}} + {{#hasProperties}} Properties ---------- @@ -41,18 +63,61 @@ Class methods {{{classMethodsSummary}}} {{/hasClassMethods}} + Detailed descriptions ===================== +{{#hasEnums}} +Enums +----- + +{{#enums}} +{{#make_subsection}}{{{name}}}{{/make_subsection}} +.. {{#write_declarator}}enum{{/write_declarator}}:: {{{declaration}}} + + {{#briefDesc}} + {{#lines}} + {{{line}}} + {{/lines}} + {{/briefDesc}} + + {{{selector}}} + + {{#enumerators}} + {{#isNotJava}} + .. {{#write_declarator}}enumerator{{/write_declarator}}:: {{{name}}} + + {{/isNotJava}} + {{#isJava}} + **{{{name}}}** + {{/isJava}} + {{#briefDesc}} + {{#lines}} + {{{line}}} + {{/lines}} + {{/briefDesc}} + + {{{selector}}} + + {{/enumerators}} +{{/enums}} +{{/hasEnums}} + {{#hasProperties}} Properties ---------- {{#properties}} + +.. _{{{ref_label}}}: + {{{title}}} {{#hasNamespaceDeclarator}} .. {{#write_declarator}}namespace{{/write_declarator}}:: {{{fullClassName}}} + {{#isJava}} + :noindex: + {{/isJava}} {{/hasNamespaceDeclarator}} {{#getter}} @@ -100,6 +165,9 @@ Public methods {{#hasNamespaceDeclarator}} .. {{#write_declarator}}namespace{{/write_declarator}}:: {{{fullClassName}}} + {{#isJava}} + :noindex: + {{/isJava}} {{/hasNamespaceDeclarator}} {{#methods}} @@ -128,6 +196,9 @@ Class methods {{#hasNamespaceDeclarator}} .. {{#write_declarator}}namespace{{/write_declarator}}:: {{{fullClassName}}} + {{#isJava}} + :noindex: + {{/isJava}} {{/hasNamespaceDeclarator}} {{#classMethods}} diff --git a/coreapi/help/doc/sphinx/conf.py.in b/coreapi/help/doc/sphinx/conf.py.in index 378b84244..3d903aaf3 100644 --- a/coreapi/help/doc/sphinx/conf.py.in +++ b/coreapi/help/doc/sphinx/conf.py.in @@ -31,7 +31,7 @@ # 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_csharp.csharp'] +extensions = ['sphinx_csharp.csharp', 'javasphinx'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -83,20 +83,33 @@ todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -#html_theme = 'alabaster' html_theme = 'classic' # 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 = {} +html_theme_options = { + 'sidebarwidth': '360', + 'body_max_width': '100%', + 'collapsiblesidebar': 'true' +} # 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'] +# Path to the picture to use as logo. +html_logo = 'logo.png' + +# Enable html5 +html_experimental_html5_writer = True + +# Side bar customization +#html_sidebars = { +# 'reference/*/*' : ['searchbox.html', 'globaltoc.html'] +#} # -- Options for HTMLHelp output ------------------------------------------ diff --git a/coreapi/help/doc/sphinx/enum_page.mustache b/coreapi/help/doc/sphinx/enum_page.mustache new file mode 100644 index 000000000..c400e96eb --- /dev/null +++ b/coreapi/help/doc/sphinx/enum_page.mustache @@ -0,0 +1,39 @@ +{{#namespace}} +.. {{#write_declarator}}namespace{{/write_declarator}}:: {{{namespace}}} + {{#isJava}} + :noindex: + {{/isJava}} +{{/namespace}} + +{{#enum}} +{{#make_chapter}}{{{name}}} enum{{/make_chapter}} + +.. {{#write_declarator}}enum{{/write_declarator}}:: {{{declaration}}} + + {{#briefDesc}} + {{#lines}} + {{{line}}} + {{/lines}} + {{/briefDesc}} + + {{{selector}}} + + {{#enumerators}} + {{#isNotJava}} + .. {{#write_declarator}}enumerator{{/write_declarator}}:: {{{name}}} + + {{/isNotJava}} + {{#isJava}} + **{{{name}}}** + {{/isJava}} + {{#briefDesc}} + {{#lines}} + {{{line}}} + {{/lines}} + {{/briefDesc}} + + {{{selector}}} + + {{/enumerators}} + +{{/enum}} diff --git a/coreapi/help/doc/sphinx/enums_page.mustache b/coreapi/help/doc/sphinx/enums_page.mustache deleted file mode 100644 index fd013094a..000000000 --- a/coreapi/help/doc/sphinx/enums_page.mustache +++ /dev/null @@ -1,30 +0,0 @@ -{{#enums}} -{{{sectionName}}} - -.. {{#write_declarator}}enum{{/write_declarator}}:: {{{fullName}}} - - {{#briefDesc}} - {{#lines}} - {{{line}}} - {{/lines}} - {{/briefDesc}} - - {{{selector}}} - - {{#hasNamespaceDeclarator}} - .. {{#write_declarator}}namespace{{/write_declarator}}:: {{{namespace}}} - {{/hasNamespaceDeclarator}} - - {{#enumerators}} - .. {{#write_declarator}}enumerator{{/write_declarator}}:: {{{name}}}{{#value}} = {{{value}}}{{/value}} - - {{#briefDesc}} - {{#lines}} - {{{line}}} - {{/lines}} - {{/briefDesc}} - - {{{selector}}} - - {{/enumerators}} -{{/enums}} diff --git a/coreapi/help/doc/sphinx/gendoc.py b/coreapi/help/doc/sphinx/gendoc.py index 800d57bc6..514dfb596 100755 --- a/coreapi/help/doc/sphinx/gendoc.py +++ b/coreapi/help/doc/sphinx/gendoc.py @@ -18,10 +18,12 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import sys -import os import argparse +import hashlib +import logging +import os import pystache +import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools')) import abstractapi @@ -30,7 +32,18 @@ import metaname import metadoc +def md5sum(file): + hasher = hashlib.md5() + with open(file, mode='rb') as f: + hasher.update(f.read()) + return hasher.hexdigest() + + class RstTools: + @staticmethod + def make_part(text): + return RstTools.make_section(text, char='#', overline=True) + @staticmethod def make_chapter(text): return RstTools.make_section(text, char='*', overline=True) @@ -55,12 +68,27 @@ class RstTools: class Table: def __init__(self): self._rows = [] - self._widths = [] - self._heights = [] - + @property def rows(self): return self._rows + + class CSVTable(Table): + def addrow(self, row): + self._rows.append(', '.join([self._format_cell(cell) for cell in row])) + + def __str__(self): + return '.. csv-table::\n\t\n\t' + '\n\t'.join(self._rows) + + def _format_cell(self, cell): + return '"{0}"'.format(cell.replace('"', '""')) + + + class GridTable(Table): + def __init__(self): + RstTools.Table.__init__(self) + self._widths = [] + self._heights = [] def addrow(self, row): if len(self._widths) == 0: @@ -124,78 +152,132 @@ class RstTools: class LangInfo: def __init__(self, langCode): + if langCode not in LangInfo._displayNames: + raise ValueError("Invalid language code '{0}'".format(langCode)) self.langCode = langCode - self.displayName = LangInfo._lang_code_to_display_name(langCode) self.nameTranslator = metaname.Translator.get(langCode) self.langTranslator = abstractapi.Translator.get(langCode) self.docTranslator = metadoc.SphinxTranslator(langCode) - - @staticmethod - def _lang_code_to_display_name(langCode): - if langCode == 'C': - return 'C' - elif langCode == 'Cpp': - return 'C++' - elif langCode == 'CSharp': - return 'C#' - else: - raise ValueError("Invalid language code: '{0}'".format(langCode)) + + @property + def displayName(self): + return LangInfo._displayNames[self.langCode] + + @property + def directory(self): + return self.langCode.lower() + + _displayNames = { + 'C' : 'C', + 'Cpp' : 'C++', + 'Java' : 'Java', + 'CSharp': 'C#' + } -class SphinxPage(object): - def __init__(self, lang, langs, filename): +class SphinxPart(object): + def __init__(self, lang, langs): object.__init__(self) self.lang = lang self.langs = langs - self.filename = filename - - @property - def hasNamespaceDeclarator(self): - return ('namespaceDeclarator' in dir(self.docTranslator)) - + @property def language(self): return self.lang.displayName - + @property def docTranslator(self): return self.lang.docTranslator - + + @property + def hasNamespaceDeclarator(self): + return ('namespaceDeclarator' in dir(self.docTranslator)) + + @property + def isJava(self): + return self.lang.langCode == 'Java' + + @property + def isNotJava(self): + return not self.isJava + + def make_part(self): + return lambda text: RstTools.make_part(pystache.render(text, self)) + def make_chapter(self): return lambda text: RstTools.make_chapter(pystache.render(text, self)) - + def make_section(self): return lambda text: RstTools.make_section(pystache.render(text, self)) - + def make_subsection(self): - return lambda text: RstTools.make_subsection(pystache.render(text, self.properties)) - + return lambda text: RstTools.make_subsection(pystache.render(text, self)) + + def make_subsection(self): + return lambda text: RstTools.make_subsubsection(pystache.render(text, self)) + def write_declarator(self): return lambda text: self.docTranslator.get_declarator(text) - - def write(self, directory): - r = pystache.Renderer() - filepath = os.path.join(directory, self.filename) - with open(filepath, mode='w') as f: - f.write(r.render(self)) - - def _get_translated_namespace(self, obj): - namespace = obj.find_first_ancestor_by_type(abstractapi.Namespace) - return namespace.name.translate(self.lang.nameTranslator, recursive=True) - + def _make_selector(self, obj): links = [] - ref = metadoc.Reference(None) - ref.relatedObject = obj for lang in self.langs: if lang is self.lang: link = lang.displayName else: + if lang.langCode == 'Java' and type(obj) is abstractapi.Enumerator: + ref = metadoc.Reference.make_ref_from_object(None, obj.parent) + else: + ref = metadoc.Reference.make_ref_from_object(None, obj) link = ref.translate(lang.docTranslator, label=lang.displayName) - links.append(link) - return ' '.join(links) + + +class EnumPart(SphinxPart): + def __init__(self, enum, lang, langs, namespace=None): + SphinxPart.__init__(self, lang, langs) + self.name = enum.name.translate(self.lang.nameTranslator) + self.fullName = enum.name.translate(self.lang.nameTranslator, recursive=True) + self.briefDesc = enum.briefDescription.translate(self.docTranslator) + self.enumerators = [self._translate_enumerator(enumerator) for enumerator in enum.enumerators] + self.selector = self._make_selector(enum) + self.sectionName = RstTools.make_section(self.name) + self.declaration = 'public enum {0}'.format(self.name) if self.lang.langCode == 'Java' else self.name + + ref = metadoc.ClassReference(None) + ref.relatedObject = enum + self.link = ref.translate(lang.docTranslator) + + def _translate_enumerator(self, enumerator): + return { + 'name' : enumerator.name.translate(self.lang.nameTranslator), + 'briefDesc' : enumerator.briefDescription.translate(self.docTranslator), + 'value' : enumerator.translate_value(self.lang.langTranslator), + 'selector' : self._make_selector(enumerator) + } + + +class SphinxPage(SphinxPart): + def __init__(self, lang, langs, filename): + SphinxPart.__init__(self, lang, langs) + self.filename = filename + + def write(self, directory): + r = pystache.Renderer() + filepath = os.path.join(directory, self.filename) + tmpFilepath = filepath + '.tmp' + with open(tmpFilepath, mode='w') as f: + f.write(r.render(self)) + if os.path.exists(filepath) and md5sum(filepath) == md5sum(tmpFilepath): + os.remove(tmpFilepath) + else: + os.rename(tmpFilepath, filepath) + return filepath + + def _get_translated_namespace(self, obj): + namespace = obj.find_first_ancestor_by_type(abstractapi.Namespace) + return namespace.name.translate(self.lang.nameTranslator, recursive=True) @staticmethod def _classname_to_filename(classname): @@ -203,60 +285,59 @@ class SphinxPage(object): class IndexPage(SphinxPage): - def __init__(self, lang, langs): - SphinxPage.__init__(self, lang, langs, 'index.rst') - self.tocEntries = [] - - def add_class_entry(self, _class): - self.tocEntries.append({'entryName': SphinxPage._classname_to_filename(_class.name)}) + def __init__(self, lang, filename): + SphinxPage.__init__(self, lang, None, filename) + self._entries = [] + self._sorted = True + + @property + def title(self): + return RstTools.make_chapter("{0} API".format(self.lang.displayName)) + + @property + def dir(self): + return self.lang.directory + + @property + def entries(self): + if not self._sorted: + self._entries.sort(key=lambda x: x['filename']) + self._sorted = True + return self._entries + + def add_entry(self, filename): + self.entries.append({'filename': filename}) + self._sorted = False -class EnumsPage(SphinxPage): - def __init__(self, lang, langs, enums): - SphinxPage.__init__(self, lang, langs, 'enums.rst') - self._translate_enums(enums) - - def _translate_enums(self, enums): - self.enums = [] - for enum in enums: - translatedEnum = { - 'name' : enum.name.translate(self.lang.nameTranslator), - 'fullName' : enum.name.translate(self.lang.nameTranslator, recursive=True), - 'briefDesc' : enum.briefDescription.translate(self.docTranslator), - 'enumerators' : self._translate_enum_values(enum), - 'selector' : self._make_selector(enum) - } - translatedEnum['namespace'] = self._get_translated_namespace(enum) if self.lang.langCode == 'Cpp' else translatedEnum['fullName'] - translatedEnum['sectionName'] = RstTools.make_section(translatedEnum['name']) - self.enums.append(translatedEnum) - - def _translate_enum_values(self, enum): - translatedEnumerators = [] - for enumerator in enum.enumerators: - translatedValue = { - 'name' : enumerator.name.translate(self.lang.nameTranslator), - 'briefDesc' : enumerator.briefDescription.translate(self.docTranslator), - 'value' : enumerator.translate_value(self.lang.langTranslator), - 'selector' : self._make_selector(enumerator) - } - translatedEnumerators.append(translatedValue) - - return translatedEnumerators +class EnumPage(SphinxPage): + def __init__(self, enum, lang, langs): + filename = SphinxPage._classname_to_filename(enum.name) + SphinxPage.__init__(self, lang, langs, filename) + namespace = enum.find_first_ancestor_by_type(abstractapi.Namespace) + self.namespace = namespace.name.translate(lang.nameTranslator) if lang.langCode != 'C' else None + self.enum = EnumPart(enum, lang, langs, namespace=namespace) class ClassPage(SphinxPage): def __init__(self, _class, lang, langs): filename = SphinxPage._classname_to_filename(_class.name) SphinxPage.__init__(self, lang, langs, filename) - self.namespace = self._get_translated_namespace(_class) + namespace = _class.find_first_ancestor_by_type(abstractapi.Namespace) + self.namespace = namespace.name.translate(self.lang.nameTranslator, recursive=True) self.className = _class.name.translate(self.lang.nameTranslator) self.fullClassName = _class.name.translate(self.lang.nameTranslator, recursive=True) self.briefDoc = _class.briefDescription.translate(self.docTranslator) self.detailedDoc = _class.detailedDescription.translate(self.docTranslator) if _class.detailedDescription is not None else None - self.properties = self._translate_properties(_class.properties) + self.enums = [EnumPart(enum, lang, langs) for enum in _class.enums] + self.properties = self._translate_properties(_class.properties) if isinstance(_class, abstractapi.Class) else [] self.methods = self._translate_methods(_class.instanceMethods) self.classMethods = self._translate_methods(_class.classMethods) self.selector = self._make_selector(_class) + + @property + def classDeclaration(self): + return 'public interface {0}'.format(self.className) if self.lang.langCode == 'Java' else self.className @property def hasMethods(self): @@ -269,17 +350,22 @@ class ClassPage(SphinxPage): @property def hasProperties(self): return len(self.properties) > 0 + + @property + def hasEnums(self): + return len(self.enums) > 0 def _translate_properties(self, properties): translatedProperties = [] for property_ in properties: propertyAttr = { 'name' : property_.name.translate(self.lang.nameTranslator), - 'ref_label' : '{0}_{1}'.format(self.lang.langCode, property_.name.to_snake_case(fullName=True)), 'getter' : self._translate_method(property_.getter) if property_.getter is not None else None, 'setter' : self._translate_method(property_.setter) if property_.setter is not None else None } propertyAttr['title'] = RstTools.make_subsubsection(propertyAttr['name']) + propertyAttr['ref_label'] = (self.lang.langCode + '_') + propertyAttr['ref_label'] += (property_.getter.name.to_snake_case(fullName=True) if property_.getter is not None else property_.setter.name.to_snake_case(fullName=True)) translatedProperties.append(propertyAttr) return translatedProperties @@ -290,80 +376,113 @@ class ClassPage(SphinxPage): return translatedMethods def _translate_method(self, method): - prototypeParams = {} - if self.lang.langCode == 'Cpp': - prototypeParams['showStdNs'] = True + namespace = method.find_first_ancestor_by_type(abstractapi.Class,abstractapi.Interface) methAttr = { - 'prototype' : method.translate_as_prototype(self.lang.langTranslator, **prototypeParams), + 'prototype' : method.translate_as_prototype(self.lang.langTranslator, namespace=namespace), 'briefDoc' : method.briefDescription.translate(self.docTranslator), 'detailedDoc' : method.detailedDescription.translate(self.docTranslator), 'selector' : self._make_selector(method) } reference = metadoc.FunctionReference(None) reference.relatedObject = method - methAttr['link'] = reference.translate(self.lang.docTranslator) + methAttr['link'] = reference.translate(self.lang.docTranslator, namespace=method.find_first_ancestor_by_type(abstractapi.Class, abstractapi.Interface)) return methAttr + + @property + def enumsSummary(self): + table = RstTools.CSVTable() + for enum in self.enums: + briefDoc = ' '.join([line['line'] for line in enum.briefDesc['lines']]) + table.addrow((enum.link, briefDoc)) + return table @property def propertiesSummary(self): - table = RstTools.Table() + table = RstTools.CSVTable() for property_ in self.properties: reference = ':ref:`{0}`'.format(property_['ref_label']) briefDoc = property_['getter']['briefDoc'] if property_['getter'] is not None else property_['setter']['briefDoc'] - briefDoc = '\n'.join([line['line'] for line in briefDoc['lines']]) + briefDoc = ' '.join([line['line'] for line in briefDoc['lines']]) table.addrow([reference, briefDoc]) return table @property def instanceMethodsSummary(self): - table = RstTools.Table() + table = RstTools.CSVTable() for method in self.methods: - briefDoc = '\n'.join([line['line'] for line in method['briefDoc']['lines']]) + briefDoc = ' '.join([line['line'] for line in method['briefDoc']['lines']]) table.addrow([method['link'], briefDoc]) return table @property def classMethodsSummary(self): - table = RstTools.Table() + table = RstTools.CSVTable() for method in self.classMethods: - briefDoc = '\n'.join([line['line'] for line in method['briefDoc']['lines']]) + briefDoc = ' '.join([line['line'] for line in method['briefDoc']['lines']]) table.addrow([method['link'], briefDoc]) return table +class OldFilesCleaner: + def __init__(self, rootDirectory): + self._filesToKeep = set() + self.root = rootDirectory + + def protect_file(self, directory): + self._filesToKeep.add(directory) + + def clean(self): + self._clean(self.root) + + def _clean(self, dir_): + if os.path.isdir(dir_): + for filename in os.listdir(dir_): + self._clean(os.path.join(dir_, filename)) + elif dir_ not in self._filesToKeep: + os.remove(dir_) + + class DocGenerator: def __init__(self, api): self.api = api self.languages = [ LangInfo('C'), LangInfo('Cpp'), + LangInfo('Java'), LangInfo('CSharp') ] def generate(self, outputdir): for lang in self.languages: - subdirectory = lang.langCode.lower() - directory = os.path.join(args.outputdir, subdirectory) + directory = os.path.join(args.outputdir, lang.directory) + cleaner = OldFilesCleaner(directory) + indexPage = IndexPage(lang, 'index.rst') if not os.path.exists(directory): os.mkdir(directory) - - enumsPage = EnumsPage(lang, self.languages, absApiParser.enums) - enumsPage.write(directory) - - indexPage = IndexPage(lang, self.languages) - for _class in absApiParser.classes: - page = ClassPage(_class, lang, self.languages) - page.write(directory) - indexPage.add_class_entry(_class) - - indexPage.write(directory) + for enum in self.api.namespace.enums: + page = EnumPage(enum, lang, self.languages) + filepath = page.write(directory) + indexPage.add_entry(page.filename) + cleaner.protect_file(filepath) + for class_ in (self.api.namespace.classes + self.api.namespace.interfaces): + page = ClassPage(class_, lang, self.languages) + filepath = page.write(directory) + indexPage.add_entry(page.filename) + cleaner.protect_file(filepath) + filepath = indexPage.write(directory) + cleaner.protect_file(filepath) + cleaner.clean() if __name__ == '__main__': argparser = argparse.ArgumentParser(description='Generate a sphinx project to generate the documentation of Linphone Core API.') argparser.add_argument('xmldir', type=str, help='directory holding the XML documentation of the C API generated by Doxygen') argparser.add_argument('-o --output', type=str, help='directory into where Sphinx source files will be written', dest='outputdir', default='.') + argparser.add_argument('-v --verbose', action='store_true', default=False, dest='verbose_mode', help='Show warning and info messages') args = argparser.parse_args() + + loglevel = logging.INFO if args.verbose_mode else logging.ERROR + logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel) cProject = capi.Project() cProject.initFromDir(args.xmldir) diff --git a/coreapi/help/doc/sphinx/guides/authentication.rst b/coreapi/help/doc/sphinx/guides/authentication.rst new file mode 100644 index 000000000..464997164 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/authentication.rst @@ -0,0 +1,4 @@ +Managing authentication: userid and passwords +============================================= + + diff --git a/coreapi/help/doc/sphinx/guides/buddy_list.rst b/coreapi/help/doc/sphinx/guides/buddy_list.rst new file mode 100644 index 000000000..c0a0591c5 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/buddy_list.rst @@ -0,0 +1,57 @@ +Managing Buddies and buddy list and presence +============================================ +Buddies and buddy list +---------------------- + +Each buddy is represented by a :cpp:type:`LinphoneFriend` object created by function :cpp:func:`linphone_friend_new`. + +Buddy configuration parameters like :cpp:func:`sip uri ` or :cpp:func:`status publication ` policy for +this :cpp:type:`friend ` are configurable for each buddy. + +Here under a typical buddy creation: + +.. code-block:: c + + LinphoneFriend* my_friend=linphone_friend_new_with_addr("sip:joe@sip.linphone.org"); /*creates friend object for buddy joe*/ + linphone_friend_enable_subscribes(my_friend,TRUE); /*configure this friend to emit SUBSCRIBE message after being added to LinphoneCore*/ + linphone_friend_set_inc_subscribe_policy(my_friend,LinphoneSPAccept); /* accept Incoming subscription request for this friend*/ + +:cpp:type:`Friends ` status changes are reported by callback LinphoneCoreVTable.notify_presence_recv + +.. code-block:: c + + static void notify_presence_recv_updated (struct _LinphoneCore *lc, LinphoneFriend *friend) { + const LinphoneAddress* friend_address = linphone_friend_get_address(friend); + printf("New state state [%s] for user id [%s] \n" + ,linphone_online_status_to_string(linphone_friend_get_status(friend)) + ,linphone_address_as_string (friend_address)); + } + +Once created a buddy can be added to the buddy list using function :cpp:func:`linphone_core_add_friend`. Added friends will be notified +about :cpp:func:`local status changes `. + +Any subsequente modifications to :cpp:type:`LinphoneFriend` must be first started by a call to function :cpp:func:`linphone_friend_edit` and validated by function :cpp:func:`linphone_friend_done`. + +.. code-block:: c + + linphone_friend_edit(my_friend); /* start editing friend */ + linphone_friend_enable_subscribes(my_friend,FALSE); /*disable subscription for this friend*/ + linphone_friend_done(my_friend); /*commit changes triggering an UNSUBSCRIBE message*/ + + +Publishing presence status +-------------------------- + +Local presence status can be changed using function :cpp:func:`linphone_core_set_presence_model`. New status is propagated to all +friends :cpp:func:`previously added ` to :cpp:type:`LinphoneCore`. + + +Handling incoming subscription request +-------------------------------------- + +New incoming subscription requests are process according to :cpp:func:`the incoming subscription policy state ` for subscription +initiated by :cpp:func:`members of the buddy list `. + +For incoming request comming from an unknown buddy, the call back LinphoneCoreVTable.new_subscription_request is invoked. + +A complete tutorial can be found at : \ref buddy_tutorials "Registration tutorial" diff --git a/coreapi/help/doc/sphinx/guides/call_control.rst b/coreapi/help/doc/sphinx/guides/call_control.rst new file mode 100644 index 000000000..e6e959348 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/call_control.rst @@ -0,0 +1,9 @@ +Placing and receiving calls +=========================== + +The :cpp:type:`LinphoneCall` object represents an incoming or outgoing call managed by the :cpp:type:`LinphoneCore`. + +Outgoing calls can be created using :cpp:func:`linphone_core_invite` or :cpp:func:`linphone_core_invite_address`, while incoming calls are notified to the application +through the LinphoneCoreVTable::call_state_changed callback. + +.. seealso:: :ref:`"Basic Call" ` source code. diff --git a/coreapi/help/doc/sphinx/guides/call_logs.rst b/coreapi/help/doc/sphinx/guides/call_logs.rst new file mode 100644 index 000000000..cf68f06fe --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/call_logs.rst @@ -0,0 +1,2 @@ +Managing call logs +================== diff --git a/coreapi/help/doc/sphinx/guides/call_misc.rst b/coreapi/help/doc/sphinx/guides/call_misc.rst new file mode 100644 index 000000000..d77b63b60 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/call_misc.rst @@ -0,0 +1,4 @@ +Obtaining information about a running call: sound volumes, quality indicators +============================================================================= + +When a call is running, it is possible to retrieve in real time current measured volumes and quality indicator. diff --git a/coreapi/help/doc/sphinx/guides/chatroom.rst b/coreapi/help/doc/sphinx/guides/chatroom.rst new file mode 100644 index 000000000..5d391845c --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/chatroom.rst @@ -0,0 +1,28 @@ +Chat room and messaging +======================= +Exchanging text messages +------------------------ + +Messages are sent using :cpp:type:`LinphoneChatRoom` object. First step is to create a :cpp:func:`chat room ` +from a peer sip uri. + +.. code-block:: c + + LinphoneChatRoom* chat_room = linphone_core_get_chat_room(lc,"sip:joe@sip.linphone.org"); + +Once created, messages are sent using function :cpp:func:`linphone_chat_room_send_message`. + +.. code-block:: c + + linphone_chat_room_send_message(chat_room,"Hello world"); /*sending message*/ + +Incoming message are received from call back LinphoneCoreVTable.text_received + +.. code-block:: c + + void text_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message) { + printf(" Message [%s] received from [%s] \n",message,linphone_address_as_string (from)); + } + +.. seealso:: A complete tutorial can be found at :ref:`"Chatroom and messaging" ` source code. + diff --git a/coreapi/help/doc/sphinx/guides/conferencing.rst b/coreapi/help/doc/sphinx/guides/conferencing.rst new file mode 100644 index 000000000..e89b2e3f7 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/conferencing.rst @@ -0,0 +1,21 @@ +Making an audio conference +========================== + +This API allows to create a conference entirely managed by the client. No server capabilities are required. + +The way such conference is created is by doing the following: + +#. The application shall makes "normal" calls to several destinations (using :cpp:func:`linphone_core_invite`), one after another. +#. While initiating the second call, the first one is automatically paused. +#. Then, once the second call is established, the application has the possibility to merge the two calls to form a conference where each participant + (the local participant, the remote destination of the first call, the remote destination of the second call) can talk together. + This must be done by adding the two calls to the conference using :cpp:func:`linphone_core_add_to_conference`. + +Once merged into a conference the :cpp:type:`LinphoneCall` objects representing the calls that were established remain unchanged, except that +they are tagged as part of the conference (see :cpp:func:`linphone_call_is_in_conference`). The calls in a conference are in the :cpp:enumerator:`LinphoneCallStreamsRunning` state. + +Only a single conference can be created: the purpose of this feature is to allow the local user to create, take part and manage the conference. +This API is not designed to create a conference server application. + +Up to 10 calls can be merged into the conference, however depending on the CPU usage required for doing the encoding/decoding of the streams of each participants, +the effective limit can be lower. diff --git a/coreapi/help/doc/sphinx/guides/event_api.rst b/coreapi/help/doc/sphinx/guides/event_api.rst new file mode 100644 index 000000000..b45f77fca --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/event_api.rst @@ -0,0 +1,4 @@ +Managing generic subscriptions and publishes +============================================ + +The :cpp:type:`LinphoneEvent` api allows application to control subscriptions, receive notifications and make publish to peers, in a generic manner. diff --git a/coreapi/help/doc/sphinx/guides/initializing.rst b/coreapi/help/doc/sphinx/guides/initializing.rst new file mode 100644 index 000000000..c0e46073d --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/initializing.rst @@ -0,0 +1,4 @@ +Initializing liblinphone +======================== + + diff --git a/coreapi/help/doc/sphinx/guides/ios_portability.rst b/coreapi/help/doc/sphinx/guides/ios_portability.rst new file mode 100644 index 000000000..84d8160d9 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/ios_portability.rst @@ -0,0 +1,285 @@ +iOS portability +=============== +Multitasking +------------ + +Liblinphone for IOS natively supports multitasking assuming application follows multitasking guides provided by Apple. + +First step is to declare application as multitasked. It means adding background mode for both audio and voip to Info.plist file. + +.. code-block:: xml + + UIBackgroundModes + + voip + audio + + + +SIP socket +^^^^^^^^^^ + +Recommended mode is SIP over TCP, because UDP usually requires frequent keep alives for maintaining NAT association at the IP router level. This can +be as frequent as one UDP packet every 15 seconds to maintain the NAT association accross NAT routers. Doing such drains the battery very fast, and +furthermore the iOS keep-alive designed by Apple to handle this task can only be called with a minimum of 10 minutes interval. + +For TCP, liblinphone automatically configures SIP socket for voip (I.E kCFStreamNetworkServiceType set to kCFStreamNetworkServiceTypeVoIP). + +.. note:: + + Since IOS > 4.1 Apple disabled voip mode for UDP sockets. + + +Entering background mode +^^^^^^^^^^^^^^^^^^^^^^^^ + +Before entering in background mode (through ``- (void)applicationDidEnterBackground:(UIApplication *)application``), the application must first refresh +sip registration using function :cpp:func:`linphone_core_refresh_registers` and register a keep-alive handler for periodically refreshing the registration. +The speudo code below shows how to register a keep alive handler: + +.. code-block:: objective-c + + //First refresh registration + linphone_core_refresh_registers(theLinphoneCore); + //wait for registration answer + int i=0; + while (!linphone_proxy_config_is_registered(proxyCfg) && i++<40 ) { + linphone_core_iterate(theLinphoneCore); + usleep(100000); + } + //register keepalive handler + [[UIApplication sharedApplication] setKeepAliveTimeout:600/*minimal interval is 600 s*/ + handler:^{ + //refresh sip registration + linphone_core_refresh_registers(theLinphoneCore); + //make sure sip REGISTER is sent + linphone_core_iterate(theLinphoneCore); + }]; + + +Incoming call notification while in background mode +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Assuming application using liblinphone is well configured for multitasking, incoming calls arriving while liblinphone is in background mode will simply wakeup +liblinphone thread but not resume GUI. To wakeup GUI, it is recommended to send a Local Notification to the user from the #LinphoneCoreCallStateChangedCb. Here +under a speudo code for this operation: + +.. code-block:: objective-c + + if ([UIApplication sharedApplication].applicationState != UIApplicationStateActive) { + // Create a new notification + UILocalNotification* notif = [[[UILocalNotification alloc] init] autorelease]; + if (notif) { + notif.repeatInterval = 0; + notif.alertBody =@"New incoming call"; + notif.alertAction = @"Answer"; + notif.soundName = @"oldphone-mono-30s.caf"; + + [[UIApplication sharedApplication] presentLocalNotificationNow:notif]; + } + + +Networking +---------- +WWAN connection +^^^^^^^^^^^^^^^ + +Liblinphone relies on iOS's standard BSD socket layer for sip/rtp networking. On IOS, WWAN connection is supposed to automatically bring up on any networking +resquest issued by an application. At least on iPhone OS 3.x, BSD sockets do not implement this behavior. So it is recomended to add a special code to make sure +the WWAN connection is properly setup. Pseudo code below describes a way to force WWAN connection by setting up a dummy TCP connection. + +.. code-block:: objective-c + + /*start a new thread to avoid blocking the main ui in case of peer host failure*/ + [NSThread detachNewThreadSelector:@selector(runNetworkConnection) toTarget:self withObject:nil]; + -(void) runNetworkConnection { + CFWriteStreamRef writeStream; + //create a dummy socket + CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.0.200", 15000, nil, &writeStream); + CFWriteStreamOpen (writeStream); + const char* buff="hello"; + //try to write on this socket + CFWriteStreamWrite (writeStream,(const UInt8*)buff,strlen(buff)); + CFWriteStreamClose (writeStream); + } + +It is recommanded to perform this task each time the application is woken up, including keep alive handler. + + +Managing IP connection state +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Liblinphone for IOS relies on the application to be informed of network connectivity changes. Network state changes when the IP connection moves from DOWN to UP, +or from WIFI to WWAN. Applications using liblinphone must inform libliblinphone of this changes using function :cpp:func:`linphone_core_set_network_reachable`. +Usually this method is called from the IOS NetworkReachability callback. Here under a sample code: + +.. code-block:: c + + //typical reachability callback + void networkReachabilityCallBack(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void * info) { + if ((flags == 0) | (flags & (kSCNetworkReachabilityFlagsConnectionRequired |kSCNetworkReachabilityFlagsConnectionOnTraffic))) { + //network state is off + linphone_core_set_network_reachable(lc,false); + ((LinphoneManager*)info).connectivity = none; + } else { + Connectivity newConnectivity = flags & kSCNetworkReachabilityFlagsIsWWAN ? wwan:wifi; + if (lLinphoneMgr.connectivity == none) { + //notify new network state + linphone_core_set_network_reachable(lc,true); + } else if (lLinphoneMgr.connectivity != newConnectivity) { + // connectivity has changed + linphone_core_set_network_reachable(lc,false); + linphone_core_set_network_reachable(lc,true); + } + //store new connectivity status + lLinphoneMgr.connectivity=newConnectivity; + } + } + + +Sound cards +----------- + +Since IOS 5.0, liblinphone supports 2 sound cards. *AU: Audio Unit Receiver* based on IO units for voice calls plus *AQ: Audio Queue Device* dedicated to rings. +Here under the recommended settings (I.E default one) + +.. code-block:: c + + linphone_core_set_playback_device(lc, "AU: Audio Unit Receiver"); + linphone_core_set_ringer_device(lc, "AQ: Audio Queue Device"); + linphone_core_set_capture_device(lc, "AU: Audio Unit Receiver"); + + +GSM call interaction +-------------------- + +To ensure gentle interaction with GSM calls, it is recommended to register an AudioSession delegate. This allows the application to be notified when its audio +session is interrupted/resumed (presumably by a GSM call). + +.. code-block:: objective-c + + // declare a class handling the AVAudioSessionDelegate protocol + @interface MyClass : NSObject { [...] } + // implement 2 methods : here's an example implementation + -(void) beginInterruption { + LinphoneCall* c = linphone_core_get_current_call(theLinphoneCore); + ms_message("Sound interruption detected!"); + if (c) { + linphone_core_pause_call(theLinphoneCore, c); + } + } + + -(void) endInterruption { + ms_message("Sound interruption ended!"); + const MSList* c = linphone_core_get_calls(theLinphoneCore); + + if (c) { + ms_message("Auto resuming call"); + linphone_core_resume_call(theLinphoneCore, (LinphoneCall*) c->data); + } + } + +.. seealso:: http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAudioSessionDelegate_ProtocolReference/Reference/Reference.html + +Declare an instance of your class as AudioSession's delegate : + +.. code-block:: objective-c + + [audioSession setDelegate:myClassInstance]; + +.. seealso:: http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVAudioSession_ClassReference/Reference/Reference.html + + +Video +----- + +Since 3.5 video support has been added to liblinphone for IOS. It requires the application to provide liblinphone with pointers to IOS's views hosting video +display and video previous. These two UIView objects must be passed to the core using functions :cpp:func:`linphone_core_set_native_video_window_id` and +:cpp:func:`linphone_core_set_native_preview_window_id`. Here under pseudo code: + +.. code-block:: objective-c + + UIView* display = [[UIView alloc] init]; + UIView* preview = [[UIView alloc] init]; + linphone_core_set_native_video_window_id(lc,(unsigned long)display); + linphone_core_set_native_preview_window_id(lc,(unsigned long)preview); + +Screen rotations are also handled by liblinphone. Two positions are currently supported, namely *UIInterfaceOrientationPortrait* and *UIInterfaceOrientationLandscapeRight*. +Applications may invoke :cpp:func:`linphone_core_set_device_rotation` followed by :cpp:func:`linphone_core_update_call` to notify liblinphone of an orientation +change. Here under a speudo code to handle orientation changes + +.. code-block:: c + + -(void) configureOrientation:(UIInterfaceOrientation) oritentation { + int oldLinphoneOrientation = linphone_core_get_device_rotation(lc); + if (oritentation == UIInterfaceOrientationPortrait ) { + linphone_core_set_native_video_window_id(lc,(unsigned long)display-portrait); + linphone_core_set_native_preview_window_id(lc,(unsigned long)preview-portrait); + linphone_core_set_device_rotation(lc, 0); + + } else if (oritentation == UIInterfaceOrientationLandscapeRight ) { + linphone_core_set_native_video_window_id(lc,(unsigned long)display-landscape); + linphone_core_set_native_preview_window_id(lc,(unsigned long)preview-landscape); + linphone_core_set_device_rotation(lc, 270); + } + + if ((oldLinphoneOrientation != linphone_core_get_device_rotation(lc)) + && linphone_core_get_current_call(lc)) { + //Orientation has changed, must call update call + linphone_core_update_call(lc, linphone_core_get_current_call(lc), NULL); + } + } + + +DTMF feedbacks +-------------- + +Liblinphone provides functions :cpp:func:`to play dtmf ` to the local user. Usually this is used to play a sound when the user +presses a digit, inside or outside of any call. On IOS, libLinphone relies on AudioUnits for interfacing with the audio system. Unfortunately the Audio Unit +initialization is a quite long operation that may trigger a bad user experience if performed each time a DTMF is played, the sound being delayed half a +second after the press. To solve this issue and thus insure real-time precision, liblinphone introduces two functions for :cpp:func:`preloading ` +and :cpp:func:`unloading ` the underlying audio graph responsible for playing DTMFs. + +For an application using function :cpp:func:`linphone_core_play_dtmf`, it is recommanded to call :cpp:func:`linphone_core_start_dtmf_stream` when entering +in foreground and #linphone_core_stop_dtmf_stream() upon entering background mode. + + +Plugins +------- + +On iOS, plugins are built as static libraries so Liblinphone will not be able to load them at runtime dynamically. Instead, you should declare their prototypes: + +.. code-block:: c + + extern void libmsamr_init(MSFactory *factory); + extern void libmsx264_init(MSFactory *factory); + extern void libmsopenh264_init(MSFactory *factory); + extern void libmssilk_init(MSFactory *factory); + extern void libmsbcg729_init(MSFactory *factory); + extern void libmswebrtc_init(MSFactory *factory); + + +Then you should register them after the instantiation of :cpp:type:`LinphoneCore`: + +.. code-block:: c + + theLinphoneCore = linphone_core_new_with_config(/* options ... */); + + // Load plugins if available in the linphone SDK - otherwise these calls will do nothing + MSFactory *f = linphone_core_get_ms_factory(theLinphoneCore); + libmssilk_init(f); + libmsamr_init(f); + libmsx264_init(f); + libmsopenh264_init(f); + libmsbcg729_init(f); + libmswebrtc_init(f); + linphone_core_reload_ms_plugins(theLinphoneCore, NULL); + + +If the plugin has not been enabled at compilation time, a stubbed library will be generated with only libplugin_init method declared, doing nothing. You should +see these trace in logs, if plugin is stubbed: + +.. code-block:: none + + I/lib/Could not find encoder for SILK + I/lib/Could not find decoder for SILK diff --git a/coreapi/help/doc/sphinx/guides/linphone_address.rst b/coreapi/help/doc/sphinx/guides/linphone_address.rst new file mode 100644 index 000000000..8dacb147e --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/linphone_address.rst @@ -0,0 +1,4 @@ +SIP address parser API +====================== + +This api is useful for manipulating SIP addresses ('from' or 'to' headers). diff --git a/coreapi/help/doc/sphinx/guides/media_parameters.rst b/coreapi/help/doc/sphinx/guides/media_parameters.rst new file mode 100644 index 000000000..9a9318a66 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/media_parameters.rst @@ -0,0 +1,11 @@ +Controlling media parameters +============================ + +Multicast +--------- + +Call using rtp multicast addresses are supported for both audio and video with some limitations. Limitations are, no stun, no ice, no encryption. + +* Incoming call with multicast address are automatically accepted. The called party switches in a media receive only mode. +* Outgoing call willing to send media to a multicast address can activate multicast using :cpp:func:`linphone_core_enable_video_multicast` + or :cpp:func:`linphone_core_enable_audio_multicast`. The calling party switches in a media listen send only mode. diff --git a/coreapi/help/doc/sphinx/guides/misc.rst b/coreapi/help/doc/sphinx/guides/misc.rst new file mode 100644 index 000000000..292840e05 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/misc.rst @@ -0,0 +1,3 @@ +Miscenalleous: logs, version strings, config storage +==================================================== + diff --git a/coreapi/help/doc/sphinx/guides/network_parameters.rst b/coreapi/help/doc/sphinx/guides/network_parameters.rst new file mode 100644 index 000000000..86faebce6 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/network_parameters.rst @@ -0,0 +1,2 @@ +Controlling network parameters (ports, mtu…) +============================================ diff --git a/coreapi/help/doc/sphinx/guides/proxies.rst b/coreapi/help/doc/sphinx/guides/proxies.rst new file mode 100644 index 000000000..dd852b0b8 --- /dev/null +++ b/coreapi/help/doc/sphinx/guides/proxies.rst @@ -0,0 +1,76 @@ +Managing proxies +================ + +User registration is controled by :cpp:type:`LinphoneProxyConfig` settings. + +Each :cpp:type:`LinphoneProxyConfig` object can be configured with registration informations like :cpp:func:`proxy address `, +:cpp:func:`user id `, :cpp:func:`refresh period `, and so on. + +A created proxy config using :cpp:func:`linphone_proxy_config_new`, once configured, must be added to :cpp:type:`LinphoneCore` using function :cpp:func:`linphone_core_add_proxy_config`. + +It is recommended to set a default :cpp:type:`proxy config ` using function :cpp:func:`linphone_core_set_default_proxy`. Once done, +if :cpp:type:`proxy config ` has been configured with attribute :cpp:func:`enable register `, +next call to :cpp:func:`linphone_core_iterate` triggers SIP register. + +Registration status is reported by LinphoneCoreRegistrationStateChangedCb. + +This pseudo code demonstrates basic registration operations: + +.. code-block:: c + + LinphoneProxyConfig* proxy_cfg; + /*create proxy config*/ + proxy_cfg = linphone_proxy_config_new(); + /*parse identity*/ + LinphoneAddress *from = linphone_address_new("sip:toto@sip.titi.com"); + LinphoneAuthInfo *info; + if (password!=NULL){ + info=linphone_auth_info_new(linphone_address_get_username(from),NULL,"secret",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*/ + + 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*/ + +Registration sate call back: + +.. code-block:: c + + static void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ + printf("New registration state %s for user id [%s] at proxy [%s]\n" + ,linphone_registration_state_to_string(cstate) + ,linphone_proxy_config_get_identity(cfg) + ,linphone_proxy_config_get_addr(cfg)); + } + +Authentication +-------------- + +Most of the time, registration requires :doc:`authentication ` to succeed. :cpp:type:`LinphoneAuthInfo` info must be either added +to :cpp:type:`LinphoneCore` using function :cpp:func:`linphone_core_add_auth_info` before :cpp:type:`LinphoneProxyConfig` is added to Linphone core, or on demand +from call back #LinphoneCoreAuthInfoRequestedCb. + +Unregistration +-------------- + +Unregistration or any changes to :cpp:type:`LinphoneProxyConfig` must be first started by a call to function :cpp:func:`linphone_proxy_config_edit` and validated by +function :cpp:func:`linphone_proxy_config_done`. + +This pseudo code shows how to unregister a user associated to a #LinphoneProxyConfig: + +.. code-block:: c + + LinphoneProxyConfig* proxy_cfg; + linphone_core_get_default_proxy(lc,&proxy_cfg); /* get default proxy config*/ + 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*/ + +.. seealso:: A complete tutorial can be found at: :ref:`"Basic registration" ` source code. + diff --git a/coreapi/help/doc/sphinx/index.rst b/coreapi/help/doc/sphinx/index.rst new file mode 100644 index 000000000..03500afe6 --- /dev/null +++ b/coreapi/help/doc/sphinx/index.rst @@ -0,0 +1,70 @@ +.. Linphone API documentation master file, created by + sphinx-quickstart on Mon Jun 19 11:58:21 2017. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Linphone API's documentation! +======================================== +What is liblinphone +------------------- + +Liblinphone is a high level library for bringing SIP video call functionnality +into an application. It aims at making easy the integration of the SIP +video calls into any applications. All variants of linphone are directly based +on it: + +* linphone (gtk interface) +* linphonec (console interface) +* linphone for iOS +* linphone for Android + +Liblinphone is GPL (see COPYING file). Please understand the licencing details +before using it! + +For any use of this library beyond the rights granted to you by the +GPL license, please contact Belledonne Communications +(contact@belledonne-communications.com). + + +Beginners' guides +----------------- + +.. toctree:: + :maxdepth: 1 + + guides/initializing + guides/call_control + guides/call_misc + guides/media_parameters + guides/proxies + guides/network_parameters + guides/authentication + guides/buddy_list + guides/chatroom + guides/call_logs + guides/linphone_address + guides/conferencing + guides/event_api + guides/misc + guides/ios_portability + + +Code samples +------------ + +.. toctree:: + :maxdepth: 1 + + samples/samples + + +API's reference documentation +----------------------------- + +.. toctree:: + :maxdepth: 1 + + reference/c/index + reference/cpp/index + reference/java/index + reference/csharp/index diff --git a/coreapi/help/doc/sphinx/index_page.mustache b/coreapi/help/doc/sphinx/index_page.mustache index 2fa38ec83..f494d825e 100644 --- a/coreapi/help/doc/sphinx/index_page.mustache +++ b/coreapi/help/doc/sphinx/index_page.mustache @@ -1,19 +1,8 @@ -{{#make_section}}{{{language}}} API{{/make_section}} - -Index of classes ----------------- +{{{title}}} .. toctree:: :maxdepth: 1 - - {{#tocEntries}} - {{{entryName}}} - {{/tocEntries}} -Index of enums --------------- - -.. toctree:: - :maxdepth 1 - - enums.rst + {{#entries}} + {{{filename}}} + {{/entries}} diff --git a/coreapi/help/doc/sphinx/logo.png b/coreapi/help/doc/sphinx/logo.png new file mode 100644 index 000000000..de261e94a Binary files /dev/null and b/coreapi/help/doc/sphinx/logo.png differ diff --git a/coreapi/help/doc/sphinx/samples/samples.rst b/coreapi/help/doc/sphinx/samples/samples.rst new file mode 100644 index 000000000..8d4cc6024 --- /dev/null +++ b/coreapi/help/doc/sphinx/samples/samples.rst @@ -0,0 +1,106 @@ +.. _basic_call_code_sample: + +Basic call +========== + +This program is a *very* simple usage example of liblinphone. It just takes a sip-uri as first argument and attempts to call it + +.. literalinclude:: helloworld.c + :language: c + + +.. _basic_registration_code_sample: + +Basic registration +================== + +This program is a *very* simple usage example of liblinphone, desmonstrating how to initiate a SIP registration from a sip uri identity +passed from the command line. First argument must be like sip:jehan@sip.linphone.org , second must be *password* . Registration is cleared +on *SIGINT*. + +Example: ``registration sip:jehan@sip.linphone.org secret`` + +.. literalinclude:: registration.c + :language: c + + +.. _subscribe_notify_code_sample: + +Generic subscribe/notify example +================================ + +This program is a *very* simple usage example of liblinphone. It demonstrates how to listen to a SIP subscription. +It then sends notify requests back periodically. First argument must be like sip:jehan@sip.linphone.org , second must be *password*. +Registration is cleared on *SIGINT*. + +Example: ``registration sip:jehan@sip.linphone.org secret`` + +.. literalinclude:: registration.c + :language: c + + + +.. _buddy_status_notification_code_sample: + +Basic buddy status notification +=============================== + +This program is a *very* simple usage example of liblinphone, demonstrating how to initiate SIP subscriptions and receive +notifications from a sip uri identity passed from the command line. Argument must be like sip:jehan@sip.linphone.org . +Subscription is cleared on *SIGINT* signal. + +Example: ``budy_list sip:jehan@sip.linphone.org`` + +.. literalinclude:: buddy_status.c + :language: c + + +.. _chatroom_code_sample: + +Chat room and messaging +======================= + +This program is a *very* simple usage example of liblinphone, desmonstrating how to send/receive SIP MESSAGE from a sip uri +identity passed from the command line. Argument must be like sip:jehan@sip.linphone.org . + +Example: ``chatroom sip:jehan@sip.linphone.org`` + +.. literalinclude:: chatroom.c + :language: c + + +.. _file_transfer_code_sample: + +File transfer +============= + +.. literalinclude:: filetransfer.c + :language: c + + + +.. _RT text receiver_code_sample: + +Real Time Text Receiver +======================= + +This program is able to receive chat message in real time on port 5060. Use realtimetext_sender to generate chat message + +Example: ``./realtimetext_receiver`` + +.. literalinclude:: realtimetext_sender.c + :language: c + + +.. _RT_text_sender_code_sample: + +Real Time Text Sender +===================== + +This program just send chat message in real time to dest uri. Use realtimetext_receiver to receive message. + +Example: ``./realtimetext_sender sip:localhost:5060`` + +.. literalinclude:: realtimetext_sender.c + :language: c + diff --git a/coreapi/help/doc/sphinx/source/index.rst b/coreapi/help/doc/sphinx/source/index.rst deleted file mode 100644 index 530adfcc3..000000000 --- a/coreapi/help/doc/sphinx/source/index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. Linphone API documentation master file, created by - sphinx-quickstart on Mon Jun 19 11:58:21 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Linphone API's documentation! -======================================== - -.. toctree:: - :maxdepth: 1 - :caption: Contents: - - c/index.rst - cpp/index.rst - csharp/index.rst - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/coreapi/help/examples/C/CMakeLists.txt b/coreapi/help/examples/C/CMakeLists.txt index 84a5b38d5..cc0ef95a4 100644 --- a/coreapi/help/examples/C/CMakeLists.txt +++ b/coreapi/help/examples/C/CMakeLists.txt @@ -24,12 +24,22 @@ if (ENABLE_TOOLS) if (IOS) set(USE_BUNDLE MACOSX_BUNDLE) endif() - file(GLOB EXECUTABLES_SOURCE RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c") - foreach(EXECUTABLE ${EXECUTABLES_SOURCE}) + set(LINPHONE_C_EXAMPLES_SOURCE + ${CMAKE_CURRENT_SOURCE_DIR}/buddy_status.c + ${CMAKE_CURRENT_SOURCE_DIR}/chatroom.c + ${CMAKE_CURRENT_SOURCE_DIR}/filetransfer.c + ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.c + ${CMAKE_CURRENT_SOURCE_DIR}/notify.c + ${CMAKE_CURRENT_SOURCE_DIR}/realtimetext_receiver.c + ${CMAKE_CURRENT_SOURCE_DIR}/realtimetext_sender.c + ${CMAKE_CURRENT_SOURCE_DIR}/registration.c + PARENT_SCOPE + ) + foreach(EXECUTABLE ${LINPHONE_C_EXAMPLES_SOURCE}) string(REPLACE ".c" "" EXECUTABLE_NAME ${EXECUTABLE}) bc_apply_compile_flags(${EXECUTABLE} STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(${EXECUTABLE_NAME} ${USE_BUNDLE} ${EXECUTABLE}) - target_link_libraries(${EXECUTABLE_NAME} ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) + target_link_libraries(${EXECUTABLE_NAME} ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") if (NOT IOS) install(TARGETS ${EXECUTABLE_NAME} diff --git a/coreapi/help/examples/C/filetransfer.c b/coreapi/help/examples/C/filetransfer.c index 485c0a662..b0cd2c08c 100644 --- a/coreapi/help/examples/C/filetransfer.c +++ b/coreapi/help/examples/C/filetransfer.c @@ -45,8 +45,8 @@ static void stop(int signum){ * function invoked to report file transfer progress. * */ static void file_transfer_progress_indication(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total) { - const LinphoneAddress* from_address = linphone_chat_message_get_from(message); - const LinphoneAddress* to_address = linphone_chat_message_get_to(message); + const LinphoneAddress* from_address = linphone_chat_message_get_from_address(message); + const LinphoneAddress* to_address = linphone_chat_message_get_to_address(message); char *address = linphone_chat_message_is_outgoing(message)?linphone_address_as_string(to_address):linphone_address_as_string(from_address); printf(" File transfer [%d%%] %s of type [%s/%s] %s [%s] \n", (int)((offset *100)/total) ,(linphone_chat_message_is_outgoing(message)?"sent":"received") @@ -70,7 +70,7 @@ static void file_transfer_received(LinphoneChatMessage *message, const LinphoneC file = (FILE*)linphone_chat_message_get_user_data(message); if (linphone_buffer_is_empty(buffer)) { printf("File transfert completed\n"); - linphone_chat_message_destroy(message); + linphone_chat_message_unref(message); fclose(file); running=FALSE; } else { /* store content on a file*/ @@ -95,7 +95,7 @@ static LinphoneBuffer * file_transfer_send(LinphoneChatMessage *message, const L * Call back to get delivery status of a message * */ static void linphone_file_transfer_state_changed(LinphoneChatMessage* msg,LinphoneChatMessageState state) { - const LinphoneAddress* to_address = linphone_chat_message_get_to(msg); + const LinphoneAddress* to_address = linphone_chat_message_get_to_address(msg); char *to = linphone_address_as_string(to_address); printf("File transfer sent to [%s] delivery status is [%s] \n" , to , linphone_chat_message_state_to_string(state)); diff --git a/coreapi/im_encryption_engine.c b/coreapi/im_encryption_engine.c index 3363b1dfe..6e32f430e 100644 --- a/coreapi/im_encryption_engine.c +++ b/coreapi/im_encryption_engine.c @@ -18,9 +18,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/core.h" -#include "linphone/im_encryption_engine.h" #include "private.h" +#include "c-wrapper/c-wrapper.h" + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneImEncryptionEngineCbs); BELLE_SIP_INSTANCIATE_VPTR(LinphoneImEncryptionEngineCbs, belle_sip_object_t, diff --git a/coreapi/im_notif_policy.c b/coreapi/im_notif_policy.c index 3502aa963..87867f83f 100644 --- a/coreapi/im_notif_policy.c +++ b/coreapi/im_notif_policy.c @@ -18,8 +18,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/core.h" -#include "private.h" +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneImNotifPolicy); @@ -30,7 +33,6 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneImNotifPolicy, belle_sip_object_t, FALSE ); - static void load_im_notif_policy_from_config(LinphoneImNotifPolicy *policy) { bctbx_list_t *default_list = bctbx_list_append(NULL, (void *)"all"); bctbx_list_t *values = lp_config_get_string_list(policy->lc->config, "sip", "im_notif_policy", default_list); @@ -203,6 +205,8 @@ LinphoneImNotifPolicy * linphone_core_get_im_notif_policy(const LinphoneCore *lc } void linphone_core_create_im_notif_policy(LinphoneCore *lc) { + if (lc->im_notif_policy) + linphone_im_notif_policy_unref(lc->im_notif_policy); lc->im_notif_policy = belle_sip_object_new(LinphoneImNotifPolicy); lc->im_notif_policy->lc = lc; load_im_notif_policy_from_config(lc->im_notif_policy); diff --git a/coreapi/info.c b/coreapi/info.c index 27eb883a4..f68bb4522 100644 --- a/coreapi/info.c +++ b/coreapi/info.c @@ -22,11 +22,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - + +#include "linphone/api/c-content.h" #include "linphone/core.h" -#include "private.h" #include "linphone/lpconfig.h" +#include "c-wrapper/c-wrapper.h" struct _LinphoneInfoMessage{ belle_sip_object_t base; @@ -76,12 +77,6 @@ LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore *lc){ return belle_sip_object_new(LinphoneInfoMessage); } -LinphoneStatus linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info) { - SalBodyHandler *body_handler = sal_body_handler_from_content(info->content); - sal_op_set_sent_custom_header(call->op, info->headers); - return sal_send_info(call->op,NULL, NULL, body_handler); -} - void linphone_info_message_add_header(LinphoneInfoMessage *im, const char *name, const char *value){ im->headers=sal_custom_header_append(im->headers, name, value); } @@ -90,21 +85,25 @@ const char *linphone_info_message_get_header(const LinphoneInfoMessage *im, cons return sal_custom_header_find(im->headers,name); } -void linphone_info_message_set_content(LinphoneInfoMessage *im, const LinphoneContent *content){ - im->content=linphone_content_copy(content); +void linphone_info_message_set_content (LinphoneInfoMessage *im, const LinphoneContent *content) { + if (im->content) + linphone_content_unref(im->content); + im->content = linphone_content_copy(content); } const LinphoneContent * linphone_info_message_get_content(const LinphoneInfoMessage *im){ return (im->content && linphone_content_get_type(im->content)) ? im->content : NULL; } -void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body_handler){ - LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); - if (call){ - LinphoneInfoMessage *info=linphone_core_create_info_message(lc); - info->headers=sal_custom_header_clone(sal_op_get_recv_custom_header(op)); - if (body_handler) info->content=linphone_content_from_sal_body_handler(body_handler); - linphone_call_notify_info_message_received(call, info); - linphone_info_message_unref(info); - } +SalCustomHeader *linphone_info_message_get_headers (const LinphoneInfoMessage *im) { + return im->headers; +} + +void linphone_info_message_set_headers (LinphoneInfoMessage *im, const SalCustomHeader *headers) { + if (im->headers) { + sal_custom_header_free(im->headers); + im->headers = nullptr; + } + if (headers) + im->headers = sal_custom_header_clone(headers); } diff --git a/coreapi/ios-helpers.cpp b/coreapi/ios-helpers.cpp deleted file mode 100644 index f3671667c..000000000 --- a/coreapi/ios-helpers.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* -linphone -Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifdef __APPLE__ -#include "TargetConditionals.h" -#endif - -#if TARGET_OS_IPHONE - -#include "private.h" -#include "platform-helpers.h" - - - -namespace LinphonePrivate{ - -class IosPlatformHelpers : public PlatformHelpers{ -public: - IosPlatformHelpers(LinphoneCore *lc, void *system_context); - virtual void setDnsServers(); - virtual void acquireWifiLock(); - virtual void releaseWifiLock(); - virtual void acquireMcastLock(); - virtual void releaseMcastLock(); - virtual void acquireCpuLock(); - virtual void releaseCpuLock(); - ~IosPlatformHelpers(); -private: - void bgTaskTimeout(); - static void sBgTaskTimeout(void *data); - long int mCpuLockTaskId; - int mCpuLockCount; -}; - - -IosPlatformHelpers::IosPlatformHelpers(LinphoneCore *lc, void *system_context) : PlatformHelpers(lc) { - mCpuLockCount = 0; - mCpuLockTaskId = 0; - ms_message("IosPlatformHelpers is fully initialised"); -} - -IosPlatformHelpers::~IosPlatformHelpers(){ - -} - - -void IosPlatformHelpers::setDnsServers(){ -} - -void IosPlatformHelpers::acquireWifiLock(){ -} - -void IosPlatformHelpers::releaseWifiLock(){ -} - -void IosPlatformHelpers::acquireMcastLock(){ -} - -void IosPlatformHelpers::releaseMcastLock(){ -} - -void IosPlatformHelpers::bgTaskTimeout(){ - ms_error("IosPlatformHelpers: the system requests that the cpu lock is released now."); - if (mCpuLockTaskId != 0){ - belle_sip_end_background_task(mCpuLockTaskId); - mCpuLockTaskId = 0; - } -} - -void IosPlatformHelpers::sBgTaskTimeout(void *data){ - IosPlatformHelpers *zis = (IosPlatformHelpers*)data; - zis->bgTaskTimeout(); -} - -void IosPlatformHelpers::acquireCpuLock(){ - if (mCpuLockCount == 0){ - /* on iOS, cpu lock is implemented by a long running task (obcj-C) and it is abstracted by belle-sip, - so let's use belle-sip directly.*/ - mCpuLockTaskId = belle_sip_begin_background_task("Liblinphone cpu lock", sBgTaskTimeout, this); - } - mCpuLockCount++; -} - -void IosPlatformHelpers::releaseCpuLock(){ - mCpuLockCount--; - if (mCpuLockCount == 0){ - if (mCpuLockTaskId != 0){ - belle_sip_end_background_task(mCpuLockTaskId); - mCpuLockTaskId = 0; - }else{ - ms_error("IosPlatformHelpers::releaseCpuLock(): too late, the lock has been released already by the system."); - } - } -} - - -PlatformHelpers *createIosPlatformHelpers(LinphoneCore *lc, void *system_context){ - return new IosPlatformHelpers(lc, system_context); -} - -}//end of namespace - -#endif diff --git a/coreapi/lime.c b/coreapi/lime.c index 486895c25..13d82101c 100644 --- a/coreapi/lime.c +++ b/coreapi/lime.c @@ -17,6 +17,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "linphone/api/c-content.h" + #include "lime.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -93,21 +95,21 @@ int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys) { /* retrieve values : peerZid, sndKey, sndSId, sndIndex, valid from columns 1,2,3,4,5 */ length = sqlite3_column_bytes(sqlStmt, 1); if (length==12) { /* peerZID */ - memcpy(currentPeerKey->peerZID, sqlite3_column_blob(sqlStmt, 1), length); + memcpy(currentPeerKey->peerZID, sqlite3_column_blob(sqlStmt, 1), (size_t)length); } else { /* something wrong with that one, skip it */ continue; } length = sqlite3_column_bytes(sqlStmt, 2); if (length==32) { /* sndKey */ - memcpy(currentPeerKey->key, sqlite3_column_blob(sqlStmt, 2), length); + memcpy(currentPeerKey->key, sqlite3_column_blob(sqlStmt, 2), (size_t)length); } else { /* something wrong with that one, skip it */ continue; } length = sqlite3_column_bytes(sqlStmt, 3); if (length==32) { /* sndSId */ - memcpy(currentPeerKey->sessionId, sqlite3_column_blob(sqlStmt, 3), length); + memcpy(currentPeerKey->sessionId, sqlite3_column_blob(sqlStmt, 3), (size_t)length); } else { /* something wrong with that one, skip it */ continue; } @@ -126,14 +128,14 @@ int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys) { length = sqlite3_column_bytes(sqlStmt, 5); if (length==8) { /* sndIndex : 8 bytes of a int64_t, stored as a blob in big endian */ uint8_t *validity = (uint8_t *)sqlite3_column_blob(sqlStmt, 5); - validityTimeSpec.tv_sec = ((uint64_t)(validity[0]))<<56 | + validityTimeSpec.tv_sec = (int64_t)(((uint64_t)(validity[0]))<<56 | ((uint64_t)(validity[1]))<<48 | ((uint64_t)(validity[2]))<<40 | ((uint64_t)(validity[3]))<<32 | ((uint64_t)(validity[4]))<<24 | ((uint64_t)(validity[5]))<<16 | ((uint64_t)(validity[6]))<<8 | - ((uint64_t)(validity[7])); + ((uint64_t)(validity[7]))); } else { /* something wrong with that one, skip it */ continue; } @@ -144,7 +146,7 @@ int lime_getCachedSndKeysByURI(void *cachedb, limeURIKeys_t *associatedKeys) { /* check validity */ bctbx_get_utc_cur_time(¤tTimeSpec); if (validityTimeSpec.tv_sec == 0 || bctbx_timespec_compare(¤tTimeSpec, &validityTimeSpec)<0) { - associatedKeys->associatedZIDNumber +=1; + associatedKeys->associatedZIDNumber++; /* extend array of pointer to limeKey_t structures to add the one we found */ associatedKeys->peerKeys = (limeKey_t **)bctbx_realloc(associatedKeys->peerKeys, (associatedKeys->associatedZIDNumber)*sizeof(limeKey_t *)); @@ -210,7 +212,7 @@ int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const cha /* retrieve values : rcvKey, rcvSId, rcvIndex from columns 1,2,3 */ length = sqlite3_column_bytes(sqlStmt, 1); if (length==32) { /* rcvKey */ - memcpy(associatedKey->key, sqlite3_column_blob(sqlStmt, 1), length); + memcpy(associatedKey->key, sqlite3_column_blob(sqlStmt, 1), (size_t)length); } else { /* something wrong */ ms_error("[LIME] Get Cached Rcv Key by Zid fetched a rcvKey with wrong length"); sqlite3_finalize(sqlStmt); @@ -219,7 +221,7 @@ int lime_getCachedRcvKeyByZid(void *cachedb, limeKey_t *associatedKey, const cha length = sqlite3_column_bytes(sqlStmt, 2); if (length==32) { /* rcvSId */ - memcpy(associatedKey->sessionId, sqlite3_column_blob(sqlStmt, 2), length); + memcpy(associatedKey->sessionId, sqlite3_column_blob(sqlStmt, 2), (size_t)length); } else { /* something wrong */ ms_error("[LIME] Get Cached Rcv Key by Zid fetched a rcvSid with wrong length"); sqlite3_finalize(sqlStmt); @@ -261,14 +263,14 @@ int lime_setCachedKey(void *cachedb, limeKey_t *associatedKey, uint8_t role, uin uint8_t *colValues[4]; uint8_t sessionIndex[4]; /* buffer to hold the uint32_t buffer index in big endian */ size_t colLength[] = {32, 32, 4, 8}; /* data length: keys and session ID : 32 bytes, Index: 4 bytes(uint32_t), validity : 8 bytes(UTC time as int64_t) */ - int colNums; + uint8_t colNums; if (cachedb == NULL || associatedKey == NULL) { /* there is no cache return error */ return LIME_INVALID_CACHE; } /* wrap values to be written */ - sessionIndex[0] = (associatedKey->sessionIndex>>24)&0xFF; + sessionIndex[0] = (uint8_t)((associatedKey->sessionIndex>>24)&0xFF); sessionIndex[1] = (associatedKey->sessionIndex>>16)&0xFF; sessionIndex[2] = (associatedKey->sessionIndex>>8)&0xFF; sessionIndex[3] = (associatedKey->sessionIndex)&0xFF; @@ -279,16 +281,16 @@ int lime_setCachedKey(void *cachedb, limeKey_t *associatedKey, uint8_t role, uin /* shall we update valid column? Enforce only when receiver, if timeSpan is 0, just ignore */ if (validityTimeSpan > 0 && role == LIME_RECEIVER) { bctbx_get_utc_cur_time(¤tTime); - bctbx_timespec_add(¤tTime, validityTimeSpan); + bctbx_timespec_add(¤tTime, (int64_t)validityTimeSpan); /* store the int64_t in big endian in the cache(cache is not typed, all data seen as blob) */ - colValues[3][0] = (currentTime.tv_sec>>56)&0xFF; - colValues[3][1] = (currentTime.tv_sec>>48)&0xFF; - colValues[3][2] = (currentTime.tv_sec>>40)&0xFF; - colValues[3][3] = (currentTime.tv_sec>>32)&0xFF; - colValues[3][4] = (currentTime.tv_sec>>24)&0xFF; - colValues[3][5] = (currentTime.tv_sec>>16)&0xFF; - colValues[3][6] = (currentTime.tv_sec>>8)&0xFF; - colValues[3][7] = (currentTime.tv_sec)&0xFF; + colValues[3][0] = (uint8_t)((currentTime.tv_sec>>56)&0xFF); + colValues[3][1] = (uint8_t)((currentTime.tv_sec>>48)&0xFF); + colValues[3][2] = (uint8_t)((currentTime.tv_sec>>40)&0xFF); + colValues[3][3] = (uint8_t)((currentTime.tv_sec>>32)&0xFF); + colValues[3][4] = (uint8_t)((currentTime.tv_sec>>24)&0xFF); + colValues[3][5] = (uint8_t)((currentTime.tv_sec>>16)&0xFF); + colValues[3][6] = (uint8_t)((currentTime.tv_sec>>8)&0xFF); + colValues[3][7] = (uint8_t)((currentTime.tv_sec)&0xFF); colNums = 4; } else { @@ -296,7 +298,11 @@ int lime_setCachedKey(void *cachedb, limeKey_t *associatedKey, uint8_t role, uin } /* update cache */ - return bzrtp_cache_write(cachedb, associatedKey->zuid, "lime", role==LIME_SENDER?colNamesSender:colNamesReceiver, colValues, colLength, colNums); + return bzrtp_cache_write( + cachedb, associatedKey->zuid, "lime", + role == LIME_SENDER ? colNamesSender : colNamesReceiver, + colValues, colLength, colNums + ); } /** @@ -315,7 +321,7 @@ static int lime_deriveKey(limeKey_t *key) { return LIME_UNABLE_TO_DERIVE_KEY; } - /* Derivation is made derived Key = HMAC_SHA256(Key, 0x0000001||"MessageKey"||0x00||SessionId||SessionIndex||0x00000100)*/ + /* Derivation is made derived Key = HMAC_SHA256(Key, 0x0000001||"MessageKey"||0x00||SessionId||SessionIndex||0x00000100)*/ /* total data to be hashed is 55 bytes : 4 + 10 + 1 + 32 + 4 + 4 */ inputData[0] = 0x00; inputData[1] = 0x00; @@ -396,6 +402,8 @@ int lime_encryptMessage(limeKey_t *key, const uint8_t *plainMessage, uint32_t me int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { bctbx_aes_gcm_context_t *gcmContext; + if (key == NULL) return -1; + if (*cryptoContext == NULL) { /* first call to the function, allocate a crypto context and initialise it */ /* key contains 192bits of key || 64 bits of Initialisation Vector, no additional data */ gcmContext = bctbx_aes_gcm_context_new(key, 24, NULL, 0, key+24, 8, BCTBX_GCM_ENCRYPT); @@ -417,6 +425,8 @@ int lime_encryptFile(void **cryptoContext, unsigned char *key, size_t length, ch int lime_decryptFile(void **cryptoContext, unsigned char *key, size_t length, char *plain, char *cipher) { bctbx_aes_gcm_context_t *gcmContext; + if (key == NULL) return -1; + if (*cryptoContext == NULL) { /* first call to the function, allocate a crypto context and initialise it */ /* key contains 192bits of key || 64 bits of Initialisation Vector, no additional data */ gcmContext = bctbx_aes_gcm_context_new(key, 24, NULL, 0, key+24, 8, BCTBX_GCM_DECRYPT); @@ -569,8 +579,8 @@ int lime_createMultipartMessage(void *cachedb, const char *contentType, uint8_t /* dump the whole message doc into the output */ xmlDocDumpFormatMemoryEnc(xmlOutputMessage, &local_output, &xmlStringLength, "UTF-8", 0); - *output = (uint8_t *)ms_malloc(xmlStringLength + 1); - memcpy(*output, local_output, xmlStringLength); + *output = (uint8_t *)ms_malloc((size_t)xmlStringLength + 1); + memcpy(*output, local_output, (size_t)xmlStringLength); (*output)[xmlStringLength] = '\0'; xmlFree(local_output); @@ -603,7 +613,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se /* retrieve selfZID from cache, and convert it to an Hexa buffer to easily match it against hex string containg in xml message as pzid */ if (bzrtp_getSelfZID(cachedb, selfURI, selfZid, NULL) != 0) { - ms_error("[LIME] Couldn't get self ZID"); + ms_error("[LIME] Couldn't get self ZID"); return LIME_UNABLE_TO_DECRYPT_MESSAGE; } bctbx_int8_to_str(selfZidHex, selfZid, 12); @@ -613,13 +623,13 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se xmlSetGenericErrorFunc(xml_ctx, linphone_xmlparsing_genericxml_error); xml_ctx->doc = xmlReadDoc((const unsigned char*)message, 0, NULL, 0); if (xml_ctx->doc == NULL) { - ms_error("[LIME] XML doc is null"); + ms_error("[LIME] XML doc is null"); retval = LIME_INVALID_ENCRYPTED_MESSAGE; goto error; } if (linphone_create_xml_xpath_context(xml_ctx) < 0) { - ms_error("[LIME] Couldn't create xml xpath context"); + ms_error("[LIME] Couldn't create xml xpath context"); retval = LIME_INVALID_ENCRYPTED_MESSAGE; goto error; } @@ -644,7 +654,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se if ((msg_object != NULL) && (msg_object->nodesetval != NULL)) { for (i = 1; i <= msg_object->nodesetval->nodeNr; i++) { char *currentZidHex; - + char *encryptedMessageb64; char *encryptedContentTypeb64; snprintf(xpath_str, sizeof(xpath_str), "/doc/msg[%i]/pzid", i); @@ -682,7 +692,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se /* do we have retrieved correctly all the needed data */ if (encryptedMessage == NULL) { - ms_error("[LIME] Encrypted message is null, something went wrong..."); + ms_error("[LIME] Encrypted message is null, something went wrong..."); retval = LIME_UNABLE_TO_DECRYPT_MESSAGE; goto error; } @@ -692,7 +702,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se /* something wen't wrong with the cache, this shall never happen */ uint8_t associatedKeyIndexHex[9]; bctbx_uint32_to_str(associatedKeyIndexHex, associatedKey.sessionIndex); - ms_error("[LIME] Session index [%s] < associated key's session index [%s], should not happen !", sessionIndexHex, associatedKeyIndexHex); + ms_error("[LIME] Session index [%s] < associated key's session index [%s], should not happen !", sessionIndexHex, associatedKeyIndexHex); ms_free(encryptedMessage); retval = LIME_UNABLE_TO_DECRYPT_MESSAGE; goto error; @@ -700,7 +710,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se if ((usedSessionIndex - associatedKey.sessionIndex > MAX_DERIVATION_NUMBER) ) { /* we missed to many messages, ask for a cache reset via a ZRTP call */ - ms_error("[LIME] Too many messages missed (%i), cache should be reset by ZRTP call", usedSessionIndex - associatedKey.sessionIndex); + ms_error("[LIME] Too many messages missed (%i), cache should be reset by ZRTP call", usedSessionIndex - associatedKey.sessionIndex); ms_free(encryptedMessage); retval = LIME_UNABLE_TO_DECRYPT_MESSAGE; goto error; @@ -709,7 +719,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se if (associatedKey.sessionIndex != usedSessionIndex) { uint8_t associatedKeyIndexHex[9]; bctbx_uint32_to_str(associatedKeyIndexHex, associatedKey.sessionIndex); - ms_warning("LIME] unexpected session index [%s] received from [%s] (expected [%s]), [%i] messages will be discarded", + ms_warning("LIME] unexpected session index [%s] received from [%s] (expected [%s]), [%i] messages will be discarded", sessionIndexHex, peerURI, associatedKeyIndexHex, usedSessionIndex-associatedKey.sessionIndex); } @@ -724,7 +734,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se if (retval != 0) { ms_free(*output); *output = NULL; - ms_error("[LIME] Couldn't decrypt message"); + ms_error("[LIME] Couldn't decrypt message"); retval = LIME_UNABLE_TO_DECRYPT_MESSAGE; goto error; } @@ -737,7 +747,7 @@ int lime_decryptMultipartMessage(void *cachedb, uint8_t *message, const char *se if (retval != 0) { ms_free(*content_type); *content_type = NULL; - ms_error("[LIME] Couldn't decrypt content type"); + ms_error("[LIME] Couldn't decrypt content type"); retval = LIME_UNABLE_TO_DECRYPT_MESSAGE; goto error; } @@ -757,17 +767,21 @@ error: bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr) { if (cr) { - switch (linphone_core_lime_enabled(cr->lc)) { + switch (linphone_core_lime_enabled(linphone_chat_room_get_core(cr))) { case LinphoneLimeDisabled: return FALSE; case LinphoneLimeMandatory: case LinphoneLimePreferred: { - void *zrtp_cache_db = linphone_core_get_zrtp_cache_db(cr->lc); + void *zrtp_cache_db = linphone_core_get_zrtp_cache_db(linphone_chat_room_get_core(cr)); if (zrtp_cache_db != NULL) { bool_t res; limeURIKeys_t associatedKeys; - char *peer = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(linphone_chat_room_get_peer_address(cr)) - , linphone_address_get_username(linphone_chat_room_get_peer_address(cr)) - , linphone_address_get_domain(linphone_chat_room_get_peer_address(cr))); + const LinphoneAddress *peerAddr = linphone_chat_room_get_peer_address(cr); + char *peer = ms_strdup_printf( + "%s:%s@%s", + linphone_address_get_scheme(peerAddr), + linphone_address_get_username(peerAddr), + linphone_address_get_domain(peerAddr) + ); /* retrieve keys associated to the peer URI */ associatedKeys.peerURI = bctbx_strdup(peer); associatedKeys.selfURI = NULL; /* TODO : there is no sender associated to chatroom so check for any local URI available, shall we add sender to chatroom? */ @@ -790,7 +804,9 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine); int errcode = -1; /* check if we have a xml/cipher message to be decrypted */ - if (msg->content_type && (strcmp("xml/cipher", msg->content_type) == 0 || strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0)) { + if (linphone_chat_message_get_content_type(msg) && + (strcmp("xml/cipher", linphone_chat_message_get_content_type(msg)) == 0 || + strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", linphone_chat_message_get_content_type(msg)) == 0)) { errcode = 0; int retval; void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */ @@ -799,7 +815,7 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn char *peerUri = NULL; char *selfUri = NULL; - ms_debug("Content type is known (%s), try to decrypt it", msg->content_type); + ms_debug("Content type is known (%s), try to decrypt it", linphone_chat_message_get_content_type(msg)); zrtp_cache_db = linphone_core_get_zrtp_cache_db(lc); if (zrtp_cache_db == NULL) { @@ -807,14 +823,23 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn errcode = 500; return errcode; } - peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(msg->from) - , linphone_address_get_username(msg->from) - , linphone_address_get_domain(msg->from)); - selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(msg->to) - , linphone_address_get_username(msg->to) - , linphone_address_get_domain(msg->to)); + const LinphoneAddress *fromAddr = linphone_chat_message_get_from_address(msg); + peerUri = ms_strdup_printf( + "%s:%s@%s", + linphone_address_get_scheme(fromAddr), + linphone_address_get_username(fromAddr), + linphone_address_get_domain(fromAddr) + ); - retval = lime_decryptMultipartMessage(zrtp_cache_db, (uint8_t *)msg->message, selfUri, peerUri, &decrypted_body, &decrypted_content_type, + const LinphoneAddress *toAddr = linphone_chat_message_get_to_address(msg); + selfUri = ms_strdup_printf( + "%s:%s@%s", + linphone_address_get_scheme(toAddr), + linphone_address_get_username(toAddr), + linphone_address_get_domain(toAddr) + ); + + retval = lime_decryptMultipartMessage(zrtp_cache_db, (uint8_t *)linphone_chat_message_get_text(msg), selfUri, peerUri, &decrypted_body, &decrypted_content_type, bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0"))); ms_free(peerUri); ms_free(selfUri); @@ -825,17 +850,15 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn return errcode; } else { /* swap encrypted message with plain text message */ - if (msg->message) { - ms_free(msg->message); - } - msg->message = (char *)decrypted_body; + linphone_chat_message_set_text(msg, (char *)decrypted_body); + ms_free(decrypted_body); if (decrypted_content_type != NULL) { ms_debug("Decrypted content type is ", decrypted_content_type); linphone_chat_message_set_content_type(msg, decrypted_content_type); ms_free(decrypted_content_type); } else { ms_debug("Decrypted content type is unknown, use plain/text or application/vnd.gsma.rcs-ft-http+xml"); - if (strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", msg->content_type) == 0) { + if (strcmp("application/cipher.vnd.gsma.rcs-ft-http+xml", linphone_chat_message_get_content_type(msg)) == 0) { linphone_chat_message_set_content_type(msg, "application/vnd.gsma.rcs-ft-http+xml"); } else { linphone_chat_message_set_content_type(msg, "text/plain"); @@ -843,7 +866,7 @@ int lime_im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEn } } } else { - ms_message("Content type is unknown (%s), don't try to decrypt it", msg->content_type); + ms_message("Content type is unknown (%s), don't try to decrypt it", linphone_chat_message_get_content_type(msg)); } return errcode; } @@ -852,17 +875,17 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn LinphoneCore *lc = linphone_im_encryption_engine_get_core(engine); int errcode = -1; const char *new_content_type = "xml/cipher"; - if(linphone_core_lime_enabled(room->lc)) { + if(linphone_core_lime_enabled(linphone_chat_room_get_core(room))) { if (linphone_chat_room_lime_available(room)) { void *zrtp_cache_db = NULL; /* use a void * instead of sqlite3 * to avoid problems and ifdef when SQLITE is not available(the get function shall return NULL in that case) */ - if (msg->content_type) { - if (strcmp(msg->content_type, "application/vnd.gsma.rcs-ft-http+xml") == 0) { + if (linphone_chat_message_get_content_type(msg)) { + if (strcmp(linphone_chat_message_get_content_type(msg), "application/vnd.gsma.rcs-ft-http+xml") == 0) { /* It's a file transfer, content type shall be set to application/cipher.vnd.gsma.rcs-ft-http+xml - TODO: As of january 2017, the content type is now included in the encrypted body, this - application/cipher.vnd.gsma.rcs-ft-http+xml is kept for compatibility with previous versions, - but may be dropped in the future to use xml/cipher instead. */ + TODO: As of january 2017, the content type is now included in the encrypted body, this + application/cipher.vnd.gsma.rcs-ft-http+xml is kept for compatibility with previous versions, + but may be dropped in the future to use xml/cipher instead. */ new_content_type = "application/cipher.vnd.gsma.rcs-ft-http+xml"; - } else if (strcmp(msg->content_type, "application/im-iscomposing+xml") == 0) { + } else if (strcmp(linphone_chat_message_get_content_type(msg), "application/im-iscomposing+xml") == 0) { /* We don't encrypt composing messages */ return errcode; } @@ -877,23 +900,29 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn } else { int retval; uint8_t *crypted_body = NULL; - char *peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(linphone_chat_room_get_peer_address(room)) - , linphone_address_get_username(linphone_chat_room_get_peer_address(room)) - , linphone_address_get_domain(linphone_chat_room_get_peer_address(room))); - char *selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(msg->from) - , linphone_address_get_username(msg->from) - , linphone_address_get_domain(msg->from)); + const LinphoneAddress *peerAddr = linphone_chat_room_get_peer_address(room); + char *peerUri = ms_strdup_printf( + "%s:%s@%s", + linphone_address_get_scheme(peerAddr), + linphone_address_get_username(peerAddr), + linphone_address_get_domain(peerAddr) + ); + const LinphoneAddress *fromAddr = linphone_chat_message_get_from_address(msg); + char *selfUri = ms_strdup_printf( + "%s:%s@%s", + linphone_address_get_scheme(fromAddr), + linphone_address_get_username(fromAddr), + linphone_address_get_domain(fromAddr) + ); - retval = lime_createMultipartMessage(zrtp_cache_db, msg->content_type, (uint8_t *)msg->message, selfUri, peerUri, &crypted_body); + retval = lime_createMultipartMessage(zrtp_cache_db, linphone_chat_message_get_content_type(msg), (uint8_t *)linphone_chat_message_get_text(msg), selfUri, peerUri, &crypted_body); if (retval != 0) { /* fail to encrypt */ - ms_warning("Unable to encrypt message for %s : %s", room->peer, lime_error_code_to_string(retval)); + ms_warning("Unable to encrypt message for %s : %s", peerUri, lime_error_code_to_string(retval)); if (crypted_body) ms_free(crypted_body); errcode = 488; } else { /* encryption ok, swap plain text message body by encrypted one */ - if (msg->message) { - ms_free(msg->message); - } - msg->message = (char *)crypted_body; + linphone_chat_message_set_text(msg, (char *)crypted_body); + ms_free(crypted_body); linphone_chat_message_set_content_type(msg, new_content_type); } ms_free(peerUri); @@ -910,34 +939,51 @@ int lime_im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEn } int lime_im_encryption_engine_process_downloading_file_cb(LinphoneImEncryptionEngine *engine, LinphoneChatMessage *msg, size_t offset, const uint8_t *buffer, size_t size, uint8_t *decrypted_buffer) { - if (linphone_content_get_key(msg->file_transfer_information) == NULL) return -1; - - if (buffer == NULL || size == 0) { - return lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL); - } - - return lime_decryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), - (unsigned char *)linphone_content_get_key(msg->file_transfer_information), size, (char *)decrypted_buffer, - (char *)buffer); + LinphoneContent *content = linphone_chat_message_get_file_transfer_information(msg); + if (!content) + return -1; + + if (!linphone_content_get_key(content)) + return -1; + + if (!buffer || size == 0) + return lime_decryptFile(linphone_content_get_cryptoContext_address(content), NULL, 0, NULL, NULL); + + return lime_decryptFile( + linphone_content_get_cryptoContext_address(content), + (unsigned char *)linphone_content_get_key(content), + size, + (char *)decrypted_buffer, + (char *)buffer + ); } int lime_im_encryption_engine_process_uploading_file_cb(LinphoneImEncryptionEngine *engine, LinphoneChatMessage *msg, size_t offset, const uint8_t *buffer, size_t *size, uint8_t *encrypted_buffer) { - size_t file_size = linphone_content_get_size(msg->file_transfer_information); - if (linphone_content_get_key(msg->file_transfer_information) == NULL) return -1; - - if (buffer == NULL || *size == 0) { - return lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), NULL, 0, NULL, NULL); - } - + LinphoneContent *content = linphone_chat_message_get_file_transfer_information(msg); + + if (!content) + return -1; + + if (!linphone_content_get_key(content)) + return -1; + + if (!buffer || *size == 0) + return lime_encryptFile(linphone_content_get_cryptoContext_address(content), NULL, 0, NULL, NULL); + + size_t file_size = linphone_content_get_file_size(content); if (file_size == 0) { ms_warning("File size has not been set, encryption will fail if not done in one step (if file is larger than 16K)"); } else if (offset + *size < file_size) { *size -= (*size % 16); } - - return lime_encryptFile(linphone_content_get_cryptoContext_address(msg->file_transfer_information), - (unsigned char *)linphone_content_get_key(msg->file_transfer_information), *size, - (char *)buffer, (char *)encrypted_buffer); + + return lime_encryptFile( + linphone_content_get_cryptoContext_address(content), + (unsigned char *)linphone_content_get_key(content), + *size, + (char *)buffer, + (char *)encrypted_buffer + ); } bool_t lime_im_encryption_engine_is_file_encryption_enabled_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room) { @@ -950,7 +996,9 @@ void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneImEncryptio /* generate a random 192 bits key + 64 bits of initial vector and store it into the * file_transfer_information->key field of the msg */ sal_get_random_bytes((unsigned char *)keyBuffer, FILE_TRANSFER_KEY_SIZE); - linphone_content_set_key(msg->file_transfer_information, keyBuffer, FILE_TRANSFER_KEY_SIZE); /* key is duplicated in the content private structure */ + LinphoneContent *content = linphone_chat_message_get_file_transfer_information(msg); + if (content) + linphone_content_set_key(content, keyBuffer, FILE_TRANSFER_KEY_SIZE); /* key is duplicated in the content private structure */ } #else /* HAVE_LIME */ @@ -996,7 +1044,7 @@ bool_t lime_im_encryption_engine_is_file_encryption_enabled_cb(LinphoneImEncrypt return FALSE; } void lime_im_encryption_engine_generate_file_transfer_key_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { - + } #endif /* HAVE_LIME */ diff --git a/coreapi/linphone_tunnel.cc b/coreapi/linphone_tunnel.cc index c82876105..6c3589147 100644 --- a/coreapi/linphone_tunnel.cc +++ b/coreapi/linphone_tunnel.cc @@ -28,6 +28,7 @@ #include "linphone/core.h" #include "private.h" #include "linphone/lpconfig.h" +#include "c-wrapper/c-wrapper.h" LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){ return lc->tunnel; @@ -42,13 +43,13 @@ struct _LinphoneTunnel { static void _linphone_tunnel_uninit(LinphoneTunnel *tunnel); BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneTunnel); -BELLE_SIP_DECLARE_VPTR(LinphoneTunnel); +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneTunnel); BELLE_SIP_INSTANCIATE_VPTR(LinphoneTunnel, belle_sip_object_t, _linphone_tunnel_uninit, // uninit NULL, // clone NULL, // marshal FALSE // unowned -) +); extern "C" LinphoneTunnel* linphone_core_tunnel_new(LinphoneCore *lc){ LinphoneTunnel* tunnel = belle_sip_object_new(LinphoneTunnel); @@ -231,13 +232,13 @@ static void linphone_tunnel_add_server_intern(LinphoneTunnel *tunnel, LinphoneTu linphone_tunnel_config_get_port(tunnel_config), linphone_tunnel_config_get_host2(tunnel_config), linphone_tunnel_config_get_port2(tunnel_config), - linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), - linphone_tunnel_config_get_delay(tunnel_config)); + (unsigned int)linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + (unsigned int)linphone_tunnel_config_get_delay(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), - linphone_tunnel_config_get_delay(tunnel_config)); + (unsigned int)linphone_tunnel_config_get_remote_udp_mirror_port(tunnel_config), + (unsigned int)linphone_tunnel_config_get_delay(tunnel_config)); } } else if (linphone_tunnel_config_get_host2(tunnel_config) != NULL) { bcTunnel(tunnel)->addServerPair(linphone_tunnel_config_get_host(tunnel_config), diff --git a/coreapi/linphone_tunnel_config.c b/coreapi/linphone_tunnel_config.c index b95d153fe..a12ac5c41 100644 --- a/coreapi/linphone_tunnel_config.c +++ b/coreapi/linphone_tunnel_config.c @@ -21,8 +21,11 @@ */ #include "linphone/tunnel.h" -#include "private.h" +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" struct _LinphoneTunnelConfig { belle_sip_object_t base; @@ -139,6 +142,3 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphoneTunnelConfig, belle_sip_object_t, NULL, // marshal FALSE ); - - - diff --git a/coreapi/linphone_tunnel_stubs.c b/coreapi/linphone_tunnel_stubs.c index 7e2994e78..d4c901009 100644 --- a/coreapi/linphone_tunnel_stubs.c +++ b/coreapi/linphone_tunnel_stubs.c @@ -38,6 +38,14 @@ LinphoneTunnel* linphone_core_get_tunnel(const LinphoneCore *lc){ void linphone_tunnel_destroy(LinphoneTunnel *tunnel){ } +LinphoneTunnel *linphone_tunnel_ref(LinphoneTunnel *tunnel) { + ms_warning("linphone_tunnel_ref() - stubbed, no implementation"); + return tunnel; +} + +void linphone_tunnel_unref(LinphoneTunnel *tunnel) { + ms_warning("linphone_tunnel_unref() - stubbed, no implementation"); +} void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config){ ms_warning("linphone_tunnel_add_server() - stubbed, no implementation"); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 98aef4e54..9ff70e6be 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1,4 +1,3 @@ - /* linphone Copyright (C) 2010 Belledonne Communications SARL @@ -18,1785 +17,14 @@ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifdef _WIN32 -#include -#endif -#include "linphone/core.h" -#include "linphone/sipsetup.h" -#include "linphone/lpconfig.h" + +#include +#include + +#include "linphone/types.h" + #include "private.h" -#include "conference_private.h" -#include -#include -#include - -#include "mediastreamer2/mediastream.h" -#include "mediastreamer2/msvolume.h" -#include "mediastreamer2/msequalizer.h" -#include "mediastreamer2/msfileplayer.h" -#include "mediastreamer2/msjpegwriter.h" -#include "mediastreamer2/msogl.h" -#include "mediastreamer2/mseventqueue.h" -#include "mediastreamer2/mssndcard.h" -#include "mediastreamer2/msrtt4103.h" - -#include - - -inline OrtpRtcpXrStatSummaryFlag operator|(OrtpRtcpXrStatSummaryFlag a, OrtpRtcpXrStatSummaryFlag b) { - return static_cast(static_cast(a) | static_cast(b)); -} - - -static const char *EC_STATE_STORE = ".linphone.ecstate"; -#define EC_STATE_MAX_LEN 1048576 // 1Mo - -static void linphone_call_stats_uninit(LinphoneCallStats *stats); -static void linphone_call_get_local_ip(LinphoneCall *call, const LinphoneAddress *remote_addr); -static void _linphone_call_set_next_video_frame_decoded_trigger(LinphoneCall *call); -void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index); - - -typedef belle_sip_object_t_vptr_t LinphoneCallCbs_vptr_t; -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallCbs); -BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallCbs, belle_sip_object_t, - NULL, // destroy - NULL, // clone - NULL, // Marshall - FALSE -); - -LinphoneCallCbs *_linphone_call_cbs_new(void) { - LinphoneCallCbs *obj = belle_sip_object_new(LinphoneCallCbs); - return obj; -} - -LinphoneCallCbs *linphone_call_cbs_ref(LinphoneCallCbs *cbs) { - return (LinphoneCallCbs *)belle_sip_object_ref(cbs); -} - -void linphone_call_cbs_unref(LinphoneCallCbs *cbs) { - belle_sip_object_unref(cbs); -} - -void *linphone_call_cbs_get_user_data(const LinphoneCallCbs *cbs) { - return cbs->user_data; -} - -void linphone_call_cbs_set_user_data(LinphoneCallCbs *cbs, void *user_data) { - cbs->user_data = user_data; -} - -LinphoneCallCbsDtmfReceivedCb linphone_call_cbs_get_dtmf_received(LinphoneCallCbs *cbs) { - return cbs->dtmf_received_cb; -} - -void linphone_call_cbs_set_dtmf_received(LinphoneCallCbs *cbs, LinphoneCallCbsDtmfReceivedCb cb) { - cbs->dtmf_received_cb = cb; -} - -LinphoneCallCbsEncryptionChangedCb linphone_call_cbs_get_encryption_changed(LinphoneCallCbs *cbs) { - return cbs->encryption_changed_cb; -} - -void linphone_call_cbs_set_encryption_changed(LinphoneCallCbs *cbs, LinphoneCallCbsEncryptionChangedCb cb) { - cbs->encryption_changed_cb = cb; -} - -LinphoneCallCbsInfoMessageReceivedCb linphone_call_cbs_get_info_message_received(LinphoneCallCbs *cbs) { - return cbs->info_message_received_cb; -} - -void linphone_call_cbs_set_info_message_received(LinphoneCallCbs *cbs, LinphoneCallCbsInfoMessageReceivedCb cb) { - cbs->info_message_received_cb = cb; -} - -LinphoneCallCbsStateChangedCb linphone_call_cbs_get_state_changed(LinphoneCallCbs *cbs) { - return cbs->state_changed_cb; -} - -void linphone_call_cbs_set_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsStateChangedCb cb) { - cbs->state_changed_cb = cb; -} - -LinphoneCallCbsStatsUpdatedCb linphone_call_cbs_get_stats_updated(LinphoneCallCbs *cbs) { - return cbs->stats_updated_cb; -} - -void linphone_call_cbs_set_stats_updated(LinphoneCallCbs *cbs, LinphoneCallCbsStatsUpdatedCb cb) { - cbs->stats_updated_cb = cb; -} - -LinphoneCallCbsTransferStateChangedCb linphone_call_cbs_get_transfer_state_changed(LinphoneCallCbs *cbs) { - return cbs->transfer_state_changed_cb; -} - -void linphone_call_cbs_set_transfer_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsTransferStateChangedCb cb) { - cbs->transfer_state_changed_cb = cb; -} - -LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_processing(LinphoneCallCbs *cbs){ - return cbs->ack_processing; -} - -void linphone_call_cbs_set_ack_processing(LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb){ - cbs->ack_processing = cb; -} - -LinphoneCallCbsTmmbrReceivedCb linphone_call_cbs_get_tmmbr_received(LinphoneCallCbs *cbs) { - return cbs->tmmbr_received_cb; -} - -void linphone_call_cbs_set_tmmbr_received(LinphoneCallCbs *cbs, LinphoneCallCbsTmmbrReceivedCb cb) { - cbs->tmmbr_received_cb = cb; -} - -LinphoneCallCbsSnapshotTakenCb linphone_call_cbs_get_snapshot_taken(LinphoneCallCbs *cbs) { - return cbs->snapshot_taken_cb; -} - -void linphone_call_cbs_set_snapshot_taken(LinphoneCallCbs *cbs, LinphoneCallCbsSnapshotTakenCb cb) { - cbs->snapshot_taken_cb = cb; -} - -LinphoneCallCbsNextVideoFrameDecodedCb linphone_call_cbs_get_next_video_frame_decoded(LinphoneCallCbs *cbs) { - return cbs->next_video_frame_decoded_cb; -} - -void linphone_call_cbs_set_next_video_frame_decoded(LinphoneCallCbs *cbs, LinphoneCallCbsNextVideoFrameDecodedCb cb) { - cbs->next_video_frame_decoded_cb = cb; -} - -bool_t linphone_call_state_is_early(LinphoneCallState state){ - switch (state){ - case LinphoneCallIdle: - case LinphoneCallOutgoingInit: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingProgress: - case LinphoneCallIncomingReceived: - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallEarlyUpdatedByRemote: - case LinphoneCallEarlyUpdating: - return TRUE; - case LinphoneCallResuming: - case LinphoneCallEnd: - case LinphoneCallUpdating: - case LinphoneCallRefered: - case LinphoneCallPausing: - case LinphoneCallPausedByRemote: - case LinphoneCallPaused: - case LinphoneCallConnected: - case LinphoneCallError: - case LinphoneCallUpdatedByRemote: - case LinphoneCallReleased: - case LinphoneCallStreamsRunning: - break; - } - return FALSE; -} - -MSWebCam *get_nowebcam_device(MSFactory* f){ -#ifdef VIDEO_ENABLED - return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(f),"StaticImage: Static picture"); -#else - return NULL; -#endif -} - -static bool_t generate_b64_crypto_key(size_t key_length, char* key_out, size_t key_out_size) { - size_t b64_size; - uint8_t* tmp = (uint8_t*) ms_malloc0(key_length); - if (sal_get_random_bytes(tmp, key_length)==NULL) { - ms_error("Failed to generate random key"); - ms_free(tmp); - return FALSE; - } - - b64_size = b64::b64_encode((const char*)tmp, key_length, NULL, 0); - if (b64_size == 0) { - ms_error("Failed to get b64 result size"); - ms_free(tmp); - return FALSE; - } - if (b64_size>=key_out_size){ - ms_error("Insufficient room for writing base64 SRTP key"); - ms_free(tmp); - return FALSE; - } - b64_size = b64::b64_encode((const char*)tmp, key_length, key_out, key_out_size); - if (b64_size == 0) { - ms_error("Failed to b64 encode key"); - ms_free(tmp); - return FALSE; - } - key_out[b64_size] = '\0'; - ms_free(tmp); - return TRUE; -} - -static bool_t linphone_call_encryption_mandatory(LinphoneCall *call){ - if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) { - ms_message("Forced encryption mandatory on call [%p] due to SRTP-DTLS",call); - return TRUE; - } - return call->params->encryption_mandatory; -} - -LinphoneCore *linphone_call_get_core(const LinphoneCall *call){ - return call->core; -} - -const char* linphone_call_get_authentication_token(LinphoneCall *call){ - return call->auth_token; -} - -bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call){ - return call->auth_token_verified; -} - -static bool_t at_least_one_stream_started(const LinphoneCall *call){ - return (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted ) - || (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) - || (call->textstream && media_stream_get_state((MediaStream *)call->textstream) == MSStreamStarted); -} - -static bool_t linphone_call_all_streams_encrypted(const LinphoneCall *call) { - int number_of_encrypted_stream = 0; - int number_of_active_stream = 0; - - if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) { - number_of_active_stream++; - if(media_stream_secured((MediaStream *)call->audiostream)) - number_of_encrypted_stream++; - } - if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) { - number_of_active_stream++; - if (media_stream_secured((MediaStream *)call->videostream)) - number_of_encrypted_stream++; - } - if (call->textstream && media_stream_get_state((MediaStream *)call->textstream) == MSStreamStarted) { - number_of_active_stream++; - if (media_stream_secured((MediaStream *)call->textstream)) - number_of_encrypted_stream++; - } - return number_of_active_stream>0 && number_of_active_stream==number_of_encrypted_stream; -} - -static bool_t linphone_call_all_streams_avpf_enabled(const LinphoneCall *call) { - int nb_active_streams = 0; - int nb_avpf_enabled_streams = 0; - if (call) { - if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) { - nb_active_streams++; - if (media_stream_avpf_enabled((MediaStream *)call->audiostream)) - nb_avpf_enabled_streams++; - } - if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) { - nb_active_streams++; - if (media_stream_avpf_enabled((MediaStream *)call->videostream)) - nb_avpf_enabled_streams++; - } - } - return ((nb_active_streams > 0) && (nb_active_streams == nb_avpf_enabled_streams)); -} - -static uint16_t linphone_call_get_avpf_rr_interval(const LinphoneCall *call) { - uint16_t rr_interval = 0; - uint16_t stream_rr_interval; - if (call) { - if (call->audiostream && media_stream_get_state((MediaStream *)call->audiostream) == MSStreamStarted) { - stream_rr_interval = media_stream_get_avpf_rr_interval((MediaStream *)call->audiostream); - if (stream_rr_interval > rr_interval) rr_interval = stream_rr_interval; - } - if (call->videostream && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) { - stream_rr_interval = media_stream_get_avpf_rr_interval((MediaStream *)call->videostream); - if (stream_rr_interval > rr_interval) rr_interval = stream_rr_interval; - } - } else { - rr_interval = 5000; - } - return rr_interval; -} - -static void propagate_encryption_changed(LinphoneCall *call){ - if (!linphone_call_all_streams_encrypted(call)) { - ms_message("Some streams are not encrypted"); - call->current_params->media_encryption=LinphoneMediaEncryptionNone; - linphone_call_notify_encryption_changed(call, FALSE, call->auth_token); - } else { - if (call->auth_token) {/* ZRTP only is using auth_token */ - call->current_params->media_encryption=LinphoneMediaEncryptionZRTP; - } else { /* otherwise it must be DTLS as SDES doesn't go through this function */ - call->current_params->media_encryption=LinphoneMediaEncryptionDTLS; - } - ms_message("All streams are encrypted key exchanged using %s", call->current_params->media_encryption==LinphoneMediaEncryptionZRTP?"ZRTP":call->current_params->media_encryption==LinphoneMediaEncryptionDTLS?"DTLS":"Unknown mechanism"); - linphone_call_notify_encryption_changed(call, TRUE, call->auth_token); -#ifdef VIDEO_ENABLED - if (linphone_call_encryption_mandatory(call) && call->videostream && media_stream_started((MediaStream *)call->videostream)) { - video_stream_send_vfu(call->videostream); /*nothing could have been sent yet so generating key frame*/ - } -#endif - } -} - -static void linphone_call_audiostream_encryption_changed(void *data, bool_t encrypted) { - char status[255]={0}; - LinphoneCall *call; - - call = (LinphoneCall *)data; - - if (encrypted) { - if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { /* if encryption is DTLS, no status to be displayed */ - snprintf(status,sizeof(status)-1,_("Authentication token is %s"),call->auth_token); - linphone_core_notify_display_status(call->core, status); - } - } - - propagate_encryption_changed(call); - -#ifdef VIDEO_ENABLED - // Enable video encryption - if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { - const LinphoneCallParams *params=linphone_call_get_current_params(call); - if (params->has_video) { - ms_message("Trying to start ZRTP encryption on video stream"); - video_stream_start_zrtp(call->videostream); - } - } -#endif -} - -static void linphone_call_audiostream_auth_token_ready(void *data, const char* auth_token, bool_t verified) { - LinphoneCall *call=(LinphoneCall *)data; - if (call->auth_token != NULL) - ms_free(call->auth_token); - - call->auth_token=ms_strdup(auth_token); - call->auth_token_verified=verified; - - ms_message("Authentication token is %s (%s)", auth_token, verified?"verified":"unverified"); -} - -void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified){ - if (call->audiostream==NULL || !media_stream_started(&call->audiostream->ms)){ - ms_error("linphone_call_set_authentication_token_verified(): No audio stream or not started"); - return; - } - if (call->audiostream->ms.sessions.zrtp_context==NULL){ - ms_error("linphone_call_set_authentication_token_verified(): No zrtp context."); - return; - } - if (!call->auth_token_verified && verified){ - ms_zrtp_sas_verified(call->audiostream->ms.sessions.zrtp_context); - }else if (call->auth_token_verified && !verified){ - ms_zrtp_sas_reset_verified(call->audiostream->ms.sessions.zrtp_context); - } - call->auth_token_verified=verified; - propagate_encryption_changed(call); -} - -static int get_max_codec_sample_rate(const bctbx_list_t *codecs){ - int max_sample_rate=0; - const bctbx_list_t *it; - for(it=codecs;it!=NULL;it=it->next){ - PayloadType *pt=(PayloadType*)it->data; - int sample_rate; - - if( strcasecmp("G722",pt->mime_type) == 0 ){ - /* G722 spec says 8000 but the codec actually requires 16000 */ - sample_rate = 16000; - }else sample_rate=pt->clock_rate; - if (sample_rate>max_sample_rate) max_sample_rate=sample_rate; - } - return max_sample_rate; -} - -static int find_payload_type_number(const bctbx_list_t *assigned, const PayloadType *pt){ - const bctbx_list_t *elem; - const PayloadType *candidate=NULL; - for(elem=assigned;elem!=NULL;elem=elem->next){ - const PayloadType *it=(const PayloadType*)elem->data; - if ((strcasecmp(pt->mime_type, payload_type_get_mime(it)) == 0) - && (it->clock_rate==pt->clock_rate) - && (it->channels==pt->channels || pt->channels<=0)) { - candidate=it; - if ((it->recv_fmtp!=NULL && pt->recv_fmtp!=NULL && strcasecmp(it->recv_fmtp, pt->recv_fmtp)==0) - || (it->recv_fmtp==NULL && pt->recv_fmtp==NULL)){ - break;/*exact match*/ - } - } - } - return candidate ? payload_type_get_number(candidate) : -1; -} - -bool_t is_payload_type_number_available(const bctbx_list_t *l, int number, const PayloadType *ignore){ - const bctbx_list_t *elem; - for (elem=l; elem!=NULL; elem=elem->next){ - const PayloadType *pt=(PayloadType*)elem->data; - if (pt!=ignore && payload_type_get_number(pt)==number) return FALSE; - } - return TRUE; -} - -static void linphone_core_assign_payload_type_numbers(LinphoneCore *lc, bctbx_list_t *codecs){ - bctbx_list_t *elem; - int dyn_number=lc->codecs_conf.dyn_pt; - PayloadType *red = NULL, *t140 = NULL; - - for (elem=codecs; elem!=NULL; elem=elem->next){ - PayloadType *pt=(PayloadType*)elem->data; - int number=payload_type_get_number(pt); - - /*check if number is duplicated: it could be the case if the remote forced us to use a mapping with a previous offer*/ - if (number!=-1 && !(pt->flags & PAYLOAD_TYPE_FROZEN_NUMBER)){ - if (!is_payload_type_number_available(codecs, number, pt)){ - ms_message("Reassigning payload type %i %s/%i because already offered.", number, pt->mime_type, pt->clock_rate); - number=-1; /*need to be re-assigned*/ - } - } - - if (number==-1){ - while(dyn_number<127){ - if (is_payload_type_number_available(codecs, dyn_number, NULL)){ - payload_type_set_number(pt, dyn_number); - dyn_number++; - break; - } - dyn_number++; - } - if (dyn_number==127){ - ms_error("Too many payload types configured ! codec %s/%i is disabled.", pt->mime_type, pt->clock_rate); - payload_type_set_enable(pt, FALSE); - } - } - - if (strcmp(pt->mime_type, payload_type_t140_red.mime_type) == 0) { - red = pt; - } else if (strcmp(pt->mime_type, payload_type_t140.mime_type) == 0) { - t140 = pt; - } - } - - if (t140 && red) { - int t140_payload_type_number = payload_type_get_number(t140); - char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_type_number, t140_payload_type_number, t140_payload_type_number); - payload_type_set_recv_fmtp(red, red_fmtp); - ms_free(red_fmtp); - } -} - -static bool_t has_telephone_event_at_rate(const bctbx_list_t *tev, int rate){ - const bctbx_list_t *it; - for(it=tev;it!=NULL;it=it->next){ - const PayloadType *pt=(PayloadType*)it->data; - if (pt->clock_rate==rate) return TRUE; - } - return FALSE; -} - -static bctbx_list_t * create_telephone_events(LinphoneCore *lc, const bctbx_list_t *codecs){ - const bctbx_list_t *it; - bctbx_list_t *ret=NULL; - for(it=codecs;it!=NULL;it=it->next){ - const PayloadType *pt=(PayloadType*)it->data; - if (!has_telephone_event_at_rate(ret,pt->clock_rate)){ - PayloadType *tev=payload_type_clone(&payload_type_telephone_event); - tev->clock_rate=pt->clock_rate; - /*let it choose the number dynamically as for normal codecs*/ - payload_type_set_number(tev, -1); - if (ret==NULL){ - /*But for first telephone-event, prefer the number that was configured in the core*/ - if (is_payload_type_number_available(codecs, lc->codecs_conf.telephone_event_pt, NULL)){ - payload_type_set_number(tev, lc->codecs_conf.telephone_event_pt); - } - } - ret=bctbx_list_append(ret,tev); - } - } - return ret; -} - -static bctbx_list_t *create_special_payload_types(LinphoneCore *lc, const bctbx_list_t *codecs){ - bctbx_list_t *ret=create_telephone_events(lc, codecs); - if (linphone_core_generic_comfort_noise_enabled(lc)){ - PayloadType *cn=payload_type_clone(&payload_type_cn); - payload_type_set_number(cn, 13); - ret=bctbx_list_append(ret, cn); - } - return ret; -} - -typedef struct _CodecConstraints{ - int bandwidth_limit; - int max_codecs; - bctbx_list_t *previously_used; -}CodecConstraints; - -static bctbx_list_t *make_codec_list(LinphoneCore *lc, CodecConstraints * hints, SalStreamType stype, const bctbx_list_t *codecs){ - bctbx_list_t *l=NULL; - const bctbx_list_t *it; - int nb = 0; - - for(it=codecs;it!=NULL;it=it->next){ - PayloadType *pt=(PayloadType*)it->data; - int num; - - if (!payload_type_enabled(pt)) { - continue; - } - if (hints->bandwidth_limit>0 && !linphone_core_is_payload_type_usable_for_bandwidth(lc,pt,hints->bandwidth_limit)){ - ms_message("Codec %s/%i eliminated because of audio bandwidth constraint of %i kbit/s", - pt->mime_type,pt->clock_rate,hints->bandwidth_limit); - continue; - } - if (!_linphone_core_check_payload_type_usability(lc, pt)) { - continue; - } - pt=payload_type_clone(pt); - - /*look for a previously assigned number for this codec*/ - num=find_payload_type_number(hints->previously_used, pt); - if (num!=-1){ - payload_type_set_number(pt,num); - payload_type_set_flag(pt, PAYLOAD_TYPE_FROZEN_NUMBER); - } - - l=bctbx_list_append(l, pt); - nb++; - if ((hints->max_codecs > 0) && (nb >= hints->max_codecs)) break; - } - if (stype==SalAudio){ - bctbx_list_t *specials=create_special_payload_types(lc,l); - l=bctbx_list_concat(l,specials); - } - linphone_core_assign_payload_type_numbers(lc, l); - return l; -} - -static void update_media_description_from_stun(SalMediaDescription *md, const StunCandidate *ac, const StunCandidate *vc, const StunCandidate *tc){ - int i; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - if ((md->streams[i].type == SalAudio) && (ac->port != 0)) { - strcpy(md->streams[i].rtp_addr,ac->addr); - md->streams[i].rtp_port=ac->port; - if ((ac->addr[0]!='\0' && vc->addr[0]!='\0' && strcmp(ac->addr,vc->addr)==0) || sal_media_description_get_nb_active_streams(md)==1){ - strcpy(md->addr,ac->addr); - } - } else if ((md->streams[i].type == SalVideo) && (vc->port != 0)) { - strcpy(md->streams[i].rtp_addr,vc->addr); - md->streams[i].rtp_port=vc->port; - } else if ((md->streams[i].type == SalText) && (tc->port != 0)) { - strcpy(md->streams[i].rtp_addr,tc->addr); - md->streams[i].rtp_port=tc->port; - } - } -} - -static int setup_encryption_key(SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag){ - size_t keylen=0; - crypto->tag=tag; - crypto->algo=suite; - switch(suite){ - case MS_AES_128_SHA1_80: - case MS_AES_128_SHA1_32: - case MS_AES_128_NO_AUTH: - case MS_NO_CIPHER_SHA1_80: /*not sure for this one*/ - keylen=30; - break; - case MS_AES_256_SHA1_80: - case MS_AES_CM_256_SHA1_80: - case MS_AES_256_SHA1_32: - keylen=46; - break; - case MS_CRYPTO_SUITE_INVALID: - break; - } - if (keylen==0 || !generate_b64_crypto_key(keylen, crypto->master_key, SAL_SRTP_KEY_SIZE)){ - ms_error("Could not generate SRTP key."); - crypto->algo = MS_CRYPTO_SUITE_INVALID; - return -1; - } - return 0; -} -static void setup_dtls_keys(LinphoneCall *call, SalMediaDescription *md){ - int i; - for(i=0; istreams[i])) continue; - /* if media encryption is set to DTLS check presence of fingerprint in the call which shall have been set at stream init but it may have failed when retrieving certificate resulting in no fingerprint present and then DTLS not usable */ - if (sal_stream_description_has_dtls(&md->streams[i]) == TRUE) { - strncpy(md->streams[i].dtls_fingerprint, call->dtls_certificate_fingerprint, sizeof(md->streams[i].dtls_fingerprint)); /* get the self fingerprint from call(it's computed at stream init) */ - md->streams[i].dtls_role = SalDtlsRoleUnset; /* if we are offering, SDP will have actpass setup attribute when role is unset, if we are responding the result mediadescription will be set to SalDtlsRoleIsClient */ - } else { - md->streams[i].dtls_fingerprint[0] = '\0'; - md->streams[i].dtls_role = SalDtlsRoleInvalid; - - } - } - -} -static void setup_encryption_keys(LinphoneCall *call, SalMediaDescription *md){ - LinphoneCore *lc=call->core; - int i,j; - SalMediaDescription *old_md=call->localdesc; - bool_t keep_srtp_keys=lp_config_get_int(lc->config,"sip","keep_srtp_keys",1); - - for(i=0; istreams[i])) continue; - if (sal_stream_description_has_srtp(&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].crypto[j],&old_md->streams[i].crypto[j],sizeof(SalSrtpCryptoAlgo)); - } - }else{ - const MSCryptoSuite *suites=linphone_core_get_srtp_crypto_suites(lc); - for(j=0;suites!=NULL && suites[j]!=MS_CRYPTO_SUITE_INVALID && jstreams[i].crypto[j],suites[j],j+1); - } - } - } - } -} - - -static void setup_zrtp_hash(LinphoneCall *call, SalMediaDescription *md) { - int i; - if (linphone_core_media_encryption_supported(call->core, LinphoneMediaEncryptionZRTP)) { /* set the hello hash for all streams */ - for(i=0; istreams[i])) continue; - if (call->sessions[i].zrtp_context!=NULL) { - ms_zrtp_getHelloHash(call->sessions[i].zrtp_context, md->streams[i].zrtphash, 128); - if (call->params->media_encryption==LinphoneMediaEncryptionZRTP) { /* turn on the flag to use it if ZRTP is set */ - md->streams[i].haveZrtpHash = 1; - } else { - md->streams[i].haveZrtpHash = 0; - } - } else { - md->streams[i].haveZrtpHash = 0; - } - } - } -} - -static void setup_rtcp_fb(LinphoneCall *call, SalMediaDescription *md) { - bctbx_list_t *pt_it; - PayloadType *pt; - PayloadTypeAvpfParams avpf_params; - LinphoneCore *lc = call->core; - int i; - - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - md->streams[i].rtcp_fb.generic_nack_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_generic_nack_enabled", 0); - md->streams[i].rtcp_fb.tmmbr_enabled = lp_config_get_int(lc->config, "rtp", "rtcp_fb_tmmbr_enabled", 1); - md->streams[i].implicit_rtcp_fb = call->params->implicit_rtcp_fb; - - 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 == FALSE && call->params->implicit_rtcp_fb == FALSE) { - payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); - memset(&avpf_params, 0, sizeof(avpf_params)); - }else { - 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; - } - payload_type_set_avpf_params(pt, avpf_params); - } - } -} - -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", 1); - if (md->rtcp_xr.enabled == TRUE) { - 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", 10000); - } - 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", 1); - } - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (!sal_stream_description_active(&md->streams[i])) continue; - memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr)); - } -} - -void linphone_call_increment_local_media_description(LinphoneCall *call){ - SalMediaDescription *md=call->localdesc; - md->session_ver++; -} - -void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call){ - LinphoneCore *lc = call->core; - if (call->ice_session != NULL) { - /*set this to FALSE once flexisip are updated everywhere, let's say in December 2016.*/ - bool_t use_nortpproxy = lp_config_get_int(lc->config, "sip", "ice_uses_nortpproxy", TRUE); - _update_local_media_description_from_ice(call->localdesc, call->ice_session, use_nortpproxy); - linphone_call_update_ice_state_in_call_stats(call); - } -#ifdef BUILD_UPNP - if(call->upnp_session != NULL) { - linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); - linphone_call_update_upnp_state_in_call_stats(call); - } -#endif //BUILD_UPNP -} - -static void transfer_already_assigned_payload_types(SalMediaDescription *old, SalMediaDescription *md){ - int i; - for(i=0;istreams[i].already_assigned_payloads=old->streams[i].already_assigned_payloads; - old->streams[i].already_assigned_payloads=NULL; - } -} - -static const char *linphone_call_get_bind_ip_for_stream(LinphoneCall *call, int stream_index){ - const char *bind_ip = lp_config_get_string(call->core->config,"rtp","bind_address", - call->af == AF_INET6 ? "::0" : "0.0.0.0"); - PortConfig *pc = &call->media_ports[stream_index]; - if (pc->multicast_ip[0]!='\0'){ - if (call->dir==LinphoneCallOutgoing){ - /*as multicast sender, we must decide a local interface to use to send multicast, and bind to it*/ - linphone_core_get_local_ip_for(strchr(pc->multicast_ip,':') ? AF_INET6 : AF_INET, - NULL, pc->multicast_bind_ip); - bind_ip = pc->multicast_bind_ip; - }else{ - /*otherwise we shall use an address family of the same family of the multicast address, because - * dual stack socket and multicast don't work well on Mac OS (linux is OK, as usual).*/ - bind_ip = strchr(pc->multicast_ip,':') ? "::0" : "0.0.0.0"; - } - } - return bind_ip; -} - -static const char *linphone_call_get_public_ip_for_stream(LinphoneCall *call, int stream_index){ - const char *public_ip=call->media_localip; - - if (call->media_ports[stream_index].multicast_ip[0]!='\0') - public_ip=call->media_ports[stream_index].multicast_ip; - return public_ip; -} - -void linphone_call_update_biggest_desc(LinphoneCall *call, SalMediaDescription *md){ - if (call->biggestdesc==NULL || md->nb_streams>call->biggestdesc->nb_streams){ - /*we have been offered and now are ready to proceed, or we added a new stream*/ - /*store the media description to remember the mapping of calls*/ - if (call->biggestdesc){ - sal_media_description_unref(call->biggestdesc); - call->biggestdesc=NULL; - } - call->biggestdesc=sal_media_description_ref(md); - } -} - -static void force_streams_dir_according_to_state(LinphoneCall *call, SalMediaDescription *md){ - int i; - - for (i=0; istreams[i]; - - switch (call->state){ - case LinphoneCallPausing: - case LinphoneCallPaused: - if (sd->dir != SalStreamInactive) { - sd->dir = SalStreamSendOnly; - if (sd->type == SalVideo){ - if (lp_config_get_int(call->core->config, "sip", "inactive_video_on_pause", 0)) { - sd->dir = SalStreamInactive; - } - } - } - break; - default: - break; - } - - /* Reflect the stream directions in the call params */ - if (i == call->main_audio_stream_index) { - linphone_call_params_set_audio_direction(call->current_params, media_direction_from_sal_stream_dir(sd->dir)); - } else if (i == call->main_video_stream_index) { - linphone_call_params_set_video_direction(call->current_params, media_direction_from_sal_stream_dir(sd->dir)); - } - } -} - -void linphone_call_make_local_media_description(LinphoneCall *call) { - bctbx_list_t *l; - SalMediaDescription *old_md=call->localdesc; - int i; - int max_index = 0; - SalMediaDescription *md=sal_media_description_new(); - LinphoneAddress *addr; - const char *subject; - CodecConstraints codec_hints={0}; - LinphoneCallParams *params = call->params; - LinphoneCore *lc = call->core; - bool_t rtcp_mux = lp_config_get_int(lc->config, "rtp", "rtcp_mux", 0); - - /*multicast is only set in case of outgoing call*/ - if (call->dir == LinphoneCallOutgoing && linphone_call_params_audio_multicast_enabled(params)) { - md->streams[call->main_audio_stream_index].ttl=linphone_core_get_audio_multicast_ttl(lc); - md->streams[call->main_audio_stream_index].multicast_role = SalMulticastSender; - } - - if (call->dir == LinphoneCallOutgoing && linphone_call_params_video_multicast_enabled(params)) { - md->streams[call->main_video_stream_index].ttl=linphone_core_get_video_multicast_ttl(lc); - md->streams[call->main_video_stream_index].multicast_role = SalMulticastSender; - } - - subject=linphone_call_params_get_session_name(params); - - linphone_core_adapt_to_network(lc,call->ping_time,params); - - if (call->dest_proxy) { - addr=linphone_address_clone(linphone_proxy_config_get_identity_address(call->dest_proxy)); - } else { - addr=linphone_address_new(linphone_core_get_identity(lc)); - } - - md->session_id=(old_md ? old_md->session_id : (rand() & 0xfff)); - md->session_ver=(old_md ? (old_md->session_ver+1) : (rand() & 0xfff)); - md->nb_streams=(call->biggestdesc ? call->biggestdesc->nb_streams : 1); - - /*re-check local ip address each time we make a new offer, because it may change in case of network reconnection*/ - linphone_call_get_local_ip(call, call->dir == LinphoneCallOutgoing ? call->log->to : call->log->from); - strncpy(md->addr,call->media_localip,sizeof(md->addr)); - if (linphone_address_get_username(addr)) /*might be null in case of identity without userinfo*/ - strncpy(md->username,linphone_address_get_username(addr),sizeof(md->username)); - if (subject) strncpy(md->name,subject,sizeof(md->name)); - - if (params->down_bw) - md->bandwidth=params->down_bw; - else md->bandwidth=linphone_core_get_download_bandwidth(lc); - - if (params->custom_sdp_attributes) - md->custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_attributes); - - /*set audio capabilities */ - - codec_hints.bandwidth_limit=params->audio_bw; - codec_hints.max_codecs=-1; - codec_hints.previously_used=old_md ? old_md->streams[call->main_audio_stream_index].already_assigned_payloads : NULL; - l=make_codec_list(lc, &codec_hints, SalAudio, lc->codecs_conf.audio_codecs); - - if (params->has_audio && l != NULL) { - strncpy(md->streams[call->main_audio_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_audio_stream_index),sizeof(md->streams[call->main_audio_stream_index].rtp_addr)); - strncpy(md->streams[call->main_audio_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_audio_stream_index),sizeof(md->streams[call->main_audio_stream_index].rtcp_addr)); - strncpy(md->streams[call->main_audio_stream_index].name,"Audio",sizeof(md->streams[call->main_audio_stream_index].name)-1); - md->streams[call->main_audio_stream_index].rtp_port=call->media_ports[call->main_audio_stream_index].rtp_port; - md->streams[call->main_audio_stream_index].rtcp_port=call->media_ports[call->main_audio_stream_index].rtcp_port; - md->streams[call->main_audio_stream_index].proto=get_proto_from_call_params(params); - md->streams[call->main_audio_stream_index].dir=get_audio_dir_from_call_params(params); - md->streams[call->main_audio_stream_index].type=SalAudio; - md->streams[call->main_audio_stream_index].rtcp_mux = rtcp_mux; - if (params->down_ptime) - md->streams[call->main_audio_stream_index].ptime=params->down_ptime; - else - md->streams[call->main_audio_stream_index].ptime=linphone_core_get_download_ptime(lc); - md->streams[call->main_audio_stream_index].max_rate=get_max_codec_sample_rate(l); - md->streams[call->main_audio_stream_index].payloads=l; - if (call->audiostream && call->audiostream->ms.sessions.rtp_session) { - char* me = linphone_address_as_string_uri_only(call->me); - md->streams[call->main_audio_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->audiostream->ms.sessions.rtp_session); - strncpy(md->streams[call->main_audio_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_audio_stream_index].rtcp_cname)); - ms_free(me); - } - else - ms_warning("Cannot get audio local ssrc for call [%p]",call); - if (call->main_audio_stream_index > max_index) - max_index = call->main_audio_stream_index; - } else { - ms_message("Don't put audio stream on local offer for call [%p]",call); - md->streams[call->main_audio_stream_index].dir = SalStreamInactive; - if(l) l=bctbx_list_free_with_data(l, (void (*)(void *))payload_type_destroy); - } - if (params->custom_sdp_media_attributes[LinphoneStreamTypeAudio]) - md->streams[call->main_audio_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeAudio]); - - md->streams[call->main_video_stream_index].proto=md->streams[call->main_audio_stream_index].proto; - md->streams[call->main_video_stream_index].dir=get_video_dir_from_call_params(params); - md->streams[call->main_video_stream_index].type=SalVideo; - md->streams[call->main_video_stream_index].rtcp_mux = rtcp_mux; - strncpy(md->streams[call->main_video_stream_index].name,"Video",sizeof(md->streams[call->main_video_stream_index].name)-1); - - codec_hints.bandwidth_limit=0; - codec_hints.max_codecs=-1; - codec_hints.previously_used=old_md ? old_md->streams[call->main_video_stream_index].already_assigned_payloads : NULL; - l=make_codec_list(lc, &codec_hints, SalVideo, lc->codecs_conf.video_codecs); - - if (params->has_video && l != NULL){ - strncpy(md->streams[call->main_video_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_video_stream_index),sizeof(md->streams[call->main_video_stream_index].rtp_addr)); - strncpy(md->streams[call->main_video_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_video_stream_index),sizeof(md->streams[call->main_video_stream_index].rtcp_addr)); - md->streams[call->main_video_stream_index].rtp_port=call->media_ports[call->main_video_stream_index].rtp_port; - md->streams[call->main_video_stream_index].rtcp_port=call->media_ports[call->main_video_stream_index].rtcp_port; - md->streams[call->main_video_stream_index].payloads=l; - if (call->videostream && call->videostream->ms.sessions.rtp_session) { - char* me = linphone_address_as_string_uri_only(call->me); - md->streams[call->main_video_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->videostream->ms.sessions.rtp_session); - strncpy(md->streams[call->main_video_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_video_stream_index].rtcp_cname)); - ms_free(me); - } - else - ms_warning("Cannot get video local ssrc for call [%p]",call); - if (call->main_video_stream_index > max_index) - max_index = call->main_video_stream_index; - } else { - ms_message("Don't put video stream on local offer for call [%p]",call); - md->streams[call->main_video_stream_index].dir = SalStreamInactive; - if(l) l=bctbx_list_free_with_data(l, (void (*)(void *))payload_type_destroy); - } - if (params->custom_sdp_media_attributes[LinphoneStreamTypeVideo]) - md->streams[call->main_video_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeVideo]); - - md->streams[call->main_text_stream_index].proto=md->streams[call->main_audio_stream_index].proto; - md->streams[call->main_text_stream_index].dir=SalStreamSendRecv; - md->streams[call->main_text_stream_index].type=SalText; - md->streams[call->main_text_stream_index].rtcp_mux = rtcp_mux; - strncpy(md->streams[call->main_text_stream_index].name,"Text",sizeof(md->streams[call->main_text_stream_index].name)-1); - if (params->realtimetext_enabled) { - strncpy(md->streams[call->main_text_stream_index].rtp_addr,linphone_call_get_public_ip_for_stream(call,call->main_text_stream_index),sizeof(md->streams[call->main_text_stream_index].rtp_addr)); - strncpy(md->streams[call->main_text_stream_index].rtcp_addr,linphone_call_get_public_ip_for_stream(call,call->main_text_stream_index),sizeof(md->streams[call->main_text_stream_index].rtcp_addr)); - - md->streams[call->main_text_stream_index].rtp_port=call->media_ports[call->main_text_stream_index].rtp_port; - md->streams[call->main_text_stream_index].rtcp_port=call->media_ports[call->main_text_stream_index].rtcp_port; - - codec_hints.bandwidth_limit=0; - codec_hints.max_codecs=-1; - codec_hints.previously_used=old_md ? old_md->streams[call->main_text_stream_index].already_assigned_payloads : NULL; - l=make_codec_list(lc, &codec_hints, SalText, lc->codecs_conf.text_codecs); - md->streams[call->main_text_stream_index].payloads=l; - if (call->textstream && call->textstream->ms.sessions.rtp_session) { - char* me = linphone_address_as_string_uri_only(call->me); - md->streams[call->main_text_stream_index].rtp_ssrc=rtp_session_get_send_ssrc(call->textstream->ms.sessions.rtp_session); - strncpy(md->streams[call->main_text_stream_index].rtcp_cname,me,sizeof(md->streams[call->main_text_stream_index].rtcp_cname)); - ms_free(me); - } - else - ms_warning("Cannot get text local ssrc for call [%p]",call); - if (call->main_text_stream_index > max_index) - max_index = call->main_text_stream_index; - } else { - ms_message("Don't put text stream on local offer for call [%p]",call); - md->streams[call->main_text_stream_index].dir = SalStreamInactive; - } - if (params->custom_sdp_media_attributes[LinphoneStreamTypeText]) - md->streams[call->main_text_stream_index].custom_sdp_attributes = sal_custom_sdp_attribute_clone(params->custom_sdp_media_attributes[LinphoneStreamTypeText]); - - md->nb_streams = MAX(md->nb_streams,max_index+1); - - /* Deactivate unused streams. */ - for (i = md->nb_streams; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (md->streams[i].rtp_port == 0) { - md->streams[i].dir = SalStreamInactive; - if (call->biggestdesc && i < call->biggestdesc->nb_streams) { - md->streams[i].proto = call->biggestdesc->streams[i].proto; - md->streams[i].type = call->biggestdesc->streams[i].type; - } - } - } - setup_encryption_keys(call,md); - setup_dtls_keys(call,md); - setup_zrtp_hash(call, md); - - setup_rtcp_fb(call, md); - setup_rtcp_xr(call, md); - - update_media_description_from_stun(md, &call->ac, &call->vc, &call->tc); - call->localdesc=md; - linphone_call_update_local_media_description_from_ice_or_upnp(call); - linphone_address_unref(addr); - if (old_md){ - transfer_already_assigned_payload_types(old_md,md); - call->localdesc_changed=sal_media_description_equals(md,old_md); - sal_media_description_unref(old_md); - if (call->params->internal_call_update){ - /* - * An internal call update (ICE reINVITE) is not expected to modify the actual media stream parameters. - * However, the localdesc may change between first INVITE and ICE reINVITE, for example if the remote party has declined a video stream. - * We use the internal_call_update flag to prevent trigger an unnecessary media restart. - */ - call->localdesc_changed = 0; - } - } - force_streams_dir_according_to_state(call, md); -} - -static int find_port_offset(LinphoneCore *lc, int stream_index, int base_port){ - int offset; - bctbx_list_t *elem; - int tried_port; - int existing_port; - bool_t already_used=FALSE; - - for(offset=0;offset<100;offset+=2){ - tried_port=base_port+offset; - already_used=FALSE; - for(elem=lc->calls;elem!=NULL;elem=elem->next){ - LinphoneCall *call=(LinphoneCall*)elem->data; - existing_port=call->media_ports[stream_index].rtp_port; - if (existing_port==tried_port) { - already_used=TRUE; - break; - } - } - if (!already_used) break; - } - if (offset==100){ - ms_error("Could not find any free port !"); - return -1; - } - return offset; -} - -static int select_random_port(LinphoneCore *lc, int stream_index, int min_port, int max_port) { - bctbx_list_t *elem; - int nb_tries; - int tried_port = 0; - int existing_port = 0; - bool_t already_used = FALSE; - - tried_port = (ortp_random() % (max_port - min_port) + min_port) & ~0x1; - if (tried_port < min_port) tried_port = min_port + 2; - for (nb_tries = 0; nb_tries < 100; nb_tries++) { - for (elem = lc->calls; elem != NULL; elem = elem->next) { - LinphoneCall *call = (LinphoneCall *)elem->data; - existing_port=call->media_ports[stream_index].rtp_port; - if (existing_port == tried_port) { - already_used = TRUE; - break; - } - } - if (!already_used) break; - } - if (nb_tries == 100) { - ms_error("Could not find any free port!"); - return -1; - } - return tried_port; -} - -static void port_config_set_random(LinphoneCall *call, int stream_index){ - call->media_ports[stream_index].rtp_port=-1; - call->media_ports[stream_index].rtcp_port=-1; -} - -static void port_config_set(LinphoneCall *call, int stream_index, int min_port, int max_port){ - int port_offset; - if (min_port>0 && max_port>0){ - if (min_port == max_port) { - /* Used fixed RTP audio port. */ - port_offset=find_port_offset(call->core, stream_index, min_port); - if (port_offset==-1) { - port_config_set_random(call, stream_index); - return; - } - call->media_ports[stream_index].rtp_port=min_port+port_offset; - } else { - /* Select random RTP audio port in the specified range. */ - call->media_ports[stream_index].rtp_port = select_random_port(call->core, stream_index, min_port, max_port); - } - call->media_ports[stream_index].rtcp_port=call->media_ports[stream_index].rtp_port+1; - }else port_config_set_random(call,stream_index); -} - -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->ei = linphone_error_info_new(); - call->core->send_call_stats_periodical_updates = lp_config_get_int(call->core->config, "misc", "send_call_stats_periodical_updates", 0); - call->main_audio_stream_index = LINPHONE_CALL_STATS_AUDIO; - call->main_video_stream_index = LINPHONE_CALL_STATS_VIDEO; - call->main_text_stream_index = LINPHONE_CALL_STATS_TEXT; - call->state=LinphoneCallIdle; - call->transfer_state = LinphoneCallIdle; - call->log=linphone_call_log_new(call->dir, from, to); - call->camera_enabled=TRUE; - call->current_params = linphone_call_params_new(); - call->current_params->media_encryption=LinphoneMediaEncryptionNone; - call->dtls_certificate_fingerprint = NULL; - if (call->dir == LinphoneCallIncoming) - call->me=to; - else - call->me=from; - linphone_address_ref(call->me); - - linphone_core_get_audio_port_range(call->core, &min_port, &max_port); - port_config_set(call,call->main_audio_stream_index,min_port,max_port); - - linphone_core_get_video_port_range(call->core, &min_port, &max_port); - port_config_set(call,call->main_video_stream_index,min_port,max_port); - - linphone_core_get_text_port_range(call->core, &min_port, &max_port); - port_config_set(call,call->main_text_stream_index,min_port,max_port); - - linphone_call_init_stats(call->audio_stats, LinphoneStreamTypeAudio); - linphone_call_init_stats(call->video_stats, LinphoneStreamTypeVideo); - linphone_call_init_stats(call->text_stats, LinphoneStreamTypeText); - - if (call->dest_proxy == NULL) { - /* Try to define the destination proxy if it has not already been done to have a correct contact field in the SIP messages */ - call->dest_proxy = linphone_core_lookup_known_proxy(call->core, call->log->to); - } - - - if (call->dest_proxy != NULL) - call->nat_policy = linphone_proxy_config_get_nat_policy(call->dest_proxy); - if (call->nat_policy == NULL) - call->nat_policy = linphone_core_get_nat_policy(call->core); - - linphone_nat_policy_ref(call->nat_policy); - -} - -void linphone_call_init_stats(LinphoneCallStats *stats, LinphoneStreamType type) { - stats->type = type; - stats->received_rtcp = NULL; - stats->sent_rtcp = NULL; - stats->ice_state = LinphoneIceStateNotActivated; -#ifdef BUILD_UPNP - stats->upnp_state = LinphoneUpnpStateIdle; -#else - stats->upnp_state = LinphoneUpnpStateNotAvailable; -#endif //BUILD_UPNP -} - -static void discover_mtu(LinphoneCore *lc, const char *remote){ - int mtu; - if (lc->net_conf.mtu==0 ){ - /*attempt to discover mtu*/ - mtu=ms_discover_mtu(remote); - if (mtu>0){ - ms_factory_set_mtu(lc->factory, mtu); - ms_message("Discovered mtu is %i, RTP payload max size is %i", - mtu, ms_factory_get_payload_max_size(lc->factory)); - } - } -} - -void linphone_call_create_op_to(LinphoneCall *call, LinphoneAddress *to){ - 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,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 */ -} - -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); - /*else privacy might be set by proxy */ -} - -/* - * Choose IP version we are going to use for RTP streams IP address advertised in SDP. - * The algorithm is as follows: - * - if ipv6 is disabled at the core level, it is always AF_INET - * - Otherwise, if the call is done through a known proxy config, then use the information obtained during REGISTER - * - Otherwise if the destination address for the call is an IPv6 address, use IPv6. - * to know if IPv6 is supported by the server. -**/ -static void linphone_call_outgoing_select_ip_version(LinphoneCall *call, LinphoneAddress *to, LinphoneProxyConfig *cfg){ - char ipv4[LINPHONE_IPADDR_SIZE]; - char ipv6[LINPHONE_IPADDR_SIZE]; - bool_t have_ipv6 = FALSE; - bool_t have_ipv4 = FALSE; - - call->af = AF_UNSPEC; - if (linphone_core_get_local_ip_for(AF_INET, NULL, ipv4) == 0){ - have_ipv4 = TRUE; - } - if (linphone_core_ipv6_enabled(call->core)){ - if (linphone_core_get_local_ip_for(AF_INET6, NULL, ipv6) == 0){ - have_ipv6 = TRUE; - } - if (cfg && cfg->op){ - /*we can determine from the proxy connection whether IPv6 works - this is the most reliable*/ - call->af = sal_op_get_address_family(cfg->op); - }else if (sal_address_is_ipv6((SalAddress*)to)){ - call->af = AF_INET6; - } - - if (lp_config_get_int(call->core->config, "rtp", "prefer_ipv6", 1) == 0 && have_ipv4){ - /* This is the case where ipv4 is to be prefered if both are available.*/ - call->af = AF_INET; /*we'll use IPv4*/ - ms_message("prefer_ipv6 is set to false, as both IP versions are available we are going to use IPv4"); - } - if (call->af == AF_UNSPEC){ - call->af = have_ipv6 ? AF_INET6 : AF_INET; - } - }else call->af=AF_INET; - /*fill the media_localip default value since we have it here*/ - strncpy(call->media_localip,call->af == AF_INET6 ? ipv6 : ipv4, LINPHONE_IPADDR_SIZE); -} - -/** - * 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 = NULL; - int af = call->af; - const char *dest = NULL; - - if (linphone_core_get_firewall_policy(call->core)==LinphonePolicyUseNatAddress - && (ip=linphone_core_get_nat_address_resolved(call->core))!=NULL){ - strncpy(call->media_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->media_localip,ip,LINPHONE_IPADDR_SIZE); - goto found; - } -#endif //BUILD_UPNP - - /*next, sometime, override from config*/ - if ((ip=lp_config_get_string(call->core->config,"rtp","bind_address",NULL)) != NULL) - goto found; - - /*if a known proxy was identified for this call, then we may have a chance to take the local ip address - * from the socket that connect to this proxy */ - if (call->dest_proxy && call->dest_proxy->op){ - if ((ip = sal_op_get_local_address(call->dest_proxy->op, NULL)) != NULL){ - if (strchr(ip, ':') != NULL && af == AF_INET){ - /*case where we've decided to use IPv4 in select_outgoing_ip_version(), but the signaling local ip address is IPv6*/ - /*we'll use the default media localip*/ - }else{ - ms_message("Found media local-ip from signaling."); - goto found; - } - } - } - - /*in last resort, attempt to find the local ip that routes to destination if given as an IP address, - or the default route (dest=NULL)*/ - if (call->dest_proxy == NULL) { - struct addrinfo hints; - struct addrinfo *res = NULL; - int err; - /*FIXME the following doesn't work for IPv6 address because of brakets*/ - 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 (dest != NULL || call->media_localip[0] == '\0' || call->need_localip_refresh){ - call->need_localip_refresh = FALSE; - linphone_core_get_local_ip(call->core, af, dest, call->media_localip); - } - return; -found: - strncpy(call->media_localip,ip,LINPHONE_IPADDR_SIZE); -} - -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 -); - -void linphone_call_fill_media_multicast_addr(LinphoneCall *call) { - if (linphone_call_params_audio_multicast_enabled(call->params)){ - strncpy(call->media_ports[call->main_audio_stream_index].multicast_ip, - linphone_core_get_audio_multicast_addr(call->core), sizeof(call->media_ports[call->main_audio_stream_index].multicast_ip)); - } else - call->media_ports[call->main_audio_stream_index].multicast_ip[0]='\0'; - - if (linphone_call_params_video_multicast_enabled(call->params)){ - strncpy(call->media_ports[call->main_video_stream_index].multicast_ip, - linphone_core_get_video_multicast_addr(call->core), sizeof(call->media_ports[call->main_video_stream_index].multicast_ip)); - } else - call->media_ports[call->main_video_stream_index].multicast_ip[0]='\0'; -} - -void linphone_call_check_ice_session(LinphoneCall *call, IceRole role, bool_t is_reinvite){ - if (call->ice_session) return; /*already created*/ - - if (!linphone_nat_policy_ice_enabled(call->nat_policy)){ - return; - } - - if (is_reinvite && lp_config_get_int(call->core->config, "net", "allow_late_ice", 0) == 0) return; - - call->ice_session = ice_session_new(); - /*for backward compatibility purposes, shall be enabled by default in futur*/ - ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(call->core->config,"net","ice_session_enable_message_integrity_check",1)); - if (lp_config_get_int(call->core->config, "net", "dont_default_to_stun_candidates", 0)){ - IceCandidateType types[ICT_CandidateTypeMax]; - types[0] = ICT_HostCandidate; - types[1] = ICT_RelayedCandidate; - types[2] = ICT_CandidateInvalid; - ice_session_set_default_candidates_types(call->ice_session, types); - } - ice_session_set_role(call->ice_session, role); -} - -LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg){ - LinphoneCall *call = belle_sip_object_new(LinphoneCall); - call->dir=LinphoneCallOutgoing; - call->core=lc; - call->dest_proxy=cfg; - call->audio_stats = linphone_call_stats_ref(linphone_call_stats_new()); - call->video_stats = linphone_call_stats_ref(linphone_call_stats_new()); - call->text_stats = linphone_call_stats_ref(linphone_call_stats_new()); - linphone_call_outgoing_select_ip_version(call,to,cfg); - linphone_call_get_local_ip(call, to); - call->params = linphone_call_params_copy(params); - linphone_call_init_common(call, from, to); - - /*reserve the sockets immediately*/ - linphone_call_init_media_streams(call); - - call->current_params->update_call_when_ice_completed = call->params->update_call_when_ice_completed; /*copy param*/ - - linphone_call_fill_media_multicast_addr(call); - - linphone_call_check_ice_session(call, IR_Controlling, FALSE); - - if (linphone_nat_policy_stun_enabled(call->nat_policy) && !(linphone_nat_policy_ice_enabled(call->nat_policy) - || linphone_nat_policy_turn_enabled(call->nat_policy))) { - call->ping_time=linphone_core_run_stun_tests(call->core,call); - } -#ifdef BUILD_UPNP - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseUpnp) { - if(!lc->rtp_conf.disable_upnp) { - call->upnp_session = linphone_upnp_session_new(call); - } - } -#endif //BUILD_UPNP - - discover_mtu(lc,linphone_address_get_domain (to)); - if (params->referer){ - call->referer=linphone_call_ref(params->referer); - } - - linphone_call_create_op_to(call, to); - return call; -} - -/*Select IP version to use for advertising local addresses of RTP streams, for an incoming call. - *If the call is received through a know proxy that is IPv6, use IPv6. - *Otherwise check the remote contact address. - *If later the resulting media description tells that we have to send IPv4, it won't be a problem because the RTP sockets - * are dual stack. - */ -static void linphone_call_incoming_select_ip_version(LinphoneCall *call, LinphoneProxyConfig *cfg){ - if (linphone_core_ipv6_enabled(call->core)){ - if (cfg && cfg->op){ - call->af=sal_op_get_address_family(cfg->op); - }else{ - call->af=sal_op_get_address_family(call->op); - } - }else call->af=AF_INET; -} - -/** - * 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, SalMediaDescription *md) { - /* Handle AVPF, SRTP and DTLS. */ - call->params->avpf_enabled = sal_media_description_has_avpf(md); - if (call->dest_proxy != NULL) { - call->params->avpf_rr_interval = linphone_proxy_config_get_avpf_rr_interval(call->dest_proxy) * 1000; - } else { - call->params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(call->core)*1000; - } - - if ((sal_media_description_has_zrtp(md) == TRUE) && (linphone_core_media_encryption_supported(call->core, LinphoneMediaEncryptionZRTP) == TRUE)) { - call->params->media_encryption = LinphoneMediaEncryptionZRTP; - }else if ((sal_media_description_has_dtls(md) == TRUE) && (media_stream_dtls_supported() == TRUE)) { - call->params->media_encryption = LinphoneMediaEncryptionDTLS; - }else if ((sal_media_description_has_srtp(md) == TRUE) && (ms_srtp_supported() == TRUE)) { - call->params->media_encryption = LinphoneMediaEncryptionSRTP; - }else if (call->params->media_encryption != LinphoneMediaEncryptionZRTP){ - call->params->media_encryption = LinphoneMediaEncryptionNone; - } - - /*in case of nat64, even ipv4 addresses are reachable from v6. Should be enhanced to manage stream by stream connectivity (I.E v6 or v4)*/ - /*if (!sal_media_description_has_ipv6(md)){ - ms_message("The remote SDP doesn't seem to offer any IPv6 connectivity, so disabling IPv6 for this call."); - call->af = AF_INET; - }*/ - linphone_call_fix_call_parameters(call, md); -} - -static void linphone_call_compute_streams_indexes(LinphoneCall *call, const SalMediaDescription *md) { - int i, j; - bool_t audio_found = FALSE, video_found = FALSE, text_found = FALSE; - - for (i = 0; i < md->nb_streams; i++) { - if (md->streams[i].type == SalAudio) { - if (!audio_found) { - call->main_audio_stream_index = i; - audio_found = TRUE; - ms_message("audio stream index found: %i, updating main audio stream index", i); - } else { - ms_message("audio stream index found: %i, but main audio stream already set to %i", i, call->main_audio_stream_index); - } - - // Check that the default value of a another stream doesn't match the new one - if (i == call->main_video_stream_index) { - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { - if (sal_stream_description_active(&md->streams[j])) continue; - if (j != call->main_video_stream_index && j != call->main_text_stream_index) { - ms_message("%i was used for video stream ; now using %i", i, j); - call->main_video_stream_index = j; - break; - } - } - } - if (i == call->main_text_stream_index) { - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { - if (sal_stream_description_active(&md->streams[j])) continue; - if (j != call->main_video_stream_index && j != call->main_text_stream_index) { - ms_message("%i was used for text stream ; now using %i", i, j); - call->main_text_stream_index = j; - break; - } - } - } - } else if (md->streams[i].type == SalVideo) { - if (!video_found) { - call->main_video_stream_index = i; - video_found = TRUE; - ms_message("video stream index found: %i, updating main video stream index", i); - } else { - ms_message("video stream index found: %i, but main video stream already set to %i", i, call->main_video_stream_index); - } - - // Check that the default value of a another stream doesn't match the new one - if (i == call->main_audio_stream_index) { - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { - if (sal_stream_description_active(&md->streams[j])) continue; - if (j != call->main_audio_stream_index && j != call->main_text_stream_index) { - ms_message("%i was used for audio stream ; now using %i", i, j); - call->main_audio_stream_index = j; - break; - } - } - } - if (i == call->main_text_stream_index) { - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { - if (sal_stream_description_active(&md->streams[j])) continue; - if (j != call->main_audio_stream_index && j != call->main_text_stream_index) { - ms_message("%i was used for text stream ; now using %i", i, j); - call->main_text_stream_index = j; - break; - } - } - } - } else if (md->streams[i].type == SalText) { - if (!text_found) { - call->main_text_stream_index = i; - text_found = TRUE; - ms_message("text stream index found: %i, updating main text stream index", i); - } else { - ms_message("text stream index found: %i, but main text stream already set to %i", i, call->main_text_stream_index); - } - - // Check that the default value of a another stream doesn't match the new one - if (i == call->main_audio_stream_index) { - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { - if (sal_stream_description_active(&md->streams[j])) continue; - if (j != call->main_video_stream_index && j != call->main_audio_stream_index) { - ms_message("%i was used for audio stream ; now using %i", i, j); - call->main_audio_stream_index = j; - break; - } - } - } - if (i == call->main_video_stream_index) { - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { - if (sal_stream_description_active(&md->streams[j])) continue; - if (j != call->main_video_stream_index && j != call->main_audio_stream_index) { - ms_message("%i was used for video stream ; now using %i", i, j); - call->main_video_stream_index = j; - break; - } - } - } - } - } -} - -LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op){ - LinphoneCall *call = belle_sip_object_new(LinphoneCall); - SalMediaDescription *md; - LinphoneNatPolicy *nat_policy = NULL; - int i; - call->dir=LinphoneCallIncoming; - call->audio_stats = linphone_call_stats_ref(linphone_call_stats_new()); - call->video_stats = linphone_call_stats_ref(linphone_call_stats_new()); - call->text_stats = linphone_call_stats_ref(linphone_call_stats_new()); - sal_op_set_user_pointer(op,call); - call->op=op; - call->core=lc; - - call->dest_proxy = linphone_core_lookup_known_proxy(call->core, to); - linphone_call_incoming_select_ip_version(call, call->dest_proxy); - /*note that the choice of IP version for streams is later refined by - * linphone_call_set_compatible_incoming_call_parameters() when examining the remote offer, if any. - * If the remote offer contains IPv4 addresses, we should propose IPv4 as well*/ - - sal_op_cnx_ip_to_0000_if_sendonly_enable(op,lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0)); - - md = sal_call_get_remote_media_description(op); - - if (lc->sip_conf.ping_with_options){ -#ifdef BUILD_UPNP - if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp && - linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) { -#else //BUILD_UPNP - { -#endif //BUILD_UPNP - /*the following sends an option request back to the caller so that - we get a chance to discover our nat'd address before answering.*/ - call->ping_op=sal_op_new(lc->sal); - - 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,sal_op_get_from(call->ping_op), sal_op_get_to(call->ping_op)); - } - } - - linphone_address_clean(from); - linphone_call_get_local_ip(call, from); - call->params = linphone_call_params_new(); - linphone_call_init_common(call, from, to); - call->log->call_id=ms_strdup(sal_op_get_call_id(op)); /*must be known at that time*/ - linphone_core_init_default_params(lc, call->params); - - /* - * 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); - /*config params*/ - call->current_params->update_call_when_ice_completed = call->params->update_call_when_ice_completed; /*copy config params*/ - - /*set video support */ - call->params->has_video = linphone_core_video_enabled(lc) && lc->video_policy.automatically_accept; - if (md) { - // It is licit to receive an INVITE without SDP - // In this case WE chose the media parameters according to policy. - linphone_call_set_compatible_incoming_call_parameters(call, md); - /* set multicast role & address if any*/ - if (!sal_call_is_offerer(op)){ - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - if (md->streams[i].dir == SalStreamInactive) { - continue; - } - - if (md->streams[i].rtp_addr[0]!='\0' && ms_is_multicast(md->streams[i].rtp_addr)){ - md->streams[i].multicast_role = SalMulticastReceiver; - strncpy(call->media_ports[i].multicast_ip,md->streams[i].rtp_addr,sizeof(call->media_ports[i].multicast_ip)); - } - } - } - } - - nat_policy=call->nat_policy; - if ((nat_policy != NULL) && linphone_nat_policy_ice_enabled(nat_policy)) { - /* Create the ice session now if ICE is required */ - if (md){ - linphone_call_check_ice_session(call, IR_Controlled, FALSE); - }else{ - nat_policy = NULL; - ms_warning("ICE not supported for incoming INVITE without SDP."); - } - } - - /*reserve the sockets immediately*/ - linphone_call_init_media_streams(call); - if (nat_policy != NULL) { - if (linphone_nat_policy_ice_enabled(nat_policy)) { - call->defer_notify_incoming = linphone_call_prepare_ice(call,TRUE) == 1; - } else if (linphone_nat_policy_stun_enabled(nat_policy)) { - call->ping_time=linphone_core_run_stun_tests(call->core,call); - } else if (linphone_nat_policy_upnp_enabled(nat_policy)) { -#ifdef BUILD_UPNP - if(!lc->rtp_conf.disable_upnp) { - call->upnp_session = linphone_upnp_session_new(call); - if (call->upnp_session != NULL) { - if (linphone_call_update_upnp_from_remote_media_description(call, sal_call_get_remote_media_description(op))<0) { - /* uPnP port mappings failed, proceed with the call anyway. */ - linphone_call_delete_upnp_session(call); - } - } - } -#endif //BUILD_UPNP - } - } - - discover_mtu(lc,linphone_address_get_domain(from)); - return call; -} - -/* - * Frees the media resources of the call. - * This has to be done at the earliest, unlike signaling resources that sometimes need to be kept a bit more longer. - * It is called by linphone_call_set_terminated() (for termination of calls signaled to the application), or directly by the destructor of LinphoneCall - * (_linphone_call_destroy) if the call was never notified to the application. - */ -static void linphone_call_free_media_resources(LinphoneCall *call){ - int i; - - linphone_call_stop_media_streams(call); - linphone_call_delete_upnp_session(call); - linphone_call_delete_ice_session(call); - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){ - ms_media_stream_sessions_uninit(&call->sessions[i]); - } - linphone_call_stats_uninit(call->audio_stats); - linphone_call_stats_uninit(call->video_stats); - linphone_call_stats_uninit(call->text_stats); -} - -/* - * Called internally when reaching the Released state, to perform cleanups to break circular references. -**/ -static void linphone_call_set_released(LinphoneCall *call){ - if (call->op!=NULL) { - /*transfer the last error so that it can be obtained even in Released state*/ - if (!call->non_op_error){ - linphone_error_info_from_sal_op(call->ei, call->op); - } - /* so that we cannot have anymore upcalls for SAL - concerning this call*/ - sal_op_release(call->op); - call->op=NULL; - } - /*it is necessary to reset pointers to other call to prevent circular references that would result in memory never freed.*/ - if (call->referer){ - linphone_call_unref(call->referer); - call->referer=NULL; - } - if (call->transfer_target){ - linphone_call_unref(call->transfer_target); - call->transfer_target=NULL; - } - if (call->chat_room){ - linphone_chat_room_unref(call->chat_room); - call->chat_room = NULL; - } - linphone_call_unref(call); -} - -/* this function is called internally to get rid of a call that was notified to the application, because it reached the end or error state. - It performs the following tasks: - - remove the call from the internal list of calls - - update the call logs accordingly -*/ -static void linphone_call_set_terminated(LinphoneCall *call){ - LinphoneCore *lc=call->core; - - linphone_call_free_media_resources(call); - linphone_call_log_completed(call); - - if (call == lc->current_call){ - ms_message("Resetting the current call"); - lc->current_call=NULL; - } - - if (linphone_core_del_call(lc,call) != 0){ - ms_error("Could not remove the call from the list !!!"); - } - if(lc->conf_ctx) linphone_conference_on_call_terminating(lc->conf_ctx, call); - if (call->ringing_beep){ - linphone_core_stop_dtmf(lc); - call->ringing_beep=FALSE; - } - if (call->chat_room){ - call->chat_room->call = NULL; - } - if (lc->calls == NULL){ - ms_bandwidth_controller_reset_state(lc->bw_controller); - } -} - -/*function to be called at each incoming reINVITE, in order to adjust various local parameters to what is being offered by remote: - * - the video enablement parameter according to what is offered and our local policy. - * Fixing the call->params to proper values avoid request video by accident during internal call updates, pauses and resumes - * - the stream indexes. - */ -void linphone_call_fix_call_parameters(LinphoneCall *call, SalMediaDescription *rmd){ - const LinphoneCallParams* rcp; - - if (rmd) { - linphone_call_compute_streams_indexes(call, rmd); - linphone_call_update_biggest_desc(call, rmd); - /* Why disabling implicit_rtcp_fb ? It is a local policy choice actually. It doesn't disturb to propose it again and again - * even if the other end apparently doesn't support it. - * The following line of code is causing trouble, while for example making an audio call, then adding video. - * Due to the 200Ok response of the audio-only offer where no rtcp-fb attribute is present, implicit_rtcp_fb is set to - * FALSE, which is then preventing it to be eventually used when video is later added to the call. - * I did the choice of commenting it out. - */ - /*call->params->implicit_rtcp_fb &= sal_media_description_has_implicit_avpf(rmd);*/ - } - rcp = linphone_call_get_remote_params(call); - if (rcp){ - if (call->params->has_audio && !rcp->has_audio){ - ms_message("Call [%p]: disabling audio in our call params because the remote doesn't want it.", call); - call->params->has_audio = FALSE; - } - if (call->params->has_video && !rcp->has_video){ - ms_message("Call [%p]: disabling video in our call params because the remote doesn't want it.", call); - call->params->has_video = FALSE; - } - - if (rcp->has_video && call->core->video_policy.automatically_accept && linphone_core_video_enabled(call->core) && !call->params->has_video){ - ms_message("Call [%p]: re-enabling video in our call params because the remote wants it and the policy allows to automatically accept.", call); - linphone_call_params_enable_video(call->params, TRUE); - } - - if (rcp->realtimetext_enabled && !call->params->realtimetext_enabled) { - call->params->realtimetext_enabled = TRUE; - } - } -} const char *linphone_call_state_to_string(LinphoneCallState cs){ switch (cs){ @@ -1846,585 +74,6 @@ const char *linphone_call_state_to_string(LinphoneCallState cs){ return "undefined state"; } -void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message){ - LinphoneCore *lc=call->core; - - if (call->state!=cstate){ - call->prevstate=call->state; - - /*Make sanity checks with call state changes. Any bad transition can result in unpredictable results - *or irrecoverable errors in the application*/ - if (call->state==LinphoneCallEnd || call->state==LinphoneCallError){ - if (cstate!=LinphoneCallReleased){ - ms_fatal("Abnormal call resurection from %s to %s, aborting." ,linphone_call_state_to_string(call->state) - ,linphone_call_state_to_string(cstate)); - return; - } - }else if (cstate == LinphoneCallReleased && (call->prevstate != LinphoneCallError && call->prevstate != LinphoneCallEnd)){ - ms_fatal("Attempt to move call [%p] to Released state while it was not previously in Error or End state. Aborting.", call); - return; - } - ms_message("Call %p: moving from state %s to %s",call - ,linphone_call_state_to_string(call->state) - ,linphone_call_state_to_string(cstate)); - - if (cstate!=LinphoneCallRefered){ - /*LinphoneCallRefered is rather an event, not a state. - Indeed it does not change the state of the call (still paused or running)*/ - call->state=cstate; - } - - switch (cstate) { - case LinphoneCallOutgoingInit: - case LinphoneCallIncomingReceived: - getPlatformHelpers(lc)->acquireWifiLock(); - getPlatformHelpers(lc)->acquireMcastLock(); - getPlatformHelpers(lc)->acquireCpuLock(); - break; - case LinphoneCallEnd: - case LinphoneCallError: - switch(linphone_error_info_get_reason(linphone_call_get_error_info(call))) { - case LinphoneReasonDeclined: - if(call->log->status != LinphoneCallMissed) // Do not re-change the status of a call if it's already set - call->log->status = LinphoneCallDeclined; - break; - case LinphoneReasonNotAnswered: - if (call->log->dir == LinphoneCallIncoming) - call->log->status = LinphoneCallMissed; - break; - case LinphoneReasonNone: - if (call->log->dir == LinphoneCallIncoming){ - const LinphoneErrorInfo *ei = linphone_call_get_error_info(call); - if (ei) { - int code = linphone_error_info_get_protocol_code(ei); - if((code >= 200 && code < 300)) { - // error between 200-299 means accepted elsewhere - call->log->status=LinphoneCallAcceptedElsewhere; - break; - } - } - } - break; - case LinphoneReasonDoNotDisturb: - if (call->log->dir == LinphoneCallIncoming){ - const LinphoneErrorInfo *ei = linphone_call_get_error_info(call); - if (ei) { - int code = linphone_error_info_get_protocol_code(ei); - if(code >= 600 && code < 700) { - // error between 600-699 means declined elsewhere - call->log->status=LinphoneCallDeclinedElsewhere; - break; - } - } - } - break; - default: - break; - } - linphone_call_set_terminated(call); - break; - case LinphoneCallConnected: - call->log->status=LinphoneCallSuccess; - call->log->connected_date_time = ms_time(NULL); - break; - case LinphoneCallReleased: - getPlatformHelpers(lc)->releaseWifiLock(); - getPlatformHelpers(lc)->releaseMcastLock(); - getPlatformHelpers(lc)->releaseCpuLock(); - break; - case LinphoneCallStreamsRunning: - if (call->prevstate == LinphoneCallUpdating || call->prevstate == LinphoneCallUpdatedByRemote) { - LinphoneReason reason = linphone_call_get_reason(call); - char *msg; - if (reason != LinphoneReasonNone) { - msg = ms_strdup_printf(_("Call parameters could not be modified: %s."), linphone_reason_to_string(reason)); - } else { - msg = ms_strdup(_("Call parameters were successfully modified.")); - } - linphone_core_notify_display_status(lc, msg); - ms_free(msg); - } - break; - default: - break; - } - - if(cstate!=LinphoneCallStreamsRunning) { - if (call->dtmfs_timer!=NULL){ - /*cancelling DTMF sequence, if any*/ - linphone_call_cancel_dtmfs(call); - } - } - if (!message) { - ms_error("%s(): You must fill a reason when changing call state (from %s o %s)." - , __FUNCTION__ - , linphone_call_state_to_string(call->prevstate) - , linphone_call_state_to_string(call->state)); - } - linphone_call_notify_state_changed(call, cstate, message ? message : ""); - linphone_reporting_call_state_updated(call); - if (cstate==LinphoneCallReleased) {/*shall be performed after app notification*/ - linphone_call_set_released(call); - } - } -} - -static void linphone_call_destroy(LinphoneCall *obj){ - ms_message("Call [%p] freed.",obj); - bctbx_list_free_with_data(obj->callbacks, (bctbx_list_free_func)linphone_call_cbs_unref); - if (obj->audiostream || obj->videostream){ - linphone_call_free_media_resources(obj); - } - if (obj->audio_stats) { - linphone_call_stats_unref(obj->audio_stats); - obj->audio_stats = NULL; - } - if (obj->video_stats) { - linphone_call_stats_unref(obj->video_stats); - obj->video_stats = NULL; - } - if (obj->text_stats) { - linphone_call_stats_unref(obj->text_stats); - obj->text_stats = NULL; - } - if (obj->op!=NULL) { - sal_op_release(obj->op); - obj->op=NULL; - } - if (obj->biggestdesc!=NULL){ - sal_media_description_unref(obj->biggestdesc); - obj->biggestdesc=NULL; - } - if (obj->resultdesc!=NULL) { - sal_media_description_unref(obj->resultdesc); - obj->resultdesc=NULL; - } - if (obj->localdesc!=NULL) { - sal_media_description_unref(obj->localdesc); - obj->localdesc=NULL; - } - if (obj->ping_op) { - sal_op_release(obj->ping_op); - obj->ping_op=NULL; - } - if (obj->refer_to){ - ms_free(obj->refer_to); - obj->refer_to=NULL; - } - if (obj->referer){ - linphone_call_unref(obj->referer); - obj->referer=NULL; - } - if (obj->transfer_target){ - linphone_call_unref(obj->transfer_target); - obj->transfer_target=NULL; - } - if (obj->log) { - linphone_call_log_unref(obj->log); - obj->log=NULL; - } - if (obj->auth_token) { - ms_free(obj->auth_token); - obj->auth_token=NULL; - } - if (obj->dtls_certificate_fingerprint) { - ms_free(obj->dtls_certificate_fingerprint); - obj->dtls_certificate_fingerprint=NULL; - } - if (obj->dtmfs_timer) { - linphone_call_cancel_dtmfs(obj); - } - if (obj->params){ - linphone_call_params_unref(obj->params); - obj->params=NULL; - } - if (obj->current_params){ - linphone_call_params_unref(obj->current_params); - obj->current_params=NULL; - } - if (obj->remote_params != NULL) { - linphone_call_params_unref(obj->remote_params); - obj->remote_params=NULL; - } - if (obj->me) { - linphone_address_unref(obj->me); - obj->me = NULL; - } - if (obj->onhold_file) ms_free(obj->onhold_file); - - if (obj->ei) linphone_error_info_unref(obj->ei); - if (obj->nat_policy) - linphone_nat_policy_unref(obj->nat_policy); -} - -LinphoneCall * linphone_call_ref(LinphoneCall *obj){ - belle_sip_object_ref(obj); - return obj; -} - -void linphone_call_unref(LinphoneCall *obj){ - belle_sip_object_unref(obj); -} - -static unsigned int linphone_call_get_n_active_streams(const LinphoneCall *call) { - SalMediaDescription *md=NULL; - if (call->op) - md = sal_call_get_remote_media_description(call->op); - if (!md) - return 0; - return sal_media_description_nb_active_streams_of_type(md, SalAudio) + sal_media_description_nb_active_streams_of_type(md, SalVideo) + sal_media_description_nb_active_streams_of_type(md, SalText); -} - -const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call){ - SalMediaDescription *md=call->resultdesc; - int all_streams_encrypted = 0; -#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); -#ifdef VIDEO_ENABLED - if (call->current_params->sent_vdef != NULL) linphone_video_definition_unref(call->current_params->sent_vdef); - call->current_params->sent_vdef = NULL; - if (call->current_params->recv_vdef != NULL) linphone_video_definition_unref(call->current_params->recv_vdef); - call->current_params->recv_vdef = NULL; - 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_vdef = linphone_factory_create_video_definition( - linphone_factory_get(), call->current_params->sent_vsize.width, call->current_params->sent_vsize.height); - call->current_params->recv_vdef = linphone_factory_create_video_definition( - linphone_factory_get(), call->current_params->recv_vsize.width, call->current_params->recv_vsize.height); - call->current_params->sent_fps = video_stream_get_sent_framerate(vstream); - call->current_params->received_fps = video_stream_get_received_framerate(vstream); - } -#endif - - /* REVISITED - * Previous code was buggy. - * Relying on the mediastream's state (added by jehan: only) to know the current encryption is unreliable. - * For (added by jehan: both DTLS and) ZRTP it is though necessary. - * But for all others the current_params->media_encryption state should reflect (added by jehan: both) what is agreed by the offer/answer - * mechanism (added by jehan: and encryption status from media which is much stronger than only result of offer/answer ) - * Typically there can be inactive streams for which the media layer has no idea of whether they are encrypted or not. - */ - - switch (call->params->media_encryption) { - case LinphoneMediaEncryptionZRTP: - if (at_least_one_stream_started(call)){ - if ((all_streams_encrypted = linphone_call_all_streams_encrypted(call)) && linphone_call_get_authentication_token(call)) { - call->current_params->media_encryption=LinphoneMediaEncryptionZRTP; - } else { - /*to avoid to many traces*/ - ms_debug("Encryption was requested to be %s, but isn't effective (all_streams_encrypted=%i, auth_token=%s)", - linphone_media_encryption_to_string(call->params->media_encryption), all_streams_encrypted, call->auth_token == NULL ? "" : call->auth_token); - call->current_params->media_encryption=LinphoneMediaEncryptionNone; - } - }//else don't update the state if all streams are shutdown. - break; - case LinphoneMediaEncryptionDTLS: - case LinphoneMediaEncryptionSRTP: - if (at_least_one_stream_started(call)){ - if (linphone_call_get_n_active_streams(call)==0 || (all_streams_encrypted = linphone_call_all_streams_encrypted(call))) { - call->current_params->media_encryption = call->params->media_encryption; - } else { - /*to avoid to many traces*/ - ms_debug("Encryption was requested to be %s, but isn't effective (all_streams_encrypted=%i)", - linphone_media_encryption_to_string(call->params->media_encryption), all_streams_encrypted); - call->current_params->media_encryption=LinphoneMediaEncryptionNone; - } - }//else don't update the state if all streams are shutdown. - break; - case LinphoneMediaEncryptionNone: - /* check if we actually switched to ZRTP */ - if (at_least_one_stream_started(call) && (all_streams_encrypted = linphone_call_all_streams_encrypted(call)) && linphone_call_get_authentication_token(call)) { - call->current_params->media_encryption=LinphoneMediaEncryptionZRTP; - } else { - call->current_params->media_encryption=LinphoneMediaEncryptionNone; - } - break; - } - call->current_params->avpf_enabled = linphone_call_all_streams_avpf_enabled(call) && sal_media_description_has_avpf(md); - 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; - } - if (md){ - const char *rtp_addr; - - SalStreamDescription *sd=sal_media_description_find_best_stream(md,SalAudio); - - call->current_params->audio_dir=sd ? media_direction_from_sal_stream_dir(sd->dir) : LinphoneMediaDirectionInactive; - if (call->current_params->audio_dir != LinphoneMediaDirectionInactive) { - rtp_addr = sd->rtp_addr[0]!='\0' ? sd->rtp_addr : call->resultdesc->addr; - call->current_params->audio_multicast_enabled = ms_is_multicast(rtp_addr); - } else - call->current_params->audio_multicast_enabled = FALSE; - - sd=sal_media_description_find_best_stream(md,SalVideo); - call->current_params->implicit_rtcp_fb = sd ? sal_stream_description_has_implicit_avpf(sd): FALSE; - call->current_params->video_dir=sd ? media_direction_from_sal_stream_dir(sd->dir) : LinphoneMediaDirectionInactive; - if (call->current_params->video_dir != LinphoneMediaDirectionInactive) { - rtp_addr = sd->rtp_addr[0]!='\0' ? sd->rtp_addr : call->resultdesc->addr; - call->current_params->video_multicast_enabled = ms_is_multicast(rtp_addr); - } else - call->current_params->video_multicast_enabled = FALSE; - - } - - return call->current_params; -} - -const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call){ - if (call->op){ - LinphoneCallParams *cp; - SalMediaDescription *md; - const SalCustomHeader *ch; - - md=sal_call_get_remote_media_description(call->op); - if (md) { - SalStreamDescription *sd; - unsigned int i; - unsigned int nb_audio_streams = sal_media_description_nb_active_streams_of_type(md, SalAudio); - unsigned int nb_video_streams = sal_media_description_nb_active_streams_of_type(md, SalVideo); - unsigned int nb_text_streams = sal_media_description_nb_active_streams_of_type(md, SalText); - if (call->remote_params != NULL) linphone_call_params_unref(call->remote_params); - cp = call->remote_params = linphone_call_params_new(); - - for (i = 0; i < nb_video_streams; i++) { - sd = sal_media_description_get_active_stream_of_type(md, SalVideo, i); - if (sal_stream_description_active(sd) == TRUE) cp->has_video = TRUE; - if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP; - } - for (i = 0; i < nb_audio_streams; i++) { - sd = sal_media_description_get_active_stream_of_type(md, SalAudio, i); - if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP; - } - for (i = 0; i < nb_text_streams; i++) { - sd = sal_media_description_get_active_stream_of_type(md, SalText, i); - if (sal_stream_description_has_srtp(sd) == TRUE) cp->media_encryption = LinphoneMediaEncryptionSRTP; - cp->realtimetext_enabled = TRUE; - } - if (!cp->has_video){ - if (md->bandwidth>0 && md->bandwidth<=linphone_core_get_edge_bw(call->core)){ - cp->low_bandwidth=TRUE; - } - } - if (md->name[0]!='\0') linphone_call_params_set_session_name(cp,md->name); - - linphone_call_params_set_custom_sdp_attributes(call->remote_params, md->custom_sdp_attributes); - linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeAudio, md->streams[call->main_audio_stream_index].custom_sdp_attributes); - linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeVideo, md->streams[call->main_video_stream_index].custom_sdp_attributes); - linphone_call_params_set_custom_sdp_media_attributes(call->remote_params, LinphoneStreamTypeText, md->streams[call->main_text_stream_index].custom_sdp_attributes); - } - ch = sal_op_get_recv_custom_header(call->op); - if (ch){ - /*instanciate a remote_params only if a SIP message was received before (custom headers indicates this).*/ - if (call->remote_params == NULL) call->remote_params = linphone_call_params_new(); - linphone_call_params_set_custom_headers(call->remote_params, ch); - } - return call->remote_params; - } - return NULL; -} - -const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call){ - return call->dir==LinphoneCallIncoming ? call->log->from : call->log->to; -} - -const LinphoneAddress * linphone_call_get_to_address(const LinphoneCall *call){ - return (const LinphoneAddress *)sal_op_get_to_address(call->op); -} - -const char *linphone_call_get_to_header(const LinphoneCall *call, const char *name){ - return sal_custom_header_find(sal_op_get_recv_custom_header(call->op),name); -} - -char *linphone_call_get_remote_address_as_string(const LinphoneCall *call){ - return linphone_address_as_string(linphone_call_get_remote_address(call)); -} - -const LinphoneAddress * linphone_call_get_diversion_address(const LinphoneCall *call){ - return call->op?(const LinphoneAddress *)sal_op_get_diversion_address(call->op):NULL; -} - -LinphoneCallState linphone_call_get_state(const LinphoneCall *call){ - return call->state; -} - -LinphoneReason linphone_call_get_reason(const LinphoneCall *call){ - return linphone_error_info_get_reason(linphone_call_get_error_info(call)); -} - -const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call){ - if (!call->non_op_error){ - linphone_error_info_from_sal_op(call->ei, call->op); - } - return call->ei; -} - -void *linphone_call_get_user_data(const LinphoneCall *call) -{ - return call->user_data; -} - -void linphone_call_set_user_data(LinphoneCall *call, void *user_pointer) -{ - call->user_data = user_pointer; -} - -LinphoneCallLog *linphone_call_get_call_log(const LinphoneCall *call){ - return call->log; -} - -const char *linphone_call_get_refer_to(const LinphoneCall *call){ - return call->refer_to; -} - -LinphoneCall *linphone_call_get_transferer_call(const LinphoneCall *call){ - return call->referer; -} - -LinphoneCall *linphone_call_get_transfer_target_call(const LinphoneCall *call){ - return call->transfer_target; -} - -LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call){ - return call->log->dir; -} - -const char *linphone_call_get_remote_user_agent(LinphoneCall *call){ - if (call->op){ - return sal_op_get_remote_ua (call->op); - } - return NULL; -} - -const char *linphone_call_get_remote_contact(LinphoneCall *call){ - if( call->op ){ - /*sal_op_get_remote_contact preserves header params*/ - return sal_op_get_remote_contact(call->op); - } - return NULL; -} - -bool_t linphone_call_has_transfer_pending(const LinphoneCall *call){ - return call->refer_pending; -} - -static int _linphone_call_compute_duration (const LinphoneCall *call) { - if (call->log->connected_date_time == 0) return 0; - else return (int)(ms_time(NULL) - call->log->connected_date_time); -} - -int linphone_call_get_duration(const LinphoneCall *call) { - switch (call->state) { - case LinphoneCallEnd: - case LinphoneCallError: - case LinphoneCallReleased: - return call->log->duration; - default: - return _linphone_call_compute_duration(call); - } -} - -LinphoneCall *linphone_call_get_replaced_call(LinphoneCall *call){ - SalOp *op=sal_call_get_replaces(call->op); - if (op){ - return (LinphoneCall*)sal_op_get_user_pointer(op); - } - return NULL; -} - -void linphone_call_enable_camera (LinphoneCall *call, bool_t enable){ -#ifdef VIDEO_ENABLED - call->camera_enabled=enable; - switch(call->state) { - case LinphoneCallStreamsRunning: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallConnected: - if(call->videostream!=NULL - && video_stream_started(call->videostream) - && video_stream_get_camera(call->videostream) != linphone_call_get_video_device(call)) { - const char *cur_cam, *new_cam; - cur_cam = video_stream_get_camera(call->videostream) ? ms_web_cam_get_name(video_stream_get_camera(call->videostream)) : "NULL"; - new_cam = linphone_call_get_video_device(call) ? ms_web_cam_get_name(linphone_call_get_video_device(call)) : "NULL"; - ms_message("Switching video cam from [%s] to [%s] on call [%p]" , cur_cam, new_cam, call); - video_stream_change_camera(call->videostream, linphone_call_get_video_device(call)); - } - break; - - default: break; - } -#endif -} - -void linphone_call_send_vfu_request(LinphoneCall *call) { -#ifdef VIDEO_ENABLED - const LinphoneCallParams *current_params = linphone_call_get_current_params(call); - - if (call->videostream && call->videostream->ms.decoder) { - ms_filter_call_method_noarg(call->videostream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); - } - - if ((current_params->avpf_enabled || current_params->implicit_rtcp_fb )&& call->videostream && media_stream_get_state((const MediaStream *)call->videostream) == MSStreamStarted) { // || sal_media_description_has_implicit_avpf((const SalMediaDescription *)call->resultdesc) - ms_message("Request Full Intra Request on call [%p]", call); - video_stream_send_fir(call->videostream); - } else if (call->core->sip_conf.vfu_with_info) { - ms_message("Request SIP INFO FIR on call [%p]", call); - if (LinphoneCallStreamsRunning == linphone_call_get_state(call)) - sal_call_send_vfu_request(call->op); - } else { - ms_message("vfu request using sip disabled from config [sip,vfu_with_info]"); - } -#endif -} - -#ifdef VIDEO_ENABLED -static void snapshot_taken(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { - if (id == MS_JPEG_WRITER_SNAPSHOT_TAKEN) { - LinphoneCall *call = (LinphoneCall *)userdata; - if (call) { - const char *filepath = (const char *) arg; - linphone_call_notify_snapshot_taken(call, filepath); - } - linphone_call_unref(call); - } -} -#endif - -LinphoneStatus linphone_call_take_video_snapshot(LinphoneCall *call, const char *file) { -#ifdef VIDEO_ENABLED - if (call->videostream!=NULL && call->videostream->jpegwriter!=NULL){ - ms_filter_clear_notify_callback(call->videostream->jpegwriter); - ms_filter_add_notify_callback(call->videostream->jpegwriter, snapshot_taken, linphone_call_ref(call), TRUE); - 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."); -#endif - return -1; -} - -LinphoneStatus linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file) { -#ifdef VIDEO_ENABLED - if (call->videostream!=NULL && call->videostream->local_jpegwriter!=NULL){ - ms_filter_clear_notify_callback(call->videostream->local_jpegwriter); - ms_filter_add_notify_callback(call->videostream->local_jpegwriter, snapshot_taken, linphone_call_ref(call), TRUE); - return ms_filter_call_method(call->videostream->local_jpegwriter,MS_JPEG_WRITER_TAKE_SNAPSHOT,(void*)file); - } - ms_warning("Cannot take local snapshot: no currently running video stream on this call."); - return -1; -#endif - return -1; -} - -bool_t linphone_call_camera_enabled (const LinphoneCall *call){ - return call->camera_enabled; -} - /** * @ingroup call_control * @return string value of LinphonePrivacy enum @@ -2442,3891 +91,8 @@ const char* linphone_privacy_to_string(LinphonePrivacy privacy) { } } - -#ifdef TEST_EXT_RENDERER -static void rendercb(void *data, const MSPicture *local, const MSPicture *remote){ - ms_message("rendercb, local buffer=%p, remote buffer=%p", - local ? local->planes[0] : NULL, remote? remote->planes[0] : NULL); -} -#endif - -#ifdef VIDEO_ENABLED -static void video_stream_event_cb(void *user_pointer, const MSFilter *f, const unsigned int event_id, const void *args){ - LinphoneCall* call = (LinphoneCall*) user_pointer; - switch (event_id) { - case 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 = NULL; - call->nextVideoFrameDecoded._user_data = NULL; - } - linphone_call_notify_next_video_frame_decoded(call); - break; - case MS_VIDEO_DECODER_SEND_PLI: - case MS_VIDEO_DECODER_SEND_SLI: - case MS_VIDEO_DECODER_SEND_RPSI: - /* Handled internally by mediastreamer2. */ - break; - default: - ms_warning("Unhandled event %i", event_id); - break; - } -} -#endif - -static void _linphone_call_set_next_video_frame_decoded_trigger(LinphoneCall *call){ -#ifdef VIDEO_ENABLED - if (call->videostream && call->videostream->ms.decoder) - ms_filter_call_method_noarg(call->videostream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); -#endif -} - -void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void* user_data) { - call->nextVideoFrameDecoded._func = cb; - call->nextVideoFrameDecoded._user_data = user_data; - _linphone_call_set_next_video_frame_decoded_trigger(call); -} - -static void port_config_set_random_choosed(LinphoneCall *call, int stream_index, RtpSession *session){ - call->media_ports[stream_index].rtp_port=rtp_session_get_local_port(session); - call->media_ports[stream_index].rtcp_port=rtp_session_get_local_rtcp_port(session); -} - -static void _linphone_call_prepare_ice_for_stream(LinphoneCall *call, int stream_index, bool_t create_checklist){ - MediaStream *ms = stream_index == call->main_audio_stream_index ? (MediaStream*)call->audiostream : stream_index == call->main_video_stream_index ? (MediaStream*)call->videostream : (MediaStream*)call->textstream; - if (linphone_nat_policy_ice_enabled(call->nat_policy) && (call->ice_session != NULL)){ - IceCheckList *cl; - rtp_session_set_pktinfo(ms->sessions.rtp_session, TRUE); - cl=ice_session_check_list(call->ice_session, stream_index); - if (cl == NULL && create_checklist) { - cl=ice_check_list_new(); - ice_session_add_check_list(call->ice_session, cl, stream_index); - ms_message("Created new ICE check list for stream [%i]",stream_index); - } - if (cl) { - media_stream_set_ice_check_list(ms, cl); - } - } -} - -int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer){ - SalMediaDescription *remote = NULL; - int err; - bool_t has_video=FALSE; - - if (linphone_nat_policy_ice_enabled(call->nat_policy) && (call->ice_session != NULL)){ - if (incoming_offer){ - remote=sal_call_get_remote_media_description(call->op); - has_video=linphone_core_video_enabled(call->core) && linphone_core_media_description_contains_video_stream(remote); - }else has_video=call->params->has_video; - - _linphone_call_prepare_ice_for_stream(call,call->main_audio_stream_index,TRUE); - if (has_video) _linphone_call_prepare_ice_for_stream(call,call->main_video_stream_index,TRUE); - if (call->params->realtimetext_enabled) _linphone_call_prepare_ice_for_stream(call,call->main_text_stream_index,TRUE); - /*start ICE gathering*/ - if (incoming_offer) - linphone_call_update_ice_from_remote_media_description(call, remote, TRUE); /*this may delete the ice session*/ - if (call->ice_session && !ice_session_candidates_gathered(call->ice_session)){ - if (call->audiostream->ms.state==MSStreamInitialized) - audio_stream_prepare_sound(call->audiostream, NULL, NULL); -#ifdef VIDEO_ENABLED - if (has_video && call->videostream && call->videostream->ms.state==MSStreamInitialized) { - video_stream_prepare_video(call->videostream); - } -#endif - if (call->params->realtimetext_enabled && call->textstream->ms.state==MSStreamInitialized) { - text_stream_prepare_text(call->textstream); - } - err = linphone_core_gather_ice_candidates(call->core,call); - if (err == 0) { - /* Ice candidates gathering wasn't started, but we can proceed with the call anyway. */ - linphone_call_stop_media_streams_for_ice_gathering(call); - }else if (err == -1) { - linphone_call_stop_media_streams_for_ice_gathering(call); - linphone_call_delete_ice_session(call); - } - return err;/* 1= gathering in progress, wait; 0=proceed*/ - } - } - return 0; -} - -/*eventually join to a multicast group if told to do so*/ -static void linphone_call_join_multicast_group(LinphoneCall *call, int stream_index, MediaStream *ms){ - if (call->media_ports[stream_index].multicast_ip[stream_index]!='\0'){ - media_stream_join_multicast_group(ms, call->media_ports[stream_index].multicast_ip); - } else - ms_error("Cannot join multicast group if multicast ip is not set for call [%p]",call); -} - -static SalMulticastRole linphone_call_get_multicast_role(const LinphoneCall *call,SalStreamType type) { - SalMulticastRole multicast_role=SalMulticastInactive; - SalMediaDescription *remotedesc, *localdesc; - SalStreamDescription *stream_desc = NULL; - if (!call->op) goto end; - remotedesc = sal_call_get_remote_media_description(call->op); - localdesc = call->localdesc; - if (!localdesc && !remotedesc && call->dir == LinphoneCallOutgoing) { - /*well using call dir*/ - if ((type == SalAudio && linphone_call_params_audio_multicast_enabled(call->params)) - || (type == SalVideo && linphone_call_params_video_multicast_enabled(call->params))) - multicast_role=SalMulticastSender; - } else if (localdesc && (!remotedesc || sal_call_is_offerer(call->op))) { - stream_desc = sal_media_description_find_best_stream(localdesc, type); - } else if (!sal_call_is_offerer(call->op) && remotedesc) - stream_desc = sal_media_description_find_best_stream(remotedesc, type); - - if (stream_desc) - multicast_role = stream_desc->multicast_role; - - end: - ms_message("Call [%p], stream type [%s], multicast role is [%s]",call, sal_stream_type_to_string(type), - sal_multicast_role_to_string(multicast_role)); - return multicast_role; -} - -static void setup_dtls_params(LinphoneCall *call, MediaStream* stream) { - LinphoneCore *lc=call->core; - if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) { - MSDtlsSrtpParams params; - char *certificate, *key; - memset(¶ms,0,sizeof(MSDtlsSrtpParams)); - /* TODO : search for a certificate with CNAME=sip uri(retrieved from variable me) or default : linphone-dtls-default-identity */ - /* This will parse the directory to find a matching fingerprint or generate it if not found */ - /* returned string must be freed */ - sal_certificates_chain_parse_directory(&certificate, &key, &call->dtls_certificate_fingerprint, lc->user_certificates_path, "linphone-dtls-default-identity", SAL_CERTIFICATE_RAW_FORMAT_PEM, TRUE, TRUE); - - if (key!= NULL && certificate!=NULL) { - params.pem_certificate = (char *)certificate; - params.pem_pkey = (char *)key; - params.role = MSDtlsSrtpRoleUnset; /* default is unset, then check if we have a result SalMediaDescription */ - media_stream_enable_dtls(stream,¶ms); - ms_free(certificate); - ms_free(key); - } else { - ms_error("Unable to retrieve or generate DTLS certificate and key - DTLS disabled"); - /* TODO : check if encryption forced, if yes, stop call */ - } - } -} - -static void setZrtpCryptoTypesParameters(MSZrtpParams *params, LinphoneCore *lc) -{ - int i; - const MSCryptoSuite *srtp_suites; - MsZrtpCryptoTypesCount ciphersCount, authTagsCount; - - if (params == NULL) return; - if (lc == NULL) return; - - srtp_suites = linphone_core_get_srtp_crypto_suites(lc); - if (srtp_suites!=NULL) { - for(i=0; srtp_suites[i]!=MS_CRYPTO_SUITE_INVALID && iciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1; - params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS32; - break; - case MS_AES_128_NO_AUTH: - params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1; - break; - case MS_NO_CIPHER_SHA1_80: - params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80; - break; - case MS_AES_128_SHA1_80: - params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1; - params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80; - break; - case MS_AES_CM_256_SHA1_80: - ms_warning("Deprecated crypto suite MS_AES_CM_256_SHA1_80, use MS_AES_256_SHA1_80 instead"); - BCTBX_NO_BREAK; - case MS_AES_256_SHA1_80: - params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES3; - params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80; - break; - case MS_AES_256_SHA1_32: - params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES3; - params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS32; - break; - case MS_CRYPTO_SUITE_INVALID: - break; - } - } - } - - /* linphone_core_get_srtp_crypto_suites is used to determine sensible defaults; here each can be overridden */ - ciphersCount = linphone_core_get_zrtp_cipher_suites(lc, params->ciphers); /* if not present in config file, params->ciphers is not modified */ - if (ciphersCount!=0) { /* use zrtp_cipher_suites config only when present, keep config from srtp_crypto_suite otherwise */ - params->ciphersCount = ciphersCount; - } - params->hashesCount = linphone_core_get_zrtp_hash_suites(lc, params->hashes); - authTagsCount = linphone_core_get_zrtp_auth_suites(lc, params->authTags); /* if not present in config file, params->authTags is not modified */ - if (authTagsCount!=0) { - params->authTagsCount = authTagsCount; /* use zrtp_auth_suites config only when present, keep config from srtp_crypto_suite otherwise */ - } - params->sasTypesCount = linphone_core_get_zrtp_sas_suites(lc, params->sasTypes); - params->keyAgreementsCount = linphone_core_get_zrtp_key_agreement_suites(lc, params->keyAgreements); -} - -static OrtpJitterBufferAlgorithm name_to_jb_algo(const char *value){ - if (value){ - if (strcasecmp(value, "basic") == 0) return OrtpJitterBufferBasic; - else if (strcasecmp(value, "rls") == 0) return OrtpJitterBufferRecursiveLeastSquare; - } - ms_error("Invalid jitter buffer algorithm: %s", value); - return OrtpJitterBufferRecursiveLeastSquare; -} - -static void apply_jitter_buffer_params(LinphoneCore *lc, RtpSession *session, LinphoneStreamType type){ - JBParameters params; - - rtp_session_get_jitter_buffer_params(session, ¶ms); - params.min_size = lp_config_get_int(lc->config, "rtp", "jitter_buffer_min_size", 40); - params.max_size = lp_config_get_int(lc->config, "rtp", "jitter_buffer_max_size", 500); - params.max_packets = params.max_size * 200 / 1000; /*allow 200 packet per seconds, quite large*/ - params.buffer_algorithm = name_to_jb_algo(lp_config_get_string(lc->config, "rtp", "jitter_buffer_algorithm", "rls")); - params.refresh_ms = lp_config_get_int(lc->config, "rtp", "jitter_buffer_refresh_period", 5000); - params.ramp_refresh_ms = lp_config_get_int(lc->config, "rtp", "jitter_buffer_ramp_refresh_period", 5000); - params.ramp_step_ms = lp_config_get_int(lc->config, "rtp", "jitter_buffer_ramp_step", 20); - params.ramp_threshold = lp_config_get_int(lc->config, "rtp", "jitter_buffer_ramp_threshold", 70); - - switch (type){ - case LinphoneStreamTypeAudio: - case LinphoneStreamTypeText: /*let's use the same params for text as for audio.*/ - params.nom_size = linphone_core_get_audio_jittcomp(lc); - params.adaptive = linphone_core_audio_adaptive_jittcomp_enabled(lc); - break; - case LinphoneStreamTypeVideo: - params.nom_size = linphone_core_get_video_jittcomp(lc); - params.adaptive = linphone_core_video_adaptive_jittcomp_enabled(lc); - break; - case LinphoneStreamTypeUnknown: - ms_fatal("apply_jitter_buffer_params: should not happen"); - break; - } - params.enabled = params.nom_size > 0; - if (params.enabled){ - if (params.min_size > params.nom_size){ - params.min_size = params.nom_size; - } - if (params.max_size < params.nom_size){ - params.max_size = params.nom_size; - } - } - rtp_session_set_jitter_buffer_params(session, ¶ms); -} - -void linphone_call_init_audio_stream(LinphoneCall *call){ - LinphoneCore *lc=call->core; - AudioStream *audiostream; - const char *location; - int dscp; - const char *rtcp_tool=linphone_core_get_user_agent(call->core); - char* cname; - - if (call->audiostream != NULL) return; - - if (call->sessions[call->main_audio_stream_index].rtp_session==NULL){ - SalMulticastRole multicast_role = linphone_call_get_multicast_role(call,SalAudio); - SalMediaDescription *remotedesc=NULL; - SalStreamDescription *stream_desc = NULL; - if (call->op) remotedesc = sal_call_get_remote_media_description(call->op); - if (remotedesc) - stream_desc = sal_media_description_find_best_stream(remotedesc, SalAudio); - - call->audiostream=audiostream=audio_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_audio_stream_index), - multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_audio_stream_index].rtp_port, - multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_audio_stream_index].rtcp_port); - if (multicast_role == SalMulticastReceiver) - linphone_call_join_multicast_group(call, call->main_audio_stream_index, &audiostream->ms); - rtp_session_enable_network_simulation(call->audiostream->ms.sessions.rtp_session, &lc->net_conf.netsim_params); - apply_jitter_buffer_params(lc, call->audiostream->ms.sessions.rtp_session, LinphoneStreamTypeAudio); - cname = linphone_address_as_string_uri_only(call->me); - audio_stream_set_rtcp_information(call->audiostream, cname, rtcp_tool); - ms_free(cname); - rtp_session_set_symmetric_rtp(audiostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc)); - setup_dtls_params(call, &audiostream->ms); - - /* init zrtp even if we didn't explicitely set it, just in case peer offers it */ - if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)) { - LinphoneAddress *peerAddr = (call->dir==LinphoneCallIncoming) ? call->log->from : call->log->to; - LinphoneAddress *selfAddr = (call->dir==LinphoneCallIncoming) ? call->log->to : call->log->from; - char *peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(peerAddr) - , linphone_address_get_username(peerAddr) - , linphone_address_get_domain(peerAddr)); - char *selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(selfAddr) - , linphone_address_get_username(selfAddr) - , linphone_address_get_domain(selfAddr)); - MSZrtpParams params; - memset(¶ms,0,sizeof(MSZrtpParams)); - /*call->current_params.media_encryption will be set later when zrtp is activated*/ - params.zidCacheDB = linphone_core_get_zrtp_cache_db(lc); - params.peerUri=peerUri; - params.selfUri=selfUri; - params.limeKeyTimeSpan = bctbx_time_string_to_sec(lp_config_get_string(lc->config, "sip", "lime_key_validity", "0")); /* get key lifespan from config file, default is 0:forever valid */ - setZrtpCryptoTypesParameters(¶ms,call->core); - audio_stream_enable_zrtp(call->audiostream,¶ms); - if (peerUri != NULL) ms_free(peerUri); - if (selfUri != NULL) ms_free(selfUri); - } - - media_stream_reclaim_sessions(&audiostream->ms, &call->sessions[call->main_audio_stream_index]); - }else{ - call->audiostream=audio_stream_new_with_sessions(lc->factory, &call->sessions[call->main_audio_stream_index]); - - } - audiostream=call->audiostream; - if (call->media_ports[call->main_audio_stream_index].rtp_port==-1){ - port_config_set_random_choosed(call,call->main_audio_stream_index,audiostream->ms.sessions.rtp_session); - } - dscp=linphone_core_get_audio_dscp(lc); - if (dscp!=-1) - audio_stream_set_dscp(audiostream,dscp); - if (linphone_core_echo_limiter_enabled(lc)){ - const char *type=lp_config_get_string(lc->config,"sound","el_type","mic"); - if (strcasecmp(type,"mic")==0) - audio_stream_enable_echo_limiter(audiostream,ELControlMic); - 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; - 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 (audiostream->ec) { - char *statestr=reinterpret_cast(ms_malloc0(EC_STATE_MAX_LEN)); - if (lp_config_relative_file_exists(lc->config, EC_STATE_STORE) - && lp_config_read_relative_file(lc->config, EC_STATE_STORE, statestr, EC_STATE_MAX_LEN) == 0) { - ms_filter_call_method(audiostream->ec, MS_ECHO_CANCELLER_SET_STATE_STRING, statestr); - } - ms_free(statestr); - } - } - audio_stream_enable_automatic_gain_control(audiostream,linphone_core_agc_enabled(lc)); - { - int enabled=lp_config_get_int(lc->config,"sound","noisegate",0); - audio_stream_enable_noise_gate(audiostream,enabled); - } - - audio_stream_set_features(audiostream,linphone_core_get_audio_features(lc)); - - if (lc->rtptf){ - RtpTransport *meta_rtp; - RtpTransport *meta_rtcp; - - rtp_session_get_transports(audiostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp); - if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) { - ms_message("LinphoneCall[%p]: using custom audio RTP transport endpoint.", call); - meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[call->main_audio_stream_index].rtp_port)); - } - if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) { - meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[call->main_audio_stream_index].rtcp_port)); - } - } - - call->audiostream_app_evq = ortp_ev_queue_new(); - rtp_session_register_event_queue(audiostream->ms.sessions.rtp_session,call->audiostream_app_evq); - - _linphone_call_prepare_ice_for_stream(call,call->main_audio_stream_index,FALSE); -} - -void linphone_call_init_video_stream(LinphoneCall *call){ -#ifdef VIDEO_ENABLED - LinphoneCore *lc=call->core; - char* cname; - const char *rtcp_tool = linphone_core_get_user_agent(call->core); - - if (call->videostream == NULL){ - int video_recv_buf_size=lp_config_get_int(lc->config,"video","recv_buf_size",0); - int dscp=linphone_core_get_video_dscp(lc); - const char *display_filter=linphone_core_get_video_display_filter(lc); - - if (call->sessions[call->main_video_stream_index].rtp_session==NULL){ - SalMulticastRole multicast_role = linphone_call_get_multicast_role(call,SalVideo); - SalMediaDescription *remotedesc=NULL; - SalStreamDescription *stream_desc = NULL; - if (call->op) remotedesc = sal_call_get_remote_media_description(call->op); - if (remotedesc) - stream_desc = sal_media_description_find_best_stream(remotedesc, SalVideo); - - call->videostream=video_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_video_stream_index), - multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_video_stream_index].rtp_port, - multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_video_stream_index].rtcp_port); - if (multicast_role == SalMulticastReceiver) - linphone_call_join_multicast_group(call, call->main_video_stream_index, &call->videostream->ms); - rtp_session_enable_network_simulation(call->videostream->ms.sessions.rtp_session, &lc->net_conf.netsim_params); - apply_jitter_buffer_params(lc, call->videostream->ms.sessions.rtp_session, LinphoneStreamTypeVideo); - cname = linphone_address_as_string_uri_only(call->me); - video_stream_set_rtcp_information(call->videostream, cname, rtcp_tool); - ms_free(cname); - rtp_session_set_symmetric_rtp(call->videostream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc)); - setup_dtls_params(call, &call->videostream->ms); - /* init zrtp even if we didn't explicitely set it, just in case peer offers it */ - if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP)) { - video_stream_enable_zrtp(call->videostream, call->audiostream); - } - - media_stream_reclaim_sessions(&call->videostream->ms, &call->sessions[call->main_video_stream_index]); - }else{ - call->videostream=video_stream_new_with_sessions(lc->factory, &call->sessions[call->main_video_stream_index]); - } - - if (call->media_ports[call->main_video_stream_index].rtp_port==-1){ - port_config_set_random_choosed(call,call->main_video_stream_index,call->videostream->ms.sessions.rtp_session); - } - if (dscp!=-1) - video_stream_set_dscp(call->videostream,dscp); - video_stream_enable_display_filter_auto_rotate(call->videostream, lp_config_get_int(lc->config,"video","display_filter_auto_rotate",0)); - if (video_recv_buf_size>0) rtp_session_set_recv_buf_size(call->videostream->ms.sessions.rtp_session,video_recv_buf_size); - - if (display_filter != NULL) - video_stream_set_display_filter_name(call->videostream,display_filter); - video_stream_set_event_callback(call->videostream,video_stream_event_cb, call); - - if (lc->rtptf){ - RtpTransport *meta_rtp; - RtpTransport *meta_rtcp; - - rtp_session_get_transports(call->videostream->ms.sessions.rtp_session,&meta_rtp,&meta_rtcp); - if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) { - ms_message("LinphoneCall[%p]: using custom video RTP transport endpoint.", call); - meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->video_rtp_func(lc->rtptf->video_rtp_func_data, call->media_ports[call->main_video_stream_index].rtp_port)); - } - if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) { - meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->video_rtcp_func(lc->rtptf->video_rtcp_func_data, call->media_ports[call->main_video_stream_index].rtcp_port)); - } - } - 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,call->main_video_stream_index,FALSE); -#ifdef TEST_EXT_RENDERER - video_stream_set_render_callback(call->videostream,rendercb,NULL); -#endif - } -#else - call->videostream=NULL; -#endif -} - -void linphone_call_init_text_stream(LinphoneCall *call){ - TextStream *textstream; - LinphoneCore *lc=call->core; - char* cname; - - if (call->textstream != NULL) return; - if (call->sessions[call->main_text_stream_index].rtp_session == NULL) { - SalMulticastRole multicast_role = linphone_call_get_multicast_role(call, SalText); - SalMediaDescription *remotedesc = NULL; - SalStreamDescription *stream_desc = NULL; - if (call->op) remotedesc = sal_call_get_remote_media_description(call->op); - if (remotedesc) stream_desc = sal_media_description_find_best_stream(remotedesc, SalText); - - call->textstream = textstream = text_stream_new2(lc->factory, linphone_call_get_bind_ip_for_stream(call,call->main_text_stream_index), - multicast_role == SalMulticastReceiver ? stream_desc->rtp_port : call->media_ports[call->main_text_stream_index].rtp_port, - multicast_role == SalMulticastReceiver ? 0 /*disabled for now*/ : call->media_ports[call->main_text_stream_index].rtcp_port); - if (multicast_role == SalMulticastReceiver) - linphone_call_join_multicast_group(call, call->main_text_stream_index, &textstream->ms); - rtp_session_enable_network_simulation(call->textstream->ms.sessions.rtp_session, &lc->net_conf.netsim_params); - apply_jitter_buffer_params(lc, call->textstream->ms.sessions.rtp_session, LinphoneStreamTypeText); - cname = linphone_address_as_string_uri_only(call->me); - ms_free(cname); - rtp_session_set_symmetric_rtp(textstream->ms.sessions.rtp_session,linphone_core_symmetric_rtp_enabled(lc)); - setup_dtls_params(call, &textstream->ms); - media_stream_reclaim_sessions(&textstream->ms, &call->sessions[call->main_text_stream_index]); - } else { - call->textstream = text_stream_new_with_sessions(lc->factory, &call->sessions[call->main_text_stream_index]); - } - textstream = call->textstream; - if (call->media_ports[call->main_text_stream_index].rtp_port == -1) { - port_config_set_random_choosed(call, call->main_text_stream_index, textstream->ms.sessions.rtp_session); - } - - if (lc->rtptf){ - RtpTransport *meta_rtp; - RtpTransport *meta_rtcp; - - rtp_session_get_transports(textstream->ms.sessions.rtp_session, &meta_rtp, &meta_rtcp); - if (meta_rtp_transport_get_endpoint(meta_rtp) == NULL) { - meta_rtp_transport_set_endpoint(meta_rtp,lc->rtptf->audio_rtp_func(lc->rtptf->audio_rtp_func_data, call->media_ports[call->main_text_stream_index].rtp_port)); - } - if (meta_rtp_transport_get_endpoint(meta_rtcp) == NULL) { - meta_rtp_transport_set_endpoint(meta_rtcp,lc->rtptf->audio_rtcp_func(lc->rtptf->audio_rtcp_func_data, call->media_ports[call->main_text_stream_index].rtcp_port)); - } - } - - call->textstream_app_evq = ortp_ev_queue_new(); - rtp_session_register_event_queue(textstream->ms.sessions.rtp_session, call->textstream_app_evq); - - _linphone_call_prepare_ice_for_stream(call, call->main_text_stream_index, FALSE); -} - -void linphone_call_init_media_streams(LinphoneCall *call){ - linphone_call_init_audio_stream(call); - linphone_call_init_video_stream(call); - linphone_call_init_text_stream(call); -} - - -static int dtmf_tab[16]={'0','1','2','3','4','5','6','7','8','9','*','#','A','B','C','D'}; - -static void linphone_core_dtmf_received(LinphoneCall *call, int dtmf){ - if (dtmf<0 || dtmf>15){ - ms_warning("Bad dtmf value %i",dtmf); - return; - } - linphone_call_notify_dtmf_received(call, dtmf_tab[dtmf]); -} - -static void parametrize_equalizer(LinphoneCore *lc, AudioStream *st){ - const char *eq_active = lp_config_get_string(lc->config, "sound", "eq_active", NULL); - const char *eq_gains = lp_config_get_string(lc->config, "sound", "eq_gains", NULL); - - if(eq_active) ms_warning("'eq_active' linphonerc parameter has not effect anymore. Please use 'mic_eq_active' or 'spk_eq_active' instead"); - if(eq_gains) ms_warning("'eq_gains' linphonerc parameter has not effect anymore. Please use 'mic_eq_gains' or 'spk_eq_gains' instead"); - if (st->mic_equalizer){ - MSFilter *f=st->mic_equalizer; - int enabled=lp_config_get_int(lc->config,"sound","mic_eq_active",0); - const char *gains=lp_config_get_string(lc->config,"sound","mic_eq_gains",NULL); - ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled); - if (enabled && gains){ - bctbx_list_t *gains_list = ms_parse_equalizer_string(gains); - bctbx_list_t *it; - for(it=gains_list; it; it=it->next) { - MSEqualizerGain *g = (MSEqualizerGain *)it->data; - ms_message("Read microphone equalizer gains: %f(~%f) --> %f",g->frequency,g->width,g->gain); - ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN, g); - } - if(gains_list) bctbx_list_free_with_data(gains_list, ms_free); - } - } - if (st->spk_equalizer){ - MSFilter *f=st->spk_equalizer; - int enabled=lp_config_get_int(lc->config,"sound","spk_eq_active",0); - const char *gains=lp_config_get_string(lc->config,"sound","spk_eq_gains",NULL); - ms_filter_call_method(f,MS_EQUALIZER_SET_ACTIVE,&enabled); - if (enabled && gains){ - bctbx_list_t *gains_list = ms_parse_equalizer_string(gains); - bctbx_list_t *it; - for(it=gains_list; it; it=it->next) { - MSEqualizerGain *g = (MSEqualizerGain *)it->data; - ms_message("Read speaker equalizer gains: %f(~%f) --> %f",g->frequency,g->width,g->gain); - ms_filter_call_method(f,MS_EQUALIZER_SET_GAIN, g); - } - if(gains_list) bctbx_list_free_with_data(gains_list, ms_free); - } - } -} - -void set_mic_gain_db(AudioStream *st, float gain){ - audio_stream_set_mic_gain_db(st, gain); -} - void set_playback_gain_db(AudioStream *st, float gain){ if (st->volrecv){ ms_filter_call_method(st->volrecv,MS_VOLUME_SET_DB_GAIN,&gain); }else ms_warning("Could not apply playback gain: gain control wasn't activated."); } - -/*This function is not static because used internally in linphone-daemon project*/ -void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted){ - float mic_gain=lc->sound_conf.soft_mic_lev; - float thres = 0; - float recv_gain; - float ng_thres=lp_config_get_float(lc->config,"sound","ng_thres",0.05f); - float ng_floorgain=lp_config_get_float(lc->config,"sound","ng_floorgain",0); - int dc_removal=lp_config_get_int(lc->config,"sound","dc_removal",0); - float speed; - float force; - int sustain; - float transmit_thres; - MSFilter *f=NULL; - float floorgain; - int spk_agc; - - if (!muted) - set_mic_gain_db(st,mic_gain); - else - audio_stream_set_mic_gain(st,0); - - recv_gain = lc->sound_conf.soft_play_lev; - if (recv_gain != 0) { - set_playback_gain_db(st,recv_gain); - } - - if (st->volsend){ - ms_filter_call_method(st->volsend,MS_VOLUME_REMOVE_DC,&dc_removal); - speed=lp_config_get_float(lc->config,"sound","el_speed",-1); - thres=lp_config_get_float(lc->config,"sound","el_thres",-1); - force=lp_config_get_float(lc->config,"sound","el_force",-1); - sustain=lp_config_get_int(lc->config,"sound","el_sustain",-1); - transmit_thres=lp_config_get_float(lc->config,"sound","el_transmit_thres",-1); - f=st->volsend; - if (speed==-1) speed=0.03f; - if (force==-1) force=25; - ms_filter_call_method(f,MS_VOLUME_SET_EA_SPEED,&speed); - ms_filter_call_method(f,MS_VOLUME_SET_EA_FORCE,&force); - if (thres!=-1) - ms_filter_call_method(f,MS_VOLUME_SET_EA_THRESHOLD,&thres); - if (sustain!=-1) - ms_filter_call_method(f,MS_VOLUME_SET_EA_SUSTAIN,&sustain); - if (transmit_thres!=-1) - ms_filter_call_method(f,MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD,&transmit_thres); - - ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres); - ms_filter_call_method(st->volsend,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&ng_floorgain); - } - if (st->volrecv){ - /* parameters for a limited noise-gate effect, using echo limiter threshold */ - floorgain = (float)(1/pow(10,mic_gain/10)); - spk_agc=lp_config_get_int(lc->config,"sound","speaker_agc_enabled",0); - ms_filter_call_method(st->volrecv, MS_VOLUME_ENABLE_AGC, &spk_agc); - ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_THRESHOLD,&ng_thres); - ms_filter_call_method(st->volrecv,MS_VOLUME_SET_NOISE_GATE_FLOORGAIN,&floorgain); - } - parametrize_equalizer(lc,st); -} - -static void post_configure_audio_streams(LinphoneCall *call, bool_t muted){ - AudioStream *st=call->audiostream; - LinphoneCore *lc=call->core; - _post_configure_audio_stream(st,lc,muted); - if (linphone_core_dtmf_received_has_listener(lc)){ - audio_stream_play_received_dtmfs(call->audiostream,FALSE); - } - if (call->record_active) - linphone_call_start_recording(call); -} - -static int get_ideal_audio_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){ - int remote_bw=0; - int upload_bw; - int total_upload_bw=linphone_core_get_upload_bandwidth(call->core); - const LinphoneCallParams *params=call->params; - bool_t will_use_video=linphone_core_media_description_contains_video_stream(md); - bool_t forced=FALSE; - - if (desc->bandwidth>0) remote_bw=desc->bandwidth; - else if (md->bandwidth>0) { - /*case where b=AS is given globally, not per stream*/ - remote_bw=md->bandwidth; - } - if (params->up_bw>0){ - forced=TRUE; - upload_bw=params->up_bw; - }else upload_bw=total_upload_bw; - upload_bw=get_min_bandwidth(upload_bw,remote_bw); - if (!will_use_video || forced) return upload_bw; - - if (bandwidth_is_greater(upload_bw,512)){ - upload_bw=100; - }else if (bandwidth_is_greater(upload_bw,256)){ - upload_bw=64; - }else if (bandwidth_is_greater(upload_bw,128)){ - upload_bw=40; - }else if (bandwidth_is_greater(upload_bw,0)){ - upload_bw=24; - } - return upload_bw; -} - -static int get_video_bw(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc){ - int remote_bw=0; - int bw; - if (desc->bandwidth>0) remote_bw=desc->bandwidth; - else if (md->bandwidth>0) { - /*case where b=AS is given globally, not per stream*/ - remote_bw=get_remaining_bandwidth_for_video(md->bandwidth,call->audio_bw); - } - - bw=get_min_bandwidth(get_remaining_bandwidth_for_video(linphone_core_get_upload_bandwidth(call->core),call->audio_bw),remote_bw); - return bw; -} - -static RtpProfile *make_profile(LinphoneCall *call, const SalMediaDescription *md, const SalStreamDescription *desc, int *used_pt){ - int bw=0; - const bctbx_list_t *elem; - RtpProfile *prof=rtp_profile_new("Call profile"); - bool_t first=TRUE; - LinphoneCore *lc=call->core; - int up_ptime=0; - const LinphoneCallParams *params=call->params; - - *used_pt=-1; - - if (desc->type==SalAudio) - bw=get_ideal_audio_bw(call,md,desc); - else if (desc->type==SalVideo) - bw=get_video_bw(call,md,desc); - //else if (desc->type== SalText) - - - for(elem=desc->payloads;elem!=NULL;elem=elem->next){ - PayloadType *pt=(PayloadType*)elem->data; - int number; - /* make a copy of the payload type, so that we left the ones from the SalStreamDescription unchanged. - If the SalStreamDescription is freed, this will have no impact on the running streams*/ - pt=payload_type_clone(pt); - - if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) { - /*first codec in list is the selected one*/ - if (desc->type==SalAudio){ - /*this will update call->audio_bw*/ - linphone_core_update_allocated_audio_bandwidth_in_call(call,pt,bw); - bw=call->audio_bw; - if (params->up_ptime) - up_ptime=params->up_ptime; - else up_ptime=linphone_core_get_upload_ptime(lc); - } - first=FALSE; - } - if (*used_pt == -1){ - /*don't select telephone-event as a payload type*/ - if (strcasecmp(pt->mime_type, "telephone-event") != 0){ - *used_pt = payload_type_get_number(pt); - } - } - - if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){ - ms_message("Payload type [%s/%i] has explicit bitrate [%i] kbit/s", pt->mime_type, pt->clock_rate, pt->normal_bitrate/1000); - pt->normal_bitrate=get_min_bandwidth(pt->normal_bitrate,bw*1000); - } else pt->normal_bitrate=bw*1000; - if (desc->ptime>0){ - up_ptime=desc->ptime; - } - if (up_ptime>0){ - char tmp[40]; - snprintf(tmp,sizeof(tmp),"ptime=%i",up_ptime); - payload_type_append_send_fmtp(pt,tmp); - } - number=payload_type_get_number(pt); - if (rtp_profile_get_payload(prof,number)!=NULL){ - ms_warning("A payload type with number %i already exists in profile !",number); - }else - rtp_profile_set_payload(prof,number,pt); - } - return prof; -} - -static void setup_ring_player(LinphoneCore *lc, LinphoneCall *call){ - int pause_time=3000; - audio_stream_play(call->audiostream,lc->sound_conf.ringback_tone); - ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); -} - -static bool_t linphone_call_sound_resources_available(LinphoneCall *call){ - LinphoneCore *lc=call->core; - LinphoneCall *current=linphone_core_get_current_call(lc); - return !linphone_core_is_in_conference(lc) && - (current==NULL || current==call); -} - -static int find_crypto_index_from_tag(const SalSrtpCryptoAlgo crypto[],unsigned char tag) { - int i; - for(i=0; itype == SalAudio) { - session = call->audiostream->ms.sessions.rtp_session; - } else if (stream->type == SalVideo) { - session = call->videostream->ms.sessions.rtp_session; - } else { - // Do nothing for streams that are not audio or video - return; - } - if (stream->rtcp_fb.generic_nack_enabled) - rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, TRUE); - else - rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, FALSE); - if (stream->rtcp_fb.tmmbr_enabled) - rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, TRUE); - else - rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, FALSE); -} - -static void configure_rtp_session_for_rtcp_xr(LinphoneCore *lc, LinphoneCall *call, SalStreamType type) { - RtpSession *session = NULL; - const OrtpRtcpXrConfiguration *localconfig; - const OrtpRtcpXrConfiguration *remoteconfig; - OrtpRtcpXrConfiguration currentconfig; - const SalStreamDescription *localstream; - const SalStreamDescription *remotestream; - SalMediaDescription *remotedesc = sal_call_get_remote_media_description(call->op); - - if (!remotedesc) return; - - localstream = sal_media_description_find_best_stream(call->localdesc, type); - if (!localstream) return; - localconfig = &localstream->rtcp_xr; - remotestream = sal_media_description_find_best_stream(remotedesc, type); - if (!remotestream) return; - remoteconfig = &remotestream->rtcp_xr; - - if (localstream->dir == SalStreamInactive) return; - else if (localstream->dir == SalStreamRecvOnly) { - /* Use local config for unilateral parameters and remote config for collaborative parameters. */ - memcpy(¤tconfig, localconfig, sizeof(currentconfig)); - currentconfig.rcvr_rtt_mode = remoteconfig->rcvr_rtt_mode; - currentconfig.rcvr_rtt_max_size = remoteconfig->rcvr_rtt_max_size; - } else { - memcpy(¤tconfig, remoteconfig, sizeof(currentconfig)); - } - if (type == SalAudio) { - session = call->audiostream->ms.sessions.rtp_session; - } else if (type == SalVideo) { - session = call->videostream->ms.sessions.rtp_session; - } else if (type == SalText) { - session = call->textstream->ms.sessions.rtp_session; - } - rtp_session_configure_rtcp_xr(session, ¤tconfig); -} - -static void start_dtls( MSMediaStreamSessions *sessions, const SalStreamDescription *sd,const SalStreamDescription *remote) { - if (sal_stream_description_has_dtls(sd) == TRUE) { - /*DTLS*/ - SalDtlsRole salRole = sd->dtls_role; - if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */ - /* give the peer certificate fingerprint to dtls context */ - ms_dtls_srtp_set_peer_fingerprint(sessions->dtls_context, remote->dtls_fingerprint); - ms_dtls_srtp_set_role(sessions->dtls_context, (salRole == SalDtlsRoleIsClient)?MSDtlsSrtpRoleIsClient:MSDtlsSrtpRoleIsServer); /* set the role to client */ - ms_dtls_srtp_start(sessions->dtls_context); /* then start the engine, it will send the DTLS client Hello */ - } else { - ms_warning("unable to start DTLS engine on stream session [%p], Dtls role in resulting media description is invalid",sessions); - } - } -} - -static void start_dtls_on_all_streams(LinphoneCall *call) { - SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); - SalMediaDescription *result_desc = sal_call_get_final_media_description(call->op); - if( remote_desc == NULL || result_desc == NULL ){ - /* this can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */ - return; - } - - if (call->audiostream && (media_stream_get_state((const MediaStream *)call->audiostream) == MSStreamStarted))/*dtls must start at the end of ice*/ - start_dtls(&call->audiostream->ms.sessions - ,sal_media_description_find_best_stream(result_desc,SalAudio) - ,sal_media_description_find_best_stream(remote_desc,SalAudio)); -#if VIDEO_ENABLED - if (call->videostream && (media_stream_get_state((const MediaStream *)call->videostream) == MSStreamStarted))/*dtls must start at the end of ice*/ - start_dtls(&call->videostream->ms.sessions - ,sal_media_description_find_best_stream(result_desc,SalVideo) - ,sal_media_description_find_best_stream(remote_desc,SalVideo)); -#endif - if (call->textstream && (media_stream_get_state((const MediaStream *)call->textstream) == MSStreamStarted))/*dtls must start at the end of ice*/ - start_dtls(&call->textstream->ms.sessions - ,sal_media_description_find_best_stream(result_desc,SalText) - ,sal_media_description_find_best_stream(remote_desc,SalText)); - return; -} - -static void set_dtls_fingerprint( MSMediaStreamSessions *sessions, const SalStreamDescription *sd,const SalStreamDescription *remote) { - if (sal_stream_description_has_dtls(sd) == TRUE) { - /*DTLS*/ - SalDtlsRole salRole = sd->dtls_role; - if (salRole!=SalDtlsRoleInvalid) { /* if DTLS is available at both end points */ - /* give the peer certificate fingerprint to dtls context */ - ms_dtls_srtp_set_peer_fingerprint(sessions->dtls_context, remote->dtls_fingerprint); - } else { - ms_warning("unable to start DTLS engine on stream session [%p], Dtls role in resulting media description is invalid",sessions); - } - } -} - -static void set_dtls_fingerprint_on_all_streams(LinphoneCall *call) { - SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); - SalMediaDescription *result_desc = sal_call_get_final_media_description(call->op); - - if( remote_desc == NULL || result_desc == NULL ){ - /* this can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */ - return; - } - - if (call->audiostream && (media_stream_get_state((const MediaStream *)call->audiostream) == MSStreamStarted))/*dtls must start at the end of ice*/ - set_dtls_fingerprint(&call->audiostream->ms.sessions - ,sal_media_description_find_best_stream(result_desc,SalAudio) - ,sal_media_description_find_best_stream(remote_desc,SalAudio)); -#if VIDEO_ENABLED - if (call->videostream && (media_stream_get_state((const MediaStream *)call->videostream) == MSStreamStarted))/*dtls must start at the end of ice*/ - set_dtls_fingerprint(&call->videostream->ms.sessions - ,sal_media_description_find_best_stream(result_desc,SalVideo) - ,sal_media_description_find_best_stream(remote_desc,SalVideo)); -#endif - if (call->textstream && (media_stream_get_state((const MediaStream *)call->textstream) == MSStreamStarted))/*dtls must start at the end of ice*/ - set_dtls_fingerprint(&call->textstream->ms.sessions - ,sal_media_description_find_best_stream(result_desc,SalText) - ,sal_media_description_find_best_stream(remote_desc,SalText)); - return; -} - -static RtpSession * create_audio_rtp_io_session(LinphoneCall *call) { - PayloadType *pt; - LinphoneCore *lc = call->core; - const char *local_ip = lp_config_get_string(lc->config, "sound", "rtp_local_addr", "127.0.0.1"); - const char *remote_ip = lp_config_get_string(lc->config, "sound", "rtp_remote_addr", "127.0.0.1"); - int local_port = lp_config_get_int(lc->config, "sound", "rtp_local_port", 17076); - int remote_port = lp_config_get_int(lc->config, "sound", "rtp_remote_port", 17078); - int ptnum = lp_config_get_int(lc->config, "sound", "rtp_ptnum", 0); - const char *rtpmap = lp_config_get_string(lc->config, "sound", "rtp_map", "pcmu/8000/1"); - int symmetric = lp_config_get_int(lc->config, "sound", "rtp_symmetric", 0); - int jittcomp = lp_config_get_int(lc->config, "sound", "rtp_jittcomp", 0); /* 0 means no jitter buffer*/ - RtpSession *rtp_session = NULL; - pt = rtp_profile_get_payload_from_rtpmap(call->audio_profile, rtpmap); - if (pt != NULL) { - call->rtp_io_audio_profile = rtp_profile_new("RTP IO audio profile"); - rtp_profile_set_payload(call->rtp_io_audio_profile, ptnum, payload_type_clone(pt)); - rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1, ms_factory_get_mtu(lc->factory)); - rtp_session_set_profile(rtp_session, call->rtp_io_audio_profile); - rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1); - rtp_session_enable_rtcp(rtp_session, FALSE); - rtp_session_set_payload_type(rtp_session, ptnum); - rtp_session_set_jitter_compensation(rtp_session, jittcomp); - rtp_session_enable_jitter_buffer(rtp_session, jittcomp>0); - rtp_session_set_symmetric_rtp(rtp_session, (bool_t)symmetric); - } - return rtp_session; -} - -static void linphone_call_set_on_hold_file(LinphoneCall *call, const char *file){ - if (call->onhold_file){ - ms_free(call->onhold_file); - call->onhold_file = NULL; - } - if (file){ - call->onhold_file = ms_strdup(file); - } -} - -static void configure_adaptive_rate_control(LinphoneCall *call, MediaStream *ms, PayloadType *pt, bool_t video_will_be_used){ - LinphoneCore *lc = call->core; - bool_t enabled = linphone_core_adaptive_rate_control_enabled(lc); - - if (enabled){ - const char *algo = linphone_core_get_adaptive_rate_algorithm(lc); - bool_t is_advanced = TRUE; - if (strcasecmp(algo, "basic") == 0) is_advanced = FALSE; - else if (strcasecmp(algo, "advanced") == 0) is_advanced = TRUE; - - if (is_advanced){ - /*we can't use media_stream_avpf_enabled() here because the active PayloadType is not set yet in the MediaStream.*/ - if (!pt || !(pt->flags & PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED)){ - ms_warning("LinphoneCall[%p] - advanced adaptive rate control requested but avpf is not activated in this stream. Reverting to basic rate control instead.", call); - is_advanced = FALSE; - }else{ - ms_message("LinphoneCall[%p] - setting up advanced rate control.", call); - } - } - - if (is_advanced){ - ms_bandwidth_controller_add_stream(lc->bw_controller, ms); - media_stream_enable_adaptive_bitrate_control(ms, FALSE); - }else{ - media_stream_set_adaptive_bitrate_algorithm(ms, MSQosAnalyzerAlgorithmSimple); - if (ms->type == MSAudio && video_will_be_used){ - enabled = FALSE; /*if this is an audio stream but video is going to be used, there is - no need to perform basic rate control on the audio stream, just the video stream.*/ - } - media_stream_enable_adaptive_bitrate_control(ms, enabled); - } - }else{ - media_stream_enable_adaptive_bitrate_control(ms, FALSE); - } -} - -static void linphone_call_start_audio_stream(LinphoneCall *call, LinphoneCallState next_state, bool_t video_will_be_used){ - LinphoneCore *lc=call->core; - int used_pt=-1; - const SalStreamDescription *stream; - MSSndCard *playcard; - MSSndCard *captcard; - bool_t use_ec; - bool_t mute; - const char *playfile; - const char *recfile; - const char *file_to_play = NULL; - const SalStreamDescription *local_st_desc; - int crypto_idx; - MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER; - bool_t use_rtp_io = lp_config_get_int(lc->config, "sound", "rtp_io", FALSE); - bool_t use_rtp_io_enable_local_output = lp_config_get_int(lc->config, "sound", "rtp_io_enable_local_output", FALSE); - - stream = sal_media_description_find_best_stream(call->resultdesc, SalAudio); - if (stream && stream->dir!=SalStreamInactive && stream->rtp_port!=0){ - /* get remote stream description to check for zrtp-hash presence */ - SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); - const SalStreamDescription *remote_stream = sal_media_description_find_best_stream(remote_desc, SalAudio); - - const char *rtp_addr=stream->rtp_addr[0]!='\0' ? stream->rtp_addr : call->resultdesc->addr; - bool_t is_multicast=ms_is_multicast(rtp_addr); - playcard=lc->sound_conf.lsd_card ? - lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; - captcard=lc->sound_conf.capt_sndcard; - playfile=lc->play_file; - recfile=lc->rec_file; - call->audio_profile=make_profile(call,call->resultdesc,stream,&used_pt); - - if (used_pt!=-1){ - bool_t ok = TRUE; - call->current_params->audio_codec = rtp_profile_get_payload(call->audio_profile, used_pt); - call->current_params->has_audio = TRUE; - if (playcard==NULL) { - ms_warning("No card defined for playback !"); - } - if (captcard==NULL) { - ms_warning("No card defined for capture !"); - } - /*Don't use file or soundcard capture when placed in recv-only mode*/ - if (stream->rtp_port==0 - || stream->dir==SalStreamRecvOnly - || (stream->multicast_role == SalMulticastReceiver && is_multicast)){ - captcard=NULL; - playfile=NULL; - } - if (next_state == LinphoneCallPaused){ - /*in paused state, we never use soundcard*/ - playcard=NULL; - captcard=NULL; - recfile=NULL; - /*And we will eventually play "playfile" if set by the user*/ - } - if (call->playing_ringbacktone){ - captcard=NULL; - playfile=NULL;/* it is setup later*/ - if (lp_config_get_int(lc->config,"sound","send_ringback_without_playback", 0) == 1){ - playcard = NULL; - recfile = NULL; - } - } - /*if playfile are supplied don't use soundcards*/ - if (lc->use_files || (use_rtp_io && !use_rtp_io_enable_local_output)) { - captcard=NULL; - playcard=NULL; - } - if (call->params->in_conference){ - /* first create the graph without soundcard resources*/ - captcard=playcard=NULL; - } - if (!linphone_call_sound_resources_available(call)){ - ms_message("Sound resources are used by another call, not using soundcard."); - captcard=playcard=NULL; - } - media_stream_set_max_network_bitrate(&call->audiostream->ms, linphone_core_get_upload_bandwidth(lc) * 1000); - use_ec=captcard==NULL ? FALSE : linphone_core_echo_cancellation_enabled(lc); - audio_stream_enable_echo_canceller(call->audiostream, use_ec); - 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); - - rtp_session_enable_rtcp_mux(call->audiostream->ms.sessions.rtp_session, stream->rtcp_mux); - 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) { - local_st_desc=sal_media_description_find_stream(call->localdesc,stream->proto,SalAudio); - crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, stream->crypto_local_tag); - - if (crypto_idx >= 0) { - ms_media_stream_sessions_set_srtp_recv_key_b64(&call->audiostream->ms.sessions, stream->crypto[0].algo,stream->crypto[0].master_key); - ms_media_stream_sessions_set_srtp_send_key_b64(&call->audiostream->ms.sessions, stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key); - } else { - ms_warning("Failed to find local crypto algo with tag: %d", stream->crypto_local_tag); - } - } - configure_rtp_session_for_rtcp_fb(call, stream); - configure_rtp_session_for_rtcp_xr(lc, call, SalAudio); - configure_adaptive_rate_control(call, (MediaStream*)call->audiostream, call->current_params->audio_codec, video_will_be_used); - if (is_multicast) - rtp_session_set_multicast_ttl(call->audiostream->ms.sessions.rtp_session,stream->ttl); - - if (use_rtp_io) { - if(use_rtp_io_enable_local_output){ - io.input.type = MSResourceRtp; - io.input.session = create_audio_rtp_io_session(call); - - if (playcard){ - io.output.type = MSResourceSoundcard; - io.output.soundcard = playcard; - }else{ - io.output.type = MSResourceFile; - io.output.file = recfile; - } - } - else { - io.input.type = io.output.type = MSResourceRtp; - io.input.session = io.output.session = create_audio_rtp_io_session(call); - } - - if (io.input.session == NULL) { - ok = FALSE; - } - }else { - if (playcard){ - io.output.type = MSResourceSoundcard; - io.output.soundcard = playcard; - }else{ - io.output.type = MSResourceFile; - io.output.file = recfile; - } - if (captcard){ - io.input.type = MSResourceSoundcard; - io.input.soundcard = captcard; - }else{ - io.input.type = MSResourceFile; - file_to_play = playfile; - io.input.file = NULL; /*we prefer to use the remote_play api, that allows to play multimedia files */ - } - - } - if (playcard){ - ms_snd_card_set_stream_type(playcard, MS_SND_CARD_STREAM_VOICE); - } - if (ok == TRUE) { - int err = audio_stream_start_from_io(call->audiostream, - call->audio_profile, - rtp_addr, - stream->rtp_port, - stream->rtcp_addr[0]!='\0' ? stream->rtcp_addr : call->resultdesc->addr, - (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port+1) : 0, - used_pt, - &io); - if (err == 0){ - post_configure_audio_streams(call, (call->all_muted || call->audio_muted) && !call->playing_ringbacktone); - } - } - - ms_media_stream_sessions_set_encryption_mandatory(&call->audiostream->ms.sessions, linphone_call_encryption_mandatory(call)); - - if (next_state == LinphoneCallPaused && captcard == NULL && playfile != NULL){ - int pause_time=500; - ms_filter_call_method(call->audiostream->soundread,MS_FILE_PLAYER_LOOP,&pause_time); - } - if (call->playing_ringbacktone){ - setup_ring_player(lc,call); - } - - if (call->params->in_conference && lc->conf_ctx){ - /*transform the graph to connect it to the conference filter */ - mute = stream->dir==SalStreamRecvOnly; - linphone_conference_on_call_stream_starting(lc->conf_ctx, call, mute); - } - call->current_params->in_conference=call->params->in_conference; - call->current_params->low_bandwidth=call->params->low_bandwidth; - - /* start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */ - if (linphone_core_media_encryption_supported(lc, LinphoneMediaEncryptionZRTP) && - (call->params->media_encryption == LinphoneMediaEncryptionZRTP || remote_stream->haveZrtpHash==1) ){ - audio_stream_start_zrtp(call->audiostream); - if (remote_stream->haveZrtpHash == 1) { - int retval; - if ((retval = ms_zrtp_setPeerHelloHash(call->audiostream->ms.sessions.zrtp_context, (uint8_t *)remote_stream->zrtphash, strlen((const char *)(remote_stream->zrtphash)))) != 0) { - ms_error("Zrtp hash mismatch 0x%x", retval); - } - } - } - }else ms_warning("No audio stream accepted ?"); - } - linphone_call_set_on_hold_file(call, file_to_play); -} - -#ifdef VIDEO_ENABLED -static RtpSession * create_video_rtp_io_session(LinphoneCall *call) { - PayloadType *pt; - LinphoneCore *lc = call->core; - const char *local_ip = lp_config_get_string(lc->config, "video", "rtp_local_addr", "127.0.0.1"); - const char *remote_ip = lp_config_get_string(lc->config, "video", "rtp_remote_addr", "127.0.0.1"); - int local_port = lp_config_get_int(lc->config, "video", "rtp_local_port", 19076); - int remote_port = lp_config_get_int(lc->config, "video", "rtp_remote_port", 19078); - int ptnum = lp_config_get_int(lc->config, "video", "rtp_ptnum", 0); - const char *rtpmap = lp_config_get_string(lc->config, "video", "rtp_map", "vp8/90000/1"); - int symmetric = lp_config_get_int(lc->config, "video", "rtp_symmetric", 0); - int jittcomp = lp_config_get_int(lc->config, "video", "rtp_jittcomp", 0); /* 0 means no jitter buffer*/ - RtpSession *rtp_session = NULL; - pt = rtp_profile_get_payload_from_rtpmap(call->video_profile, rtpmap); - if (pt != NULL) { - call->rtp_io_video_profile = rtp_profile_new("RTP IO video profile"); - rtp_profile_set_payload(call->rtp_io_video_profile, ptnum, payload_type_clone(pt)); - rtp_session = ms_create_duplex_rtp_session(local_ip, local_port, -1, ms_factory_get_mtu(lc->factory)); - rtp_session_set_profile(rtp_session, call->rtp_io_video_profile); - rtp_session_set_remote_addr_and_port(rtp_session, remote_ip, remote_port, -1); - rtp_session_enable_rtcp(rtp_session, FALSE); - rtp_session_set_payload_type(rtp_session, ptnum); - rtp_session_set_symmetric_rtp(rtp_session, (bool_t)symmetric); - rtp_session_set_jitter_compensation(rtp_session, jittcomp); - rtp_session_enable_jitter_buffer(rtp_session, jittcomp>0); - } - return rtp_session; -} -#endif - -static void linphone_call_start_video_stream(LinphoneCall *call, LinphoneCallState next_state){ -#ifdef VIDEO_ENABLED - LinphoneCore *lc=call->core; - int used_pt=-1; - const SalStreamDescription *vstream; - MSFilter* source = NULL; - bool_t reused_preview = FALSE; - bool_t use_rtp_io = lp_config_get_int(lc->config, "video", "rtp_io", FALSE); - MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER; - - /* shutdown preview */ - if (lc->previewstream!=NULL) { - 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; - } - - vstream = sal_media_description_find_best_stream(call->resultdesc, SalVideo); - if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->rtp_port!=0) { - const char *rtp_addr=vstream->rtp_addr[0]!='\0' ? vstream->rtp_addr : call->resultdesc->addr; - const char *rtcp_addr=vstream->rtcp_addr[0]!='\0' ? vstream->rtcp_addr : call->resultdesc->addr; - const SalStreamDescription *local_st_desc=sal_media_description_find_stream(call->localdesc,vstream->proto,SalVideo); - bool_t is_multicast=ms_is_multicast(rtp_addr); - call->video_profile=make_profile(call,call->resultdesc,vstream,&used_pt); - - if (used_pt!=-1){ - MediaStreamDir dir= MediaStreamSendRecv; - bool_t is_inactive=FALSE; - MSWebCam *cam; - - call->current_params->video_codec = rtp_profile_get_payload(call->video_profile, used_pt); - call->current_params->has_video=TRUE; - - media_stream_set_max_network_bitrate(&call->videostream->ms, linphone_core_get_upload_bandwidth(lc) * 1000); - rtp_session_enable_rtcp_mux(call->videostream->ms.sessions.rtp_session, vstream->rtcp_mux); - if (lc->video_conf.preview_vsize.width!=0) - video_stream_set_preview_size(call->videostream,lc->video_conf.preview_vsize); - video_stream_set_fps(call->videostream,linphone_core_get_preferred_framerate(lc)); - if (lp_config_get_int(lc->config, "video", "nowebcam_uses_normal_fps", 0)) - call->videostream->staticimage_webcam_fps_optimization = FALSE; - video_stream_set_sent_video_size(call->videostream,linphone_core_get_preferred_video_size(lc)); - video_stream_enable_self_view(call->videostream,lc->video_conf.selfview); - if (call->video_window_id != NULL) - video_stream_set_native_window_id(call->videostream, call->video_window_id); - else if (lc->video_window_id != NULL) - video_stream_set_native_window_id(call->videostream, lc->video_window_id); - if (lc->preview_window_id != NULL) - video_stream_set_native_preview_window_id(call->videostream, lc->preview_window_id); - video_stream_use_preview_video_window (call->videostream,lc->use_preview_window); - - if (is_multicast){ - if (vstream->multicast_role == SalMulticastReceiver) - dir=MediaStreamRecvOnly; - else - dir=MediaStreamSendOnly; - } else if (vstream->dir==SalStreamSendOnly && lc->video_conf.capture ){ - dir=MediaStreamSendOnly; - }else if (vstream->dir==SalStreamRecvOnly && lc->video_conf.display ){ - dir=MediaStreamRecvOnly; - }else if (vstream->dir==SalStreamSendRecv){ - if (lc->video_conf.display && lc->video_conf.capture) - dir=MediaStreamSendRecv; - else if (lc->video_conf.display) - dir=MediaStreamRecvOnly; - else - dir=MediaStreamSendOnly; - }else{ - ms_warning("video stream is inactive."); - /*either inactive or incompatible with local capabilities*/ - is_inactive=TRUE; - } - cam = linphone_call_get_video_device(call); - if (!is_inactive){ - /* get remote stream description to check for zrtp-hash presence */ - SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); - const SalStreamDescription *remote_stream = sal_media_description_find_best_stream(remote_desc, SalVideo); - - if (sal_stream_description_has_srtp(vstream) == TRUE) { - int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, vstream->crypto_local_tag); - if (crypto_idx >= 0) { - ms_media_stream_sessions_set_srtp_recv_key_b64(&call->videostream->ms.sessions, vstream->crypto[0].algo,vstream->crypto[0].master_key); - ms_media_stream_sessions_set_srtp_send_key_b64(&call->videostream->ms.sessions, vstream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key); - } - } - configure_rtp_session_for_rtcp_fb(call, vstream); - configure_rtp_session_for_rtcp_xr(lc, call, SalVideo); - configure_adaptive_rate_control(call, (MediaStream*)call->videostream, call->current_params->video_codec, TRUE); - - call->log->video_enabled = TRUE; - video_stream_set_direction (call->videostream, dir); - ms_message("%s lc rotation:%d\n", __FUNCTION__, lc->device_rotation); - video_stream_set_device_rotation(call->videostream, lc->device_rotation); - video_stream_set_freeze_on_error(call->videostream, lp_config_get_int(lc->config, "video", "freeze_on_error", 1)); - if (is_multicast) - rtp_session_set_multicast_ttl(call->videostream->ms.sessions.rtp_session,vstream->ttl); - - video_stream_use_video_preset(call->videostream, lp_config_get_string(lc->config, "video", "preset", NULL)); - 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, -1, cam, source); - reused_preview = TRUE; - } else { - bool_t ok = TRUE; - if (use_rtp_io) { - io.input.type = io.output.type = MSResourceRtp; - io.input.session = io.output.session = create_video_rtp_io_session(call); - if (io.input.session == NULL) { - ok = FALSE; - ms_warning("Cannot create video RTP IO session"); - } - } else { - io.input.type = MSResourceCamera; - io.input.camera = cam; - io.output.type = MSResourceDefault; - } - if (ok) { - video_stream_start_from_io(call->videostream, - call->video_profile, rtp_addr, vstream->rtp_port, - rtcp_addr, - (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port+1) : 0, - used_pt, &io); - } - } - ms_media_stream_sessions_set_encryption_mandatory(&call->videostream->ms.sessions, - linphone_call_encryption_mandatory(call)); - _linphone_call_set_next_video_frame_decoded_trigger(call); - - /* start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */ - if (call->params->media_encryption==LinphoneMediaEncryptionZRTP || remote_stream->haveZrtpHash==1) { - /*audio stream is already encrypted and video stream is active*/ - if (media_stream_secured((MediaStream *)call->audiostream) && media_stream_get_state((MediaStream *)call->videostream) == MSStreamStarted) { - video_stream_start_zrtp(call->videostream); - if (remote_stream->haveZrtpHash == 1) { - int retval; - if ((retval = ms_zrtp_setPeerHelloHash(call->videostream->ms.sessions.zrtp_context, (uint8_t *)remote_stream->zrtphash, strlen((const char *)(remote_stream->zrtphash)))) != 0) { - ms_error("video stream ZRTP hash mismatch 0x%x", retval); - } - } - } - } - } - }else ms_warning("No video stream accepted."); - }else{ - 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 -} - -static void real_time_text_character_received(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { - if (id == MS_RTT_4103_RECEIVED_CHAR) { - LinphoneCall *call = (LinphoneCall *)userdata; - RealtimeTextReceivedCharacter *data = (RealtimeTextReceivedCharacter *)arg; - LinphoneChatRoom * chat_room = linphone_call_get_chat_room(call); - linphone_core_real_time_text_received(call->core, chat_room, data->character, call); - } -} - -static void linphone_call_start_text_stream(LinphoneCall *call) { - LinphoneCore *lc = call->core; - int used_pt = -1; - const SalStreamDescription *tstream; - - tstream = sal_media_description_find_best_stream(call->resultdesc, SalText); - if (tstream != NULL && tstream->dir != SalStreamInactive && tstream->rtp_port != 0) { - const char *rtp_addr = tstream->rtp_addr[0] != '\0' ? tstream->rtp_addr : call->resultdesc->addr; - const char *rtcp_addr = tstream->rtcp_addr[0] != '\0' ? tstream->rtcp_addr : call->resultdesc->addr; - const SalStreamDescription *local_st_desc = sal_media_description_find_stream(call->localdesc, tstream->proto, SalText); - bool_t is_multicast = ms_is_multicast(rtp_addr); - call->text_profile = make_profile(call, call->resultdesc, tstream, &used_pt); - - if (used_pt != -1) { - call->current_params->text_codec = rtp_profile_get_payload(call->text_profile, used_pt); - call->current_params->realtimetext_enabled = TRUE; - - if (sal_stream_description_has_srtp(tstream) == TRUE) { - int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, tstream->crypto_local_tag); - if (crypto_idx >= 0) { - ms_media_stream_sessions_set_srtp_recv_key_b64(&call->textstream->ms.sessions, tstream->crypto[0].algo, tstream->crypto[0].master_key); - ms_media_stream_sessions_set_srtp_send_key_b64(&call->textstream->ms.sessions, tstream->crypto[0].algo, local_st_desc->crypto[crypto_idx].master_key); - } - } - - configure_rtp_session_for_rtcp_fb(call, tstream); - configure_rtp_session_for_rtcp_xr(lc, call, SalText); - rtp_session_enable_rtcp_mux(call->textstream->ms.sessions.rtp_session, tstream->rtcp_mux); - - if (is_multicast) rtp_session_set_multicast_ttl(call->textstream->ms.sessions.rtp_session,tstream->ttl); - - text_stream_start(call->textstream, call->text_profile, rtp_addr, tstream->rtp_port, rtcp_addr, (linphone_core_rtcp_enabled(lc) && !is_multicast) ? (tstream->rtcp_port ? tstream->rtcp_port : tstream->rtp_port + 1) : 0, used_pt); - ms_filter_add_notify_callback(call->textstream->rttsink, real_time_text_character_received, call, FALSE); - - ms_media_stream_sessions_set_encryption_mandatory(&call->textstream->ms.sessions, - linphone_call_encryption_mandatory(call)); - } else ms_warning("No text stream accepted."); - } else { - ms_message("No valid text stream defined."); - } -} - -void linphone_call_set_symmetric_rtp(LinphoneCall *call, bool_t val){ - int i; - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){ - MSMediaStreamSessions *mss = &call->sessions[i]; - if (mss->rtp_session){ - rtp_session_set_symmetric_rtp(mss->rtp_session, val); - } - } -} - -void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState next_state){ - LinphoneCore *lc=call->core; - bool_t video_will_be_used = FALSE; -#ifdef VIDEO_ENABLED - const SalStreamDescription *vstream=sal_media_description_find_best_stream(call->resultdesc,SalVideo); -#endif - - switch (next_state){ - case LinphoneCallIncomingEarlyMedia: - if (linphone_core_get_remote_ringback_tone(lc)){ - call->playing_ringbacktone = TRUE; - } - BCTBX_NO_BREAK; - case LinphoneCallOutgoingEarlyMedia: - if (!call->params->real_early_media){ - call->all_muted = TRUE; - } - break; - default: - call->playing_ringbacktone = FALSE; - call->all_muted = FALSE; - break; - } - - call->current_params->audio_codec = NULL; - call->current_params->video_codec = NULL; - call->current_params->text_codec = NULL; - - if ((call->audiostream == NULL) && (call->videostream == NULL)) { - ms_fatal("start_media_stream() called without prior init !"); - return; - } - - if (call->ice_session != NULL){ - /*if there is an ICE session when we are about to start streams, then ICE will conduct the media path checking and authentication properly. - * Symmetric RTP must be turned off*/ - linphone_call_set_symmetric_rtp(call, FALSE); - } - - call->nb_media_starts++; -#if defined(VIDEO_ENABLED) - if (vstream!=NULL && vstream->dir!=SalStreamInactive && vstream->payloads!=NULL){ - /*when video is used, do not make adaptive rate control on audio, it is stupid.*/ - video_will_be_used = TRUE; - } -#endif - ms_message("linphone_call_start_media_streams() call=[%p] local upload_bandwidth=[%i] kbit/s; local download_bandwidth=[%i] kbit/s", - call, linphone_core_get_upload_bandwidth(lc),linphone_core_get_download_bandwidth(lc)); - - call->current_params->has_audio = FALSE; - if (call->audiostream!=NULL) { - linphone_call_start_audio_stream(call, next_state, video_will_be_used); - } else { - ms_warning("linphone_call_start_media_streams(): no audio stream!"); - } - 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, next_state); - } - /*the onhold file is to be played once both audio and video are ready.*/ - if (call->onhold_file && !call->params->in_conference && call->audiostream){ - MSFilter *player = audio_stream_open_remote_play(call->audiostream, call->onhold_file); - if (player){ - int pause_time=500; - ms_filter_call_method(player, MS_PLAYER_SET_LOOP, &pause_time); - ms_filter_call_method_noarg(player, MS_PLAYER_START); - } - } - - call->up_bw=linphone_core_get_upload_bandwidth(lc); - - if (call->params->realtimetext_enabled) { - linphone_call_start_text_stream(call); - } - - set_dtls_fingerprint_on_all_streams(call); - - if ((call->ice_session != NULL) && (ice_session_state(call->ice_session) != IS_Completed)) { - if (call->params->media_encryption==LinphoneMediaEncryptionDTLS) { - call->current_params->update_call_when_ice_completed = FALSE; - ms_message("Disabling update call when ice completed on call [%p]",call); - } - ice_session_start_connectivity_checks(call->ice_session); - } else { - /*should not start dtls until ice is completed*/ - start_dtls_on_all_streams(call); - } - -} - -void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call){ - if(call->audiostream && call->audiostream->ms.state==MSStreamPreparing) - audio_stream_unprepare_sound(call->audiostream); -#ifdef VIDEO_ENABLED - if (call->videostream && call->videostream->ms.state==MSStreamPreparing) - video_stream_unprepare_video(call->videostream); -#endif - if (call->textstream && call->textstream->ms.state == MSStreamPreparing) - text_stream_unprepare_text(call->textstream); -} - -static bool_t update_stream_crypto_params(LinphoneCall *call, const SalStreamDescription *local_st_desc, SalStreamDescription *old_stream, SalStreamDescription *new_stream, MediaStream *ms){ - int crypto_idx = find_crypto_index_from_tag(local_st_desc->crypto, new_stream->crypto_local_tag); - if (crypto_idx >= 0) { - if (call->localdesc_changed & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) - ms_media_stream_sessions_set_srtp_send_key_b64(&ms->sessions, new_stream->crypto[0].algo,local_st_desc->crypto[crypto_idx].master_key); - if (strcmp(old_stream->crypto[0].master_key,new_stream->crypto[0].master_key)!=0){ - ms_media_stream_sessions_set_srtp_recv_key_b64(&ms->sessions, new_stream->crypto[0].algo,new_stream->crypto[0].master_key); - } - return TRUE; - } else { - ms_warning("Failed to find local crypto algo with tag: %d", new_stream->crypto_local_tag); - } - return FALSE; -} - -void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md) { - SalStreamDescription *old_stream; - SalStreamDescription *new_stream; - const SalStreamDescription *local_st_desc; - - local_st_desc = sal_media_description_find_secure_stream_of_type(call->localdesc, SalAudio); - old_stream = sal_media_description_find_secure_stream_of_type(old_md, SalAudio); - new_stream = sal_media_description_find_secure_stream_of_type(new_md, SalAudio); - if (call->audiostream && local_st_desc && old_stream && new_stream && - update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->audiostream->ms)){ - } - - local_st_desc = sal_media_description_find_secure_stream_of_type(call->localdesc, SalText); - old_stream = sal_media_description_find_secure_stream_of_type(old_md, SalText); - new_stream = sal_media_description_find_secure_stream_of_type(new_md, SalText); - if (call->textstream && local_st_desc && old_stream && new_stream && - update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->textstream->ms)){ - } - - start_dtls_on_all_streams(call); - -#ifdef VIDEO_ENABLED - local_st_desc = sal_media_description_find_secure_stream_of_type(call->localdesc, SalVideo); - old_stream = sal_media_description_find_secure_stream_of_type(old_md, SalVideo); - new_stream = sal_media_description_find_secure_stream_of_type(new_md, SalVideo); - if (call->videostream && local_st_desc && old_stream && new_stream && - update_stream_crypto_params(call,local_st_desc,old_stream,new_stream,&call->videostream->ms)){ - } -#endif -} - -void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call) { - SalMediaDescription *remote_desc = sal_call_get_remote_media_description(call->op); - if (remote_desc) { - call->remote_session_id = remote_desc->session_id; - call->remote_session_ver = remote_desc->session_ver; - } -} - -void linphone_call_delete_ice_session(LinphoneCall *call){ - if (call->ice_session != NULL) { - ice_session_destroy(call->ice_session); - call->ice_session = NULL; - if (call->audiostream != NULL) call->audiostream->ms.ice_check_list = NULL; - if (call->videostream != NULL) call->videostream->ms.ice_check_list = NULL; - if (call->textstream != NULL) call->textstream->ms.ice_check_list = NULL; - call->audio_stats->ice_state = LinphoneIceStateNotActivated; - call->video_stats->ice_state = LinphoneIceStateNotActivated; - call->text_stats->ice_state = LinphoneIceStateNotActivated; - } -} - -void linphone_call_delete_upnp_session(LinphoneCall *call){ -#ifdef BUILD_UPNP - if(call->upnp_session!=NULL) { - linphone_upnp_session_destroy(call->upnp_session); - call->upnp_session=NULL; - } -#endif //BUILD_UPNP -} - -static void linphone_call_log_fill_stats(LinphoneCallLog *log, MediaStream *st){ - float quality=media_stream_get_average_quality_rating(st); - if (quality>=0){ - if (log->quality!=-1){ - log->quality*=quality/5.0f; - }else log->quality=quality; - } -} - -static void update_rtp_stats(LinphoneCall *call, int stream_index) { - if (call->sessions[stream_index].rtp_session) { - const rtp_stats_t *stats = rtp_session_get_stats(call->sessions[stream_index].rtp_session); - LinphoneCallStats *call_stats = NULL; - if (stream_index == call->main_audio_stream_index) { - call_stats = call->audio_stats; - } else if (stream_index == call->main_video_stream_index) { - call_stats = call->video_stats; - } else { - call_stats = call->text_stats; - } - if (call_stats) memcpy(&(call_stats->rtp_stats), stats, sizeof(*stats)); - } -} - -static void linphone_call_stop_audio_stream(LinphoneCall *call) { - LinphoneCore *lc = call->core; - if (call->audiostream!=NULL) { - linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_AUDIO); - media_stream_reclaim_sessions(&call->audiostream->ms,&call->sessions[call->main_audio_stream_index]); - - if (call->audiostream->ec){ - char *state_str=NULL; - 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_write_relative_file(call->core->config, EC_STATE_STORE, state_str); - } - } - audio_stream_get_local_rtp_stats(call->audiostream,&call->log->local_stats); - linphone_call_log_fill_stats (call->log,(MediaStream*)call->audiostream); - if (call->endpoint){ - linphone_conference_on_call_stream_stopping(lc->conf_ctx, call); - } - ms_bandwidth_controller_remove_stream(lc->bw_controller, (MediaStream*)call->audiostream); - audio_stream_stop(call->audiostream); - update_rtp_stats(call, call->main_audio_stream_index); - call->audiostream=NULL; - linphone_call_handle_stream_events(call, call->main_audio_stream_index); - rtp_session_unregister_event_queue(call->sessions[call->main_audio_stream_index].rtp_session, call->audiostream_app_evq); - ortp_ev_queue_flush(call->audiostream_app_evq); - ortp_ev_queue_destroy(call->audiostream_app_evq); - call->audiostream_app_evq=NULL; - - call->current_params->audio_codec = NULL; - } -} - -static void linphone_call_stop_video_stream(LinphoneCall *call) { -#ifdef VIDEO_ENABLED - if (call->videostream!=NULL){ - linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_VIDEO); - media_stream_reclaim_sessions(&call->videostream->ms,&call->sessions[call->main_video_stream_index]); - linphone_call_log_fill_stats(call->log,(MediaStream*)call->videostream); - ms_bandwidth_controller_remove_stream(call->core->bw_controller, (MediaStream*)call->videostream); - video_stream_stop(call->videostream); - update_rtp_stats(call, call->main_video_stream_index); - call->videostream=NULL; - linphone_call_handle_stream_events(call, call->main_video_stream_index); - rtp_session_unregister_event_queue(call->sessions[call->main_video_stream_index].rtp_session, call->videostream_app_evq); - ortp_ev_queue_flush(call->videostream_app_evq); - ortp_ev_queue_destroy(call->videostream_app_evq); - call->videostream_app_evq=NULL; - call->current_params->video_codec = NULL; - } -#endif -} - -static void unset_rtp_profile(LinphoneCall *call, int i){ - if (call->sessions[i].rtp_session) - rtp_session_set_profile(call->sessions[i].rtp_session,&av_profile); -} - -static void linphone_call_stop_text_stream(LinphoneCall *call) { - if (call->textstream != NULL) { - linphone_reporting_update_media_info(call, LINPHONE_CALL_STATS_TEXT); - media_stream_reclaim_sessions(&call->textstream->ms, &call->sessions[call->main_text_stream_index]); - linphone_call_log_fill_stats(call->log, (MediaStream*)call->textstream); - text_stream_stop(call->textstream); - update_rtp_stats(call, call->main_text_stream_index); - call->textstream = NULL; - linphone_call_handle_stream_events(call, call->main_text_stream_index); - rtp_session_unregister_event_queue(call->sessions[call->main_text_stream_index].rtp_session, call->textstream_app_evq); - ortp_ev_queue_flush(call->textstream_app_evq); - ortp_ev_queue_destroy(call->textstream_app_evq); - call->textstream_app_evq = NULL; - call->current_params->text_codec = NULL; - } -} - -void linphone_call_stop_media_streams(LinphoneCall *call){ - if (call->audiostream || call->videostream || call->textstream) { - if (call->audiostream && call->videostream) - audio_stream_unlink_video(call->audiostream, call->videostream); - linphone_call_stop_audio_stream(call); - linphone_call_stop_video_stream(call); - linphone_call_stop_text_stream(call); - - if (call->core->msevq != NULL) { - ms_event_queue_skip(call->core->msevq); - } - } - - if (call->audio_profile){ - rtp_profile_destroy(call->audio_profile); - call->audio_profile=NULL; - unset_rtp_profile(call,call->main_audio_stream_index); - } - if (call->video_profile){ - rtp_profile_destroy(call->video_profile); - call->video_profile=NULL; - unset_rtp_profile(call,call->main_video_stream_index); - } - if (call->text_profile){ - rtp_profile_destroy(call->text_profile); - call->text_profile=NULL; - unset_rtp_profile(call,call->main_text_stream_index); - } - if (call->rtp_io_audio_profile) { - rtp_profile_destroy(call->rtp_io_audio_profile); - call->rtp_io_audio_profile = NULL; - } - if (call->rtp_io_video_profile) { - rtp_profile_destroy(call->rtp_io_video_profile); - call->rtp_io_video_profile = NULL; - } - - linphone_core_soundcard_hint_check(call->core); -} - -void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t enable) { - if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){ - bool_t bypass_mode = !enable; - ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_SET_BYPASS_MODE,&bypass_mode); - } -} - -bool_t linphone_call_echo_cancellation_enabled(LinphoneCall *call) { - if (call!=NULL && call->audiostream!=NULL && call->audiostream->ec){ - bool_t val; - ms_filter_call_method(call->audiostream->ec,MS_ECHO_CANCELLER_GET_BYPASS_MODE,&val); - return !val; - } else { - return linphone_core_echo_cancellation_enabled(call->core); - } -} - -void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val){ - if (call!=NULL && call->audiostream!=NULL ) { - if (val) { - const char *type=lp_config_get_string(call->core->config,"sound","el_type","mic"); - if (strcasecmp(type,"mic")==0) - audio_stream_enable_echo_limiter(call->audiostream,ELControlMic); - else if (strcasecmp(type,"full")==0) - audio_stream_enable_echo_limiter(call->audiostream,ELControlFull); - } else { - audio_stream_enable_echo_limiter(call->audiostream,ELInactive); - } - } -} - -bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call){ - if (call!=NULL && call->audiostream!=NULL ){ - return call->audiostream->el_type !=ELInactive ; - } else { - return linphone_core_echo_limiter_enabled(call->core); - } -} - -float linphone_call_get_play_volume(LinphoneCall *call){ - AudioStream *st=call->audiostream; - if (st && st->volrecv){ - float vol=0; - ms_filter_call_method(st->volrecv,MS_VOLUME_GET,&vol); - return vol; - - } - return LINPHONE_VOLUME_DB_LOWEST; -} - -float linphone_call_get_record_volume(LinphoneCall *call){ - AudioStream *st=call->audiostream; - if (st && st->volsend && !call->audio_muted && call->state==LinphoneCallStreamsRunning){ - float vol=0; - ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); - return vol; - - } - return LINPHONE_VOLUME_DB_LOWEST; -} - -float linphone_call_get_speaker_volume_gain(const LinphoneCall *call) { - if(call->audiostream) return audio_stream_get_sound_card_output_gain(call->audiostream); - else { - ms_error("Could not get playback volume: no audio stream"); - return -1.0f; - } -} - -void linphone_call_set_speaker_volume_gain(LinphoneCall *call, float volume) { - if(call->audiostream) audio_stream_set_sound_card_output_gain(call->audiostream, volume); - else ms_error("Could not set playback volume: no audio stream"); -} - -float linphone_call_get_microphone_volume_gain(const LinphoneCall *call) { - if(call->audiostream) return audio_stream_get_sound_card_input_gain(call->audiostream); - else { - ms_error("Could not get record volume: no audio stream"); - return -1.0f; - } -} - -void linphone_call_set_microphone_volume_gain(LinphoneCall *call, float volume) { - if(call->audiostream) audio_stream_set_sound_card_input_gain(call->audiostream, volume); - else ms_error("Could not set record volume: no audio stream"); -} - -static float agregate_ratings(float audio_rating, float video_rating){ - float result; - if (audio_rating<0 && video_rating<0) result=-1; - else if (audio_rating<0) result=video_rating*5.0f; - else if (video_rating<0) result=audio_rating*5.0f; - else result=audio_rating*video_rating*5.0f; - return result; -} - -float linphone_call_get_current_quality(LinphoneCall *call){ - float audio_rating=-1.f; - float video_rating=-1.f; - - if (call->audiostream){ - audio_rating=media_stream_get_quality_rating((MediaStream*)call->audiostream)/5.0f; - } - if (call->videostream){ - video_rating=media_stream_get_quality_rating((MediaStream*)call->videostream)/5.0f; - } - return agregate_ratings(audio_rating, video_rating); -} - -float linphone_call_get_average_quality(LinphoneCall *call){ - float audio_rating=-1.f; - float video_rating=-1.f; - - if (call->audiostream){ - audio_rating = media_stream_get_average_quality_rating((MediaStream*)call->audiostream)/5.0f; - } - if (call->videostream){ - video_rating = media_stream_get_average_quality_rating((MediaStream*)call->videostream)/5.0f; - } - return agregate_ratings(audio_rating, video_rating); -} - -static void update_local_stats(LinphoneCallStats *stats, MediaStream *stream) { - PayloadType *pt; - RtpSession *session = stream->sessions.rtp_session; - const MSQualityIndicator *qi = media_stream_get_quality_indicator(stream); - if (qi) { - stats->local_late_rate=ms_quality_indicator_get_local_late_rate(qi); - stats->local_loss_rate=ms_quality_indicator_get_local_loss_rate(qi); - } - media_stream_get_local_rtp_stats(stream, &stats->rtp_stats); - pt = rtp_profile_get_payload(rtp_session_get_profile(session), rtp_session_get_send_payload_type(session)); - stats->clockrate = pt ? pt->clock_rate : 8000; -} - -static MediaStream *linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type){ - switch(type){ - case LinphoneStreamTypeAudio: - return &call->audiostream->ms; - case LinphoneStreamTypeVideo: - return &call->videostream->ms; - case LinphoneStreamTypeText: - return &call->textstream->ms; - case LinphoneStreamTypeUnknown: - break; - } - return NULL; -} - -static void _linphone_call_stats_clone(LinphoneCallStats *dst, const LinphoneCallStats *src) { - /* - * Save the belle_sip_object_t part, copy the entire structure and restore the belle_sip_object_t part - */ - belle_sip_object_t tmp = dst->base; - memcpy(dst, src, sizeof(LinphoneCallStats)); - dst->base = tmp; - - dst->received_rtcp = NULL; - dst->sent_rtcp = NULL; -} - -LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type){ - if ((int)type >=0 && type<=LinphoneStreamTypeText){ - LinphoneCallStats *stats = NULL; - LinphoneCallStats *stats_copy = linphone_call_stats_new(); - if (type == LinphoneStreamTypeAudio) { - stats = call->audio_stats; - } else if (type == LinphoneStreamTypeVideo) { - stats = call->video_stats; - } else if (type == LinphoneStreamTypeText) { - stats = call->text_stats; - } - MediaStream *ms = linphone_call_get_stream(call, type); - if (ms && stats) update_local_stats(stats, ms); - _linphone_call_stats_clone(stats_copy, stats); - return stats_copy; - } - ms_error("Invalid stream type %i", (int)type); - return NULL; -} - -LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call) { - return linphone_call_get_stats(call, LinphoneStreamTypeAudio); -} - -LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call) { - return linphone_call_get_stats(call, LinphoneStreamTypeVideo); -} - -LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call) { - return linphone_call_get_stats(call, LinphoneStreamTypeText); -} - -static bool_t ice_in_progress(LinphoneCallStats *stats){ - return stats->ice_state==LinphoneIceStateInProgress; -} - -bool_t linphone_call_media_in_progress(LinphoneCall *call){ - bool_t ret=FALSE; - if (ice_in_progress(call->audio_stats) || ice_in_progress(call->video_stats) || ice_in_progress(call->text_stats)) - ret=TRUE; - /*TODO: could check zrtp state, upnp state*/ - return ret; -} - -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallStats); - -BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallStats, belle_sip_object_t, - NULL, // destroy - _linphone_call_stats_clone, // clone - NULL, // marshal - TRUE -); - -LinphoneCallStats *linphone_call_stats_new() { - LinphoneCallStats *stats = belle_sip_object_new(LinphoneCallStats); - return stats; -} - -LinphoneCallStats* linphone_call_stats_ref(LinphoneCallStats* stats) { - return (LinphoneCallStats*) belle_sip_object_ref(stats); -} - -void linphone_call_stats_unref(LinphoneCallStats* stats) { - belle_sip_object_unref(stats); -} - -void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats) { - return stats->user_data; -} - -void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data) { - stats->user_data = data; -} - -LinphoneStreamType linphone_call_stats_get_type(const LinphoneCallStats *stats) { - return stats->type; -} - -float linphone_call_stats_get_sender_loss_rate(const LinphoneCallStats *stats) { - const report_block_t *srb = NULL; - - if (!stats || !stats->sent_rtcp) - return 0.0; - /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ - if (stats->sent_rtcp->b_cont != NULL) - msgpullup(stats->sent_rtcp, -1); - - do{ - if (rtcp_is_SR(stats->sent_rtcp)) - srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0); - else if (rtcp_is_RR(stats->sent_rtcp)) - srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0); - if (srb) break; - }while (rtcp_next_packet(stats->sent_rtcp)); - rtcp_rewind(stats->sent_rtcp); - if (!srb) - return 0.0; - return 100.0f * report_block_get_fraction_lost(srb) / 256.0f; -} - -float linphone_call_stats_get_receiver_loss_rate(const LinphoneCallStats *stats) { - const report_block_t *rrb = NULL; - - if (!stats || !stats->received_rtcp) - return 0.0; - /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ - if (stats->received_rtcp->b_cont != NULL) - msgpullup(stats->received_rtcp, -1); - - do{ - if (rtcp_is_RR(stats->received_rtcp)) - rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0); - else if (rtcp_is_SR(stats->received_rtcp)) - rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0); - if (rrb) break; - }while (rtcp_next_packet(stats->received_rtcp)); - rtcp_rewind(stats->received_rtcp); - if (!rrb) - return 0.0; - return 100.0f * report_block_get_fraction_lost(rrb) / 256.0f; -} - -float linphone_call_stats_get_local_loss_rate(const LinphoneCallStats *stats) { - return stats->local_loss_rate; -} - -float linphone_call_stats_get_local_late_rate(const LinphoneCallStats *stats) { - return stats->local_late_rate; -} - -float linphone_call_stats_get_sender_interarrival_jitter(const LinphoneCallStats *stats) { - const report_block_t *srb = NULL; - - if (!stats || !stats->sent_rtcp) - return 0.0; - /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ - if (stats->sent_rtcp->b_cont != NULL) - msgpullup(stats->sent_rtcp, -1); - if (rtcp_is_SR(stats->sent_rtcp)) - srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0); - else if (rtcp_is_RR(stats->sent_rtcp)) - srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0); - if (!srb) - return 0.0; - if (stats->clockrate == 0) - return 0.0; - return (float)report_block_get_interarrival_jitter(srb) / (float)stats->clockrate; -} - -float linphone_call_stats_get_receiver_interarrival_jitter(const LinphoneCallStats *stats) { - const report_block_t *rrb = NULL; - - if (!stats || !stats->received_rtcp) - return 0.0; - /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ - if (stats->received_rtcp->b_cont != NULL) - msgpullup(stats->received_rtcp, -1); - if (rtcp_is_SR(stats->received_rtcp)) - rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0); - else if (rtcp_is_RR(stats->received_rtcp)) - rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0); - if (!rrb) - return 0.0; - if (stats->clockrate == 0) - return 0.0; - return (float)report_block_get_interarrival_jitter(rrb) / (float)stats->clockrate; -} - -const rtp_stats_t *linphone_call_stats_get_rtp_stats(const LinphoneCallStats *stats) { - return &stats->rtp_stats; -} - -uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCallStats *stats) { - return linphone_call_stats_get_rtp_stats(stats)->outoftime; -} - -float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats) { - return stats->download_bandwidth; -} - -float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats) { - return stats->upload_bandwidth; -} - -float linphone_call_stats_get_estimated_download_bandwidth(const LinphoneCallStats *stats) { - return stats->estimated_download_bandwidth; -} - -LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats) { - return stats->ice_state; -} - -LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats) { - return stats->upnp_state; -} - -LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remote(const LinphoneCallStats *stats) { - return (LinphoneAddressFamily)stats->rtp_remote_family; -} - -float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *stats) { - return stats->jitter_stats.jitter_buffer_size_ms; -} - -float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats) { - return stats->round_trip_delay; -} - -void linphone_call_start_recording(LinphoneCall *call){ - if (!call->params->record_file){ - ms_error("linphone_call_start_recording(): no output file specified. Use linphone_call_params_set_record_file()."); - return; - } - if (call->audiostream && !call->params->in_conference){ - audio_stream_mixed_record_start(call->audiostream); - } - call->record_active=TRUE; -} - -void linphone_call_stop_recording(LinphoneCall *call){ - if (call->audiostream && !call->params->in_conference){ - audio_stream_mixed_record_stop(call->audiostream); - } - call->record_active=FALSE; -} - -static void report_bandwidth_for_stream(LinphoneCall *call, MediaStream *ms, LinphoneStreamType type){ - bool_t active = ms ? (media_stream_get_state(ms) == MSStreamStarted) : FALSE; - LinphoneCallStats *stats = NULL; - if (type == LinphoneStreamTypeAudio) { - stats = call->audio_stats; - } else if (type == LinphoneStreamTypeVideo) { - stats = call->video_stats; - } else if (type == LinphoneStreamTypeText) { - stats = call->text_stats; - } else { - return; - } - - stats->download_bandwidth=(active) ? (float)(media_stream_get_down_bw(ms)*1e-3) : 0.f; - stats->upload_bandwidth=(active) ? (float)(media_stream_get_up_bw(ms)*1e-3) : 0.f; - stats->rtcp_download_bandwidth=(active) ? (float)(media_stream_get_rtcp_down_bw(ms)*1e-3) : 0.f; - stats->rtcp_upload_bandwidth=(active) ? (float)(media_stream_get_rtcp_up_bw(ms)*1e-3) : 0.f; - stats->rtp_remote_family=(active) - ? (ortp_stream_is_ipv6(&ms->sessions.rtp_session->rtp.gs) ? LinphoneAddressFamilyInet6 : LinphoneAddressFamilyInet) : LinphoneAddressFamilyUnspec; - - if (call->core->send_call_stats_periodical_updates){ - if (active) update_local_stats(stats, ms); - stats->updated |= LINPHONE_CALL_STATS_PERIODICAL_UPDATE; - linphone_call_notify_stats_updated(call, stats); - stats->updated=0; - } -} - -static void report_bandwidth(LinphoneCall *call, MediaStream *as, MediaStream *vs, MediaStream *ts){ - report_bandwidth_for_stream(call, as, LinphoneStreamTypeAudio); - report_bandwidth_for_stream(call, vs, LinphoneStreamTypeVideo); - report_bandwidth_for_stream(call, ts, LinphoneStreamTypeText); - - ms_message( "Bandwidth usage for call [%p]:\n" - "\tRTP audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f, ed=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec\n" - "\tRTCP audio=[d=%5.1f,u=%5.1f], video=[d=%5.1f,u=%5.1f], text=[d=%5.1f,u=%5.1f] kbits/sec", - call, - call->audio_stats->download_bandwidth, - call->audio_stats->upload_bandwidth, - call->video_stats->download_bandwidth, - call->video_stats->upload_bandwidth, - call->video_stats->estimated_download_bandwidth, - call->text_stats->download_bandwidth, - call->text_stats->upload_bandwidth, - call->audio_stats->rtcp_download_bandwidth, - call->audio_stats->rtcp_upload_bandwidth, - call->video_stats->rtcp_download_bandwidth, - call->video_stats->rtcp_upload_bandwidth, - call->text_stats->rtcp_download_bandwidth, - call->text_stats->rtcp_upload_bandwidth - ); -} - -static void linphone_call_lost(LinphoneCall *call){ - LinphoneCore *lc = call->core; - char *temp = NULL; - char *from = NULL; - - from = linphone_call_get_remote_address_as_string(call); - temp = ms_strdup_printf("Media connectivity with %s is lost, call is going to be closed.", from ? from : "?"); - if (from) ms_free(from); - ms_message("LinphoneCall [%p]: %s", call, temp); - linphone_core_notify_display_warning(lc, temp); - call->non_op_error = TRUE; - linphone_error_info_set(call->ei,NULL, LinphoneReasonIOError, 503, "Media lost", NULL); - linphone_call_terminate(call); - linphone_core_play_named_tone(lc, LinphoneToneCallLost); - ms_free(temp); -} - -static void linphone_call_on_ice_gathering_finished(LinphoneCall *call){ - int ping_time; - const SalMediaDescription *rmd = sal_call_get_remote_media_description(call->op); - if (rmd){ - linphone_call_clear_unused_ice_candidates(call, rmd); - } - ice_session_compute_candidates_foundations(call->ice_session); - ice_session_eliminate_redundant_candidates(call->ice_session); - ice_session_choose_default_candidates(call->ice_session); - ping_time = ice_session_average_gathering_round_trip_time(call->ice_session); - if (ping_time >=0) { - call->ping_time=ping_time; - } -} - -static void handle_ice_events(LinphoneCall *call, OrtpEvent *ev){ - OrtpEventType evt=ortp_event_get_type(ev); - OrtpEventData *evd=ortp_event_get_data(ev); - - if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) { - switch (ice_session_state(call->ice_session)) { - case IS_Completed: - case IS_Failed: - /* At least one ICE check list has succeeded, so perform a call update. */ - if (ice_session_has_completed_check_list(call->ice_session) == TRUE) { - const LinphoneCallParams *current_param = linphone_call_get_current_params(call); - if (ice_session_role(call->ice_session) == IR_Controlling && current_param->update_call_when_ice_completed ) { - LinphoneCallParams *params = linphone_core_create_call_params(call->core, call); - params->internal_call_update = TRUE; - linphone_call_update(call, params); - linphone_call_params_unref(params); - }else if (ice_session_role(call->ice_session) == IR_Controlled && call->incoming_ice_reinvite_pending){ - linphone_call_accept_update(call, NULL); - call->incoming_ice_reinvite_pending = FALSE; - } - start_dtls_on_all_streams(call); - } - break; - default: - break; - } - linphone_call_update_ice_state_in_call_stats(call); - } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) { - if (evd->info.ice_processing_successful==FALSE) { - ms_warning("No STUN answer from [%s], continuing without STUN",linphone_core_get_stun_server(call->core)); - } - linphone_call_on_ice_gathering_finished(call); - switch (call->state) { - case LinphoneCallUpdating: - linphone_call_start_update(call); - break; - case LinphoneCallUpdatedByRemote: - linphone_call_start_accept_update(call, call->prevstate,linphone_call_state_to_string(call->prevstate)); - break; - case LinphoneCallOutgoingInit: - linphone_call_stop_media_streams_for_ice_gathering(call); - linphone_call_proceed_with_invite_if_ready(call, NULL); - break; - case LinphoneCallIdle: - linphone_call_stop_media_streams_for_ice_gathering(call); - linphone_call_update_local_media_description_from_ice_or_upnp(call); - sal_call_set_local_media_description(call->op,call->localdesc); - linphone_core_notify_incoming_call(call->core, call); - break; - default: - break; - } - } else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) { - if (call->state==LinphoneCallUpdatedByRemote){ - linphone_call_start_accept_update(call, call->prevstate, linphone_call_state_to_string(call->prevstate)); - linphone_call_update_ice_state_in_call_stats(call); - } - } else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) { - ice_session_restart(call->ice_session, IR_Controlling); - linphone_call_update(call, call->current_params); - } else if (evt == ORTP_EVENT_ICE_DEACTIVATION_NEEDED) { - if (ice_session_role(call->ice_session) == IR_Controlling) { - ice_session_destroy(call->ice_session); - call->ice_session = NULL; - LinphoneCallParams *params = linphone_core_create_call_params(call->core, call); - params->internal_call_update = TRUE; - linphone_call_update(call, params); - linphone_call_params_unref(params); - } - } -} - -/*do not change the prototype of this function, it is also used internally in linphone-daemon.*/ -void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev){ - OrtpEventType evt=ortp_event_get_type(ev); - OrtpEventData *evd=ortp_event_get_data(ev); - - if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { - stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session); - if(stats->received_rtcp != NULL) - freemsg(stats->received_rtcp); - stats->received_rtcp = evd->packet; - stats->rtcp_received_via_mux = evd->info.socket_type == OrtpRTPSocket; - evd->packet = NULL; - stats->updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; - update_local_stats(stats,ms); - } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { - memcpy(&stats->jitter_stats, rtp_session_get_jitter_stats(ms->sessions.rtp_session), sizeof(jitter_stats_t)); - if (stats->sent_rtcp != NULL) - freemsg(stats->sent_rtcp); - stats->sent_rtcp = evd->packet; - evd->packet = NULL; - stats->updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; - update_local_stats(stats,ms); - } -} - -void linphone_call_stats_uninit(LinphoneCallStats *stats){ - if (stats->received_rtcp) { - freemsg(stats->received_rtcp); - stats->received_rtcp=NULL; - } - if (stats->sent_rtcp){ - freemsg(stats->sent_rtcp); - stats->sent_rtcp=NULL; - } -} - -void linphone_call_notify_stats_updated_with_stream_index(LinphoneCall *call, int stream_index){ - LinphoneCallStats *stats = NULL; - if (stream_index == call->main_audio_stream_index) { - stats = call->audio_stats; - } else if (stream_index == call->main_video_stream_index) { - stats = call->video_stats; - } else { - stats = call->text_stats; - } - if (stats->updated){ - switch(stats->updated) { - case LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE: - case LINPHONE_CALL_STATS_SENT_RTCP_UPDATE: - linphone_reporting_on_rtcp_update(call, stream_index == call->main_audio_stream_index ? SalAudio : stream_index == call->main_video_stream_index ? SalVideo : SalText); - break; - default: - break; - } - linphone_call_notify_stats_updated(call, stats); - stats->updated = 0; - } -} - -static MediaStream * linphone_call_get_media_stream(LinphoneCall *call, int stream_index){ - if (stream_index == call->main_audio_stream_index) - return (MediaStream*)call->audiostream; - if (stream_index == call->main_video_stream_index) - return (MediaStream*)call->videostream; - if (stream_index == call->main_text_stream_index) - return (MediaStream*)call->textstream; - ms_error("linphone_call_get_media_stream(): no stream index %i", stream_index); - return NULL; -} - -static OrtpEvQueue *linphone_call_get_event_queue(LinphoneCall *call, int stream_index){ - if (stream_index == call->main_audio_stream_index) - return call->audiostream_app_evq; - if (stream_index == call->main_video_stream_index) - return call->videostream_app_evq; - if (stream_index == call->main_text_stream_index) - return call->textstream_app_evq; - ms_error("linphone_call_get_event_queue(): no stream index %i", stream_index); - return NULL; -} - -void linphone_call_handle_stream_events(LinphoneCall *call, int stream_index){ - MediaStream *ms = stream_index == call->main_audio_stream_index ? (MediaStream *)call->audiostream : (stream_index == call->main_video_stream_index ? (MediaStream *)call->videostream : (MediaStream *)call->textstream); - OrtpEvQueue *evq; - OrtpEvent *ev; - - if (ms){ - /* Ensure there is no dangling ICE check list. */ - if (call->ice_session == NULL) { - media_stream_set_ice_check_list(ms, NULL); - } - - switch(ms->type){ - case MSAudio: - audio_stream_iterate((AudioStream*)ms); - break; - case MSVideo: - #ifdef VIDEO_ENABLED - video_stream_iterate((VideoStream*)ms); - #endif - break; - case MSText: - text_stream_iterate((TextStream*)ms); - break; - default: - ms_error("linphone_call_handle_stream_events(): unsupported stream type."); - return; - break; - } - } - /*yes the event queue has to be taken at each iteration, because ice events may perform operations re-creating the streams*/ - while((evq = linphone_call_get_event_queue(call, stream_index)) != NULL && NULL != (ev=ortp_ev_queue_get(evq))){ - OrtpEventType evt=ortp_event_get_type(ev); - OrtpEventData *evd=ortp_event_get_data(ev); - int stats_index; - LinphoneCallStats *stats = NULL; - - if (stream_index == call->main_audio_stream_index) { - stats_index = LINPHONE_CALL_STATS_AUDIO; - stats = call->audio_stats; - } else if (stream_index == call->main_video_stream_index) { - stats_index = LINPHONE_CALL_STATS_VIDEO; - stats = call->video_stats; - } else { - stats_index = LINPHONE_CALL_STATS_TEXT; - stats = call->text_stats; - } - - /*This MUST be done before any call to "linphone_call_stats_fill" since it has ownership over evd->packet*/ - if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { - do { - if (rtcp_is_RTPFB(evd->packet)) { - if (rtcp_RTPFB_get_type(evd->packet) == RTCP_RTPFB_TMMBR) { - linphone_call_notify_tmmbr_received(call, stream_index, (int)rtcp_RTPFB_tmmbr_get_max_bitrate(evd->packet)); - } - } - } while (rtcp_next_packet(evd->packet)); - rtcp_rewind(evd->packet); - } - - /*and yes the MediaStream must be taken at each iteration, because it may have changed due to the handling of events - * in this loop*/ - ms = linphone_call_get_media_stream(call, stream_index); - - if (ms) linphone_call_stats_fill(stats,ms,ev); - linphone_call_notify_stats_updated_with_stream_index(call,stats_index); - - if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED){ - if (stream_index == call->main_audio_stream_index) - linphone_call_audiostream_encryption_changed(call, evd->info.zrtp_stream_encrypted); - else if (stream_index == call->main_video_stream_index) { - propagate_encryption_changed(call); - } - } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) { - if (stream_index == call->main_audio_stream_index) - linphone_call_audiostream_auth_token_ready(call, evd->info.zrtp_info.sas, evd->info.zrtp_info.verified); - } else if (evt == ORTP_EVENT_DTLS_ENCRYPTION_CHANGED) { - if (stream_index == call->main_audio_stream_index) - linphone_call_audiostream_encryption_changed(call, evd->info.dtls_stream_encrypted); - else if (stream_index == call->main_video_stream_index) - propagate_encryption_changed(call); - }else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) - || (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED) - || (evt == ORTP_EVENT_ICE_DEACTIVATION_NEEDED)) { - if (ms) handle_ice_events(call, ev); - } else if (evt==ORTP_EVENT_TELEPHONE_EVENT){ - linphone_core_dtmf_received(call,evd->info.telephone_event); - } else if (evt == ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE) { - ms_message("Video bandwidth estimation is %i kbit/s", (int)evd->info.video_bandwidth_available / 1000); - /* If this event happens then it should be a video stream */ - if (stream_index == call->main_video_stream_index) - stats->estimated_download_bandwidth = (float)(evd->info.video_bandwidth_available)*(float)1e-3; - } - ortp_event_destroy(ev); - } -} - -void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed){ - int disconnect_timeout = linphone_core_get_nortp_timeout(call->core); - bool_t disconnected=FALSE; - - switch (call->state) { - case LinphoneCallStreamsRunning: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallPausedByRemote: - case LinphoneCallPaused: - if (one_second_elapsed){ - float audio_load=0, video_load=0, text_load=0; - if (call->audiostream != NULL) { - if (call->audiostream->ms.sessions.ticker) - audio_load = ms_ticker_get_average_load(call->audiostream->ms.sessions.ticker); - } - if (call->videostream != NULL) { - if (call->videostream->ms.sessions.ticker) - video_load = ms_ticker_get_average_load(call->videostream->ms.sessions.ticker); - } - if (call->textstream != NULL) { - if (call->textstream->ms.sessions.ticker) - text_load = ms_ticker_get_average_load(call->textstream->ms.sessions.ticker); - } - report_bandwidth(call, (MediaStream*)call->audiostream, (MediaStream*)call->videostream, (MediaStream*)call->textstream); - ms_message("Thread processing load: audio=%f\tvideo=%f\ttext=%f", audio_load, video_load, text_load); - } - break; - default: - /*no stats for other states*/ - break; - } - -#ifdef BUILD_UPNP - linphone_upnp_call_process(call); -#endif //BUILD_UPNP - - linphone_call_handle_stream_events(call, call->main_audio_stream_index); - linphone_call_handle_stream_events(call, call->main_video_stream_index); - linphone_call_handle_stream_events(call, call->main_text_stream_index); - if ((call->state == LinphoneCallStreamsRunning || - call->state == LinphoneCallPausedByRemote) && one_second_elapsed && call->audiostream!=NULL - && call->audiostream->ms.state==MSStreamStarted && disconnect_timeout>0 ) { - disconnected=!audio_stream_alive(call->audiostream,disconnect_timeout); - } - if (disconnected) linphone_call_lost(call); -} - -void linphone_call_log_completed(LinphoneCall *call){ - LinphoneCore *lc=call->core; - - call->log->duration= _linphone_call_compute_duration(call); /*store duration since connected*/ - call->log->error_info = linphone_error_info_ref((LinphoneErrorInfo*)linphone_call_get_error_info(call)); - - if (call->log->status==LinphoneCallMissed){ - char *info; - lc->missed_calls++; - info=ortp_strdup_printf(ngettext("You have missed %i call.", - "You have missed %i calls.", lc->missed_calls), - lc->missed_calls); - linphone_core_notify_display_status(lc,info); - ms_free(info); - } - linphone_core_report_call_log(lc, call->log); -} - -LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call) { - return call->transfer_state; -} - -void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state) { - if (state != call->transfer_state) { - ms_message("Transfer state for call [%p] changed from [%s] to [%s]",call - ,linphone_call_state_to_string(call->transfer_state) - ,linphone_call_state_to_string(state)); - call->transfer_state = state; - linphone_call_notify_transfer_state_changed(call, state); - } -} - -bool_t linphone_call_is_in_conference(const LinphoneCall *call) { - return call->params->in_conference; -} - -LinphoneConference *linphone_call_get_conference(const LinphoneCall *call) { - return call->conf_ref; -} - -void linphone_call_zoom_video(LinphoneCall* call, float zoom_factor, float* cx, float* cy) { - VideoStream* vstream = call->videostream; - if (vstream && vstream->output) { - float zoom[3]; - float halfsize; - - if (zoom_factor < 1) - zoom_factor = 1; - halfsize = 0.5f * 1.0f / zoom_factor; - - if ((*cx - halfsize) < 0) - *cx = 0 + halfsize; - if ((*cx + halfsize) > 1) - *cx = 1 - halfsize; - if ((*cy - halfsize) < 0) - *cy = 0 + halfsize; - if ((*cy + halfsize) > 1) - *cy = 1 - halfsize; - - zoom[0] = zoom_factor; - zoom[1] = *cx; - zoom[2] = *cy; - ms_filter_call_method(vstream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom); - }else ms_warning("Could not apply zoom: video output wasn't activated."); -} - -static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , LinphoneProxyConfig *dest_proxy){ - LinphoneAddress *ctt=NULL; - LinphoneAddress *ret=NULL; - //const char *localip=call->localip; - - /* first use user's supplied ip address if asked*/ - 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; - } else if (call->op && sal_op_get_contact_address(call->op)!=NULL){ - /* if already choosed, don't change it */ - return NULL; - } else if (call->ping_op && sal_op_get_contact_address(call->ping_op)) { - /* if the ping OPTIONS request succeeded use the contact guessed from the - received, rport*/ - ms_message("Contact has been fixed using OPTIONS"/* to %s",guessed*/); - ret=linphone_address_clone(sal_op_get_contact_address(call->ping_op));; - } else if (dest_proxy && dest_proxy->op && sal_op_get_contact_address(dest_proxy->op)){ - /*if using a proxy, use the contact address as guessed with the REGISTERs*/ - ms_message("Contact has been fixed using proxy" /*to %s",fixed_contact*/); - ret=linphone_address_clone(sal_op_get_contact_address(dest_proxy->op)); - } else { - ctt=linphone_core_get_primary_contact_parsed(lc); - if (ctt!=NULL){ - /*otherwise use supplied localip*/ - linphone_address_set_domain(ctt,NULL/*localip*/); - linphone_address_set_port(ctt,-1/*linphone_core_get_sip_port(lc)*/); - ms_message("Contact has not been fixed stack will do"/* to %s",ret*/); - ret=ctt; - } - } - return ret; -} - -void linphone_call_set_contact_op(LinphoneCall* call) { - LinphoneAddress *contact; - if ((contact=get_fixed_contact(call->core,call,call->dest_proxy))) - sal_op_set_and_clean_contact_address(call->op, (SalAddress *)contact); - /*else, we already have a contact so keep it "as is"*/ -} - -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_params(LinphoneCall *call, const LinphoneCallParams *params){ - if ( call->state == LinphoneCallOutgoingInit || call->state == LinphoneCallIncomingReceived){ - _linphone_call_set_new_params(call, params); - } - else { - ms_error("linphone_call_set_params() invalid state %s to call this function", linphone_call_state_to_string(call->state)); - } -} - - -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; -} - -const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call){ - return call->params; -} - - -static int send_dtmf_handler(void *data, unsigned int revents){ - LinphoneCall *call = (LinphoneCall*)data; - /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/ - if (linphone_core_get_use_rfc2833_for_dtmf(call->core)!=0 || linphone_core_get_use_info_for_dtmf(call->core)==0) - { - /* In Band DTMF */ - if (call->audiostream!=NULL){ - audio_stream_send_dtmf(call->audiostream,*call->dtmf_sequence); - } - else - { - ms_error("Cannot send RFC2833 DTMF when we are not in communication."); - return FALSE; - } - } - if (linphone_core_get_use_info_for_dtmf(call->core)!=0){ - /* Out of Band DTMF (use INFO method) */ - sal_call_send_dtmf(call->op,*call->dtmf_sequence); - } - - /*this check is needed because linphone_call_send_dtmf does not set the timer since its a single character*/ - if (call->dtmfs_timer!=NULL) { - memmove(call->dtmf_sequence, call->dtmf_sequence+1, strlen(call->dtmf_sequence)); - } - /* continue only if the dtmf sequence is not empty*/ - if (call->dtmf_sequence!=NULL&&*call->dtmf_sequence!='\0') { - return TRUE; - } else { - linphone_call_cancel_dtmfs(call); - return FALSE; - } -} - -LinphoneStatus linphone_call_send_dtmf(LinphoneCall *call, char dtmf) { - if (call==NULL){ - ms_warning("linphone_call_send_dtmf(): invalid call, canceling DTMF."); - return -1; - } - call->dtmf_sequence = &dtmf; - send_dtmf_handler(call,0); - call->dtmf_sequence = NULL; - return 0; -} - -LinphoneStatus linphone_call_send_dtmfs(LinphoneCall *call,const char *dtmfs) { - if (call==NULL){ - ms_warning("linphone_call_send_dtmfs(): invalid call, canceling DTMF sequence."); - return -1; - } - if (call->dtmfs_timer!=NULL){ - ms_warning("linphone_call_send_dtmfs(): a DTMF sequence is already in place, canceling DTMF sequence."); - return -2; - } - if (dtmfs != NULL) { - int delay_ms = lp_config_get_int(call->core->config,"net","dtmf_delay_ms",200); - call->dtmf_sequence = ms_strdup(dtmfs); - call->dtmfs_timer = sal_create_timer(call->core->sal, send_dtmf_handler, call, delay_ms, "DTMF sequence timer"); - } - return 0; -} - -void linphone_call_cancel_dtmfs(LinphoneCall *call) { - /*nothing to do*/ - if (!call || !call->dtmfs_timer) return; - - sal_cancel_timer(call->core->sal, call->dtmfs_timer); - belle_sip_object_unref(call->dtmfs_timer); - call->dtmfs_timer = NULL; - if (call->dtmf_sequence != NULL) { - ms_free(call->dtmf_sequence); - call->dtmf_sequence = NULL; - } -} - -void * linphone_call_get_native_video_window_id(const LinphoneCall *call) { - if (call->video_window_id) { - /* The video id was previously set by the app. */ - return call->video_window_id; - } -#ifdef VIDEO_ENABLED - else if (call->videostream) { - /* It was not set but we want to get the one automatically created by mediastreamer2 (desktop versions only). */ - return video_stream_get_native_window_id(call->videostream); - } -#endif - return 0; -} - -void linphone_call_set_native_video_window_id(LinphoneCall *call, void *id) { - call->video_window_id = id; -#ifdef VIDEO_ENABLED - if (call->videostream) { - video_stream_set_native_window_id(call->videostream, id); - } -#endif -} - -MSWebCam *linphone_call_get_video_device(const LinphoneCall *call) { - LinphoneCallState state = linphone_call_get_state(call); - bool_t paused = (state == LinphoneCallPausing) || (state == LinphoneCallPaused); - if (paused || call->all_muted || (call->camera_enabled == FALSE)) - return get_nowebcam_device(call->core->factory); - else - return call->core->video_conf.device; -} - -void linphone_call_set_audio_route(LinphoneCall *call, LinphoneAudioRoute route) { - if (call != NULL && call->audiostream != NULL){ - audio_stream_set_audio_route(call->audiostream, (MSAudioRoute) route); - } -} - -LinphoneChatRoom * linphone_call_get_chat_room(LinphoneCall *call) { - if (!call->chat_room){ - if (call->state != LinphoneCallReleased && call->state != LinphoneCallEnd){ - call->chat_room = _linphone_core_create_chat_room_from_call(call); - } - } - return call->chat_room; -} - -int linphone_call_get_stream_count(LinphoneCall *call) { - // Revisit when multiple media streams will be implemented -#ifdef VIDEO_ENABLED - if (linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) { - return 3; - } - return 2; -#else - if (linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) { - return 2; - } - return 1; -#endif -} - -MSFormatType linphone_call_get_stream_type(LinphoneCall *call, int stream_index) { - // Revisit when multiple media streams will be implemented - if (stream_index == call->main_video_stream_index) { - return MSVideo; - } else if (stream_index == call->main_text_stream_index) { - return MSText; - } else if (stream_index == call->main_audio_stream_index){ - return MSAudio; - } - return MSUnknownMedia; -} - -RtpTransport* linphone_call_get_meta_rtp_transport(LinphoneCall *call, int stream_index) { - RtpTransport *meta_rtp; - RtpTransport *meta_rtcp; - - if (!call || stream_index < 0 || stream_index >= linphone_call_get_stream_count(call)) { - return NULL; - } - - rtp_session_get_transports(call->sessions[stream_index].rtp_session, &meta_rtp, &meta_rtcp); - return meta_rtp; -} - -RtpTransport* linphone_call_get_meta_rtcp_transport(LinphoneCall *call, int stream_index) { - RtpTransport *meta_rtp; - RtpTransport *meta_rtcp; - - if (!call || stream_index < 0 || stream_index >= linphone_call_get_stream_count(call)) { - return NULL; - } - - rtp_session_get_transports(call->sessions[stream_index].rtp_session, &meta_rtp, &meta_rtcp); - return meta_rtcp; -} - -LinphoneStatus linphone_call_pause(LinphoneCall *call) { - int err = _linphone_call_pause(call); - if (err == 0) call->paused_by_app = TRUE; - return err; -} - -/* Internal version that does not play tone indication*/ -int _linphone_call_pause(LinphoneCall *call) { - LinphoneCore *lc; - const char *subject = NULL; - - if ((call->state != LinphoneCallStreamsRunning) && (call->state != LinphoneCallPausedByRemote)) { - ms_warning("Cannot pause this call, it is not active."); - return -1; - } - if (sal_media_description_has_dir(call->resultdesc, SalStreamSendRecv)) { - subject = "Call on hold"; - } else if (sal_media_description_has_dir(call->resultdesc, SalStreamRecvOnly)) { - subject = "Call on hold for me too"; - } else { - ms_error("No reason to pause this call, it is already paused or inactive."); - return -1; - } - - lc = linphone_call_get_core(call); - call->broken = FALSE; - linphone_call_set_state(call, LinphoneCallPausing, "Pausing call"); - linphone_call_make_local_media_description(call); -#ifdef BUILD_UPNP - if (call->upnp_session != NULL) { - linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); - } -#endif // BUILD_UPNP - sal_call_set_local_media_description(call->op, call->localdesc); - 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_core_notify_display_status(lc, _("Pausing the current call...")); - if (call->audiostream || call->videostream || call->textstream) - linphone_call_stop_media_streams(call); - call->paused_by_app = FALSE; - return 0; -} - -LinphoneStatus linphone_call_resume(LinphoneCall *call) { - LinphoneCore *lc; - const char *subject = "Call resuming"; - char *remote_address; - char *display_status; - - if (call->state != LinphoneCallPaused) { - ms_warning("we cannot resume a call that has not been established and paused before"); - return -1; - } - lc = linphone_call_get_core(call); - 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; - } - linphone_core_preempt_sound_resources(lc); - ms_message("Resuming call %p", call); - } - - call->was_automatically_paused = FALSE; - call->broken = FALSE; - - /* Stop playing music immediately. If remote side is a conference it - prevents the participants to hear it while the 200OK comes back. */ - if (call->audiostream) audio_stream_play(call->audiostream, NULL); - - linphone_call_make_local_media_description(call); -#ifdef BUILD_UPNP - if (call->upnp_session != NULL) { - linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); - } -#endif // BUILD_UPNP - if (!lc->sip_conf.sdp_200_ack) { - sal_call_set_local_media_description(call->op, call->localdesc); - } else { - sal_call_set_local_media_description(call->op, NULL); - } - 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, FALSE) != 0) { - return -1; - } - linphone_call_set_state(call, LinphoneCallResuming,"Resuming"); - if (call->params->in_conference == FALSE) - lc->current_call = call; - remote_address = linphone_call_get_remote_address_as_string(call); - display_status = ms_strdup_printf("Resuming the call with with %s", remote_address); - ms_free(remote_address); - linphone_core_notify_display_status(lc, display_status); - ms_free(display_status); - - if (lc->sip_conf.sdp_200_ack) { - /* We are NOT offering, set local media description after sending the call so that we are ready to - process the remote offer when it will arrive. */ - sal_call_set_local_media_description(call->op, call->localdesc); - } - return 0; -} - -static void terminate_call(LinphoneCall *call) { - LinphoneCore *lc = linphone_call_get_core(call); - const bctbx_list_t *calls = linphone_core_get_calls(lc); - bool_t stop_ringing = TRUE; - - if ((call->state == LinphoneCallIncomingReceived) && (linphone_error_info_get_reason(call->ei) != LinphoneReasonNotAnswered)){ - linphone_error_info_set_reason(call->ei, LinphoneReasonDeclined); - call->non_op_error = TRUE; - } - - /* Stop ringing */ - bool_t ring_during_early_media = linphone_core_get_ring_during_incoming_early_media(lc); - while(calls) { - if (((LinphoneCall *)calls->data)->state == LinphoneCallIncomingReceived || (ring_during_early_media && ((LinphoneCall *)calls->data)->state == LinphoneCallIncomingEarlyMedia)) { - stop_ringing = FALSE; - break; - } - calls = calls->next; - } - if(stop_ringing) { - linphone_core_stop_ringing(lc); - } - linphone_call_stop_media_streams(call); - -#ifdef BUILD_UPNP - linphone_call_delete_upnp_session(call); -#endif // BUILD_UPNP - - linphone_core_notify_display_status(lc, _("Call ended") ); - linphone_call_set_state(call, LinphoneCallEnd, "Call terminated"); -} - -LinphoneStatus linphone_call_terminate(LinphoneCall *call) { - return linphone_call_terminate_with_error_info(call, NULL); -} - - -LinphoneStatus linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneErrorInfo *ei){ - SalErrorInfo sei; - LinphoneErrorInfo* p_ei = (LinphoneErrorInfo*) ei; - - memset(&sei, 0, sizeof(sei)); - ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state)); - switch (call->state) { - case LinphoneCallReleased: - case LinphoneCallEnd: - case LinphoneCallError: - ms_warning("No need to terminate a call [%p] in state [%s]", call, linphone_call_state_to_string(call->state)); - return -1; - case LinphoneCallIncomingReceived: - case LinphoneCallIncomingEarlyMedia: - return linphone_call_decline_with_error_info(call, p_ei); - case LinphoneCallOutgoingInit: - /* In state OutgoingInit, op has to be destroyed */ - sal_op_release(call->op); - call->op = NULL; - break; - default: - - if (ei == NULL){ - sal_call_terminate(call->op); - } - else{ - linphone_error_info_to_sal(ei, &sei); - sal_call_terminate_with_error(call->op, &sei); - sal_error_info_reset(&sei); - } - break; - } - - terminate_call(call); - return 0; - -} - -LinphoneStatus linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { - char *real_url = NULL; - LinphoneCore *lc; - LinphoneAddress *real_parsed_url; - SalErrorInfo sei; - - if (call->state != LinphoneCallIncomingReceived) { - ms_error("Bad state for call redirection."); - return -1; - } - - lc = linphone_call_get_core(call); - real_parsed_url = linphone_core_interpret_url(lc, redirect_uri); - if (!real_parsed_url) { - /* Bad url */ - ms_error("Bad redirect URI: %s", redirect_uri ? redirect_uri : "NULL"); - return -1; - } - - memset(&sei, 0, sizeof(sei)); - real_url = linphone_address_as_string(real_parsed_url); - sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(call->op, &sei, real_url); - ms_free(real_url); - linphone_error_info_set(call->ei, NULL, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL); - call->non_op_error = TRUE; - terminate_call(call); - linphone_address_unref(real_parsed_url); - sal_error_info_reset(&sei); - return 0; -} - -LinphoneStatus linphone_call_decline(LinphoneCall * call, LinphoneReason reason) { - LinphoneStatus status; - LinphoneErrorInfo *ei = linphone_error_info_new(); - linphone_error_info_set(ei, "SIP", reason,linphone_reason_to_error_code(reason), NULL, NULL); - status = linphone_call_decline_with_error_info(call, ei); - linphone_error_info_unref(ei); - return status; -} - - -LinphoneStatus linphone_call_decline_with_error_info(LinphoneCall * call, const LinphoneErrorInfo *ei) { - SalErrorInfo sei; - SalErrorInfo sub_sei; - - memset(&sei, 0, sizeof(sei)); - memset(&sub_sei, 0, sizeof(sub_sei)); - sei.sub_sei = &sub_sei; - - if ((call->state != LinphoneCallIncomingReceived) && (call->state != LinphoneCallIncomingEarlyMedia)) { - ms_error("Cannot decline a call that is in state %s", linphone_call_state_to_string(call->state)); - return -1; - } - if (ei) { - linphone_error_info_to_sal(ei, &sei); - sal_call_decline_with_error_info(call->op, &sei , NULL); - }else{ - sal_call_decline(call->op, SalReasonDeclined, NULL); - } - sal_error_info_reset(&sei); - sal_error_info_reset(&sub_sei); - terminate_call(call); - return 0; -} - -LinphoneStatus linphone_call_accept(LinphoneCall *call) { - return linphone_call_accept_with_params(call, NULL); -} - -LinphoneStatus linphone_call_accept_with_params(LinphoneCall *call, const LinphoneCallParams *params) { - LinphoneCore *lc; - SalOp *replaced; - SalMediaDescription *new_md; - bool_t was_ringing = FALSE; - bctbx_list_t *iterator, *copy; - - switch (call->state) { - case LinphoneCallIncomingReceived: - case LinphoneCallIncomingEarlyMedia: - break; - default: - ms_error("linphone_core_accept_call_with_params() call [%p] is in state [%s], operation not permitted.", - call, linphone_call_state_to_string(call->state)); - return -1; - } - - lc = linphone_call_get_core(call); - for (iterator = copy = bctbx_list_copy(linphone_core_get_calls(lc)); iterator != NULL; iterator = bctbx_list_next(iterator)) { - LinphoneCall *a_call = (LinphoneCall *)bctbx_list_get_data(iterator); - if (a_call == call) continue; - switch (a_call->state) { - case LinphoneCallOutgoingInit: - case LinphoneCallOutgoingProgress: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - ms_message("Already existing call [%p] in state [%s], canceling it before accepting new call [%p]", - a_call, linphone_call_state_to_string(a_call->state), call); - linphone_call_terminate(a_call); - break; - default: - break; /* Nothing to do */ - } - } - bctbx_list_free(copy); - - /* Check if this call is supposed to replace an already running one */ - replaced = sal_call_get_replaces(call->op); - if (replaced) { - LinphoneCall *rc = (LinphoneCall *)sal_op_get_user_pointer(replaced); - if (rc) { - ms_message("Call %p replaces call %p. This last one is going to be terminated automatically.", call, rc); - linphone_call_terminate(rc); - } - } - - if (lc->current_call != call) { - linphone_core_preempt_sound_resources(lc); - } - - /* Stop ringing */ - if (linphone_ringtoneplayer_is_started(lc->ringtoneplayer)) { - ms_message("Stop ringing"); - linphone_core_stop_ringing(lc); - was_ringing = TRUE; - } - if (call->ringing_beep) { - linphone_core_stop_dtmf(lc); - call->ringing_beep = FALSE; - } - - /* Try to be best-effort in giving real local or routable contact address */ - linphone_call_set_contact_op(call); - if (params) { - _linphone_call_set_new_params(call, params); - linphone_call_prepare_ice(call, TRUE); - linphone_call_make_local_media_description(call); - sal_call_set_local_media_description(call->op, call->localdesc); - sal_op_set_sent_custom_header(call->op, params->custom_headers); - } - - /* Give a chance a set card prefered sampling frequency */ - if (call->localdesc->streams[0].max_rate > 0) { - ms_message("Configuring prefered card sampling rate to [%i]", call->localdesc->streams[0].max_rate); - if (lc->sound_conf.play_sndcard) - ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate); - if (lc->sound_conf.capt_sndcard) - ms_snd_card_set_preferred_sample_rate(lc->sound_conf.capt_sndcard, call->localdesc->streams[0].max_rate); - } - - if (!was_ringing && (call->audiostream->ms.state == MSStreamInitialized) && !lc->use_files) { - audio_stream_prepare_sound(call->audiostream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard); - } - - linphone_call_update_remote_session_id_and_ver(call); - - sal_call_accept(call->op); - 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); - linphone_call_stop_ice_for_inactive_streams(call, new_md); - if (new_md) { - linphone_call_update_streams(call, new_md, LinphoneCallStreamsRunning); - linphone_call_set_state(call, LinphoneCallStreamsRunning, "Connected (streams running)"); - } else { - call->expect_media_in_ack = TRUE; - } - - ms_message("Call answered"); - return 0; -} - -LinphoneStatus linphone_call_accept_early_media(LinphoneCall* call) { - return linphone_call_accept_early_media_with_params(call, NULL); -} - -LinphoneStatus linphone_call_accept_early_media_with_params(LinphoneCall *call, const LinphoneCallParams *params) { - SalMediaDescription* md; - - if (call->state != LinphoneCallIncomingReceived) { - ms_error("Bad state %s for linphone_core_accept_early_media_with_params()", linphone_call_state_to_string(call->state)); - return -1; - } - - /* Try to be best-effort in giving real local or routable contact address for 100Rel case */ - linphone_call_set_contact_op(call); - - /* If parameters are passed, update the media description */ - if (params) { - _linphone_call_set_new_params(call, params); - linphone_call_make_local_media_description(call); - sal_call_set_local_media_description(call->op, call->localdesc); - sal_op_set_sent_custom_header(call->op, params->custom_headers); - } - - sal_call_notify_ringing(call->op, TRUE); - - linphone_call_set_state(call, LinphoneCallIncomingEarlyMedia, "Incoming call early media"); - md = sal_call_get_final_media_description(call->op); - if (md) linphone_call_update_streams(call, md, call->state); - return 0; -} - -LinphoneStatus linphone_call_update(LinphoneCall *call, const LinphoneCallParams *params) { - int err = 0; - LinphoneCallState nextstate; - LinphoneCallState initial_state = call->state; - const LinphoneCallParams *current_params; - -#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - bool_t has_video = FALSE; -#endif - - switch (initial_state) { - case LinphoneCallIncomingReceived: - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - nextstate = LinphoneCallEarlyUpdating; - break; - case LinphoneCallStreamsRunning: - case LinphoneCallPausedByRemote: - case LinphoneCallUpdatedByRemote: - nextstate = LinphoneCallUpdating; - break; - case LinphoneCallPaused: - nextstate = LinphoneCallPausing; - break; - case LinphoneCallOutgoingProgress: - case LinphoneCallPausing: - case LinphoneCallResuming: - case LinphoneCallUpdating: - nextstate = initial_state; - break; - default: - ms_error("linphone_call_update() is not allowed in [%s] state", linphone_call_state_to_string(call->state)); - return -1; - } - - current_params = linphone_call_get_current_params(call); - if ((current_params != NULL) && (current_params == params)) { - ms_warning("linphone_call_update() is given the current params of the call, this probably not what you intend to do!"); - } - - linphone_call_check_ice_session(call, IR_Controlling, TRUE); - - if (params != NULL) { - call->broken = FALSE; - linphone_call_set_state(call, nextstate, "Updating call"); -#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - has_video = call->params->has_video; - - /* Video removal */ - if ((call->videostream != NULL) && !params->has_video) { - if (call->upnp_session != NULL) { - if (linphone_call_update_upnp(call) < 0) { - /* uPnP port mappings failed, proceed with the call anyway. */ - linphone_call_delete_upnp_session(call); - } - } - } -#endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */ - _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"); - return 0; - } - -#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - /* Video adding */ - 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); - if (linphone_call_update_upnp(call) < 0) { - /* uPnP port mappings failed, proceed with the call anyway. */ - linphone_call_delete_upnp_session(call); - } else { - return err; - } - } - } -#endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */ - if ((err = linphone_call_start_update(call)) && (call->state != initial_state)) { - /* Restore initial state */ - linphone_call_set_state(call, initial_state, "Restore initial state"); - } - } else { -#ifdef VIDEO_ENABLED - LinphoneCore *lc = linphone_call_get_core(call); - 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); - } - } -#endif - } - - return err; -} - -int linphone_call_start_update(LinphoneCall *call) { - const char *subject; - int err; - bool_t no_user_consent = call->params->no_user_consent; - LinphoneCore *lc = linphone_call_get_core(call); - - linphone_call_fill_media_multicast_addr(call); - - if (!no_user_consent) linphone_call_make_local_media_description(call); -#ifdef BUILD_UPNP - if (call->upnp_session != NULL) { - linphone_call_update_local_media_description_from_upnp(call->localdesc, call->upnp_session); - } -#endif // BUILD_UPNP - if (call->params->in_conference) { - subject = "Conference"; - } else if (call->params->internal_call_update) { - subject = "ICE processing concluded"; - } else if (no_user_consent) { - subject = "Refreshing"; - } else { - subject = "Media change"; - } - linphone_core_notify_display_status(lc, _("Modifying call parameters...")); - if (!lc->sip_conf.sdp_200_ack) { - sal_call_set_local_media_description(call->op, call->localdesc); - } else { - sal_call_set_local_media_description(call->op, NULL); - } - 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); - } - err = sal_call_update(call->op, subject, no_user_consent); - if (lc->sip_conf.sdp_200_ack) { - /* We are NOT offering, set local media description after sending the call so that we are ready to - process the remote offer when it will arrive. */ - sal_call_set_local_media_description(call->op, call->localdesc); - } - return err; -} - -LinphoneStatus linphone_call_defer_update(LinphoneCall *call) { - if (call->state != LinphoneCallUpdatedByRemote) { - ms_error("linphone_call_defer_update() not done in state LinphoneCallUpdatedByRemote"); - return -1; - } - - if (call->expect_media_in_ack) { - ms_error("linphone_call_defer_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)"); - return -1; - } - - call->defer_update=TRUE; - return 0; -} - -int linphone_call_start_accept_update(LinphoneCall *call, LinphoneCallState next_state, const char *state_info) { - SalMediaDescription *md; - - if ((call->ice_session != NULL) && (ice_session_nb_losing_pairs(call->ice_session) > 0)) { - /* Defer the sending of the answer until there are no losing pairs left */ - return 0; - } - - linphone_call_make_local_media_description(call); - linphone_call_update_remote_session_id_and_ver(call); - sal_call_set_local_media_description(call->op, call->localdesc); - sal_call_accept(call->op); - md = sal_call_get_final_media_description(call->op); - linphone_call_stop_ice_for_inactive_streams(call, md); - if (md && !sal_media_description_empty(md)) { - linphone_call_update_streams(call, md, next_state); - } - linphone_call_set_state(call, next_state, state_info); - return 0; -} - -int _linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info) { - SalMediaDescription *remote_desc; - bool_t keep_sdp_version; - LinphoneCore *lc = linphone_call_get_core(call); -#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP) - bool_t old_has_video = call->params->has_video; -#endif - - remote_desc = sal_call_get_remote_media_description(call->op); - keep_sdp_version = lp_config_get_int(lc->config, "sip", "keep_sdp_version", 0); - if (keep_sdp_version && (remote_desc->session_id == call->remote_session_id) && (remote_desc->session_ver == call->remote_session_ver)) { - /* 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, next_state, state_info); - return 0; - } - if (params == NULL) { - if (!sal_call_is_offerer(call->op)) { - /* Reset call param for multicast because this param is only relevant when offering */ - linphone_call_params_enable_audio_multicast(call->params, FALSE); - linphone_call_params_enable_video_multicast(call->params, FALSE); - } - } else { - _linphone_call_set_new_params(call, params); - } - - if (call->params->has_video && !linphone_core_video_enabled(lc)) { - ms_warning("Requested video but video support is globally disabled. Refusing video."); - call->params->has_video = FALSE; - } - if (call->current_params->in_conference) { - ms_warning("Video isn't supported in conference"); - call->params->has_video = FALSE; - } - /* Update multicast params according to call params */ - linphone_call_fill_media_multicast_addr(call); - - linphone_call_check_ice_session(call, IR_Controlled, TRUE); - linphone_call_init_media_streams(call); /* So that video stream is initialized if necessary */ - if (linphone_call_prepare_ice(call, TRUE) == 1) { - return 0; /* Deferred until completion of ICE gathering */ - } - -#ifdef BUILD_UPNP - if (call->upnp_session != NULL) { - linphone_call_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)) { - video_stream_prepare_video(call->videostream); - if (linphone_call_update_upnp(call) < 0) { - /* uPnP update failed, proceed with the call anyway. */ - linphone_call_delete_upnp_session(call); - } else return 0; - } -#endif // VIDEO_ENABLED - } -#endif // BUILD_UPNP - - linphone_call_start_accept_update(call, next_state, state_info); - return 0; -} - -LinphoneStatus linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params) { - if (call->state != LinphoneCallUpdatedByRemote) { - ms_error("linphone_call_accept_update(): invalid state %s to call this function.", linphone_call_state_to_string(call->state)); - return -1; - } - if (call->expect_media_in_ack) { - ms_error("linphone_call_accept_update() is not possible during a late offer incoming reINVITE (INVITE without SDP)"); - return -1; - } - return _linphone_call_accept_update(call, params, call->prevstate, linphone_call_state_to_string(call->prevstate)); -} - -LinphoneStatus linphone_call_transfer(LinphoneCall *call, const char *refer_to) { - char *real_url = NULL; - LinphoneCore *lc = linphone_call_get_core(call); - LinphoneAddress *real_parsed_url = linphone_core_interpret_url(lc, refer_to); - - if (!real_parsed_url) { - /* bad url */ - return -1; - } - //lc->call = NULL; // Do not do that you will lose the call afterward... - real_url = linphone_address_as_string(real_parsed_url); - sal_call_refer(call->op, real_url); - ms_free(real_url); - linphone_address_unref(real_parsed_url); - linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit); - return 0; -} - -LinphoneStatus linphone_call_transfer_to_another(LinphoneCall *call, LinphoneCall *dest) { - int result = sal_call_refer_with_replaces (call->op, dest->op); - linphone_call_set_transfer_state(call, LinphoneCallOutgoingInit); - return result; -} - -int linphone_call_abort(LinphoneCall *call, const char *error) { - LinphoneCore *lc = linphone_call_get_core(call); - - sal_call_terminate(call->op); - - /* Stop ringing */ - linphone_core_stop_ringing(lc); - linphone_call_stop_media_streams(call); - -#ifdef BUILD_UPNP - linphone_call_delete_upnp_session(call); -#endif // BUILD_UPNP - - linphone_core_notify_display_status(lc, _("Call aborted")); - linphone_call_set_state(call, LinphoneCallError, error); - return 0; -} - -int linphone_call_proceed_with_invite_if_ready(LinphoneCall *call, LinphoneProxyConfig *dest_proxy) { - bool_t ice_ready = FALSE; - bool_t upnp_ready = FALSE; - bool_t ping_ready = FALSE; - - if (call->ice_session != NULL) { - if (ice_session_candidates_gathered(call->ice_session)) ice_ready = TRUE; - } else { - ice_ready = TRUE; - } -#ifdef BUILD_UPNP - if (call->upnp_session != NULL) { - if (linphone_upnp_session_get_state(call->upnp_session) == LinphoneUpnpStateOk) upnp_ready = TRUE; - } else { - upnp_ready = TRUE; - } -#else - upnp_ready=TRUE; -#endif // BUILD_UPNP - if (call->ping_op != NULL) { - if (call->ping_replied == TRUE) ping_ready = TRUE; - } else { - ping_ready = TRUE; - } - - if ((ice_ready == TRUE) && (upnp_ready == TRUE) && (ping_ready == TRUE)) { - return linphone_call_start_invite(call, NULL); - } - return 0; -} - -int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destination /* = NULL if to be taken from the call log */) { - int err; - char *real_url, *barmsg; - char *from; - LinphoneCore *lc = linphone_call_get_core(call); - - /* Try to be best-effort in giving real local or routable contact address */ - linphone_call_set_contact_op(call); - - linphone_core_stop_dtmf_stream(lc); - linphone_call_make_local_media_description(call); - - if (lc->ringstream == NULL) { - if (lc->sound_conf.play_sndcard && lc->sound_conf.capt_sndcard) { - /* Give a chance a set card prefered sampling frequency */ - if (call->localdesc->streams[0].max_rate > 0) { - ms_snd_card_set_preferred_sample_rate(lc->sound_conf.play_sndcard, call->localdesc->streams[0].max_rate); - } - if (!lc->use_files) { - audio_stream_prepare_sound(call->audiostream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard); - } - } - } - real_url = linphone_address_as_string(destination ? destination : call->log->to); - from = linphone_address_as_string(call->log->from); - - if (!lc->sip_conf.sdp_200_ack) { - /* We are offering, set local media description before sending the call */ - sal_call_set_local_media_description(call->op, call->localdesc); - } - - barmsg = ms_strdup_printf("%s %s", _("Contacting"), real_url); - linphone_core_notify_display_status(lc, barmsg); - ms_free(barmsg); - - linphone_call_ref(call); /* Take a ref because sal_call() may destroy the call if no SIP transport is available */ - err = sal_call(call->op, from, real_url); - - if (err < 0) { - if ((call->state != LinphoneCallError) && (call->state != LinphoneCallReleased)) { - /* sal_call() may invoke call_failure() and call_released() SAL callbacks synchronously, - in which case there is no need to perform a state change here. */ - linphone_core_notify_display_status(lc, _("Could not call")); - linphone_call_stop_media_streams(call); - linphone_call_set_state(call, LinphoneCallError, "Call failed"); - } - goto end; - } - if (lc->sip_conf.sdp_200_ack) { - /* We are NOT offering, set local media description after sending the call so that we are ready to - process the remote offer when it will arrive. */ - sal_call_set_local_media_description(call->op, call->localdesc); - } - call->log->call_id = ms_strdup(sal_op_get_call_id(call->op)); /* Must be known at that time */ - linphone_call_set_state(call, LinphoneCallOutgoingProgress, "Outgoing call in progress"); - -end: - linphone_call_unref(call); /* Revert the ref taken before calling sal_call() */ - ms_free(real_url); - ms_free(from); - return err; -} - -int linphone_call_restart_invite(LinphoneCall *call) { - linphone_call_create_op(call); - linphone_call_stop_media_streams(call); - linphone_call_init_media_streams(call); - return linphone_call_start_invite(call, NULL); -} - -void linphone_call_set_broken(LinphoneCall *call){ - switch(call->state){ - /*for all the early states, we prefer to drop the call*/ - case LinphoneCallOutgoingInit: - case LinphoneCallOutgoingProgress: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallIncomingReceived: - case LinphoneCallIncomingEarlyMedia: - /*during the early states, the SAL layer reports the failure from the dialog or transaction layer, - * hence, there is nothing special to do*/ - //break; - case LinphoneCallStreamsRunning: - case LinphoneCallUpdating: - case LinphoneCallPausing: - case LinphoneCallResuming: - case LinphoneCallPaused: - case LinphoneCallPausedByRemote: - case LinphoneCallUpdatedByRemote: - /*during these states, the dialog is established. A failure of a transaction is not expected to close it. - * Instead we have to repair the dialog by sending a reINVITE*/ - call->broken = TRUE; - call->need_localip_refresh = TRUE; - break; - default: - ms_error("linphone_call_set_broken() unimplemented case."); - break; - } -} - -static void linphone_call_repair_by_invite_with_replaces(LinphoneCall *call) { - const char *call_id = sal_op_get_call_id(call->op); - const char *from_tag = sal_call_get_local_tag(call->op); - const char *to_tag = sal_call_get_remote_tag(call->op); - sal_op_kill_dialog(call->op); - linphone_call_create_op(call); - sal_call_set_replaces(call->op, call_id, from_tag, to_tag); - linphone_call_start_invite(call, NULL); -} - -void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call) { - LinphoneCallParams *params; - ms_message("LinphoneCall[%p] is going to be updated (reINVITE) in order to recover from lost connectivity", call); - if (call->ice_session){ - ice_session_reset(call->ice_session, IR_Controlling); - } - params = linphone_core_create_call_params(call->core, call); - linphone_call_update(call, params); - linphone_call_params_unref(params); -} - -void linphone_call_repair_if_broken(LinphoneCall *call){ - SalErrorInfo sei; - if (!call->broken) return; - if (!call->core->media_network_reachable) return; - - memset(&sei, 0, sizeof(sei)); - - /*Make sure that the proxy from which we received this call, or to which we routed this call is registered first*/ - if (call->dest_proxy){ - /*in all other cases, ie no proxy config, or a proxy config for which no registration was requested, we can start the - * call repair immediately.*/ - if (linphone_proxy_config_register_enabled(call->dest_proxy) - && linphone_proxy_config_get_state(call->dest_proxy) != LinphoneRegistrationOk) return; - } - - switch (call->state){ - case LinphoneCallUpdating: - case LinphoneCallPausing: - if (sal_call_dialog_request_pending(call->op)) { - /* Need to cancel first re-INVITE as described in section 5.5 of RFC 6141 */ - if (sal_call_cancel_invite(call->op) == 0){ - call->reinvite_on_cancel_response_requested = TRUE; - } - } - break; - case LinphoneCallStreamsRunning: - case LinphoneCallPaused: - case LinphoneCallPausedByRemote: - if (!sal_call_dialog_request_pending(call->op)) { - linphone_call_reinvite_to_recover_from_connection_loss(call); - } - break; - case LinphoneCallUpdatedByRemote: - if (sal_call_dialog_request_pending(call->op)) { - sal_error_info_set(&sei, SalReasonServiceUnavailable,"SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(call->op, &sei,NULL); - } - linphone_call_reinvite_to_recover_from_connection_loss(call); - break; - case LinphoneCallOutgoingInit: - case LinphoneCallOutgoingProgress: - if (sal_call_cancel_invite(call->op) == 0){ - call->reinvite_on_cancel_response_requested = TRUE; - } - break; - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallOutgoingRinging: - linphone_call_repair_by_invite_with_replaces(call); - break; - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallIncomingReceived: - /* Keep the call broken until a forked INVITE is received from the server. */ - break; - default: - ms_warning("linphone_call_repair_if_broken(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state)); - call->broken = FALSE; - break; - } - sal_error_info_reset(&sei); -} - -void linphone_call_refresh_sockets(LinphoneCall *call){ - int i; - for (i=0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; ++i){ - MSMediaStreamSessions *mss = &call->sessions[i]; - if (mss->rtp_session){ - rtp_session_refresh_sockets(mss->rtp_session); - } - } -} - -void linphone_call_replace_op(LinphoneCall *call, SalOp *op) { - SalOp *oldop = call->op; - LinphoneCallState oldstate = linphone_call_get_state(call); - call->op = op; - sal_op_set_user_pointer(call->op, call); - sal_call_set_local_media_description(call->op, call->localdesc); - switch (linphone_call_get_state(call)) { - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallIncomingReceived: - sal_call_notify_ringing(call->op, (linphone_call_get_state(call) == LinphoneCallIncomingEarlyMedia) ? TRUE : FALSE); - break; - case LinphoneCallConnected: - case LinphoneCallStreamsRunning: - sal_call_accept(call->op); - break; - default: - ms_warning("linphone_call_replace_op(): don't know what to do in state [%s]", linphone_call_state_to_string(call->state)); - break; - } - switch (oldstate) { - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallIncomingReceived: - sal_op_set_user_pointer(oldop, NULL); /* To make the call does not get terminated by terminating this op. */ - /* Do not terminate a forked INVITE */ - if (sal_call_get_replaces(op)) { - sal_call_terminate(oldop); - } else { - sal_op_kill_dialog(oldop); - } - break; - case LinphoneCallConnected: - case LinphoneCallStreamsRunning: - sal_call_terminate(oldop); - sal_op_kill_dialog(oldop); - break; - default: - break; - } - sal_op_release(oldop); -} - -void linphone_call_ogl_render(const LinphoneCall *call) { - #ifdef VIDEO_ENABLED - - VideoStream *stream = call->videostream; - if (stream && stream->output && ms_filter_get_id(stream->output) == MS_OGL_ID) - ms_filter_call_method(stream->output, MS_OGL_RENDER, NULL); - - #endif -} - -void linphone_call_add_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs) { - call->callbacks = bctbx_list_append(call->callbacks, linphone_call_cbs_ref(cbs)); -} - -void linphone_call_remove_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs) { - call->callbacks = bctbx_list_remove(call->callbacks, cbs); - linphone_call_cbs_unref(cbs); -} - -LinphoneCallCbs *linphone_call_get_current_callbacks(const LinphoneCall *call) { - return call->current_cbs; -} - -#define NOTIFY_IF_EXIST(function_name, ...) \ - bctbx_list_t* iterator; \ - for (iterator = call->callbacks; iterator != NULL; iterator = bctbx_list_next(iterator)) { \ - call->current_cbs = (LinphoneCallCbs *)bctbx_list_get_data(iterator); \ - if (call->current_cbs->function_name != NULL) { \ - call->current_cbs->function_name(__VA_ARGS__); \ - } \ - } - -void linphone_call_notify_state_changed(LinphoneCall *call, LinphoneCallState cstate, const char *message) { - NOTIFY_IF_EXIST(state_changed_cb, call, cstate, message) - linphone_core_notify_call_state_changed(linphone_call_get_core(call), call, cstate, message); -} - -void linphone_call_notify_dtmf_received(LinphoneCall *call, int dtmf) { - NOTIFY_IF_EXIST(dtmf_received_cb, call, dtmf) - linphone_core_notify_dtmf_received(linphone_call_get_core(call), call, dtmf); -} - -void linphone_call_notify_encryption_changed(LinphoneCall *call, bool_t on, const char *authentication_token) { - NOTIFY_IF_EXIST(encryption_changed_cb, call, on, authentication_token) - linphone_core_notify_call_encryption_changed(linphone_call_get_core(call), call, on, authentication_token); -} - -void linphone_call_notify_transfer_state_changed(LinphoneCall *call, LinphoneCallState cstate) { - NOTIFY_IF_EXIST(transfer_state_changed_cb, call, cstate) - linphone_core_notify_transfer_state_changed(linphone_call_get_core(call), call, cstate); -} - -void linphone_call_notify_stats_updated(LinphoneCall *call, const LinphoneCallStats *stats) { - NOTIFY_IF_EXIST(stats_updated_cb, call, stats) - linphone_core_notify_call_stats_updated(linphone_call_get_core(call), call, stats); -} - -void linphone_call_notify_info_message_received(LinphoneCall *call, const LinphoneInfoMessage *msg) { - NOTIFY_IF_EXIST(info_message_received_cb, call, msg) - linphone_core_notify_info_received(linphone_call_get_core(call), call, msg); -} - -void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received) { - NOTIFY_IF_EXIST(ack_processing, call, msg, is_received) -} - -void linphone_call_notify_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr) { - NOTIFY_IF_EXIST(tmmbr_received_cb, call, stream_index, tmmbr) -} - -void linphone_call_notify_snapshot_taken(LinphoneCall *call, const char *file_path) { - NOTIFY_IF_EXIST(snapshot_taken_cb, call, file_path) -} - -void linphone_call_notify_next_video_frame_decoded(LinphoneCall *call) { - NOTIFY_IF_EXIST(next_video_frame_decoded_cb, call) -} diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index abc4325df..135013f8a 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -18,15 +18,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "linphone/api/c-content.h" +#include "linphone/core_utils.h" #include "linphone/core.h" -#include "linphone/sipsetup.h" -#include "linphone/lpconfig.h" #include "linphone/logging.h" +#include "linphone/lpconfig.h" +#include "linphone/sipsetup.h" + #include "private.h" #include "logging-private.h" #include "quality_reporting.h" #include "lime.h" #include "conference_private.h" +#include "logger/logger.h" #ifdef SQLITE_STORAGE_ENABLED #include "sqlite3_bctbx_vfs.h" @@ -38,10 +42,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include #include - #include "bctoolbox/defs.h" -#include "bctoolbox/crypto.h" #include "bctoolbox/regex.h" +#include "belr/grammarbuilder.h" #include "mediastreamer2/dtmfgen.h" #include "mediastreamer2/mediastream.h" @@ -51,10 +54,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msjpegwriter.h" #include "mediastreamer2/msogl.h" #include "mediastreamer2/msvolume.h" +#include "mediastreamer2/msqrcodereader.h" +#include "bctoolbox/charconv.h" +#include "chat/chat-room/client-group-chat-room-p.h" +#include "chat/chat-room/client-group-to-basic-chat-room.h" +#include "chat/chat-room/server-group-chat-room-p.h" +#include "conference/handlers/local-conference-list-event-handler.h" +#include "conference/handlers/remote-conference-event-handler.h" +#include "conference/handlers/remote-conference-list-event-handler.h" +#include "content/content-manager.h" +#include "content/content-type.h" +#include "core/core-p.h" + +// For migration purpose. +#include "address/address-p.h" +#include "c-wrapper/c-wrapper.h" -#include #ifdef INET6 #ifndef _WIN32 @@ -71,6 +88,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "TargetConditionals.h" #endif +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "conference/params/media-session-params-p.h" + #ifdef HAVE_ZLIB #define COMPRESSED_LOG_COLLECTION_EXTENSION "gz" #ifdef _WIN32 @@ -123,14 +144,12 @@ static void set_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t cu static void set_sip_network_reachable(LinphoneCore* lc,bool_t isReachable, time_t curtime); static void set_media_network_reachable(LinphoneCore* lc,bool_t isReachable); static void linphone_core_run_hooks(LinphoneCore *lc); -static void linphone_core_uninit(LinphoneCore *lc); static void linphone_core_zrtp_cache_close(LinphoneCore *lc); void linphone_core_zrtp_cache_db_init(LinphoneCore *lc, const char *fileName); #include "enum.h" #include "contact_providers_priv.h" - const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); static void toggle_video_preview(LinphoneCore *lc, bool_t val); @@ -144,7 +163,11 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val); #define HOLD_MUSIC_WAV "toy-mono.wav" #define HOLD_MUSIC_MKV "dont_wait_too_long.mkv" -extern SalCallbacks linphone_sal_callbacks; +using namespace std; + +using namespace LinphonePrivate; + +extern Sal::Callbacks linphone_sal_callbacks; static void _linphone_core_cbs_uninit(LinphoneCoreCbs *cbs); @@ -355,6 +378,14 @@ void linphone_core_cbs_set_notify_received(LinphoneCoreCbs *cbs, LinphoneCoreCbs cbs->vtable->notify_received = cb; } +LinphoneCoreCbsSubscribeReceivedCb linphone_core_cbs_get_subscribe_received(LinphoneCoreCbs *cbs) { + return cbs->vtable->subscribe_received; +} + +void linphone_core_cbs_set_subscribe_received(LinphoneCoreCbs *cbs, LinphoneCoreCbsSubscribeReceivedCb cb) { + cbs->vtable->subscribe_received = cb; +} + LinphoneCoreCbsPublishStateChangedCb linphone_core_cbs_get_rpublish_state_changed(LinphoneCoreCbs *cbs) { return cbs->vtable->publish_state_changed; } @@ -427,19 +458,38 @@ void linphone_core_cbs_set_version_update_check_result_received(LinphoneCoreCbs cbs->vtable->version_update_check_result_received = cb; } +LinphoneCoreCbsChatRoomStateChangedCb linphone_core_cbs_get_chat_room_state_changed (LinphoneCoreCbs *cbs) { + return cbs->vtable->chat_room_state_changed; +} + +void linphone_core_cbs_set_chat_room_state_changed (LinphoneCoreCbs *cbs, LinphoneCoreCbsChatRoomStateChangedCb cb) { + cbs->vtable->chat_room_state_changed = cb; +} + +LinphoneCoreCbsQrcodeFoundCb linphone_core_cbs_get_qrcode_found(LinphoneCoreCbs *cbs) { + return cbs->vtable->qrcode_found; +} + +void linphone_core_cbs_set_qrcode_found(LinphoneCoreCbs *cbs, LinphoneCoreCbsQrcodeFoundCb cb) { + cbs->vtable->qrcode_found = cb; +} + +void linphone_core_cbs_set_ec_calibration_result(LinphoneCoreCbs *cbs, LinphoneCoreCbsEcCalibrationResultCb cb) { + cbs->vtable->ec_calibration_result = cb; +} + +void linphone_core_cbs_set_ec_calibration_audio_init(LinphoneCoreCbs *cbs, LinphoneCoreCbsEcCalibrationAudioInitCb cb) { + cbs->vtable->ec_calibration_audio_init = cb; +} + +void linphone_core_cbs_set_ec_calibration_audio_uninit(LinphoneCoreCbs *cbs, LinphoneCoreCbsEcCalibrationAudioUninitCb cb) { + cbs->vtable->ec_calibration_audio_uninit = cb; +} -typedef belle_sip_object_t_vptr_t LinphoneCore_vptr_t; -BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCore); -BELLE_SIP_INSTANCIATE_VPTR(LinphoneCore, belle_sip_object_t, - linphone_core_uninit, // destroy - NULL, // clone - NULL, // Marshall - FALSE -); void lc_callback_obj_init(LCCallbackObj *obj,LinphoneCoreCbFunc func,void* ud) { - obj->_func=func; - obj->_user_data=ud; + obj->_func=func; + obj->_user_data=ud; } int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){ @@ -447,14 +497,6 @@ int lc_callback_obj_invoke(LCCallbackObj *obj, LinphoneCore *lc){ return 0; } -bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call){ - //return TRUE if the unique(for the moment) incoming call asked to be autoanswered - if(call) - return sal_call_autoanswer_asked(call->op); - else - return FALSE; -} - int linphone_core_get_current_call_duration(const LinphoneCore *lc){ LinphoneCall *call=linphone_core_get_current_call((LinphoneCore *)lc); if (call) return linphone_call_get_duration(call); @@ -478,13 +520,13 @@ void _linphone_core_set_log_handler(OrtpLogFunc logfunc) { } } -void linphone_core_set_log_handler(OrtpLogFunc logfunc) { +void linphone_core_set_log_handler(OrtpLogFunc logfunc){ _linphone_core_set_log_handler(logfunc); } void linphone_core_set_log_file(FILE *file) { if (file == NULL) file = stdout; - linphone_core_set_log_handler(NULL); + _linphone_core_set_log_handler(NULL); bctbx_set_log_file(file); /*gather everythings*/ } @@ -522,7 +564,7 @@ static int _open_log_collection_file_with_idx(int idx) { return -1; } - liblinphone_log_collection_file_size = statbuf.st_size; + liblinphone_log_collection_file_size = (size_t)statbuf.st_size; return 0; } @@ -610,7 +652,7 @@ static void linphone_core_log_collection_handler(const char *domain, OrtpLogLeve 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, (int)(tp.tv_usec / 1000), domain, lname, msg); fflush(liblinphone_log_collection_file); if (ret > 0) { - liblinphone_log_collection_file_size += ret; + liblinphone_log_collection_file_size += (size_t)ret; if (liblinphone_log_collection_file_size > liblinphone_log_collection_max_file_size) { _close_log_collection_file(); _open_log_collection_file(); @@ -831,7 +873,7 @@ static void process_response_from_post_file_log_collection(void *data, const bel cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */ while (cur != NULL) { if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) { - file_url = xmlGetProp(cur, (const xmlChar *)"url"); + file_url = xmlGetProp(cur, (const xmlChar *)"url"); } cur=cur->next; } @@ -845,7 +887,9 @@ static void process_response_from_post_file_log_collection(void *data, const bel } if (file_url != NULL) { linphone_core_notify_log_collection_upload_state_changed(core, LinphoneCoreLogCollectionUploadStateDelivered, (const char *)file_url); + xmlFree(file_url); } + xmlFreeDoc(xmlMessageBody); clean_log_collection_upload_context(core); } else { ms_error("Unexpected HTTP response code %i during log collection upload to %s", code, linphone_core_get_log_collection_upload_server_url(core)); @@ -932,7 +976,7 @@ static size_t get_size_of_file_to_upload(const char *filename) { fstat(fileno(output_file), &statbuf); fclose(output_file); ms_free(output_filename); - return statbuf.st_size; + return (size_t)statbuf.st_size; } void linphone_core_upload_log_collection(LinphoneCore *core) { @@ -1033,7 +1077,7 @@ void linphone_core_enable_logs(FILE *file){ } void linphone_core_enable_logs_with_cb(OrtpLogFunc logfunc){ - linphone_core_set_log_handler(logfunc); + _linphone_core_set_log_handler(logfunc); linphone_core_set_log_level(ORTP_MESSAGE); } @@ -1054,7 +1098,9 @@ static void net_config_read(LinphoneCore *lc) { nat_policy_ref = lp_config_get_string(lc->config, "net", "nat_policy_ref", NULL); if (nat_policy_ref != NULL) { - lc->nat_policy = linphone_core_create_nat_policy_from_config(lc, nat_policy_ref); + LinphoneNatPolicy *nat_policy = linphone_core_create_nat_policy_from_config(lc, nat_policy_ref); + linphone_core_set_nat_policy(lc, nat_policy); + linphone_nat_policy_unref(nat_policy); } if (lc->nat_policy == NULL){ /*this will create a default nat policy according to deprecated config keys, or an empty nat policy otherwise*/ @@ -1073,7 +1119,7 @@ static void net_config_read(LinphoneCore *lc) { if (tmpstr!=NULL && (strlen(tmpstr)<1)) tmpstr=NULL; linphone_core_set_nat_address(lc,tmpstr); tmp=lp_config_get_int(lc->config,"net","nat_sdp_only",0); - lc->net_conf.nat_sdp_only=tmp; + lc->net_conf.nat_sdp_only=!!tmp; tmp=lp_config_get_int(lc->config,"net","mtu",1300); linphone_core_set_mtu(lc,tmp); tmp=lp_config_get_int(lc->config,"net","download_ptime",-1); @@ -1082,9 +1128,9 @@ static void net_config_read(LinphoneCore *lc) { linphone_core_set_download_ptime(lc,tmp); } tmp = lp_config_get_int(lc->config, "net", "dns_srv_enabled", 1); - linphone_core_enable_dns_srv(lc, tmp); + linphone_core_enable_dns_srv(lc, !!tmp); tmp = lp_config_get_int(lc->config, "net", "dns_search_enabled", 1); - linphone_core_enable_dns_search(lc, tmp); + linphone_core_enable_dns_search(lc, !!tmp); } static void build_sound_devices_table(LinphoneCore *lc){ @@ -1144,7 +1190,7 @@ static void sound_config_read(LinphoneCore *lc) card=ms_alsa_card_new_custom(d+l,d+l); ms_snd_card_manager_add_card(ms_factory_get_snd_card_manager(lc->factory),card); *i=s; - l=i-d+1; + l=(size_t)(i-d)+1; } if(d[l]!='\0') { card=ms_alsa_card_new_custom(d+l,d+l); @@ -1224,12 +1270,10 @@ static void sound_config_read(LinphoneCore *lc) tmp=FALSE; /* on iOS we have builtin echo cancellation.*/ #endif tmp=lp_config_get_int(lc->config,"sound","echocancellation",tmp); - linphone_core_enable_echo_cancellation(lc,tmp); + linphone_core_enable_echo_cancellation(lc, !!tmp); linphone_core_set_echo_canceller_filter_name(lc, linphone_core_get_echo_canceller_filter_name(lc)); - linphone_core_enable_echo_limiter(lc, - lp_config_get_int(lc->config,"sound","echolimiter",0)); - linphone_core_enable_agc(lc, - lp_config_get_int(lc->config,"sound","agc",0)); + linphone_core_enable_echo_limiter(lc, !!lp_config_get_int(lc->config,"sound","echolimiter",0)); + linphone_core_enable_agc(lc, !!lp_config_get_int(lc->config,"sound","agc",0)); linphone_core_set_playback_gain_db (lc,lp_config_get_float(lc->config,"sound","playback_gain_db",0)); linphone_core_set_mic_gain_db (lc,lp_config_get_float(lc->config,"sound","mic_gain_db",0)); @@ -1275,26 +1319,24 @@ static void certificates_config_read(LinphoneCore *lc) { const char *data_dir = linphone_factory_get_data_resources_dir(factory); char *root_ca_path = bctbx_strdup_printf("%s/rootca.pem", data_dir); const char *rootca = lp_config_get_string(lc->config,"sip","root_ca", NULL); - // If rootca is not existing anymore, we reset it to the default value - if (rootca == NULL || (bctbx_file_exist(rootca) != 0)) { -#ifdef __linux - struct stat sb; - if (stat("/etc/ssl/certs", &sb) == 0 && S_ISDIR(sb.st_mode)) { - rootca = "/etc/ssl/certs"; - } else -#endif - { - if (bctbx_file_exist(root_ca_path) == 0) { - rootca = root_ca_path; - } - } + + // If rootca is not existing anymore, we try data_resources_dir/rootca.pem else default from belle-sip + if (rootca == NULL || ((bctbx_file_exist(rootca) != 0 && !bctbx_directory_exists(rootca)))) { + //Check root_ca_path + if ((bctbx_file_exist(root_ca_path) == 0) || bctbx_directory_exists(root_ca_path)) + rootca = root_ca_path; + else + rootca = NULL; } - linphone_core_set_root_ca(lc,rootca); - linphone_core_verify_server_certificates(lc,lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE)); - linphone_core_verify_server_cn(lc,lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE)); + + if (rootca) + linphone_core_set_root_ca(lc,rootca); + /*else use default value from belle-sip*/ + linphone_core_verify_server_certificates(lc, !!lp_config_get_int(lc->config,"sip","verify_server_certs",TRUE)); + linphone_core_verify_server_cn(lc, !!lp_config_get_int(lc->config,"sip","verify_server_cn",TRUE)); bctbx_free(root_ca_path); - - sal_set_tls_postcheck_callback(lc->sal, _linphone_core_tls_postcheck_callback, lc); + + lc->sal->setTlsPostcheckCallback(_linphone_core_tls_postcheck_callback, lc); } static void sip_config_read(LinphoneCore *lc) { @@ -1305,11 +1347,12 @@ static void sip_config_read(LinphoneCore *lc) { int ipv6_default = TRUE; if (lp_config_get_int(lc->config,"sip","use_session_timers",0)==1){ - sal_use_session_timers(lc->sal,200); + lc->sal->useSessionTimers(200); } - sal_use_no_initial_route(lc->sal,lp_config_get_int(lc->config,"sip","use_no_initial_route",0)); - sal_use_rport(lc->sal,lp_config_get_int(lc->config,"sip","use_rport",1)); + lc->sal->useNoInitialRoute(!!lp_config_get_int(lc->config,"sip","use_no_initial_route",0)); + lc->sal->useRport(!!lp_config_get_int(lc->config,"sip","use_rport",1)); + lc->sal->setContactLinphoneSpecs(lp_config_get_string(lc->config, "sip", "linphone_specs", "")); if (!lp_config_get_int(lc->config,"sip","ipv6_migration_done",FALSE) && lp_config_has_entry(lc->config,"sip","use_ipv6")) { lp_config_clean_entry(lc->config,"sip","use_ipv6"); @@ -1317,7 +1360,7 @@ static void sip_config_read(LinphoneCore *lc) { ms_message("IPV6 settings migration done."); } - lc->sip_conf.ipv6_enabled=lp_config_get_int(lc->config,"sip","use_ipv6",ipv6_default); + lc->sip_conf.ipv6_enabled = !!lp_config_get_int(lc->config,"sip","use_ipv6",ipv6_default); memset(&tr,0,sizeof(tr)); @@ -1328,7 +1371,7 @@ static void sip_config_read(LinphoneCore *lc) { certificates_config_read(lc); /*setting the dscp must be done before starting the transports, otherwise it is not taken into effect*/ - sal_set_dscp(lc->sal,linphone_core_get_sip_dscp(lc)); + lc->sal->setDscp(linphone_core_get_sip_dscp(lc)); /*start listening on ports*/ linphone_core_set_sip_transports(lc,&tr); @@ -1352,7 +1395,7 @@ static void sip_config_read(LinphoneCore *lc) { } tmp=lp_config_get_int(lc->config,"sip","guess_hostname",1); - linphone_core_set_guess_hostname(lc,tmp); + linphone_core_set_guess_hostname(lc, !!tmp); tmp=lp_config_get_int(lc->config,"sip","lime",LinphoneLimeDisabled); linphone_core_enable_lime(lc,static_cast(tmp)); @@ -1393,24 +1436,27 @@ static void sip_config_read(LinphoneCore *lc) { /*this is to filter out unsupported encryption schemes*/ linphone_core_set_media_encryption(lc,linphone_core_get_media_encryption(lc)); + /*enable the reconnection to the primary server when it is up again asap*/ + lc->sal->enableReconnectToPrimaryAsap(!!lp_config_get_int(lc->config,"sip","reconnect_to_primary_asap",0)); + /*for tuning or test*/ - lc->sip_conf.sdp_200_ack=lp_config_get_int(lc->config,"sip","sdp_200_ack",0); + lc->sip_conf.sdp_200_ack = !!lp_config_get_int(lc->config,"sip","sdp_200_ack",0); lc->sip_conf.register_only_when_network_is_up= - lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1); + !!lp_config_get_int(lc->config,"sip","register_only_when_network_is_up",1); lc->sip_conf.register_only_when_upnp_is_ok= - lp_config_get_int(lc->config,"sip","register_only_when_upnp_is_ok",1); - lc->sip_conf.ping_with_options=lp_config_get_int(lc->config,"sip","ping_with_options",0); - lc->sip_conf.auto_net_state_mon=lp_config_get_int(lc->config,"sip","auto_net_state_mon",1); - lc->sip_conf.keepalive_period=lp_config_get_int(lc->config,"sip","keepalive_period",10000); - lc->sip_conf.tcp_tls_keepalive=lp_config_get_int(lc->config,"sip","tcp_tls_keepalive",0); + !!lp_config_get_int(lc->config,"sip","register_only_when_upnp_is_ok",1); + lc->sip_conf.ping_with_options= !!lp_config_get_int(lc->config,"sip","ping_with_options",0); + lc->sip_conf.auto_net_state_mon = !!lp_config_get_int(lc->config,"sip","auto_net_state_mon",1); + lc->sip_conf.keepalive_period = (unsigned int)lp_config_get_int(lc->config,"sip","keepalive_period",10000); + lc->sip_conf.tcp_tls_keepalive = !!lp_config_get_int(lc->config,"sip","tcp_tls_keepalive",0); linphone_core_enable_keep_alive(lc, (lc->sip_conf.keepalive_period > 0)); - sal_use_one_matching_codec_policy(lc->sal,lp_config_get_int(lc->config,"sip","only_one_codec",0)); - sal_use_dates(lc->sal,lp_config_get_int(lc->config,"sip","put_date",0)); - 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); + lc->sal->useOneMatchingCodecPolicy(!!lp_config_get_int(lc->config,"sip","only_one_codec",0)); + lc->sal->useDates(!!lp_config_get_int(lc->config,"sip","put_date",0)); + lc->sal->enableSipUpdateMethod(!!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"/*, gruu" not yet enabled by default*/)); - lc->sip_conf.save_auth_info = lp_config_get_int(lc->config, "sip", "save_auth_info", 1); + lc->sal->setSupportedTags(lp_config_get_string(lc->config,"sip","supported","replaces, outbound, gruu")); + lc->sip_conf.save_auth_info = !!lp_config_get_int(lc->config, "sip", "save_auth_info", 1); linphone_core_create_im_notif_policy(lc); } @@ -1457,34 +1503,38 @@ static void rtp_config_read(LinphoneCore *lc) { linphone_core_set_video_jittcomp(lc,jitt_comp); nortp_timeout=lp_config_get_int(lc->config,"rtp","nortp_timeout",30); linphone_core_set_nortp_timeout(lc,nortp_timeout); - rtp_no_xmit_on_audio_mute=lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE); + rtp_no_xmit_on_audio_mute = !!lp_config_get_int(lc->config,"rtp","rtp_no_xmit_on_audio_mute",FALSE); linphone_core_set_rtp_no_xmit_on_audio_mute(lc,rtp_no_xmit_on_audio_mute); - adaptive_jitt_comp_enabled = lp_config_get_int(lc->config, "rtp", "audio_adaptive_jitt_comp_enabled", TRUE); + adaptive_jitt_comp_enabled = !!lp_config_get_int(lc->config, "rtp", "audio_adaptive_jitt_comp_enabled", TRUE); linphone_core_enable_audio_adaptive_jittcomp(lc, adaptive_jitt_comp_enabled); - adaptive_jitt_comp_enabled = lp_config_get_int(lc->config, "rtp", "video_adaptive_jitt_comp_enabled", TRUE); + 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,static_cast(lp_config_get_int(lc->config,"rtp","avpf",LinphoneAVPFDisabled))); if ((tmp=lp_config_get_string(lc->config,"rtp","audio_multicast_addr",NULL))) linphone_core_set_audio_multicast_addr(lc,tmp); - else + else { + if (lc->rtp_conf.audio_multicast_addr) bctbx_free(lc->rtp_conf.audio_multicast_addr); lc->rtp_conf.audio_multicast_addr=ms_strdup("224.1.2.3"); + } if ((tmp_int=lp_config_get_int(lc->config,"rtp","audio_multicast_enabled",-1)) >-1) - linphone_core_enable_audio_multicast(lc,tmp_int); + linphone_core_enable_audio_multicast(lc, !!tmp_int); if ((tmp_int=lp_config_get_int(lc->config,"rtp","audio_multicast_ttl",-1))>0) linphone_core_set_audio_multicast_ttl(lc,tmp_int); else lc->rtp_conf.audio_multicast_ttl=1;/*local network*/ if ((tmp=lp_config_get_string(lc->config,"rtp","video_multicast_addr",NULL))) linphone_core_set_video_multicast_addr(lc,tmp); - else + else { + if (lc->rtp_conf.video_multicast_addr) bctbx_free(lc->rtp_conf.video_multicast_addr); lc->rtp_conf.video_multicast_addr=ms_strdup("224.1.2.3"); + } if ((tmp_int=lp_config_get_int(lc->config,"rtp","video_multicast_ttl",-1))>-1) linphone_core_set_video_multicast_ttl(lc,tmp_int); else lc->rtp_conf.video_multicast_ttl=1;/*local network*/ if ((tmp_int=lp_config_get_int(lc->config,"rtp","video_multicast_enabled",-1)) >0) - linphone_core_enable_video_multicast(lc,tmp_int); + linphone_core_enable_video_multicast(lc, !!tmp_int); } static PayloadType * find_payload(const bctbx_list_t *default_list, const char *mime_type, int clock_rate, int channels, const char *recv_fmtp){ @@ -1578,8 +1628,10 @@ static bool_t get_codec(LinphoneCore *lc, SalStreamType type, int index, Payload payload_type_set_recv_fmtp(pt,fmtp); *default_list=bctbx_list_append(*default_list, pt); } - if (enabled ) pt->flags|=PAYLOAD_TYPE_ENABLED; - else pt->flags&=~PAYLOAD_TYPE_ENABLED; + if (enabled) + payload_type_set_enable(pt, TRUE); + else + payload_type_set_enable(pt, FALSE); *ret=pt; return TRUE; } @@ -1602,10 +1654,9 @@ static SalStreamType payload_type_get_stream_type(const PayloadType *pt){ /*this function merges the payload types from the codec default list with the list read from configuration file. * If a new codec becomes supported in Liblinphone or if the list from configuration file is empty or incomplete, all the supported codecs are added - * automatically. This 'l' list is entirely destroyed and rewritten.*/ + * automatically. This 'l' list is entirely rewritten.*/ static bctbx_list_t *add_missing_supported_codecs(LinphoneCore *lc, const bctbx_list_t *default_list, bctbx_list_t *l){ const bctbx_list_t *elem; - bctbx_list_t *newlist; PayloadType *last_seen = NULL; for(elem=default_list; elem!=NULL; elem=elem->next){ @@ -1623,46 +1674,38 @@ static bctbx_list_t *add_missing_supported_codecs(LinphoneCore *lc, const bctbx_ } last_seen = pt; ms_message("Supported codec %s/%i fmtp=%s automatically added to codec list.", pt->mime_type, - pt->clock_rate, pt->recv_fmtp ? pt->recv_fmtp : ""); + pt->clock_rate, pt->recv_fmtp ? pt->recv_fmtp : ""); }else{ last_seen = (PayloadType*)elem2->data; } } - newlist=bctbx_list_copy_with_data(l,(void *(*)(void*))payload_type_clone); - bctbx_list_free(l); - return newlist; + return l; } /* * This function adds missing codecs, if required by configuration. - * This 'l' list is entirely destroyed and a new list is returned. + * This 'l' list is entirely rewritten if required. */ -static bctbx_list_t *handle_missing_codecs(LinphoneCore *lc, const bctbx_list_t *default_list, bctbx_list_t *l, MSFormatType ft){ +static bctbx_list_t *handle_missing_codecs (LinphoneCore *lc, const bctbx_list_t *default_list, bctbx_list_t *l, MSFormatType ft) { const char *name = "unknown"; - int add_missing; - bctbx_list_t *ret; - switch(ft){ + switch (ft) { case MSAudio: name = "add_missing_audio_codecs"; - break; + break; case MSVideo: name = "add_missing_video_codecs"; - break; + break; case MSText: name = "add_missing_text_codecs"; - break; + break; case MSUnknownMedia: break; } - add_missing = lp_config_get_int(lc->config, "misc", name, 1); - if (add_missing){ - ret = add_missing_supported_codecs(lc, default_list, l); - }else{ - ret = bctbx_list_copy_with_data(l,(void *(*)(void*))payload_type_clone); - bctbx_list_free(l); - } - return ret; + + if (lp_config_get_int(lc->config, "misc", name, 1)) + return add_missing_supported_codecs(lc, default_list, l); + return l; } static bctbx_list_t *codec_append_if_new(bctbx_list_t *l, PayloadType *pt){ @@ -1734,7 +1777,6 @@ static void build_video_devices_table(LinphoneCore *lc){ static void video_config_read(LinphoneCore *lc){ #ifdef VIDEO_ENABLED - int capture, display, self_view, reuse_source; int automatic_video=1; const char *str; LinphoneVideoPolicy vpol; @@ -1756,17 +1798,13 @@ static void video_config_read(LinphoneCore *lc){ #if defined(__ANDROID__) || TARGET_OS_IPHONE automatic_video=0; #endif - 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); + 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, !!lp_config_get_int(lc->config,"video","capture",1)); + linphone_core_enable_video_display(lc, !!lp_config_get_int(lc->config,"video","display",1)); + linphone_core_enable_video_preview(lc, !!lp_config_get_int(lc->config,"video","show_local",0)); + linphone_core_enable_self_view(lc, !!lp_config_get_int(lc->config,"video","self_view",1)); + linphone_core_enable_video_source_reuse(lc, !!lp_config_get_int(lc->config,"video","reuse_source",0)); linphone_core_set_video_policy(lc,&vpol); #endif } @@ -1791,7 +1829,7 @@ static void ui_config_read(LinphoneCore *lc) read_friends_from_rc(lc); } if (!lc->logs_db) { - lc->call_logs = call_logs_read_from_config_file(lc); + lc->call_logs = linphone_core_read_call_logs_from_config_file(lc); } #endif } @@ -1822,7 +1860,7 @@ void linphone_core_enable_adaptive_rate_control(LinphoneCore *lc, bool_t enabled } bool_t linphone_core_adaptive_rate_control_enabled(const LinphoneCore *lc){ - return lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE); + return !!lp_config_get_int(lc->config,"net","adaptive_rate_control",TRUE); } void linphone_core_set_adaptive_rate_algorithm(LinphoneCore *lc, const char* algorithm){ @@ -1843,7 +1881,7 @@ const char * linphone_core_get_adaptive_rate_algorithm(const LinphoneCore *lc){ } bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc){ - return lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE); + return !!lp_config_get_int(lc->config,"rtp","rtcp_enabled",TRUE); } void linphone_core_set_download_bandwidth(LinphoneCore *lc, int bw){ @@ -1864,13 +1902,13 @@ void linphone_core_set_expected_bandwidth(LinphoneCore *lc, int bw){ } void linphone_core_set_sip_transport_timeout(LinphoneCore *lc, int timeout_ms) { - sal_set_transport_timeout(lc->sal, timeout_ms); + lc->sal->setTransportTimeout(timeout_ms); if (linphone_core_ready(lc)) lp_config_set_int(lc->config, "sip", "transport_timeout", timeout_ms); } int linphone_core_get_sip_transport_timeout(LinphoneCore *lc) { - return sal_get_transport_timeout(lc->sal); + return lc->sal->getTransportTimeout(); } bool_t linphone_core_get_dns_set_by_app(LinphoneCore *lc) { @@ -1883,27 +1921,27 @@ void linphone_core_set_dns_servers_app(LinphoneCore *lc, const bctbx_list_t *ser } void linphone_core_set_dns_servers(LinphoneCore *lc, const bctbx_list_t *servers){ - sal_set_dns_servers(lc->sal, servers); + lc->sal->setDnsServers(servers); } void linphone_core_enable_dns_srv(LinphoneCore *lc, bool_t enable) { - sal_enable_dns_srv(lc->sal, enable); + lc->sal->enableDnsSrv(!!enable); if (linphone_core_ready(lc)) lp_config_set_int(lc->config, "net", "dns_srv_enabled", enable ? 1 : 0); } bool_t linphone_core_dns_srv_enabled(const LinphoneCore *lc) { - return sal_dns_srv_enabled(lc->sal); + return lc->sal->dnsSrvEnabled(); } void linphone_core_enable_dns_search(LinphoneCore *lc, bool_t enable) { - sal_enable_dns_search(lc->sal, enable); + lc->sal->enableDnsSearch(!!enable); if (linphone_core_ready(lc)) lp_config_set_int(lc->config, "net", "dns_search_enabled", enable ? 1 : 0); } bool_t linphone_core_dns_search_enabled(const LinphoneCore *lc) { - return sal_dns_search_enabled(lc->sal); + return lc->sal->dnsSearchEnabled(); } int linphone_core_get_download_bandwidth(const LinphoneCore *lc){ @@ -1979,22 +2017,16 @@ void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const linphone_core_notify_global_state_changed(lc,gstate,message); } -static void misc_config_read(LinphoneCore *lc) { - LpConfig *config=lc->config; - const char *uuid; +static void misc_config_read (LinphoneCore *lc) { + LpConfig *config = lc->config; - lc->max_call_logs=lp_config_get_int(config,"misc","history_max_size",LINPHONE_MAX_CALL_HISTORY_SIZE); - lc->max_calls=lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS); + lc->max_call_logs = lp_config_get_int(config,"misc","history_max_size",LINPHONE_MAX_CALL_HISTORY_SIZE); + lc->max_calls = lp_config_get_int(config,"misc","max_calls",NB_MAX_CALLS); - uuid=lp_config_get_string(config,"misc","uuid",NULL); - if (!uuid){ - char tmp[64]; - sal_create_uuid(lc->sal,tmp,sizeof(tmp)); - lp_config_set_string(config,"misc","uuid",tmp); - }else if (strcmp(uuid,"0")!=0) /*to allow to disable sip.instance*/ - sal_set_uuid(lc->sal, uuid); + if (lc->user_certificates_path) bctbx_free(lc->user_certificates_path); + lc->user_certificates_path = bctbx_strdup(lp_config_get_string(config, "misc", "user_certificates_path", ".")); - lc->user_certificates_path=ms_strdup(lp_config_get_string(config,"misc","user_certificates_path",".")); + lc->send_call_stats_periodical_updates = !!lp_config_get_int(config, "misc", "send_call_stats_periodical_updates", 0); } void linphone_core_reload_ms_plugins(LinphoneCore *lc, const char *path){ @@ -2003,12 +2035,7 @@ void linphone_core_reload_ms_plugins(LinphoneCore *lc, const char *path){ codecs_config_read(lc); } -static void linphone_core_start(LinphoneCore * lc) { - LinphoneFriendList *list = linphone_core_create_friend_list(lc); - linphone_friend_list_set_display_name(list, "_default"); - linphone_core_add_friend_list(lc, list); - linphone_friend_list_unref(list); - +static void _linphone_core_read_config(LinphoneCore * lc) { sip_setup_register_all(lc->factory); sound_config_read(lc); net_config_read(lc); @@ -2017,8 +2044,6 @@ static void linphone_core_start(LinphoneCore * lc) { sip_config_read(lc); video_config_read(lc); //autoreplier_config_init(&lc->autoreplier_conf); - lc->presence_model=linphone_presence_model_new(); - linphone_presence_model_set_basic_status(lc->presence_model, LinphonePresenceBasicStatusOpen); misc_config_read(lc); ui_config_read(lc); #ifdef TUNNEL_ENABLED @@ -2027,10 +2052,7 @@ static void linphone_core_start(LinphoneCore * lc) { } #endif - - 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) { @@ -2039,12 +2061,15 @@ void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState if (state == LinphoneConfiguringSuccessful) { if (linphone_core_is_provisioning_transient(lc) == TRUE) linphone_core_set_provisioning_uri(lc, NULL); + _linphone_core_read_config(lc); } if (lc->provisioning_http_listener){ belle_sip_object_unref(lc->provisioning_http_listener); lc->provisioning_http_listener = NULL; } - linphone_core_start(lc); + + L_GET_PRIVATE_FROM_C_OBJECT(lc)->init(); + linphone_core_set_state(lc,LinphoneGlobalOn,"Ready"); } @@ -2139,13 +2164,71 @@ static void linphone_core_register_default_codecs(LinphoneCore *lc){ static void linphone_core_internal_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body) { if (strcmp(notified_event, "Presence") == 0) { - const bctbx_list_t* friendLists = linphone_core_get_friends_lists(lc); - while( friendLists != NULL ){ - LinphoneFriendList* list = reinterpret_cast(friendLists->data); - ms_message("notify presence for list %p", list); + for (const bctbx_list_t *it = linphone_core_get_friends_lists(lc); it; it = bctbx_list_next(it)) { + LinphoneFriendList *list = reinterpret_cast(bctbx_list_get_data(it)); + ms_message("Notify presence for list %p", list); linphone_friend_list_notify_presence_received(list, lev, body); - friendLists = friendLists->next; } + } else if (strcmp(notified_event, "conference") == 0) { + const LinphoneAddress *resource = linphone_event_get_resource(lev); + char *resourceAddrStr = linphone_address_as_string_uri_only(resource); + if (strcmp(resourceAddrStr, linphone_proxy_config_get_conference_factory_uri(linphone_core_get_default_proxy_config(lc))) == 0) { + bctbx_free(resourceAddrStr); + L_GET_PRIVATE_FROM_C_OBJECT(lc)->remoteListEventHandler->notifyReceived(L_GET_CPP_PTR_FROM_C_OBJECT(body)); + return; + } + bctbx_free(resourceAddrStr); + + const LinphoneAddress *from = linphone_event_get_from(lev); + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(LinphonePrivate::ChatRoomId( + IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)), + IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(from)) + )); + if (!chatRoom) + return; + + shared_ptr cgcr; + if (chatRoom->getCapabilities() & ChatRoom::Capabilities::Proxy) + cgcr = static_pointer_cast( + static_pointer_cast(chatRoom)->getProxiedChatRoom()); + else + cgcr = static_pointer_cast(chatRoom); + + if (linphone_content_is_multipart(body)) { + // TODO : migrate to c++ 'Content'. + int i = 0; + LinphoneContent *part = nullptr; + while ((part = linphone_content_get_part(body, i))) { + i++; + L_GET_PRIVATE(cgcr)->notifyReceived(linphone_content_get_string_buffer(part)); + linphone_content_unref(part); + } + } else + L_GET_PRIVATE(cgcr)->notifyReceived(linphone_content_get_string_buffer(body)); + } +} + +static void _linphone_core_conference_subscribe_received(LinphoneCore *lc, LinphoneEvent *lev, const LinphoneContent *body) { + if (body && linphone_event_get_custom_header(lev, "Content-Disposition") && strcasecmp(linphone_event_get_custom_header(lev, "Content-Disposition"), "recipient-list") == 0) { + // List subscription + L_GET_PRIVATE_FROM_C_OBJECT(lc)->localListEventHandler->subscribeReceived(lev, body); + return; + } + + const LinphoneAddress *resource = linphone_event_get_resource(lev); + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->findChatRoom(LinphonePrivate::ChatRoomId( + IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)), + IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(resource)) + )); + if (chatRoom) + L_GET_PRIVATE(static_pointer_cast(chatRoom))->subscribeReceived(lev); + else + linphone_event_deny_subscription(lev, LinphoneReasonDeclined); +} + +static void linphone_core_internal_subscribe_received(LinphoneCore *lc, LinphoneEvent *lev, const char *subscribe_event, const LinphoneContent *body) { + if (strcmp(linphone_event_get_name(lev), "conference") == 0) { + _linphone_core_conference_subscribe_received(lc, lev, body); } } @@ -2186,8 +2269,7 @@ static void _linphone_core_init_account_creator_service(LinphoneCore *lc) { linphone_core_set_account_creator_service(lc, service); } -static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig *config, void * userdata, void *system_context){ - const char *remote_provisioning_uri = NULL; +static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig *config, void * userdata, void *system_context, bool_t automatically_start) { LinphoneFactory *lfactory = linphone_factory_get(); LinphoneCoreCbs *internal_cbs = _linphone_core_cbs_new(); const char *msplugins_dir; @@ -2203,6 +2285,15 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig lc->data=userdata; lc->ringstream_autorelease=TRUE; + // We need the Sal on the Android platform helper init + lc->sal=new Sal(NULL); + lc->sal->setRefresherRetryAfter(lp_config_get_int(lc->config, "sip", "refresher_retry_after", 60000)); + lc->sal->setHttpProxyHost(L_C_TO_STRING(linphone_core_get_http_proxy_host(lc))); + lc->sal->setHttpProxyPort(linphone_core_get_http_proxy_port(lc)); + + lc->sal->setUserPointer(lc); + lc->sal->setCallbacks(&linphone_sal_callbacks); + #ifdef __ANDROID__ if (system_context) lc->platform_helper = LinphonePrivate::createAndroidPlatformHelpers(lc, system_context); @@ -2212,51 +2303,40 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig if (lc->platform_helper == NULL) lc->platform_helper = new LinphonePrivate::StubbedPlatformHelpers(lc); + msplugins_dir = linphone_factory_get_msplugins_dir(lfactory); + image_resources_dir = linphone_factory_get_image_resources_dir(lfactory); + // MS Factory MUST be created after Android has been set, otherwise no camera will be detected ! + lc->factory = ms_factory_new_with_voip_and_directories(msplugins_dir, image_resources_dir); + lc->sal->setFactory(lc->factory); + + belr::GrammarLoader::get().addPath(std::string(linphone_factory_get_top_resources_dir(lfactory)).append("/belr/grammars")); linphone_task_list_init(&lc->hooks); _linphone_core_init_account_creator_service(lc); linphone_core_cbs_set_notify_received(internal_cbs, linphone_core_internal_notify_received); + linphone_core_cbs_set_subscribe_received(internal_cbs, linphone_core_internal_subscribe_received); linphone_core_cbs_set_subscription_state_changed(internal_cbs, linphone_core_internal_subscription_state_changed); linphone_core_cbs_set_publish_state_changed(internal_cbs, linphone_core_internal_publish_state_changed); _linphone_core_add_callbacks(lc, internal_cbs, TRUE); belle_sip_object_unref(internal_cbs); - if (cbs != NULL) { _linphone_core_add_callbacks(lc, cbs, FALSE); - } else { - LinphoneCoreCbs *fallback_cbs = linphone_factory_create_core_cbs(linphone_factory_get()); - _linphone_core_add_callbacks(lc, fallback_cbs, FALSE); - belle_sip_object_unref(fallback_cbs); } - - linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up"); ortp_set_log_handler(NULL); /*remove ortp default log handler*/ ortp_init(); linphone_core_activate_log_serialization_if_needed(); - msplugins_dir = linphone_factory_get_msplugins_dir(lfactory); - image_resources_dir = linphone_factory_get_image_resources_dir(lfactory); - lc->factory = ms_factory_new_with_voip_and_directories(msplugins_dir, image_resources_dir); linphone_core_register_default_codecs(lc); linphone_core_register_offer_answer_providers(lc); /* Get the mediastreamer2 event queue */ /* This allows to run event's callback in linphone_core_iterate() */ lc->msevq=ms_factory_create_event_queue(lc->factory); - lc->sal=sal_init(lc->factory); - - sal_set_refresher_retry_after(lc->sal, lp_config_get_int(lc->config, "sip", "refresher_retry_after", 60000)); - sal_set_http_proxy_host(lc->sal, linphone_core_get_http_proxy_host(lc)); - sal_set_http_proxy_port(lc->sal, linphone_core_get_http_proxy_port(lc)); - - sal_set_user_pointer(lc->sal,lc); - sal_set_callbacks(lc->sal,&linphone_sal_callbacks); - #ifdef TUNNEL_ENABLED lc->tunnel=linphone_core_tunnel_new(lc); #endif @@ -2267,11 +2347,11 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig /* Create the http provider in dual stack mode (ipv4 and ipv6. * If this creates problem, we may need to implement parallel ipv6/ ipv4 http requests in belle-sip. */ - lc->http_provider = belle_sip_stack_create_http_provider(reinterpret_cast(sal_get_stack_impl(lc->sal)), "::0"); + lc->http_provider = belle_sip_stack_create_http_provider(reinterpret_cast(lc->sal->getStackImpl()), "::0"); lc->http_crypto_config = belle_tls_crypto_config_new(); belle_http_provider_set_tls_crypto_config(lc->http_provider,lc->http_crypto_config); - certificates_config_read(lc); + //certificates_config_read(lc); // This will be done below in _linphone_core_read_config() lc->ringtoneplayer = linphone_ringtoneplayer_new(); @@ -2279,52 +2359,96 @@ static void linphone_core_init(LinphoneCore * lc, LinphoneCoreCbs *cbs, LpConfig sqlite3_bctbx_vfs_register(0); #endif + lc->qrcode_rect.h = 0; + lc->qrcode_rect.w = 0; + lc->qrcode_rect.x = 0; + lc->qrcode_rect.y = 0; + lc->vcard_context = linphone_vcard_context_new(); linphone_core_initialize_supported_content_types(lc); + lc->bw_controller = ms_bandwidth_controller_new(); getPlatformHelpers(lc)->setDnsServers(); - 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 provisioning (see linphone_core_iterate) - lc->bw_controller = ms_bandwidth_controller_new(); + LinphoneFriendList *list = linphone_core_create_friend_list(lc); + linphone_friend_list_set_display_name(list, "_default"); + linphone_core_add_friend_list(lc, list); + linphone_friend_list_unref(list); + lc->presence_model = linphone_presence_model_new(); + linphone_presence_model_set_basic_status(lc->presence_model, LinphonePresenceBasicStatusOpen); + + _linphone_core_read_config(lc); + if (automatically_start) { + linphone_core_start(lc); + } } +void linphone_core_start (LinphoneCore *lc) { + linphone_core_set_state(lc,LinphoneGlobalStartup,"Starting up"); -LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context) { - LinphoneCore *core = belle_sip_object_new(LinphoneCore); - linphone_core_init(core, cbs, config, userdata, system_context); + //to give a chance to change uuid before starting + const char* uuid=lp_config_get_string(lc->config,"misc","uuid",NULL); + if (!uuid){ + char tmp[64]; + lc->sal->createUuid(tmp,sizeof(tmp)); + lp_config_set_string(lc->config,"misc","uuid",tmp); + }else if (strcmp(uuid,"0")!=0) /*to allow to disable sip.instance*/ + lc->sal->setUuid(uuid); + + if (!lc->sal->getRootCa().empty()) { + belle_tls_crypto_config_set_root_ca(lc->http_crypto_config, lc->sal->getRootCa().c_str()); + belle_http_provider_set_tls_crypto_config(lc->http_provider, lc->http_crypto_config); + } + + linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring"); + + const char *remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); + if (remote_provisioning_uri) { + if (linphone_remote_provisioning_download_and_apply(lc, remote_provisioning_uri) == -1) + linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "Bad URI"); + } else { + linphone_configuring_terminated(lc, LinphoneConfiguringSkipped, NULL); + } +} + +LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context, bool_t automatically_start) { + LinphoneCore *core = L_INIT(Core); + Core::create(core); + linphone_core_init(core, cbs, config, userdata, system_context, automatically_start); return core; } -LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, struct _LpConfig *config, void *userdata) { +static LinphoneCore *_linphone_core_new_with_config_and_start ( + const LinphoneCoreVTable *vtable, + LinphoneConfig *config, + void *userdata, + bool_t automatically_start +) { LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); LinphoneCoreVTable *local_vtable = linphone_core_v_table_new(); LinphoneCore *core = NULL; if (vtable != NULL) *local_vtable = *vtable; _linphone_core_cbs_set_v_table(cbs, local_vtable, TRUE); - core = _linphone_core_new_with_config(cbs, config, userdata, NULL); + core = _linphone_core_new_with_config(cbs, config, userdata, NULL, automatically_start); linphone_core_cbs_unref(cbs); return core; } -static LinphoneCore *_linphone_core_new(const LinphoneCoreVTable *vtable, - const char *config_path, const char *factory_config_path, void * userdata) { - LinphoneCore *lc; - LpConfig *config = lp_config_new_with_factory(config_path, factory_config_path); - lc=linphone_core_new_with_config(vtable, config, userdata); - lp_config_unref(config); - return lc; +LinphoneCore *linphone_core_new_with_config(const LinphoneCoreVTable *vtable, struct _LpConfig *config, void *userdata) { + return _linphone_core_new_with_config_and_start(vtable, config, userdata, TRUE); } LinphoneCore *linphone_core_new(const LinphoneCoreVTable *vtable, const char *config_path, const char *factory_config_path, void * userdata) { - return _linphone_core_new(vtable, config_path, factory_config_path, userdata); + LinphoneConfig *config = lp_config_new_with_factory(config_path, factory_config_path); + LinphoneCore *lc = _linphone_core_new_with_config_and_start(vtable, config, userdata, TRUE); + linphone_config_unref(config); + return lc; } LinphoneCore *linphone_core_ref(LinphoneCore *lc) { - return (LinphoneCore *)belle_sip_object_ref(BELLE_SIP_OBJECT(lc)); + belle_sip_object_ref(BELLE_SIP_OBJECT(lc)); + return lc; } void linphone_core_unref(LinphoneCore *lc) { @@ -2546,7 +2670,7 @@ void linphone_core_enable_generic_comfort_noise(LinphoneCore *lc, bool_t enabled } bool_t linphone_core_generic_comfort_noise_enabled(const LinphoneCore *lc){ - return lp_config_get_int(lc->config, "misc", "use_cn", FALSE); + return !!lp_config_get_int(lc->config, "misc", "use_cn", FALSE); } const bctbx_list_t* linphone_core_get_friend_list(const LinphoneCore *lc) { @@ -2594,6 +2718,35 @@ void linphone_core_add_friend_list(LinphoneCore *lc, LinphoneFriendList *list) { linphone_core_notify_friend_list_created(lc, list); } +const bctbx_list_t * linphone_core_find_contacts_by_char(LinphoneCore *core, const char *filter, bool_t sip_only) { + // Get sipuri from filter if possible + bctbx_list_t *list = NULL, *_list = NULL; + LinphoneAddress *addr = linphone_core_interpret_url(core, (sip_only) ? filter : ""); + bctbx_list_t* listFriendsList = (bctbx_list_t*)linphone_core_get_friends_lists(core); + bctbx_list_t* listFriend = (listFriendsList != NULL) + ? (bctbx_list_t*)linphone_friend_list_get_friends((LinphoneFriendList*)listFriendsList->data) : NULL; + + if (addr != NULL) + list = bctbx_list_new(addr); + + while (listFriend != NULL && listFriend->data != NULL) { + LinphoneAddress *buff = (LinphoneAddress*)linphone_friend_get_address((LinphoneFriend*)listFriend->data); + if (buff != NULL) { + bctbx_list_t *new_list = bctbx_list_new(buff); + if (list == NULL) { + _list = list = new_list; + } else { + if (_list == NULL) _list = list; + _list->next = new_list; + _list = _list->next; + } + } + listFriend = listFriend->next; + } + + return list; +} + void linphone_core_enable_audio_adaptive_jittcomp(LinphoneCore* lc, bool_t val) { lc->rtp_conf.audio_adaptive_jitt_comp_enabled = val; } @@ -2675,21 +2828,19 @@ bool_t linphone_core_get_rtp_no_xmit_on_audio_mute(const LinphoneCore *lc){ } static void apply_jitter_value(LinphoneCore *lc, int value, MSFormatType stype){ - LinphoneCall *call; - bctbx_list_t *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){ + for (const auto &call : L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getCalls()) { + MediaStream *ms = (stype == MSAudio) + ? L_GET_PRIVATE(call)->getMediaStream(LinphoneStreamTypeAudio) + : L_GET_PRIVATE(call)->getMediaStream(LinphoneStreamTypeVideo); + 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); + ms_message("Jitter buffer size set to [%i] ms on call [%p]", value, call.get()); 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); + ms_warning("Jitter buffer is disabled per application request on call [%p]", call.get()); rtp_session_enable_jitter_buffer(s,FALSE); } } @@ -2743,7 +2894,7 @@ void linphone_core_set_nortp_timeout(LinphoneCore *lc, int nortp_timeout){ } bool_t linphone_core_get_use_info_for_dtmf(LinphoneCore *lc) { - return lp_config_get_int(lc->config, "sip", "use_info", 0); + return !!lp_config_get_int(lc->config, "sip", "use_info", 0); } void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc,bool_t use_info) { @@ -2753,7 +2904,7 @@ void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc,bool_t use_info) { } bool_t linphone_core_get_use_rfc2833_for_dtmf(LinphoneCore *lc) { - return lp_config_get_int(lc->config, "sip", "use_rfc2833", 1); + return !!lp_config_get_int(lc->config, "sip", "use_rfc2833", 1); } void linphone_core_set_use_rfc2833_for_dtmf(LinphoneCore *lc,bool_t use_rfc2833) { @@ -2775,12 +2926,12 @@ void linphone_core_set_user_agent(LinphoneCore *lc, const char *name, const char 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); + lc->sal->setUserAgent(ua_string); + lc->sal->appendStackStringToUserAgent(); } } const char *linphone_core_get_user_agent(LinphoneCore *lc){ - return sal_get_user_agent(lc->sal); + return lc->sal->getUserAgent().c_str(); } const char *linphone_core_get_user_agent_name(void){ @@ -2791,13 +2942,6 @@ const char *linphone_core_get_user_agent_version(void){ return _ua_version; } -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); - linphone_core_notify_display_warning(lc,msg); - ms_free(msg); -} - static bool_t transports_unchanged(const LinphoneSipTransports * tr1, const LinphoneSipTransports * tr2){ return tr2->udp_port==tr1->udp_port && @@ -2830,41 +2974,32 @@ int _linphone_core_apply_transports(LinphoneCore *lc){ else anyaddr="0.0.0.0"; - sal_unlisten_ports(sal); + sal->unlistenPorts(); listening_address = lp_config_get_string(lc->config,"sip","bind_address",anyaddr); if (linphone_core_get_http_proxy_host(lc)) { - sal_set_http_proxy_host(sal, linphone_core_get_http_proxy_host(lc)); - sal_set_http_proxy_port(sal,linphone_core_get_http_proxy_port(lc)); + sal->setHttpProxyHost(linphone_core_get_http_proxy_host(lc)); + sal->setHttpProxyPort(linphone_core_get_http_proxy_port(lc)); } if (lc->tunnel && linphone_tunnel_sip_enabled(lc->tunnel) && linphone_tunnel_get_activated(lc->tunnel)){ - if (sal_listen_port(sal,anyaddr,tr->udp_port,SalTransportUDP,TRUE)!=0){ - transport_error(lc,"udp+tunnel",tr->udp_port); - } + sal->setListenPort(anyaddr,tr->udp_port,SalTransportUDP,TRUE); }else{ if (tr->udp_port!=0){ - if (sal_listen_port(sal,listening_address,tr->udp_port,SalTransportUDP,FALSE)!=0){ - transport_error(lc,"udp",tr->udp_port); - } + sal->setListenPort(listening_address,tr->udp_port,SalTransportUDP,FALSE); } if (tr->tcp_port!=0){ - if (sal_listen_port (sal,listening_address,tr->tcp_port,SalTransportTCP,FALSE)!=0){ - transport_error(lc,"tcp",tr->tcp_port); - } + sal->setListenPort (listening_address,tr->tcp_port,SalTransportTCP,FALSE); } if (linphone_core_sip_transport_supported(lc,LinphoneTransportTls)){ - if (tr->tls_port!=0){ - if (sal_listen_port (sal,listening_address,tr->tls_port,SalTransportTLS,FALSE)!=0){ - transport_error(lc,"tls",tr->tls_port); - } - } + if (tr->tls_port!=0) + sal->setListenPort (listening_address,tr->tls_port,SalTransportTLS,FALSE); } } return 0; } bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTransportType tp){ - return sal_transport_available(lc->sal,(SalTransport)tp); + return !!lc->sal->isTransportAvailable((SalTransport)tp); } BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneTransports); @@ -3004,17 +3139,17 @@ LinphoneTransports *linphone_core_get_transports(LinphoneCore *lc){ } void linphone_core_get_sip_transports_used(LinphoneCore *lc, LinphoneSipTransports *tr){ - tr->udp_port=sal_get_listening_port(lc->sal,SalTransportUDP); - tr->tcp_port=sal_get_listening_port(lc->sal,SalTransportTCP); - tr->tls_port=sal_get_listening_port(lc->sal,SalTransportTLS); + tr->udp_port=lc->sal->getListeningPort(SalTransportUDP); + tr->tcp_port=lc->sal->getListeningPort(SalTransportTCP); + tr->tls_port=lc->sal->getListeningPort(SalTransportTLS); } LinphoneTransports *linphone_core_get_transports_used(LinphoneCore *lc){ LinphoneTransports *transports = linphone_transports_new(); - transports->udp_port = sal_get_listening_port(lc->sal, SalTransportUDP); - transports->tcp_port = sal_get_listening_port(lc->sal, SalTransportTCP); - transports->tls_port = sal_get_listening_port(lc->sal, SalTransportTLS); - transports->dtls_port = sal_get_listening_port(lc->sal, SalTransportDTLS); + transports->udp_port = lc->sal->getListeningPort(SalTransportUDP); + transports->tcp_port = lc->sal->getListeningPort(SalTransportTCP); + transports->tls_port = lc->sal->getListeningPort(SalTransportTLS); + transports->dtls_port = lc->sal->getListeningPort(SalTransportDTLS); return transports; } @@ -3046,22 +3181,32 @@ void linphone_core_enable_ipv6(LinphoneCore *lc, bool_t val){ bool_t linphone_core_content_encoding_supported(const LinphoneCore *lc, const char *content_encoding) { const char *handle_content_encoding = lp_config_get_string(lc->config, "sip", "handle_content_encoding", "deflate"); - return (strcmp(handle_content_encoding, content_encoding) == 0) && sal_content_encoding_available(lc->sal, content_encoding); + return (strcmp(handle_content_encoding, content_encoding) == 0) && lc->sal->isContentEncodingAvailable(content_encoding); +} + +static void notify_network_reachable_change (LinphoneCore *lc) { + if (!lc->network_reachable_to_be_notified) + return; + + lc->network_reachable_to_be_notified = FALSE; + linphone_core_notify_network_reachable(lc, lc->sip_network_reachable); + if (lc->sip_network_reachable) + linphone_core_resolve_stun_server(lc); } static void monitor_network_state(LinphoneCore *lc, time_t curtime){ bool_t new_status=lc->network_last_status; char newip[LINPHONE_IPADDR_SIZE]; - /* only do the network up checking every five seconds */ + // 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,NULL,newip); if (strcmp(newip,"::1")!=0 && strcmp(newip,"127.0.0.1")!=0){ new_status=TRUE; - }else new_status=FALSE; /*no network*/ + }else new_status=FALSE; //no network if (new_status==lc->network_last_status && new_status==TRUE && strcmp(newip,lc->localip)!=0){ - /*IP address change detected*/ + //IP address change detected ms_message("IP address change detected."); set_network_reachable(lc,FALSE,curtime); lc->network_last_status=FALSE; @@ -3077,6 +3222,8 @@ static void monitor_network_state(LinphoneCore *lc, time_t curtime){ } lc->network_last_check=curtime; } + + notify_network_reachable_change(lc); } static void proxy_update(LinphoneCore *lc){ @@ -3164,50 +3311,21 @@ static void linphone_core_do_plugin_tasks(LinphoneCore *lc){ } void linphone_core_iterate(LinphoneCore *lc){ - bctbx_list_t *calls; - LinphoneCall *call; uint64_t curtime_ms = ms_get_cur_time_ms(); /*monotonic time*/ - int elapsed; time_t current_real_time = ms_time(NULL); int64_t diff_time; - bool_t one_second_elapsed=FALSE; - const char *remote_provisioning_uri = NULL; + bool one_second_elapsed = false; - if (lc->network_reachable_to_be_notified) { - lc->network_reachable_to_be_notified=FALSE; - linphone_core_notify_network_reachable(lc,lc->sip_network_reachable); - if (lc->sip_network_reachable) { - linphone_core_resolve_stun_server(lc); - } - } - if (linphone_core_get_global_state(lc) == LinphoneGlobalStartup) { - if (sal_get_root_ca(lc->sal)) { - belle_tls_crypto_config_set_root_ca(lc->http_crypto_config, sal_get_root_ca(lc->sal)); - belle_http_provider_set_tls_crypto_config(lc->http_provider, lc->http_crypto_config); - } - - linphone_core_notify_display_status(lc, _("Configuring")); - linphone_core_set_state(lc, LinphoneGlobalConfiguring, "Configuring"); - - remote_provisioning_uri = linphone_core_get_provisioning_uri(lc); - if (remote_provisioning_uri) { - int err = linphone_remote_provisioning_download_and_apply(lc, remote_provisioning_uri); - if (err == -1) { - linphone_configuring_terminated(lc, LinphoneConfiguringFailed, "Bad URI"); - } - } // else linphone_configuring_terminated has already been called in linphone_core_init - } if (lc->prevtime_ms == 0){ lc->prevtime_ms = curtime_ms; } - if ((diff_time=curtime_ms-lc->prevtime_ms) >= 1000){ - one_second_elapsed=TRUE; + if ((diff_time=(int64_t)(curtime_ms-lc->prevtime_ms)) >= 1000){ + one_second_elapsed = true; if (diff_time>3000){ /*since monotonic time doesn't increment while machine is sleeping, we don't want to catchup too much*/ lc->prevtime_ms = curtime_ms; }else{ lc->prevtime_ms += 1000; - } } @@ -3238,7 +3356,7 @@ void linphone_core_iterate(LinphoneCore *lc){ } if (lc->ringstream && lc->ringstream_autorelease && lc->dmfs_playing_start_time!=0 - && (curtime_ms/1000 - lc->dmfs_playing_start_time)>5){ + && (curtime_ms/1000 - (uint64_t)lc->dmfs_playing_start_time)>5){ MSPlayerState state; bool_t stop=TRUE; if (lc->ringstream->source && ms_filter_call_method(lc->ringstream->source,MS_PLAYER_GET_STATE,&state)==0){ @@ -3250,61 +3368,17 @@ void linphone_core_iterate(LinphoneCore *lc){ } } - sal_iterate(lc->sal); + lc->sal->iterate(); if (lc->msevq) ms_event_queue_pump(lc->msevq); if (lc->auto_net_state_mon) monitor_network_state(lc, current_real_time); proxy_update(lc); - //we have to iterate for each call - calls = lc->calls; - while(calls!= NULL){ - call = (LinphoneCall *)calls->data; - elapsed = (int)(current_real_time - call->log->start_date_time); - /* get immediately a reference to next one in case the one - we are going to examine is destroy and removed during - linphone_call_start_invite() */ - calls=calls->next; - linphone_call_background_tasks(call,one_second_elapsed); - if (call->state==LinphoneCallOutgoingInit && (elapsed>=lc->sip_conf.delayed_timeout)){ - /*start the call even if the OPTIONS reply did not arrive*/ - if (call->ice_session != NULL) { - ms_warning("ICE candidates gathering from [%s] has not finished yet, proceed with the call without ICE anyway." - ,linphone_nat_policy_get_stun_server(call->nat_policy)); - linphone_call_delete_ice_session(call); - linphone_call_stop_media_streams_for_ice_gathering(call); - } -#ifdef BUILD_UPNP - if (call->upnp_session != NULL) { - ms_warning("uPnP mapping has not finished yet, proceeded with the call without uPnP anyway."); - linphone_call_delete_upnp_session(call); - } -#endif //BUILD_UPNP - linphone_call_start_invite(call, NULL); - } - 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; - ms_message("incoming call timeout (%i)",lc->sip_conf.inc_timeout); - decline_reason = (lc->current_call != call) ? LinphoneReasonBusy : LinphoneReasonDeclined; - call->log->status=LinphoneCallMissed; - call->non_op_error = TRUE; - linphone_error_info_set(call->ei, NULL, decline_reason, linphone_reason_to_error_code(decline_reason), "Not answered", NULL); - linphone_call_decline(call, decline_reason); - } - } - if ( (lc->sip_conf.in_call_timeout > 0) - && (call->log->connected_date_time != 0) - && ((current_real_time - call->log->connected_date_time) > lc->sip_conf.in_call_timeout)) - { - ms_message("in call timeout (%i)",lc->sip_conf.in_call_timeout); - linphone_call_terminate(call); - } - } + /* We have to iterate for each call */ + L_GET_PRIVATE_FROM_C_OBJECT(lc)->iterateCalls(current_real_time, one_second_elapsed); if (linphone_core_video_preview_enabled(lc)){ - if (lc->previewstream==NULL && lc->calls==NULL) + if (lc->previewstream==NULL && !L_GET_PRIVATE_FROM_C_OBJECT(lc)->hasCalls()) toggle_video_preview(lc,TRUE); #ifdef VIDEO_ENABLED if (lc->previewstream) video_stream_iterate(lc->previewstream); @@ -3363,6 +3437,21 @@ const char * linphone_core_get_identity(LinphoneCore *lc){ return from; } +char * linphone_core_get_device_identity(LinphoneCore *lc) { + char *identity = NULL; + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(lc); + if (proxy) { + const LinphoneAddress *contactAddr = linphone_proxy_config_get_contact(proxy); + if (contactAddr) + identity = linphone_address_as_string(contactAddr); + else + identity = bctbx_strdup(linphone_proxy_config_get_identity(proxy)); + } else { + identity = bctbx_strdup(linphone_core_get_primary_contact(lc)); + } + return identity; +} + const char * linphone_core_get_route(LinphoneCore *lc){ LinphoneProxyConfig *proxy=linphone_core_get_default_proxy_config(lc); const char *route=NULL; @@ -3372,65 +3461,44 @@ const char * linphone_core_get_route(LinphoneCore *lc){ return route; } -LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){ - LinphoneCallParams *cp=params ? linphone_call_params_copy(params) : linphone_core_create_call_params(lc, NULL); - LinphoneCall *newcall; - - if (call->state!=LinphoneCallPaused){ - ms_message("Automatically pausing current call to accept transfer."); - _linphone_call_pause(call); - call->was_automatically_paused=TRUE; - } - - if (!params){ - cp->has_audio = call->current_params->has_audio; - 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); - call->refer_pending=FALSE; - newcall=linphone_core_invite_with_params(lc,call->refer_to,cp); - linphone_call_params_unref(cp); - if (newcall) { - call->transfer_target=linphone_call_ref(newcall); - linphone_core_notify_refer_state(lc,call,newcall); - } - return newcall; -} - -void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, LinphoneCall *newcall){ - if (referer->op!=NULL){ - sal_call_notify_refer_state(referer->op,newcall ? newcall->op : NULL); - } +LinphoneCall * linphone_core_start_refered_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) { + shared_ptr referredCall = L_GET_PRIVATE_FROM_C_OBJECT(call)->startReferredCall(params + ? L_GET_CPP_PTR_FROM_C_OBJECT(params) : nullptr); + return L_GET_C_BACK_PTR(referredCall); } /* - returns the ideal route set for making an operation through this proxy. - The list must be freed as well as the SalAddress content + returns the ideal route set for making an operation through this proxy. + The list must be freed as well as the SalAddress content - rfc3608 - 6.1. Procedures at the UA + rfc3608 + 6.1. Procedures at the UA - /.../ - For example, some devices will use locally-configured - explicit loose routing to reach a next-hop proxy, and others will use - a default outbound-proxy routing rule. However, for the result to - function, the combination MUST provide valid routing in the local - environment. In general, the service route set is appended to any - locally configured route needed to egress the access proxy chain. - Systems designers must match the service routing policy of their - nodes with the basic SIP routing policy in order to get a workable - system. + /.../ + For example, some devices will use locally-configured + explicit loose routing to reach a next-hop proxy, and others will use + a default outbound-proxy routing rule. However, for the result to + function, the combination MUST provide valid routing in the local + environment. In general, the service route set is appended to any + locally configured route needed to egress the access proxy chain. + Systems designers must match the service routing policy of their + nodes with the basic SIP routing policy in order to get a workable + system. */ static bctbx_list_t *make_routes_for_proxy(LinphoneProxyConfig *proxy, const LinphoneAddress *dest){ - bctbx_list_t *ret=NULL; - const char *local_route=linphone_proxy_config_get_route(proxy); - const LinphoneAddress *srv_route=linphone_proxy_config_get_service_route(proxy); - if (local_route){ - ret=bctbx_list_append(ret,sal_address_new(local_route)); + bctbx_list_t *ret = NULL; + const bctbx_list_t *proxy_routes = linphone_proxy_config_get_routes(proxy); + bctbx_list_t *proxy_routes_iterator = (bctbx_list_t *)proxy_routes; + const LinphoneAddress *srv_route = linphone_proxy_config_get_service_route(proxy); + while (proxy_routes_iterator) { + const char *local_route = (const char *)bctbx_list_get_data(proxy_routes_iterator); + if (local_route) { + ret = bctbx_list_append(ret, sal_address_new(local_route)); + } + proxy_routes_iterator = bctbx_list_next(proxy_routes_iterator); } if (srv_route){ - ret=bctbx_list_append(ret,sal_address_clone((SalAddress*)srv_route)); + ret=bctbx_list_append(ret,sal_address_clone(L_GET_PRIVATE_FROM_C_OBJECT(srv_route)->getInternalAddress())); } if (ret==NULL){ /*if the proxy address matches the domain part of the destination, then use the same transport @@ -3451,13 +3519,13 @@ LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const L LinphoneProxyConfig *default_cfg=lc->default_proxy; if (linphone_address_get_domain(uri) == NULL) { - ms_message("cannot seach for proxy for uri [%p] if no domain set. returning default",uri); + ms_message("Cannot look for proxy for uri [%p] that has no domain set, returning default", uri); return default_cfg; } /*return default proxy if it is matching the destination uri*/ if (default_cfg){ const char *domain=linphone_proxy_config_get_domain(default_cfg); - if (strcmp(domain,linphone_address_get_domain(uri))==0){ + if (domain && !strcmp(domain,linphone_address_get_domain(uri))){ found_cfg=default_cfg; goto end; } @@ -3499,7 +3567,7 @@ const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAdd LinphoneCall * linphone_core_invite(LinphoneCore *lc, const char *url){ LinphoneCall *call; LinphoneCallParams *p=linphone_core_create_call_params(lc, NULL); - p->has_video &= !!lc->video_policy.automatically_initiate; + linphone_call_params_enable_video(p, linphone_call_params_video_enabled(p) && !!lc->video_policy.automatically_initiate); call=linphone_core_invite_with_params(lc,url,p); linphone_call_params_unref(p); return call; @@ -3519,7 +3587,7 @@ LinphoneCall * linphone_core_invite_with_params(LinphoneCore *lc, const char *ur LinphoneCall * linphone_core_invite_address(LinphoneCore *lc, const LinphoneAddress *addr){ LinphoneCall *call; LinphoneCallParams *p=linphone_core_create_call_params(lc, NULL); - p->has_video &= !!lc->video_policy.automatically_initiate; + linphone_call_params_enable_video(p, linphone_call_params_video_enabled(p) && !!lc->video_policy.automatically_initiate); call=linphone_core_invite_address_with_params (lc,addr,p); linphone_call_params_unref(p); return call; @@ -3529,7 +3597,7 @@ static void linphone_transfer_routes_to_op(bctbx_list_t *routes, SalOp *op){ bctbx_list_t *it; for(it=routes;it!=NULL;it=it->next){ SalAddress *addr=(SalAddress*)it->data; - sal_op_add_route_address(op,addr); + op->addRouteAddress(addr); sal_address_destroy(addr); } bctbx_list_free(routes); @@ -3542,7 +3610,7 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon if (proxy){ identity=linphone_proxy_config_get_identity(proxy); if (linphone_proxy_config_get_privacy(proxy)!=LinphonePrivacyDefault) { - sal_op_set_privacy(op,linphone_proxy_config_get_privacy(proxy)); + op->setPrivacy(linphone_proxy_config_get_privacy(proxy)); } }else identity=linphone_core_get_primary_contact(lc); /*sending out of calls*/ @@ -3550,26 +3618,22 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon routes=make_routes_for_proxy(proxy,dest); linphone_transfer_routes_to_op(routes,op); } - if (sal_address_has_uri_param((const SalAddress *)dest,"gr")) { - /*in case of gruu destination remove gruu parram from to*/ - SalAddress *dest_copy = sal_address_clone(dest); - sal_address_remove_uri_param(dest_copy,"gr"); - sal_op_set_to_address(op,dest_copy); - sal_address_unref(dest_copy); - } else { - 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)); + op->setToAddress(L_GET_PRIVATE_FROM_C_OBJECT(dest)->getInternalAddress()); + op->setFrom(identity); + op->setSentCustomHeaders(headers); + op->setRealm(L_C_TO_STRING(linphone_proxy_config_get_realm(proxy))); + if (with_contact && proxy && proxy->op){ - const SalAddress *contact; - contact=sal_op_get_contact_address(proxy->op); - SalAddress *new_contact = contact ? sal_address_clone(contact) : NULL; - sal_op_set_and_clean_contact_address(proxy->op, new_contact); + const LinphoneAddress *contact = linphone_proxy_config_get_contact(proxy); + SalAddress *salAddress = nullptr; + if (contact) + salAddress = sal_address_clone(const_cast(L_GET_PRIVATE_FROM_C_OBJECT(contact)->getInternalAddress())); + op->setContactAddress(salAddress); + if (salAddress) + sal_address_unref(salAddress); } - sal_op_cnx_ip_to_0000_if_sendonly_enable(op,lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0)); /*also set in linphone_call_new_incoming*/ + op->enableCnxIpTo0000IfSendOnly(!!lp_config_get_default_int(lc->config,"sip","cnx_ip_to_0000_if_sendonly_enabled",0)); /*also set in linphone_call_new_incoming*/ } void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact) { linphone_configure_op_with_proxy(lc, op, dest, headers,with_contact,linphone_core_lookup_known_proxy(lc,dest)); @@ -3579,9 +3643,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const const char *from=NULL; LinphoneProxyConfig *proxy=NULL; LinphoneAddress *parsed_url2=NULL; - char *real_url=NULL; LinphoneCall *call; - bool_t defer = FALSE; LinphoneCallParams *cp; if (!(!linphone_call_params_audio_enabled(params) || @@ -3593,34 +3655,29 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const return NULL; } - if(!linphone_core_can_we_add_call(lc)){ - linphone_core_notify_display_warning(lc,_("Sorry, we have reached the maximum number of simultaneous calls")); + if (!L_GET_PRIVATE_FROM_C_OBJECT(lc)->canWeAddCall()) return NULL; - } cp = linphone_call_params_copy(params); - - real_url=linphone_address_as_string(addr); proxy=linphone_core_lookup_known_proxy(lc,addr); - if (proxy!=NULL) { 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; + linphone_call_params_enable_avpf(cp, linphone_proxy_config_avpf_enabled(proxy)); + linphone_call_params_set_avpf_rr_interval(cp, (uint16_t)(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; + linphone_call_params_enable_avpf(cp, linphone_core_get_avpf_mode(lc)==LinphoneAVPFEnabled); + if (linphone_call_params_avpf_enabled(cp)) + linphone_call_params_set_avpf_rr_interval(cp, (uint16_t)(linphone_core_get_avpf_rr_interval(lc) * 1000)); } /* if no proxy or no identity defined for this proxy, default to primary contact*/ if (from==NULL) from=linphone_core_get_primary_contact(lc); parsed_url2=linphone_address_new(from); + call=linphone_call_new_outgoing(lc,parsed_url2,addr,cp,proxy); + linphone_address_unref(parsed_url2); - call=linphone_call_new_outgoing(lc,parsed_url2,linphone_address_clone(addr),cp,proxy); - - if(linphone_core_add_call(lc,call)!= 0) - { + if (L_GET_PRIVATE_FROM_C_OBJECT(lc)->addCall(L_GET_CPP_PTR_FROM_C_OBJECT(call)) != 0) { ms_warning("we had a problem in adding the call into the invite ... weird"); linphone_call_unref(call); linphone_call_params_unref(cp); @@ -3628,54 +3685,16 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const } /* Unless this call is for a conference, it becomes now the current one*/ - if (linphone_call_params_get_local_conference_mode(params) == FALSE) lc->current_call=call; - linphone_call_set_state (call,LinphoneCallOutgoingInit,"Starting outgoing call"); - call->log->start_date_time=ms_time(NULL); - - if (linphone_nat_policy_ice_enabled(call->nat_policy)) { - if (lc->sip_conf.sdp_200_ack){ - ms_warning("ICE is not supported when sending INVITE without SDP"); - }else{ - /* 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) { -#ifdef BUILD_UPNP - if (linphone_call_update_upnp(call) < 0) { - /* uPnP port mappings failed, proceed with the call anyway. */ - linphone_call_delete_upnp_session(call); - } else { - defer = TRUE; - } -#endif // BUILD_UPNP - } - - if (call->dest_proxy==NULL && lc->sip_conf.ping_with_options==TRUE){ -#ifdef BUILD_UPNP - if (lc->upnp != NULL && linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp && - linphone_upnp_context_get_state(lc->upnp) == LinphoneUpnpStateOk) { -#else //BUILD_UPNP - { -#endif //BUILD_UPNP - /*defer the start of the call after the OPTIONS ping*/ - call->ping_replied=FALSE; - call->ping_op=sal_op_new(lc->sal); - sal_ping(call->ping_op,from,real_url); - sal_op_set_user_pointer(call->ping_op,call); - defer = TRUE; + if (linphone_call_params_get_local_conference_mode(params) == FALSE) + L_GET_PRIVATE_FROM_C_OBJECT(lc)->setCurrentCall(L_GET_CPP_PTR_FROM_C_OBJECT(call)); + bool defer = L_GET_PRIVATE_FROM_C_OBJECT(call)->initiateOutgoing(); + if (!defer) { + if (L_GET_PRIVATE_FROM_C_OBJECT(call)->startInvite(nullptr) != 0) { + /* The call has already gone to error and released state, so do not return it */ + call = nullptr; } } - if (defer==FALSE) { - if (linphone_call_start_invite(call,NULL) != 0){ - /*the call has already gone to error and released state, so do not return it*/ - call = NULL; - } - } - - if (real_url!=NULL) ms_free(real_url); linphone_call_params_unref(cp); return call; } @@ -3692,12 +3711,11 @@ LinphoneStatus linphone_core_transfer_call_to_another(LinphoneCore *lc, Linphone return linphone_call_transfer_to_another(call, dest); } -bool_t linphone_core_is_incoming_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) - { - if(call->dir==LinphoneCallIncoming - && (call->state == LinphoneCallIncomingReceived || call->state == LinphoneCallIncomingEarlyMedia)) + if (call) { + if ((linphone_call_get_dir(call) == LinphoneCallIncoming) + && ((linphone_call_get_state(call) == LinphoneCallIncomingReceived) || (linphone_call_get_state(call) == LinphoneCallIncomingEarlyMedia))) return TRUE; } return FALSE; @@ -3708,24 +3726,10 @@ bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription } void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ - char *barmesg; - char *tmp; - LinphoneAddress *from_parsed; - bool_t propose_early_media=lp_config_get_int(lc->config,"sip","incoming_calls_early_media",FALSE); - - from_parsed=linphone_address_new(sal_op_get_from(call->op)); - linphone_address_clean(from_parsed); - tmp=linphone_address_as_string(from_parsed); - linphone_address_unref(from_parsed); - barmesg=ortp_strdup_printf("%s %s%s",tmp,_("is contacting you"), - (sal_call_autoanswer_asked(call->op)) ?_(" and asked autoanswer."):"."); - linphone_core_notify_show_interface(lc); - linphone_core_notify_display_status(lc,barmesg); - - /* play the ring if this is the only call*/ - if (bctbx_list_size(lc->calls)==1){ + /* Play the ring if this is the only call*/ + if (linphone_core_get_calls_nb(lc)==1){ MSSndCard *ringcard=lc->sound_conf.lsd_card ?lc->sound_conf.lsd_card : lc->sound_conf.ring_sndcard; - lc->current_call=call; + L_GET_PRIVATE_FROM_C_OBJECT(lc)->setCurrentCall(L_GET_CPP_PTR_FROM_C_OBJECT(call)); if (lc->ringstream && lc->dmfs_playing_start_time!=0){ linphone_core_stop_dtmf_stream(lc); } @@ -3733,34 +3737,9 @@ void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call){ linphone_ringtoneplayer_start(lc->factory, lc->ringtoneplayer, ringcard, lc->sound_conf.local_ring, 2000); }else{ /* else play a tone within the context of the current call */ - call->ringing_beep=TRUE; + L_GET_PRIVATE_FROM_C_OBJECT(call)->setRingingBeep(true); linphone_core_play_named_tone(lc,LinphoneToneCallWaiting); } - - linphone_call_set_state(call,LinphoneCallIncomingReceived,"Incoming call"); - /*from now on, the application is aware of the call and supposed to take background task or already submitted notification to the user. - We can then drop our background task.*/ - if (call->bg_task_id!=0) { - sal_end_background_task(call->bg_task_id); - call->bg_task_id=0; - } - - if (call->state==LinphoneCallIncomingReceived){ - /*try to be best-effort in giving real local or routable contact address for 100Rel case*/ - linphone_call_set_contact_op(call); - - if (propose_early_media){ - linphone_call_accept_early_media(call); - }else sal_call_notify_ringing(call->op,FALSE); - - if (sal_call_get_replaces(call->op)!=NULL && lp_config_get_int(lc->config,"sip","auto_answer_replacing_calls",1)){ - linphone_call_accept(call); - } - } - linphone_call_unref(call); - - ms_free(barmesg); - ms_free(tmp); } LinphoneStatus linphone_core_accept_early_media_with_params(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params) { @@ -3826,13 +3805,7 @@ LinphoneStatus linphone_core_terminate_call(LinphoneCore *lc, LinphoneCall *call } LinphoneStatus linphone_core_terminate_all_calls(LinphoneCore *lc) { - bctbx_list_t *calls=lc->calls; - while(calls) { - LinphoneCall *c=(LinphoneCall*)calls->data; - calls=calls->next; - linphone_call_terminate(c); - } - return 0; + return L_GET_CPP_PTR_FROM_C_OBJECT(lc)->terminateAllCalls(); } LinphoneStatus linphone_core_decline_call(LinphoneCore *lc, LinphoneCall *call, LinphoneReason reason) { @@ -3840,31 +3813,29 @@ LinphoneStatus linphone_core_decline_call(LinphoneCore *lc, LinphoneCall *call, } const bctbx_list_t *linphone_core_get_calls(LinphoneCore *lc) { - return lc->calls; + if (lc->callsCache) { + bctbx_list_free_with_data(lc->callsCache, (bctbx_list_free_func)linphone_call_unref); + lc->callsCache = NULL; + } + lc->callsCache = L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getCalls()); + return lc->callsCache; } bool_t linphone_core_in_call(const LinphoneCore *lc){ return linphone_core_get_current_call((LinphoneCore *)lc)!=NULL || linphone_core_is_in_conference(lc); } -LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc){ - return lc->current_call; +LinphoneCall *linphone_core_get_current_call(const LinphoneCore *lc) { + shared_ptr call = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getCurrentCall(); + return call ? L_GET_C_BACK_PTR(call) : NULL; } LinphoneStatus linphone_core_pause_call(LinphoneCore *lc, LinphoneCall *call) { return linphone_call_pause(call); } -LinphoneStatus linphone_core_pause_all_calls(LinphoneCore *lc){ - const bctbx_list_t *elem; - for(elem=lc->calls;elem!=NULL;elem=elem->next){ - LinphoneCall *call=(LinphoneCall *)elem->data; - LinphoneCallState cs=linphone_call_get_state(call); - if (cs==LinphoneCallStreamsRunning || cs==LinphoneCallPausedByRemote){ - _linphone_call_pause(call); - } - } - return 0; +LinphoneStatus linphone_core_pause_all_calls(LinphoneCore *lc) { + return L_GET_CPP_PTR_FROM_C_OBJECT(lc)->pauseAllCalls(); } int linphone_core_preempt_sound_resources(LinphoneCore *lc){ @@ -3879,7 +3850,7 @@ int linphone_core_preempt_sound_resources(LinphoneCore *lc){ current_call=linphone_core_get_current_call(lc); if(current_call != NULL){ ms_message("Pausing automatically the current call."); - err = _linphone_call_pause(current_call); + err = L_GET_CPP_PTR_FROM_C_OBJECT(current_call)->pause(); } if (lc->ringstream){ linphone_core_stop_ringing(lc); @@ -3891,11 +3862,6 @@ LinphoneStatus linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call) { return linphone_call_resume(call); } -static int remote_address_compare(LinphoneCall *call, const LinphoneAddress *raddr){ - const LinphoneAddress *addr=linphone_call_get_remote_address (call); - return !linphone_address_weak_equal (addr,raddr); -} - LinphoneCall *linphone_core_get_call_by_remote_address(const LinphoneCore *lc, const char *remote_address){ LinphoneCall *call=NULL; LinphoneAddress *raddr=linphone_address_new(remote_address); @@ -3910,11 +3876,9 @@ LinphoneCall *linphone_core_find_call_from_uri(const LinphoneCore *lc, const cha return linphone_core_get_call_by_remote_address(lc, remote_address); } -LinphoneCall *linphone_core_get_call_by_remote_address2(const LinphoneCore *lc, const LinphoneAddress *raddr){ - const bctbx_list_t *elem=bctbx_list_find_custom(lc->calls,(int (*)(const void*,const void *))remote_address_compare,raddr); - - if (elem) return (LinphoneCall*) elem->data; - return NULL; +LinphoneCall *linphone_core_get_call_by_remote_address2(const LinphoneCore *lc, const LinphoneAddress *raddr) { + shared_ptr call = L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getCallByRemoteAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(raddr)); + return call ? L_GET_C_BACK_PTR(call) : NULL; } int linphone_core_send_publish(LinphoneCore *lc, LinphonePresenceModel *presence) { @@ -4161,7 +4125,7 @@ int linphone_core_get_rec_level(LinphoneCore *lc) { void linphone_core_set_ring_level(LinphoneCore *lc, int level){ MSSndCard *sndcard; - lc->sound_conf.ring_lev=level; + lc->sound_conf.ring_lev = (char)level; sndcard=lc->sound_conf.ring_sndcard; if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_PLAYBACK,level); } @@ -4177,11 +4141,11 @@ void linphone_core_set_mic_gain_db (LinphoneCore *lc, float gaindb){ lp_config_set_float(lc->config,"sound","mic_gain_db",lc->sound_conf.soft_mic_lev); } - if (call==NULL || (st=call->audiostream)==NULL){ + if (!call || !(st = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)))) { ms_message("linphone_core_set_mic_gain_db(): no active call."); return; } - set_mic_gain_db(st,gain); + audio_stream_set_mic_gain_db(st,gain); } float linphone_core_get_mic_gain_db(LinphoneCore *lc) { @@ -4198,7 +4162,7 @@ void linphone_core_set_playback_gain_db (LinphoneCore *lc, float gaindb){ lp_config_set_float(lc->config,"sound","playback_gain_db",lc->sound_conf.soft_play_lev); } - if (call==NULL || (st=call->audiostream)==NULL){ + if (!call || !(st = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)))) { ms_message("linphone_core_set_playback_gain_db(): no active call."); return; } @@ -4211,14 +4175,14 @@ float linphone_core_get_playback_gain_db(LinphoneCore *lc) { void linphone_core_set_play_level(LinphoneCore *lc, int level){ MSSndCard *sndcard; - lc->sound_conf.play_lev=level; + lc->sound_conf.play_lev = (char)level; sndcard=lc->sound_conf.play_sndcard; if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_PLAYBACK,level); } void linphone_core_set_rec_level(LinphoneCore *lc, int level) { MSSndCard *sndcard; - lc->sound_conf.rec_lev=level; + lc->sound_conf.rec_lev = (char)level; sndcard=lc->sound_conf.capt_sndcard; if (sndcard) ms_snd_card_set_level(sndcard,MS_SND_CARD_CAPTURE,level); } @@ -4306,10 +4270,30 @@ const char** linphone_core_get_video_devices(const LinphoneCore *lc){ return lc->video_conf.cams; } +bctbx_list_t * linphone_core_get_sound_devices_list(const LinphoneCore *lc){ + bctbx_list_t *cards_list = NULL; + const char** cards = lc->sound_conf.cards; + for (const char* c = *cards; c; c=*++cards) { + cards_list = bctbx_list_append(cards_list, (char *)c); + } + return cards_list; +} + +bctbx_list_t * linphone_core_get_video_devices_list(const LinphoneCore *lc){ + bctbx_list_t *cards_list = NULL; + const char** cards = lc->video_conf.cams; + + if (cards) + for (const char* c = *cards; c; c=*++cards) + cards_list = bctbx_list_append(cards_list, (char *)c); + + return cards_list; +} + void linphone_core_set_default_sound_devices(LinphoneCore *lc){ - linphone_core_set_ringer_device(lc, NULL); - linphone_core_set_playback_device(lc, NULL); - linphone_core_set_capture_device(lc, NULL); + linphone_core_set_ringer_device(lc, NULL); + linphone_core_set_playback_device(lc, NULL); + linphone_core_set_capture_device(lc, NULL); } void linphone_core_reload_sound_devices(LinphoneCore *lc){ @@ -4398,7 +4382,7 @@ const char *linphone_core_get_ring(const LinphoneCore *lc){ } void linphone_core_set_root_ca(LinphoneCore *lc, const char *path) { - sal_set_root_ca(lc->sal, path); + lc->sal->setRootCa(L_C_TO_STRING(path)); if (lc->http_crypto_config) { belle_tls_crypto_config_set_root_ca(lc->http_crypto_config, path); } @@ -4406,8 +4390,8 @@ void linphone_core_set_root_ca(LinphoneCore *lc, const char *path) { } void linphone_core_set_root_ca_data(LinphoneCore *lc, const char *data) { - sal_set_root_ca(lc->sal, NULL); - sal_set_root_ca_data(lc->sal, data); + lc->sal->setRootCa(""); + lc->sal->setRootCaData(L_C_TO_STRING(data)); if (lc->http_crypto_config) { belle_tls_crypto_config_set_root_ca_data(lc->http_crypto_config, data); } @@ -4418,7 +4402,7 @@ const char *linphone_core_get_root_ca(LinphoneCore *lc){ } void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){ - sal_verify_server_certificates(lc->sal,yesno); + lc->sal->verifyServerCertificates(!!yesno); if (lc->http_crypto_config){ belle_tls_crypto_config_set_verify_exceptions(lc->http_crypto_config, yesno ? 0 : BELLE_TLS_VERIFY_ANY_REASON); } @@ -4426,7 +4410,7 @@ void linphone_core_verify_server_certificates(LinphoneCore *lc, bool_t yesno){ } void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yesno){ - sal_verify_server_cn(lc->sal,yesno); + lc->sal->verifyServerCn(!!yesno); if (lc->http_crypto_config){ belle_tls_crypto_config_set_verify_exceptions(lc->http_crypto_config, yesno ? 0 : BELLE_TLS_VERIFY_CN_MISMATCH); } @@ -4434,7 +4418,7 @@ void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yesno){ } void linphone_core_set_ssl_config(LinphoneCore *lc, void *ssl_config) { - sal_set_ssl_config(lc->sal, ssl_config); + lc->sal->setSslConfig(ssl_config); if (lc->http_crypto_config) { belle_tls_crypto_config_set_ssl_config(lc->http_crypto_config, ssl_config); } @@ -4526,9 +4510,10 @@ void linphone_core_enable_mic(LinphoneCore *lc, bool_t enable) { list = linphone_core_get_calls(lc); for (elem = list; elem != NULL; elem = elem->next) { call = (LinphoneCall *)elem->data; - call->audio_muted = !enable; - if (call->audiostream) - linphone_core_mute_audio_stream(lc, call->audiostream, call->audio_muted); + linphone_call_set_audio_muted(call, !enable); + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + if (astream) + linphone_core_mute_audio_stream(lc, astream, linphone_call_get_audio_muted(call)); } } @@ -4540,7 +4525,7 @@ bool_t linphone_core_mic_enabled(LinphoneCore *lc) { ms_warning("%s(): No current call!", __FUNCTION__); return TRUE; } - return !call->audio_muted; + return !linphone_call_get_audio_muted(call); } bool_t linphone_core_is_rtp_muted(LinphoneCore *lc){ @@ -4550,7 +4535,7 @@ bool_t linphone_core_is_rtp_muted(LinphoneCore *lc){ return FALSE; } if( linphone_core_get_rtp_no_xmit_on_audio_mute(lc)){ - return call->audio_muted; + return linphone_call_get_audio_muted(call); } return FALSE; } @@ -4586,27 +4571,15 @@ const char * linphone_core_get_stun_server(const LinphoneCore *lc){ bool_t linphone_core_upnp_available(){ -#ifdef BUILD_UPNP - return TRUE; -#else return FALSE; -#endif //BUILD_UPNP } LinphoneUpnpState linphone_core_get_upnp_state(const LinphoneCore *lc){ -#ifdef BUILD_UPNP - return linphone_upnp_context_get_state(lc->upnp); -#else return LinphoneUpnpStateNotAvailable; -#endif //BUILD_UPNP } const char * linphone_core_get_upnp_external_ipaddress(const LinphoneCore *lc){ -#ifdef BUILD_UPNP - return linphone_upnp_context_get_external_ipaddress(lc->upnp); -#else return NULL; -#endif //BUILD_UPNP } void linphone_core_set_nat_address(LinphoneCore *lc, const char *addr) { @@ -4675,11 +4648,7 @@ void linphone_core_set_firewall_policy(LinphoneCore *lc, LinphoneFirewallPolicy linphone_nat_policy_enable_stun(nat_policy, TRUE); break; case LinphonePolicyUseUpnp: -#ifdef BUILD_UPNP - linphone_nat_policy_enable_upnp(nat_policy, TRUE); -#else - ms_warning("UPNP is not available, reset firewall policy to no firewall"); -#endif //BUILD_UPNP + ms_warning("UPNP is no longer supported, reset firewall policy to no firewall"); break; } @@ -4746,28 +4715,10 @@ void linphone_core_set_nat_policy(LinphoneCore *lc, LinphoneNatPolicy *policy) { linphone_nat_policy_save_to_config(lc->nat_policy); } -#ifdef BUILD_UPNP - linphone_core_enable_keep_alive(lc, (lc->sip_conf.keepalive_period > 0)); - if (linphone_nat_policy_upnp_enabled(policy)) { - if (lc->upnp == NULL) { - lc->upnp = linphone_upnp_context_new(lc); - } - sal_nat_helper_enable(lc->sal, FALSE); - sal_enable_auto_contacts(lc->sal, FALSE); - sal_use_rport(lc->sal, FALSE); - } else { - if (lc->upnp != NULL) { - linphone_upnp_context_destroy(lc->upnp); - lc->upnp = NULL; - } -#endif - sal_nat_helper_enable(lc->sal, lp_config_get_int(lc->config, "net", "enable_nat_helper", 1)); - sal_enable_auto_contacts(lc->sal, TRUE); - sal_use_rport(lc->sal, lp_config_get_int(lc->config, "sip", "use_rport", 1)); - if (lc->sip_conf.contact) update_primary_contact(lc); -#ifdef BUILD_UPNP - } -#endif + lc->sal->enableNatHelper(!!lp_config_get_int(lc->config, "net", "enable_nat_helper", 1)); + lc->sal->enableAutoContacts(TRUE); + lc->sal->useRport(!!lp_config_get_int(lc->config, "sip", "use_rport", 1)); + if (lc->sip_conf.contact) update_primary_contact(lc); } LinphoneNatPolicy * linphone_core_get_nat_policy(const LinphoneCore *lc) { @@ -4868,7 +4819,7 @@ void linphone_core_migrate_logs_from_rc_to_db(LinphoneCore *lc) { return; } - logs_to_migrate = call_logs_read_from_config_file(lc); + logs_to_migrate = linphone_core_read_call_logs_from_config_file(lc); if (!logs_to_migrate) { ms_warning("nothing to migrate, skipping..."); return; @@ -4908,11 +4859,24 @@ void linphone_core_migrate_logs_from_rc_to_db(LinphoneCore *lc) { * Video related functions * ******************************************************************************/ + #ifdef VIDEO_ENABLED -static void snapshot_taken(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { - if (id == MS_JPEG_WRITER_SNAPSHOT_TAKEN) { - LinphoneCore *lc = (LinphoneCore *)userdata; - linphone_core_enable_video_preview(lc, FALSE); +static void video_filter_callback(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { + switch(id) { + case MS_JPEG_WRITER_SNAPSHOT_TAKEN: { + LinphoneCore *lc = (LinphoneCore *)userdata; + linphone_core_enable_video_preview(lc, FALSE); + break; + } + case MS_QRCODE_READER_QRCODE_FOUND: { + LinphoneCore *lc = (LinphoneCore *)userdata; + if (linphone_core_cbs_get_qrcode_found(linphone_core_get_current_callbacks(lc)) != NULL) { + char* result = ms_strdup((const char*)arg); + linphone_core_notify_qrcode_found(lc, result); + ms_free(result); + } + break; + } } } #endif @@ -4935,7 +4899,7 @@ LinphoneStatus linphone_core_take_preview_snapshot(LinphoneCore *lc, const char lc->previewstream->ms.factory = lc->factory; linphone_core_enable_video_preview(lc, TRUE); - ms_filter_add_notify_callback(lc->previewstream->local_jpegwriter, snapshot_taken, lc, TRUE); + ms_filter_add_notify_callback(lc->previewstream->local_jpegwriter, video_filter_callback, lc, TRUE); ms_filter_call_method(lc->previewstream->local_jpegwriter, MS_JPEG_WRITER_TAKE_SNAPSHOT, (void*)file); } else { ms_filter_call_method(lc->previewstream->local_jpegwriter, MS_JPEG_WRITER_TAKE_SNAPSHOT, (void*)file); @@ -4956,16 +4920,30 @@ static void toggle_video_preview(LinphoneCore *lc, bool_t val){ if (!vdef || linphone_video_definition_is_undefined(vdef)) { vdef = linphone_core_get_preferred_video_definition(lc); } - vsize.width = linphone_video_definition_get_width(vdef); - vsize.height = linphone_video_definition_get_height(vdef); - lc->previewstream=video_preview_new(lc->factory); + if (linphone_core_qrcode_video_preview_enabled(lc)) { + vsize.width = 720; + vsize.height = 1280; + } else { + vsize.width = (int)linphone_video_definition_get_width(vdef); + vsize.height = (int)linphone_video_definition_get_height(vdef); + } + lc->previewstream = video_preview_new(lc->factory); video_preview_set_size(lc->previewstream,vsize); if (display_filter) video_preview_set_display_filter_name(lc->previewstream,display_filter); if (lc->preview_window_id != NULL) video_preview_set_native_window_id(lc->previewstream,lc->preview_window_id); video_preview_set_fps(lc->previewstream,linphone_core_get_preferred_framerate(lc)); + if (linphone_core_qrcode_video_preview_enabled(lc)) { + video_preview_enable_qrcode(lc->previewstream, TRUE); + if (lc->qrcode_rect.w != 0 && lc->qrcode_rect.h != 0) { + video_preview_set_decode_rect(lc->previewstream, lc->qrcode_rect); + } + } video_preview_start(lc->previewstream,lc->video_conf.device); + if (video_preview_qrcode_enabled(lc->previewstream)) { + ms_filter_add_notify_callback(lc->previewstream->qrcode, video_filter_callback, lc, TRUE); + } } }else{ if (lc->previewstream!=NULL){ @@ -5140,6 +5118,27 @@ bool_t linphone_core_video_preview_enabled(const LinphoneCore *lc){ return lc->video_conf.show_local; } +void linphone_core_enable_qrcode_video_preview(LinphoneCore *lc, bool_t val) { + lc->video_conf.qrcode_decoder=val; + if (linphone_core_ready(lc)) + lp_config_set_int(lc->config,"video","qrcode_decoder",val); +} + +bool_t linphone_core_qrcode_video_preview_enabled(const LinphoneCore *lc) { + return lc->video_conf.qrcode_decoder; +} + +void linphone_core_set_qrcode_decode_rect(LinphoneCore *lc, const int x, const int y, const int w, const int h) { + if (lc) { + MSRect rect; + rect.x = x; + rect.y = y; + rect.w = w; + rect.h = h; + lc->qrcode_rect = rect; + } +} + void linphone_core_enable_self_view(LinphoneCore *lc, bool_t val){ #ifdef VIDEO_ENABLED LinphoneCall *call=linphone_core_get_current_call (lc); @@ -5147,8 +5146,10 @@ void linphone_core_enable_self_view(LinphoneCore *lc, bool_t val){ if (linphone_core_ready(lc)) { lp_config_set_int(lc->config,"video","self_view",linphone_core_self_view_enabled(lc)); } - if (call && call->videostream){ - video_stream_enable_self_view(call->videostream,val); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + video_stream_enable_self_view(vstream,val); } if (linphone_core_ready(lc)){ lp_config_set_int(lc->config,"video","self_view",val); @@ -5194,8 +5195,10 @@ static VideoStream * get_active_video_stream(LinphoneCore *lc){ VideoStream *vs = NULL; LinphoneCall *call=linphone_core_get_current_call (lc); /* Select the video stream from the call in the first place */ - if (call && call->videostream) { - vs = call->videostream; + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + vs = vstream; } /* If not in call, select the video stream from the preview */ if (vs == NULL && lc->previewstream) { @@ -5286,8 +5289,11 @@ void * linphone_core_get_native_video_window_id(const LinphoneCore *lc){ #ifdef VIDEO_ENABLED /*case where it was not set but we want to get the one automatically created by mediastreamer2 (desktop versions only)*/ LinphoneCall *call=linphone_core_get_current_call (lc); - if (call && call->videostream) - return video_stream_get_native_window_id(call->videostream); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + return video_stream_get_native_window_id(vstream); + } #endif } return 0; @@ -5295,11 +5301,6 @@ void * linphone_core_get_native_video_window_id(const LinphoneCore *lc){ /* unsets the video id for all calls (indeed it may be kept by filters or videostream object itself by paused calls)*/ static void unset_video_window_id(LinphoneCore *lc, bool_t preview, void *id){ -#ifdef VIDEO_ENABLED - LinphoneCall *call; - bctbx_list_t *elem; -#endif - if ((id != NULL) #ifndef _WIN32 && ((unsigned long)id != (unsigned long)-1) @@ -5308,17 +5309,7 @@ static void unset_video_window_id(LinphoneCore *lc, bool_t preview, void *id){ ms_error("Invalid use of unset_video_window_id()"); return; } -#ifdef VIDEO_ENABLED - for(elem=lc->calls;elem!=NULL;elem=elem->next){ - call=(LinphoneCall *) elem->data; - if (call->videostream){ - if (preview) - video_stream_set_native_preview_window_id(call->videostream,id); - else - video_stream_set_native_window_id(call->videostream,id); - } - } -#endif + L_GET_PRIVATE_FROM_C_OBJECT(lc)->unsetVideoWindowId(!!preview, id); } void linphone_core_set_native_video_window_id(LinphoneCore *lc, void *id){ @@ -5333,8 +5324,10 @@ void linphone_core_set_native_video_window_id(LinphoneCore *lc, void *id){ #ifdef VIDEO_ENABLED { LinphoneCall *call=linphone_core_get_current_call(lc); - if (call!=NULL && call->videostream){ - video_stream_set_native_window_id(call->videostream,id); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + video_stream_set_native_window_id(vstream,id); } } #endif @@ -5348,8 +5341,11 @@ void * linphone_core_get_native_preview_window_id(const LinphoneCore *lc){ /*case where we want the id automatically created by mediastreamer2 (desktop versions only)*/ #ifdef VIDEO_ENABLED LinphoneCall *call=linphone_core_get_current_call(lc); - if (call && call->videostream) - return video_stream_get_native_preview_window_id(call->videostream); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + return video_stream_get_native_preview_window_id(vstream); + } if (lc->previewstream) return video_preview_get_native_window_id(lc->previewstream); #endif @@ -5369,8 +5365,10 @@ void linphone_core_set_native_preview_window_id(LinphoneCore *lc, void *id){ #ifdef VIDEO_ENABLED { LinphoneCall *call=linphone_core_get_current_call(lc); - if (call!=NULL && call->videostream){ - video_stream_set_native_preview_window_id(call->videostream,id); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + video_stream_set_native_preview_window_id(vstream,id); }else if (lc->previewstream){ video_preview_set_native_window_id(lc->previewstream,id); } @@ -5382,8 +5380,10 @@ void linphone_core_show_video(LinphoneCore *lc, bool_t show){ #ifdef VIDEO_ENABLED LinphoneCall *call=linphone_core_get_current_call(lc); ms_error("linphone_core_show_video %d", show); - if (call!=NULL && call->videostream){ - video_stream_show_video(call->videostream,show); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + video_stream_show_video(vstream,show); } #endif } @@ -5402,8 +5402,10 @@ void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation) { #ifdef VIDEO_ENABLED { LinphoneCall *call=linphone_core_get_current_call(lc); - if (call!=NULL && call->videostream){ - video_stream_set_device_rotation(call->videostream,rotation); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + video_stream_set_device_rotation(vstream,rotation); } } #endif @@ -5412,8 +5414,10 @@ void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation) { int linphone_core_get_camera_sensor_rotation(LinphoneCore *lc) { #ifdef VIDEO_ENABLED LinphoneCall *call = linphone_core_get_current_call(lc); - if ((call != NULL) && (call->videostream != NULL)) { - return video_stream_get_camera_sensor_rotation(call->videostream); + if (call) { + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + if (vstream) + return video_stream_get_camera_sensor_rotation(vstream); } #endif return -1; @@ -5498,7 +5502,7 @@ void linphone_core_set_preferred_video_definition(LinphoneCore *lc, LinphoneVide void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize) { linphone_core_set_preferred_video_definition(lc, - linphone_factory_find_supported_video_definition(linphone_factory_get(), vsize.width, vsize.height)); + linphone_factory_find_supported_video_definition(linphone_factory_get(), (unsigned int)vsize.width, (unsigned int)vsize.height)); } void linphone_core_set_preview_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef) { @@ -5527,7 +5531,7 @@ void linphone_core_set_preview_video_definition(LinphoneCore *lc, LinphoneVideoD void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize) { linphone_core_set_preview_video_definition(lc, - linphone_factory_find_supported_video_definition(linphone_factory_get(), vsize.width, vsize.height)); + linphone_factory_find_supported_video_definition(linphone_factory_get(), (unsigned int)vsize.width, (unsigned int)vsize.height)); } const LinphoneVideoDefinition * linphone_core_get_preview_video_definition(const LinphoneCore *lc) { @@ -5536,8 +5540,8 @@ const LinphoneVideoDefinition * linphone_core_get_preview_video_definition(const MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc) { MSVideoSize vsize = { 0 }; - vsize.width = linphone_video_definition_get_width(lc->video_conf.preview_vdef); - vsize.height = linphone_video_definition_get_height(lc->video_conf.preview_vdef); + vsize.width = (int)linphone_video_definition_get_width(lc->video_conf.preview_vdef); + vsize.height = (int)linphone_video_definition_get_height(lc->video_conf.preview_vdef); return vsize; } @@ -5559,7 +5563,7 @@ LinphoneVideoDefinition * linphone_core_get_current_preview_video_definition(con if (lc->previewstream) { vsize = video_preview_get_current_size(lc->previewstream); } - return linphone_factory_find_supported_video_definition(linphone_factory_get(), vsize.width, vsize.height); + return linphone_factory_find_supported_video_definition(linphone_factory_get(), (unsigned int)vsize.width, (unsigned int)vsize.height); #else ms_error("Video support is disabled"); return NULL; @@ -5602,8 +5606,8 @@ const LinphoneVideoDefinition * linphone_core_get_preferred_video_definition(con MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc) { MSVideoSize vsize = { 0 }; - vsize.width = linphone_video_definition_get_width(lc->video_conf.vdef); - vsize.height = linphone_video_definition_get_height(lc->video_conf.vdef); + vsize.width = (int)linphone_video_definition_get_width(lc->video_conf.vdef); + vsize.height = (int)linphone_video_definition_get_height(lc->video_conf.vdef); return vsize; } @@ -5625,7 +5629,7 @@ void linphone_core_preview_ogl_render(const LinphoneCore *lc) { #ifdef VIDEO_ENABLED LinphoneCall *call = linphone_core_get_current_call(lc); - VideoStream *stream = call ? call->videostream : lc->previewstream; + VideoStream *stream = call ? reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)) : lc->previewstream; if (stream && stream->output2 && ms_filter_get_id(stream->output2) == MS_OGL_ID) { int mirroring = TRUE; @@ -5656,8 +5660,11 @@ void linphone_core_set_play_file(LinphoneCore *lc, const char *file){ } if (file!=NULL) { lc->play_file=ms_strdup(file); - if (call && call->audiostream && call->audiostream->ms.state==MSStreamStarted) - audio_stream_play(call->audiostream,file); + if (call) { + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + if (astream && astream->ms.state==MSStreamStarted) + audio_stream_play(astream,file); + } } } @@ -5673,8 +5680,11 @@ void linphone_core_set_record_file(LinphoneCore *lc, const char *file){ } if (file!=NULL) { lc->rec_file=ms_strdup(file); - if (call && call->audiostream) - audio_stream_record(call->audiostream,file); + if (call) { + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + if (astream) + audio_stream_record(astream,file); + } } } @@ -5683,12 +5693,12 @@ typedef enum{ LinphoneLocalPlayer }LinphoneAudioResourceType; -static MSFilter *get_audio_resource(LinphoneCore *lc, LinphoneAudioResourceType rtype, MSSndCard *card){ +static MSFilter *get_audio_resource(LinphoneCore *lc, LinphoneAudioResourceType rtype, MSSndCard *card) { LinphoneCall *call=linphone_core_get_current_call(lc); AudioStream *stream=NULL; RingStream *ringstream; if (call){ - stream=call->audiostream; + stream=reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); }else if (linphone_core_is_in_conference(lc)){ stream=linphone_conference_get_audio_stream(lc->conf_ctx); } @@ -5704,35 +5714,35 @@ static MSFilter *get_audio_resource(LinphoneCore *lc, LinphoneAudioResourceType if (lc->ringstream == NULL) { float amp=lp_config_get_float(lc->config,"sound","dtmf_player_amp",0.1f); MSSndCard *ringcard=lc->sound_conf.lsd_card - ? lc->sound_conf.lsd_card - : card - ? card - : lc->sound_conf.ring_sndcard; + ? lc->sound_conf.lsd_card + : card + ? card + : lc->sound_conf.ring_sndcard; if (ringcard == NULL) return NULL; ringstream=lc->ringstream=ring_start(lc->factory, NULL,0,ringcard); ms_filter_call_method(lc->ringstream->gendtmf,MS_DTMF_GEN_SET_DEFAULT_AMPLITUDE,&); - lc->dmfs_playing_start_time = ms_get_cur_time_ms()/1000; + lc->dmfs_playing_start_time = (time_t)ms_get_cur_time_ms()/1000; }else{ ringstream=lc->ringstream; if (lc->dmfs_playing_start_time!=0) - lc->dmfs_playing_start_time = ms_get_cur_time_ms()/1000; + lc->dmfs_playing_start_time = (time_t)ms_get_cur_time_ms()/1000; } if (rtype==LinphoneToneGenerator) return ringstream->gendtmf; if (rtype==LinphoneLocalPlayer) return ringstream->source; return NULL; } -static MSFilter *get_dtmf_gen(LinphoneCore *lc, MSSndCard *card){ - return get_audio_resource(lc, LinphoneToneGenerator, card); +static MSFilter *get_dtmf_gen(LinphoneCore *lc, MSSndCard *card) { + return get_audio_resource(lc,LinphoneToneGenerator, card); } void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){ MSSndCard *card = linphone_core_in_call(lc) - ? lc->sound_conf.play_sndcard - : lc->sound_conf.ring_sndcard; + ? lc->sound_conf.play_sndcard + : lc->sound_conf.ring_sndcard; MSFilter *f=get_dtmf_gen(lc, card); if (f==NULL){ ms_error("No dtmf generator at this time !"); @@ -5744,7 +5754,7 @@ void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int duration_ms){ else ms_filter_call_method(f, MS_DTMF_GEN_START, &dtmf); } -LinphoneStatus _linphone_core_play_local(LinphoneCore *lc, const char *audiofile, MSSndCard *card){ +LinphoneStatus _linphone_core_play_local(LinphoneCore *lc, const char *audiofile, MSSndCard *card) { MSFilter *f=get_audio_resource(lc,LinphoneLocalPlayer, card); int loopms=-1; if (!f) return -1; @@ -5756,7 +5766,7 @@ LinphoneStatus _linphone_core_play_local(LinphoneCore *lc, const char *audiofile return 0; } -LinphoneStatus linphone_core_play_local(LinphoneCore *lc, const char *audiofile){ +LinphoneStatus linphone_core_play_local(LinphoneCore *lc, const char *audiofile) { return _linphone_core_play_local(lc, audiofile, NULL); } @@ -5879,10 +5889,11 @@ void linphone_core_set_rtp_transport_factories(LinphoneCore* lc, LinphoneRtpTran int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, rtp_stats_t *remote){ LinphoneCall *call=linphone_core_get_current_call (lc); - if (call!=NULL){ - if (call->audiostream!=NULL){ + if (call){ + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + if (astream){ memset(remote,0,sizeof(*remote)); - audio_stream_get_local_rtp_stats (call->audiostream,local); + audio_stream_get_local_rtp_stats (astream,local); return 0; } } @@ -5933,32 +5944,34 @@ void sip_config_uninit(LinphoneCore *lc) for (i=0;i<20&&still_registered;i++){ still_registered=FALSE; - sal_iterate(lc->sal); + lc->sal->iterate(); for(elem=config->proxies;elem!=NULL;elem=bctbx_list_next(elem)){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)(elem->data); LinphoneRegistrationState state = linphone_proxy_config_get_state(cfg); - still_registered|=(state==LinphoneRegistrationOk||state==LinphoneRegistrationProgress); + still_registered = (state==LinphoneRegistrationOk||state==LinphoneRegistrationProgress); } ms_usleep(100000); } if (i>=20) ms_warning("Cannot complete unregistration, giving up"); } + elem = config->proxies; - config->proxies=NULL; /*to make sure proxies cannot be refferenced during deletion*/ + config->proxies=NULL; /*to make sure proxies cannot be referenced during deletion*/ bctbx_list_free_with_data(elem,(void (*)(void*)) _linphone_proxy_config_release); config->deleted_proxies=bctbx_list_free_with_data(config->deleted_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 */ + /*no longuer need to write proxy config if not changed linphone_proxy_config_write_to_config_file(lc->config,NULL,i);*/ /*mark the end */ lc->auth_info=bctbx_list_free_with_data(lc->auth_info,(void (*)(void*))linphone_auth_info_unref); + lc->default_proxy = NULL; if (lc->vcard_context) { linphone_vcard_context_destroy(lc->vcard_context); } - sal_reset_transports(lc->sal); - sal_unlisten_ports(lc->sal); /*to make sure no new messages are received*/ + lc->sal->resetTransports(); + lc->sal->unlistenPorts(); /*to make sure no new messages are received*/ if (lc->http_provider) { belle_sip_object_unref(lc->http_provider); lc->http_provider=NULL; @@ -5977,10 +5990,11 @@ void sip_config_uninit(LinphoneCore *lc) } #endif - sal_iterate(lc->sal); /*make sure event are purged*/ - sal_uninit(lc->sal); + lc->sal->iterate(); /*make sure event are purged*/ + delete lc->sal; lc->sal=NULL; + if (lc->sip_conf.guessed_contact) ms_free(lc->sip_conf.guessed_contact); if (config->contact) @@ -6083,9 +6097,9 @@ void _linphone_core_codec_config_write(LinphoneCore *lc){ static void codecs_config_uninit(LinphoneCore *lc) { _linphone_core_codec_config_write(lc); - bctbx_list_free_with_data(lc->codecs_conf.audio_codecs, (void (*)(void*))payload_type_destroy); - bctbx_list_free_with_data(lc->codecs_conf.video_codecs, (void (*)(void*))payload_type_destroy); - bctbx_list_free_with_data(lc->codecs_conf.text_codecs, (void (*)(void*))payload_type_destroy); + bctbx_list_free(lc->codecs_conf.audio_codecs); + bctbx_list_free(lc->codecs_conf.video_codecs); + bctbx_list_free(lc->codecs_conf.text_codecs); } void friends_config_uninit(LinphoneCore* lc) @@ -6102,7 +6116,15 @@ void friends_config_uninit(LinphoneCore* lc) ms_message("Destroying friends done."); } -LpConfig * linphone_core_get_config(LinphoneCore *lc){ +void linphone_core_enter_background(LinphoneCore *lc) { + L_GET_CPP_PTR_FROM_C_OBJECT(lc)->enterBackground(); +} + +void linphone_core_enter_foreground(LinphoneCore *lc) { + L_GET_CPP_PTR_FROM_C_OBJECT(lc)->enterForeground(); +} + +LpConfig * linphone_core_get_config(const LinphoneCore *lc){ return lc->config; } @@ -6114,7 +6136,15 @@ LinphoneConfig * linphone_core_create_config(LinphoneCore *lc, const char *filen return lp_config_new(filename); } -static void linphone_core_uninit(LinphoneCore *lc) +LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, const char *address) { + return linphone_address_new(address); +} + +LinphoneXmlRpcSession * linphone_core_create_xml_rpc_session(LinphoneCore *lc, const char *url) { + return linphone_xml_rpc_session_new(lc, url); +} + +void _linphone_core_uninit(LinphoneCore *lc) { bctbx_list_t *elem = NULL; int i=0; @@ -6122,12 +6152,7 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_task_list_free(&lc->hooks); lc->video_conf.show_local = FALSE; - while(lc->calls) { - LinphoneCall *the_call = reinterpret_cast(lc->calls->data); - linphone_call_terminate(the_call); - linphone_core_iterate(lc); - ms_usleep(10000); - } + L_GET_PRIVATE_FROM_C_OBJECT(lc)->uninit(); for (elem = lc->friends_lists; elem != NULL; elem = bctbx_list_next(elem)) { LinphoneFriendList *list = (LinphoneFriendList *)elem->data; @@ -6141,7 +6166,7 @@ static void linphone_core_uninit(LinphoneCore *lc) ms_usleep(10000); } - lc->chatrooms = bctbx_list_free_with_data(lc->chatrooms, (MSIterateFunc)linphone_chat_room_release); + lc->chat_rooms = bctbx_list_free_with_data(lc->chat_rooms, (bctbx_list_free_func)linphone_chat_room_unref); linphone_core_set_state(lc,LinphoneGlobalShutdown,"Shutting down"); #ifdef VIDEO_ENABLED @@ -6165,13 +6190,6 @@ static void linphone_core_uninit(LinphoneCore *lc) sip_setup_unregister_all(); -#ifdef BUILD_UPNP - if(lc->upnp != NULL) { - linphone_upnp_context_destroy(lc->upnp); - lc->upnp = NULL; - } -#endif //BUILD_UPNP - 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 */ @@ -6192,15 +6210,18 @@ static void linphone_core_uninit(LinphoneCore *lc) if(lc->rec_file!=NULL){ ms_free(lc->rec_file); } - if (lc->chat_db_file){ - ms_free(lc->chat_db_file); - } if (lc->logs_db_file) { ms_free(lc->logs_db_file); } if (lc->friends_db_file) { ms_free(lc->friends_db_file); } + if (lc->tls_key){ + ms_free(lc->tls_key); + } + if (lc->tls_cert){ + ms_free(lc->tls_cert); + } if (lc->ringtoneplayer) { linphone_ringtoneplayer_destroy(lc->ringtoneplayer); } @@ -6213,7 +6234,6 @@ static void linphone_core_uninit(LinphoneCore *lc) linphone_core_free_payload_types(lc); if (lc->supported_formats) ms_free((void *)lc->supported_formats); - linphone_core_message_storage_close(lc); linphone_core_call_log_storage_close(lc); linphone_core_friends_storage_close(lc); linphone_core_zrtp_cache_close(lc); @@ -6267,44 +6287,18 @@ static void set_sip_network_reachable(LinphoneCore* lc,bool_t is_sip_reachable, if (!lc->sip_network_reachable){ linphone_core_invalidate_friend_subscriptions(lc); - sal_reset_transports(lc->sal); - /*mark all calls as broken, so that they can be either dropped immediately or restaured when network will be back*/ - bctbx_list_for_each(lc->calls, (MSIterateFunc) linphone_call_set_broken); - } -#ifdef BUILD_UPNP - if(lc->upnp == NULL) { - if(is_sip_reachable && linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) { - lc->upnp = linphone_upnp_context_new(lc); - } - } else { - if(!is_sip_reachable && linphone_core_get_firewall_policy(lc) == LinphonePolicyUseUpnp) { - linphone_upnp_context_destroy(lc->upnp); - lc->upnp = NULL; - } - } -#endif -} - -void linphone_core_repair_calls(LinphoneCore *lc){ - if (lc->calls && lp_config_get_int(lc->config, "sip", "repair_broken_calls", 1) && lc->media_network_reachable){ - /*if we are registered and there were broken calls due to a past network disconnection, attempt to repair them*/ - bctbx_list_for_each(lc->calls, (MSIterateFunc) linphone_call_repair_if_broken); + lc->sal->resetTransports(); } } static void set_media_network_reachable(LinphoneCore* lc, bool_t is_media_reachable){ if (lc->media_network_reachable==is_media_reachable) return; // no change, ignore. + lc->network_reachable_to_be_notified=TRUE; + ms_message("Media network reachability state is now [%s]",is_media_reachable?"UP":"DOWN"); lc->media_network_reachable=is_media_reachable; - if (!lc->media_network_reachable){ - /*mark all calls as broken, so that they can be either dropped immediately or restaured when network will be back*/ - bctbx_list_for_each(lc->calls, (MSIterateFunc) linphone_call_set_broken); - }else{ - if (lp_config_get_int(lc->config, "net", "recreate_sockets_when_network_is_up", 0)){ - bctbx_list_for_each(lc->calls, (MSIterateFunc)linphone_call_refresh_sockets); - } - linphone_core_repair_calls(lc); + if (lc->media_network_reachable){ if (lc->bw_controller){ ms_bandwidth_controller_reset_state(lc->bw_controller); } @@ -6338,19 +6332,22 @@ static void disable_internal_network_reachability_detection(LinphoneCore *lc){ } } -void linphone_core_set_network_reachable(LinphoneCore* lc,bool_t isReachable) { +void linphone_core_set_network_reachable(LinphoneCore *lc, bool_t isReachable) { disable_internal_network_reachability_detection(lc); set_network_reachable(lc, isReachable, ms_time(NULL)); + notify_network_reachable_change(lc); } void linphone_core_set_media_network_reachable(LinphoneCore *lc, bool_t is_reachable){ disable_internal_network_reachability_detection(lc); set_media_network_reachable(lc, is_reachable); + notify_network_reachable_change(lc); } void linphone_core_set_sip_network_reachable(LinphoneCore *lc, bool_t is_reachable){ disable_internal_network_reachability_detection(lc); set_sip_network_reachable(lc, is_reachable, ms_time(NULL)); + notify_network_reachable_change(lc); } bool_t linphone_core_is_network_reachable(LinphoneCore* lc) { @@ -6358,88 +6355,20 @@ bool_t linphone_core_is_network_reachable(LinphoneCore* lc) { } ortp_socket_t linphone_core_get_sip_socket(LinphoneCore *lc){ - return sal_get_socket(lc->sal); + return lc->sal->getSocket(); } void linphone_core_destroy(LinphoneCore *lc){ linphone_core_unref(lc); } -int linphone_core_get_calls_nb(const LinphoneCore *lc){ - return (int)bctbx_list_size(lc->calls); +int linphone_core_get_calls_nb(const LinphoneCore *lc) { + return (int)L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getCallCount(); } -/** - * Check if we do not have exceed the number of simultaneous call - * @ingroup call_control -**/ -bool_t linphone_core_can_we_add_call(LinphoneCore *lc) -{ - if(linphone_core_get_calls_nb(lc) < lc->max_calls) - return TRUE; - ms_message("Maximum amount of simultaneous calls reached !"); - return FALSE; -} -static void notify_soundcard_usage(LinphoneCore *lc, bool_t used){ - MSSndCard *card=lc->sound_conf.capt_sndcard; - if (card && ms_snd_card_get_capabilities(card) & MS_SND_CARD_CAP_IS_SLOW){ - ms_snd_card_set_usage_hint(card,used); - } -} - -void linphone_core_soundcard_hint_check( LinphoneCore* lc){ - bctbx_list_t* the_calls = lc->calls; - LinphoneCall* call = NULL; - bool_t dont_need_sound = TRUE; - bool_t use_rtp_io = lp_config_get_int(lc->config, "sound", "rtp_io", FALSE); - bool_t use_rtp_io_enable_local_output = lp_config_get_int(lc->config, "sound", "rtp_io_enable_local_output", FALSE); - - if (lc->conf_ctx && linphone_conference_get_size(lc->conf_ctx) >= 1) return; - - /* check if the remaining calls are paused */ - while( the_calls ){ - call = reinterpret_cast(the_calls->data); - if( call->state != LinphoneCallPausing && call->state != LinphoneCallPaused && call->state != LinphoneCallEnd && call->state != LinphoneCallError){ - dont_need_sound = FALSE; - break; - } - the_calls = the_calls->next; - } - /* if no more calls or all calls are paused, we can free the soundcard */ - if ( (lc->calls==NULL || dont_need_sound) && !lc->use_files && (!use_rtp_io || (use_rtp_io && use_rtp_io_enable_local_output))){ - ms_message("Notifying soundcard that we don't need it anymore for calls."); - notify_soundcard_usage(lc,FALSE); - } -} - -int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call) { - if (linphone_core_can_we_add_call(lc)){ - if (lc->calls==NULL) notify_soundcard_usage(lc,TRUE); - lc->calls = bctbx_list_append(lc->calls,call); - linphone_core_notify_call_created(lc, call); - return 0; - } - return -1; -} - -int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call) { - bctbx_list_t *it; - bctbx_list_t *the_calls = lc->calls; - - it=bctbx_list_find(the_calls,call); - if (it) - { - the_calls = bctbx_list_erase_link(the_calls,it); - } - else - { - ms_warning("could not find the call into the list\n"); - return -1; - } - lc->calls = the_calls; - - return 0; +void linphone_core_soundcard_hint_check(LinphoneCore* lc) { + L_GET_CPP_PTR_FROM_C_OBJECT(lc)->soundcardHintCheck(); } void linphone_core_set_remote_ringback_tone(LinphoneCore *lc, const char *file){ @@ -6531,16 +6460,10 @@ LinphoneGlobalState linphone_core_get_global_state(const LinphoneCore *lc){ } -static LinphoneCallParams *_create_call_params(LinphoneCore *lc){ - LinphoneCallParams *p=linphone_call_params_new(); - linphone_core_init_default_params(lc, p); - return p; -} - LinphoneCallParams *linphone_core_create_call_params(LinphoneCore *lc, LinphoneCall *call){ - if (!call) return _create_call_params(lc); - if (call->params){ - return linphone_call_params_copy(call->params); + if (!call) return linphone_call_params_new(lc); + if (linphone_call_get_params(call)){ + return linphone_call_params_copy(linphone_call_get_params(call)); } ms_error("linphone_core_create_call_params(): call [%p] is not in a state where call params can be created or used.", call); return NULL; @@ -6551,21 +6474,16 @@ const char *linphone_error_to_string(LinphoneReason err){ } void linphone_core_enable_keep_alive(LinphoneCore* lc,bool_t enable) { -#ifdef BUILD_UPNP - if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp) { - enable = FALSE; - } -#endif //BUILD_UPNP if (enable > 0) { - sal_use_tcp_tls_keepalive(lc->sal,lc->sip_conf.tcp_tls_keepalive); - sal_set_keepalive_period(lc->sal,lc->sip_conf.keepalive_period); + lc->sal->useTcpTlsKeepAlive(!!lc->sip_conf.tcp_tls_keepalive); + lc->sal->setKeepAlivePeriod(lc->sip_conf.keepalive_period); } else { - sal_set_keepalive_period(lc->sal,0); + lc->sal->setKeepAlivePeriod(0); } } bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc) { - return sal_get_keepalive_period(lc->sal) > 0; + return lc->sal->getKeepAlivePeriod() > 0; } void linphone_core_start_dtmf_stream(LinphoneCore* lc) { @@ -6584,9 +6502,9 @@ void linphone_core_stop_ringing(LinphoneCore* lc) { lc->dmfs_playing_start_time=0; lc->ringstream_autorelease=TRUE; } - if (call && call->ringing_beep){ + if (call && L_GET_PRIVATE_FROM_C_OBJECT(call)->getRingingBeep()) { linphone_core_stop_dtmf(lc); - call->ringing_beep=FALSE; + L_GET_PRIVATE_FROM_C_OBJECT(call)->setRingingBeep(false); } } @@ -6617,6 +6535,46 @@ void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook } +// ============================================================================= +// TODO: Remove me later, code found in message_storage.c. +// ============================================================================= + +#ifdef SQLITE_STORAGE_ENABLED + +int _linphone_sqlite3_open(const char *db_file, sqlite3 **db) { + char* errmsg = NULL; + int ret; + int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; + +#if TARGET_OS_IPHONE + /* the secured filesystem of the iPHone doesn't allow writing while the app is in background mode, which is problematic. + * We workaround by asking that the open is made with no protection*/ + flags |= SQLITE_OPEN_FILEPROTECTION_NONE; +#endif + + /*since we plug our vfs into sqlite, we convert to UTF-8. + * On Windows, the filename has to be converted back to windows native charset.*/ + char *utf8_filename = bctbx_locale_to_utf8(db_file); + ret = sqlite3_open_v2(utf8_filename, db, flags, LINPHONE_SQLITE3_VFS); + ms_free(utf8_filename); + + if (ret != SQLITE_OK) return ret; + // Some platforms do not provide a way to create temporary files which are needed + // for transactions... so we work in memory only + // see http ://www.sqlite.org/compile.html#temp_store + ret = sqlite3_exec(*db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errmsg); + if (ret != SQLITE_OK) { + ms_error("Cannot set sqlite3 temporary store to memory: %s.", errmsg); + sqlite3_free(errmsg); + } + + return ret; +} + +#endif + +// ============================================================================= + void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){ LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(lc); if (lc->zrtp_secrets_cache != NULL) { @@ -6672,9 +6630,11 @@ void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){ /* We first have to close the file before renaming it */ sqlite3_close(lc->zrtp_cache_db); #endif + if (rename(tmpFile, file)==0) { /* set the flag if we were able to set the sqlite file in the correct place (even if migration failed) */ lp_config_set_int(lc->config, "sip", "zrtp_cache_migration_done", TRUE); } + #ifdef _WIN32 /* Then reopen it */ _linphone_sqlite3_open(file, &lc->zrtp_cache_db); @@ -6682,7 +6642,7 @@ void linphone_core_set_zrtp_secrets_file(LinphoneCore *lc, const char* file){ /* clean up */ bctbx_free(bkpFile); - xmlFree(cacheXml); + xmlFreeDoc(cacheXml); } bctbx_free(tmpFile); } else { @@ -6755,43 +6715,19 @@ end: #endif /* SQLITE_STORAGE_ENABLED */ } -void linphone_core_set_user_certificates_path(LinphoneCore *lc, const char* path){ - char* new_value; - new_value = path?ms_strdup(path):NULL; - if (lc->user_certificates_path) ms_free(lc->user_certificates_path); - lp_config_set_string(lc->config,"misc","user_certificates_path",lc->user_certificates_path=new_value); - return ; +void linphone_core_set_user_certificates_path (LinphoneCore *lc, const char *path) { + char *new_value = path ? bctbx_strdup(path) : NULL; + if (lc->user_certificates_path) bctbx_free(lc->user_certificates_path); + lc->user_certificates_path = new_value; + lp_config_set_string(lc->config, "misc", "user_certificates_path", lc->user_certificates_path); } const char *linphone_core_get_user_certificates_path(LinphoneCore *lc){ return lc->user_certificates_path; } -bool_t linphone_core_sound_resources_locked(LinphoneCore *lc){ - bctbx_list_t *elem; - for(elem=lc->calls;elem!=NULL;elem=elem->next) { - LinphoneCall *c=(LinphoneCall*)elem->data; - - if (linphone_call_media_in_progress(c)) { - return TRUE; - } - - switch (c->state) { - case LinphoneCallOutgoingInit: - case LinphoneCallOutgoingProgress: - case LinphoneCallOutgoingRinging: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallConnected: - case LinphoneCallRefered: - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallUpdating: - ms_message("Call %p is locking sound resources.",c); - return TRUE; - default: - break; - } - } - return FALSE; +bool_t linphone_core_sound_resources_locked(LinphoneCore *lc) { + return !!L_GET_CPP_PTR_FROM_C_OBJECT(lc)->areSoundResourcesLocked(); } void linphone_core_set_srtp_enabled(LinphoneCore *lc, bool_t enabled) { @@ -6896,26 +6832,7 @@ void linphone_core_set_media_encryption_mandatory(LinphoneCore *lc, bool_t m) { } void linphone_core_init_default_params(LinphoneCore*lc, LinphoneCallParams *params) { - params->has_audio = TRUE; - params->has_video=linphone_core_video_enabled(lc) && lc->video_policy.automatically_initiate; - if (!linphone_core_video_enabled(lc) && lc->video_policy.automatically_initiate){ - ms_error("LinphoneCore has video disabled for both capture and display, but video policy is to start the call with video. " - "This is a possible mis-use of the API. In this case, video is disabled in default LinphoneCallParams"); - } - params->media_encryption=linphone_core_get_media_encryption(lc); - params->in_conference=FALSE; - params->realtimetext_enabled = linphone_core_realtime_text_enabled(lc); - params->privacy=LinphonePrivacyDefault; - params->avpf_enabled=linphone_core_get_avpf_mode(lc); - params->implicit_rtcp_fb = lp_config_get_int(lc->config,"rtp","rtcp_fb_implicit_rtcp_fb",TRUE); - params->avpf_rr_interval = linphone_core_get_avpf_rr_interval(lc); - params->audio_dir=LinphoneMediaDirectionSendRecv; - params->video_dir=LinphoneMediaDirectionSendRecv; - params->real_early_media=lp_config_get_int(lc->config,"misc","real_early_media",FALSE); - params->audio_multicast_enabled=linphone_core_audio_multicast_enabled(lc); - params->video_multicast_enabled=linphone_core_video_multicast_enabled(lc); - params->update_call_when_ice_completed = lp_config_get_int(lc->config, "sip", "update_call_when_ice_completed", TRUE); - params->encryption_mandatory = linphone_core_is_media_encryption_mandatory(lc); + L_GET_CPP_PTR_FROM_C_OBJECT(params)->initDefault(L_GET_CPP_PTR_FROM_C_OBJECT(lc)); } void linphone_core_set_device_identifier(LinphoneCore *lc,const char* device_id) { @@ -6928,7 +6845,7 @@ const char* linphone_core_get_device_identifier(const LinphoneCore *lc) { } void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp){ - sal_set_dscp(lc->sal,dscp); + lc->sal->setDscp(dscp); if (linphone_core_ready(lc)){ lp_config_set_int_hex(lc->config,"sip","dscp",dscp); _linphone_core_apply_transports(lc); @@ -6958,19 +6875,21 @@ int linphone_core_get_video_dscp(const LinphoneCore *lc){ return lp_config_get_int(lc->config,"rtp","video_dscp",0); } -void linphone_core_set_chat_database_path(LinphoneCore *lc, const char *path){ - if (lc->chat_db_file){ - ms_free(lc->chat_db_file); - lc->chat_db_file=NULL; - } - if (path) { - lc->chat_db_file=ms_strdup(path); - linphone_core_message_storage_init(lc); +void linphone_core_set_chat_database_path (LinphoneCore *lc, const char *path) { + if (!linphone_core_conference_server_enabled(lc)) { + auto &mainDb = L_GET_PRIVATE_FROM_C_OBJECT(lc)->mainDb; + if (mainDb) { + mainDb->import(LinphonePrivate::MainDb::Sqlite3, path); + L_GET_PRIVATE_FROM_C_OBJECT(lc)->loadChatRooms(); + } else { + ms_warning("linphone_core_set_chat_database_path() needs to be called once linphone_core_start() has been called"); + } } } -const char* linphone_core_get_chat_database_path(const LinphoneCore *lc) { - return lc->chat_db_file; +const char *linphone_core_get_chat_database_path (const LinphoneCore *) { + lError() << "Do not use `linphone_core_get_chat_database_path`. Not necessary."; + return ""; } void linphone_core_enable_sdp_200_ack(LinphoneCore *lc, bool_t enable) { @@ -6990,13 +6909,13 @@ const char * linphone_core_get_file_transfer_server(LinphoneCore *core) { } 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)); + lc->sal->addSupportedTag(tag); + lp_config_set_string(lc->config,"sip","supported",lc->sal->getSupportedTags().c_str()); } 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)); + lc->sal->removeSupportedTag(tag); + lp_config_set_string(lc->config,"sip","supported",lc->sal->getSupportedTags().c_str()); } void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFMode mode){ @@ -7117,18 +7036,22 @@ bool_t linphone_core_realtime_text_enabled(LinphoneCore *lc) { return lc->text_conf.enabled; } +void linphone_core_enable_realtime_text(LinphoneCore *lc, bool_t value) { + lc->text_conf.enabled = value; +} + void linphone_core_set_http_proxy_host(LinphoneCore *lc, const char *host) { lp_config_set_string(lc->config,"sip","http_proxy_host",host); if (lc->sal) { - sal_set_http_proxy_host(lc->sal,host); - sal_set_http_proxy_port(lc->sal,linphone_core_get_http_proxy_port(lc)); /*to make sure default value is set*/ + lc->sal->setHttpProxyHost(host); + lc->sal->setHttpProxyPort(linphone_core_get_http_proxy_port(lc)); /*to make sure default value is set*/ } } void linphone_core_set_http_proxy_port(LinphoneCore *lc, int port) { lp_config_set_int(lc->config,"sip","http_proxy_port",port); if (lc->sal) - sal_set_http_proxy_port(lc->sal,port); + lc->sal->setHttpProxyPort(port); } const char *linphone_core_get_http_proxy_host(const LinphoneCore *lc) { @@ -7223,13 +7146,9 @@ LinphoneStatus linphone_core_add_to_conference(LinphoneCore *lc, LinphoneCall *c } LinphoneStatus linphone_core_add_all_to_conference(LinphoneCore *lc) { - bctbx_list_t *calls=lc->calls; - while (calls) { - LinphoneCall *call=(LinphoneCall*)calls->data; - calls=calls->next; - if(linphone_call_get_conference(call) == NULL) { // Prevent the call to the conference server from being added to the conference - linphone_core_add_to_conference(lc, call); - } + for (const auto &call : L_GET_CPP_PTR_FROM_C_OBJECT(lc)->getCalls()) { + if (!linphone_call_get_conference(L_GET_C_BACK_PTR(call))) // Prevent the call to the conference server from being added to the conference + linphone_core_add_to_conference(lc, L_GET_C_BACK_PTR(call)); } if(lc->conf_ctx && linphone_conference_check_class(lc->conf_ctx, LinphoneConferenceClassLocal)) { linphone_core_enter_conference(lc); @@ -7291,6 +7210,35 @@ LinphoneConference *linphone_core_get_conference(LinphoneCore *lc) { return lc->conf_ctx; } +void linphone_core_enable_conference_server (LinphoneCore *lc, bool_t enable) { + lp_config_set_int(linphone_core_get_config(lc), "misc", "conference_server_enabled", enable); +} + +bool_t _linphone_core_is_conference_creation (const LinphoneCore *lc, const LinphoneAddress *addr) { + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(lc); + if (!proxy) + return FALSE; + const char *uri = linphone_proxy_config_get_conference_factory_uri(proxy); + if (!uri) + return FALSE; + + LinphoneAddress *factoryAddr = linphone_address_new(uri); + if (!factoryAddr) + return FALSE; + // Do not compare ports + linphone_address_set_port(factoryAddr, 0); + LinphoneAddress *testedAddr = linphone_address_clone(addr); + linphone_address_set_port(testedAddr, 0); + bool_t result = linphone_address_weak_equal(factoryAddr, testedAddr); + linphone_address_unref(factoryAddr); + linphone_address_unref(testedAddr); + return result; +} + +bool_t linphone_core_conference_server_enabled (const LinphoneCore *lc) { + return lp_config_get_int(linphone_core_get_config(lc), "misc", "conference_server_enabled", FALSE) ? TRUE : FALSE; +} + void linphone_core_set_tls_cert(LinphoneCore *lc, const char *tls_cert) { if (lc->tls_cert) { ms_free(lc->tls_cert); @@ -7349,23 +7297,23 @@ LinphoneImEncryptionEngine *linphone_core_get_im_encryption_engine(const Linphon } void linphone_core_initialize_supported_content_types(LinphoneCore *lc) { - sal_add_content_type_support(lc->sal, "text/plain"); - sal_add_content_type_support(lc->sal, "message/external-body"); - sal_add_content_type_support(lc->sal, "application/vnd.gsma.rcs-ft-http+xml"); - sal_add_content_type_support(lc->sal, "application/im-iscomposing+xml"); - sal_add_content_type_support(lc->sal, "message/imdn+xml"); + lc->sal->addContentTypeSupport("text/plain"); + lc->sal->addContentTypeSupport("message/external-body"); + lc->sal->addContentTypeSupport("application/vnd.gsma.rcs-ft-http+xml"); + lc->sal->addContentTypeSupport("application/im-iscomposing+xml"); + lc->sal->addContentTypeSupport("message/imdn+xml"); } bool_t linphone_core_is_content_type_supported(const LinphoneCore *lc, const char *content_type) { - return sal_is_content_type_supported(lc->sal, content_type); + return lc->sal->isContentTypeSupported(content_type); } void linphone_core_add_content_type_support(LinphoneCore *lc, const char *content_type) { - sal_add_content_type_support(lc->sal, content_type); + lc->sal->addContentTypeSupport(content_type); } void linphone_core_remove_content_type_support(LinphoneCore *lc, const char *content_type) { - sal_remove_content_type_support(lc->sal, content_type); + lc->sal->removeContentTypeSupport(content_type); } #ifdef ENABLE_UPDATE_CHECK @@ -7469,6 +7417,7 @@ void linphone_core_check_for_update(LinphoneCore *lc, const char *current_versio int err; bool_t is_desktop = FALSE; const char *platform = NULL; + const char *mobilePlatform = NULL; const char *version_check_url_root = lp_config_get_string(lc->config, "misc", "version_check_url_root", NULL); if (version_check_url_root != NULL) { @@ -7484,9 +7433,14 @@ void linphone_core_check_for_update(LinphoneCore *lc, const char *current_versio if (strcmp(tag, "win32") == 0) platform = "windows"; else if (strcmp(tag, "apple") == 0) platform = "macosx"; else if (strcmp(tag, "linux") == 0) platform = "linux"; + else if (strcmp(tag, "ios") == 0) mobilePlatform = "ios"; + else if (strcmp(tag, "android") == 0) mobilePlatform = "android"; else if (strcmp(tag, "desktop") == 0) is_desktop = TRUE; } - if ((is_desktop == FALSE) || (platform == NULL)) { + if (!is_desktop) { + platform = mobilePlatform; + } + if (platform == NULL) { ms_warning("Update checking is not supported on this platform"); return; } @@ -7507,3 +7461,21 @@ void linphone_core_check_for_update(LinphoneCore *lc, const char *current_versio } #endif } + +bool_t linphone_core_has_crappy_opengl(LinphoneCore *lc) { + MSFactory * factory = linphone_core_get_ms_factory(lc); + MSDevicesInfo *devices = ms_factory_get_devices_info(factory); + SoundDeviceDescription *sound_description = ms_devices_info_get_sound_device_description(devices); + if (sound_description == NULL) return FALSE; + if (sound_description->flags & DEVICE_HAS_CRAPPY_OPENGL) return TRUE; + return FALSE; +} + +const char *linphone_core_get_linphone_specs (const LinphoneCore *core) { + return lp_config_get_string(linphone_core_get_config(core), "sip", "linphone_specs", NULL); +} + +void linphone_core_set_linphone_specs (LinphoneCore *core, const char *specs) { + lp_config_set_string(linphone_core_get_config(core), "sip", "linphone_specs", specs); + core->sal->setContactLinphoneSpecs(L_C_TO_STRING(specs)); +} diff --git a/coreapi/linphonecore_jni.cc b/coreapi/linphonecore_jni.cc index 4cc310bd4..5da325464 100644 --- a/coreapi/linphonecore_jni.cc +++ b/coreapi/linphonecore_jni.cc @@ -96,7 +96,7 @@ void linphone_android_log_handler(int prio, char *str) { } } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreFactoryImpl__1setLogHandler(JNIEnv *env, jobject jfactory, jobject jhandler) { +extern "C" void Java_org_linphone_core_LinphoneCoreFactoryImpl__1setLogHandler(JNIEnv *env, jobject jfactory, jobject jhandler) { if (handler_obj) { env->DeleteGlobalRef(handler_obj); handler_obj = NULL; @@ -163,7 +163,7 @@ extern "C" void setMediastreamerAndroidContext(JNIEnv *env, void *context) { #endif /* __ANDROID__ */ -JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved) +extern "C" jint JNI_OnLoad(JavaVM *ajvm, void *reserved) { #ifdef __ANDROID__ ms_set_jvm(ajvm); @@ -222,32 +222,33 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreFactoryImpl_createErrorInfoN } extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreFactoryImpl_getAllDialPlanNative(JNIEnv *env, jobject thiz) { - LinphoneDialPlan *countries; jclass addr_class = env->FindClass("org/linphone/core/DialPlanImpl"); jmethodID addr_constructor = env->GetMethodID(addr_class, "", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V"); jobjectArray jaddr_array; - int i, size = 0; - countries = (LinphoneDialPlan *)linphone_dial_plan_get_all(); + size_t i; + const bctbx_list_t *countries = linphone_dial_plan_get_all_list(); + size_t size = bctbx_list_size(countries); - while (countries[size].country != NULL) size++; + jaddr_array = env->NewObjectArray((int)size, addr_class, NULL); - jaddr_array = env->NewObjectArray(size, addr_class, NULL); + for (i = 0; i < size; i++) { + LinphoneDialPlan* dp = (LinphoneDialPlan*)countries->data; - for (i=0; i < size ; i++) { - jstring jcountry = env->NewStringUTF(countries[i].country); - jstring jiso = env->NewStringUTF(countries[i].iso_country_code); - jstring jccc = env->NewStringUTF(countries[i].ccc); - jint jnnl = (jint)countries[i].nnl; - jstring jicp = env->NewStringUTF(countries[i].icp); + jstring jcountry = env->NewStringUTF(linphone_dial_plan_get_country(dp)); + jstring jiso = env->NewStringUTF(linphone_dial_plan_get_iso_country_code(dp)); + jstring jccc = env->NewStringUTF(linphone_dial_plan_get_country_calling_code(dp)); + jint jnnl = (jint)linphone_dial_plan_get_national_number_length(dp); + jstring jicp = env->NewStringUTF(linphone_dial_plan_get_international_call_prefix(dp)); jobject jaddr = env->NewObject(addr_class, addr_constructor, jcountry, jiso, jccc, jnnl, jicp); - env->SetObjectArrayElement(jaddr_array, i, jaddr); + env->SetObjectArrayElement(jaddr_array, (int)i, jaddr); env->DeleteLocalRef(jcountry); env->DeleteLocalRef(jiso); env->DeleteLocalRef(jccc); env->DeleteLocalRef(jicp); + countries = countries->next; } return jaddr_array; } @@ -262,9 +263,6 @@ public: authMethodClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$AuthMethod")); authMethodFromIntId = env->GetStaticMethodID(authMethodClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$AuthMethod;"); - /*displayStatus(LinphoneCore lc,String message);*/ - displayStatusId = env->GetMethodID(listenerClass,"displayStatus","(Lorg/linphone/core/LinphoneCore;Ljava/lang/String;)V"); - /*void generalState(LinphoneCore lc,int state); */ globalStateClass = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/core/LinphoneCore$GlobalState")); globalStateFromIntId = env->GetStaticMethodID(globalStateClass,"fromInt","(I)Lorg/linphone/core/LinphoneCore$GlobalState;"); @@ -454,7 +452,6 @@ public: jobject core; jclass listenerClass; - jmethodID displayStatusId; jmethodID newSubscriptionRequestId; jmethodID notifyPresenceReceivedId; jmethodID messageReceivedId; @@ -624,12 +621,12 @@ jobject getCall(JNIEnv *env, LinphoneCall *call){ LinphoneCore *lc = linphone_call_get_core(call); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); - void *up=linphone_call_get_user_pointer(call); + void *up=linphone_call_get_user_data(call); if (up==NULL){ jobj=env->NewObject(ljb->callClass, ljb->callCtrId, (jlong)call); jobj=env->NewGlobalRef(jobj); - linphone_call_set_user_pointer(call,(void*)jobj); + linphone_call_set_user_data(call,(void*)jobj); linphone_call_ref(call); }else{ jobj=(jobject)up; @@ -835,10 +832,6 @@ public: memset(vTable, 0, sizeof(LinphoneCoreVTable)); - if (ljb->displayStatusId) { - vTable->display_status = displayStatusCb; - } - if (ljb->globalStateId) { vTable->global_state_changed = globalStateChange; } @@ -958,24 +951,6 @@ public: LinphoneCoreVTable vTable; - static void displayStatusCb(LinphoneCore *lc, const char *message) { - JNIEnv *env = 0; - jint result = jvm->AttachCurrentThread(&env,NULL); - if (result != 0) { - ms_error("cannot attach VM"); - return; - } - - LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); - LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc); - LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table); - jstring msg = message ? env->NewStringUTF(message) : NULL; - env->CallVoidMethod(lcData->listener,ljb->displayStatusId,lcData->core,msg); - handle_possible_java_exception(env, lcData->listener); - if (msg) { - env->DeleteLocalRef(msg); - } - } static void authInfoRequested(LinphoneCore *lc, const char *realm, const char *username, const char *domain) { JNIEnv *env = 0; jint result = jvm->AttachCurrentThread(&env,NULL); @@ -1112,7 +1087,7 @@ public: msg); handle_possible_java_exception(env, lcData->listener); if (state==LinphoneCallReleased) { - linphone_call_set_user_pointer(call,NULL); + linphone_call_set_user_data(call,NULL); env->DeleteGlobalRef(jcall); } if (msg) { @@ -1511,8 +1486,8 @@ public: LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc); LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table); jobject jcontent = content ? create_java_linphone_content(env, content) : NULL; - jobject jbuffer = buff ? env->NewDirectByteBuffer(buff, asking) : NULL; - *size = env->CallIntMethod(lcData->listener, + jobject jbuffer = buff ? env->NewDirectByteBuffer(buff, (jlong)asking) : NULL; + *size = (size_t)env->CallIntMethod(lcData->listener, ljb->fileTransferSendId, lcData->core, (jmsg = getChatMessage(env, message)), @@ -1544,8 +1519,8 @@ public: LinphoneCoreVTable *table = linphone_core_get_current_vtable(lc); LinphoneCoreData* lcData = (LinphoneCoreData*)linphone_core_v_table_get_user_data(table); - jbyteArray jbytes = env->NewByteArray(size); - env->SetByteArrayRegion(jbytes, 0, size, (jbyte*)buff); + jbyteArray jbytes = env->NewByteArray((jint)size); + env->SetByteArrayRegion(jbytes, 0, (jint)size, (jbyte*)buff); jobject jcontent = content ? create_java_linphone_content(env, content) : NULL; env->CallVoidMethod(lcData->listener, @@ -1748,11 +1723,11 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_migrateToMultiTransport( * Method: createInfoMessage * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneCoreImpl_createInfoMessage(JNIEnv *, jobject jobj, jlong lcptr){ +extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createInfoMessage(JNIEnv *, jobject jobj, jlong lcptr){ return (jlong) linphone_core_create_info_message((LinphoneCore*)lcptr); } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCallImpl_sendInfoMessage(JNIEnv *env, jobject jobj, jlong callptr, jlong infoptr){ +extern "C" jint Java_org_linphone_core_LinphoneCallImpl_sendInfoMessage(JNIEnv *env, jobject jobj, jlong callptr, jlong infoptr){ return linphone_call_send_info_message((LinphoneCall*)callptr,(LinphoneInfoMessage*)infoptr); } @@ -1844,13 +1819,13 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getProxyConfigLi const bctbx_list_t* proxies = linphone_core_get_proxy_config_list((LinphoneCore*)lc); size_t proxyCount = bctbx_list_size(proxies); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data((LinphoneCore *)lc); - jobjectArray jProxies = env->NewObjectArray(proxyCount,ljb->proxyClass,NULL); + jobjectArray jProxies = env->NewObjectArray((jint)proxyCount,ljb->proxyClass,NULL); for (size_t i = 0; i < proxyCount; i++ ) { LinphoneProxyConfig* proxy = (LinphoneProxyConfig*)proxies->data; jobject jproxy = getProxy(env,proxy,thiz); if(jproxy != NULL){ - env->SetObjectArrayElement(jProxies, i, jproxy); + env->SetObjectArrayElement(jProxies, (int)i, jproxy); } proxies = proxies->next; } @@ -1878,11 +1853,11 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_removeAuthInfo(JNIEnv* e extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_getAuthInfosList(JNIEnv* env, jobject thiz,jlong lc) { const bctbx_list_t* authInfos = linphone_core_get_auth_info_list((LinphoneCore*)lc); size_t listCount = bctbx_list_size(authInfos); - jlongArray jAuthInfos = env->NewLongArray(listCount); + jlongArray jAuthInfos = env->NewLongArray((jint)listCount); jlong *jInternalArray = env->GetLongArrayElements(jAuthInfos, NULL); for (size_t i = 0; i < listCount; i++ ) { - jInternalArray[i] = (unsigned long) (authInfos->data); + jInternalArray[i] = (jlong) (authInfos->data); authInfos = authInfos->next; } @@ -2131,14 +2106,14 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_sendDtmf( JNIEnv* env ,jobject thiz ,jlong lc ,jchar dtmf) { - linphone_core_send_dtmf((LinphoneCore*)lc,dtmf); + linphone_core_send_dtmf((LinphoneCore*)lc,(char)dtmf); } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_playDtmf( JNIEnv* env ,jobject thiz ,jlong lc ,jchar dtmf ,jint duration) { - linphone_core_play_dtmf((LinphoneCore*)lc,dtmf,duration); + linphone_core_play_dtmf((LinphoneCore*)lc,(char)dtmf,duration); } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_stopDtmf( JNIEnv* env ,jobject thiz @@ -2191,11 +2166,11 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_listVideoPayloadTy ,jlong lc) { const bctbx_list_t* codecs = linphone_core_get_video_codecs((LinphoneCore*)lc); size_t codecsCount = bctbx_list_size(codecs); - jlongArray jCodecs = env->NewLongArray(codecsCount); + jlongArray jCodecs = env->NewLongArray((jint)codecsCount); jlong *jInternalArray = env->GetLongArrayElements(jCodecs, NULL); for (size_t i = 0; i < codecsCount; i++ ) { - jInternalArray[i] = (unsigned long) (codecs->data); + jInternalArray[i] = (long) (codecs->data); codecs = codecs->next; } @@ -2204,7 +2179,7 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_listVideoPayloadTy return jCodecs; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setVideoCodecs(JNIEnv *env, jobject thiz, jlong lc, jlongArray jCodecs) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoCodecs(JNIEnv *env, jobject thiz, jlong lc, jlongArray jCodecs) { bctbx_list_t *pts = NULL; int codecsCount = env->GetArrayLength(jCodecs); jlong *codecs = env->GetLongArrayElements(jCodecs, NULL); @@ -2221,11 +2196,11 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_listAudioPayloadTy ,jlong lc) { const bctbx_list_t* codecs = linphone_core_get_audio_codecs((LinphoneCore*)lc); size_t codecsCount = bctbx_list_size(codecs); - jlongArray jCodecs = env->NewLongArray(codecsCount); + jlongArray jCodecs = env->NewLongArray((int)codecsCount); jlong *jInternalArray = env->GetLongArrayElements(jCodecs, NULL); for (size_t i = 0; i < codecsCount; i++ ) { - jInternalArray[i] = (unsigned long) (codecs->data); + jInternalArray[i] = (long) (codecs->data); codecs = codecs->next; } @@ -2234,7 +2209,7 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_listAudioPayloadTy return jCodecs; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setAudioCodecs(JNIEnv *env, jobject thiz, jlong lc, jlongArray jCodecs) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioCodecs(JNIEnv *env, jobject thiz, jlong lc, jlongArray jCodecs) { bctbx_list_t *pts = NULL; int codecsCount = env->GetArrayLength(jCodecs); jlong *codecs = env->GetLongArrayElements(jCodecs, NULL); @@ -2428,13 +2403,13 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendList(JN const bctbx_list_t* friends = linphone_core_get_friend_list((LinphoneCore*)lc); size_t friendsSize = bctbx_list_size(friends); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data((LinphoneCore *)lc); - jobjectArray jFriends = env->NewObjectArray(friendsSize,ljb->friendClass,NULL); + jobjectArray jFriends = env->NewObjectArray((int)friendsSize,ljb->friendClass,NULL); for (size_t i = 0; i < friendsSize; i++) { LinphoneFriend* lfriend = (LinphoneFriend*)friends->data; jobject jfriend = getFriend(env,lfriend); if(jfriend != NULL){ - env->SetObjectArrayElement(jFriends, i, jfriend); + env->SetObjectArrayElement(jFriends, (int)i, jfriend); env->DeleteLocalRef(jfriend); } friends = friends->next; @@ -2449,13 +2424,13 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendLists(J const bctbx_list_t* friends = linphone_core_get_friends_lists((LinphoneCore*)lc); size_t friendsSize = bctbx_list_size(friends); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data((LinphoneCore *)lc); - jobjectArray jFriends = env->NewObjectArray(friendsSize,ljb->friendListClass,NULL); + jobjectArray jFriends = env->NewObjectArray((int)friendsSize,ljb->friendListClass,NULL); for (size_t i = 0; i < friendsSize; i++) { LinphoneFriendList* lfriend = (LinphoneFriendList*)friends->data; jobject jfriend = getFriendList(env,lfriend); if(jfriend != NULL){ - env->SetObjectArrayElement(jFriends, i, jfriend); + env->SetObjectArrayElement(jFriends, (int)i, jfriend); } friends = friends->next; } @@ -2463,6 +2438,30 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getFriendLists(J return jFriends; } +extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_findContactsByChar(JNIEnv* env + ,jobject thiz + ,jlong lc + ,jstring jfilter + ,jboolean jsiponly) { + const char* filter = GetStringUTFChars(env, jfilter); + const bctbx_list_t* contacts = linphone_core_find_contacts_by_char((LinphoneCore*)lc, filter, jsiponly); + size_t contactsSize = bctbx_list_size(contacts); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data((LinphoneCore *)lc); + jobjectArray jContacts = env->NewObjectArray((int)contactsSize, ljb->addressClass, NULL); + + for (size_t i = 0; i < contactsSize; i++) { + LinphoneAddress *addr = (LinphoneAddress*)contacts->data; + jobject jcontact = env->NewObject(ljb->addressClass, ljb->addressCtrId, (jlong)addr); + if(jcontact != NULL){ + env->SetObjectArrayElement(jContacts, (int)i, jcontact); + } + contacts = contacts->next; + } + ReleaseStringUTFChars(env, jfilter, filter); + + return jContacts; +} + extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPresenceInfo(JNIEnv* env ,jobject thiz ,jlong lc @@ -2482,7 +2481,7 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getPresenceInfo(JNIEnv * * Method: setPresenceModel * Signature: (JILjava/lang/String;J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setPresenceModel(JNIEnv *env, jobject jobj, jlong ptr, jlong modelPtr) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPresenceModel(JNIEnv *env, jobject jobj, jlong ptr, jlong modelPtr) { LinphoneCore *lc = (LinphoneCore *)ptr; LinphonePresenceModel *model = (LinphonePresenceModel *)modelPtr; linphone_core_set_presence_model(lc, model); @@ -2493,7 +2492,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setPresenceModel( * Method: getPresenceModel * Signature: (J)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_getPresenceModel(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getPresenceModel(JNIEnv *env, jobject jobj, jlong ptr) { LinphoneCore *lc = (LinphoneCore *)ptr; LinphonePresenceModel *model = linphone_core_get_presence_model(lc); if (model == NULL) return NULL; @@ -2680,7 +2679,7 @@ extern "C" int Java_org_linphone_core_LinphoneCoreImpl_startEchoTester(JNIEnv* ,jobject thiz ,jlong lc ,jint rate) { - return linphone_core_start_echo_tester((LinphoneCore*)lc, rate); + return linphone_core_start_echo_tester((LinphoneCore*)lc, (unsigned int)rate); } extern "C" int Java_org_linphone_core_LinphoneCoreImpl_stopEchoTester(JNIEnv* env @@ -2771,7 +2770,7 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setLimeEncryption(JNIEnv * Method: disableChat * Signature: (JI)V */ -extern "C" JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_disableChat(JNIEnv *env, jobject jobj, jlong ptr, jint reason){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_disableChat(JNIEnv *env, jobject jobj, jlong ptr, jint reason){ linphone_core_disable_chat((LinphoneCore*)ptr,(LinphoneReason)reason); } @@ -2780,7 +2779,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_disabl * Method: enableChat * Signature: (J)V */ -extern "C" JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableChat(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableChat(JNIEnv *env, jobject jobj, jlong ptr){ linphone_core_enable_chat((LinphoneCore*)ptr); } @@ -2789,7 +2788,7 @@ extern "C" JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enable * Method: chatEnabled * Signature: (J)Z */ -extern "C" JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_chatEnabled(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_chatEnabled(JNIEnv *env, jobject jobj, jlong ptr){ return (jboolean) linphone_core_chat_enabled((LinphoneCore*)ptr); } @@ -2861,7 +2860,7 @@ extern "C" jstring Java_org_linphone_core_LinphoneProxyConfigImpl_getContactUriP return params ? env->NewStringUTF(params) : NULL; } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getNatPolicy(JNIEnv* env,jobject thiz,jlong proxyCfg) { +extern "C" jobject Java_org_linphone_core_LinphoneProxyConfigImpl_getNatPolicy(JNIEnv* env,jobject thiz,jlong proxyCfg) { LinphoneNatPolicy *nat_policy = linphone_proxy_config_get_nat_policy((LinphoneProxyConfig *)proxyCfg); return (nat_policy != NULL) ? getNatPolicy(env, nat_policy) : NULL; } @@ -3025,7 +3024,7 @@ extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_delete(JNIEnv* env * Method: getPassword * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getPassword +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getPassword (JNIEnv *env , jobject, jlong auth_info) { const char* passwd = linphone_auth_info_get_passwd((LinphoneAuthInfo*)auth_info); if (passwd) { @@ -3039,7 +3038,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getPasswor * Method: getRealm * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getRealm +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getRealm (JNIEnv *env , jobject, jlong auth_info) { const char* realm = linphone_auth_info_get_realm((LinphoneAuthInfo*)auth_info); if (realm) { @@ -3054,7 +3053,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getRealm * Method: getDomain * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getDomain +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getDomain (JNIEnv *env , jobject, jlong auth_info) { const char* domain = linphone_auth_info_get_domain((LinphoneAuthInfo*)auth_info); if (domain) { @@ -3069,7 +3068,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getDomain * Method: getUsername * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getUsername +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getUsername (JNIEnv *env , jobject, jlong auth_info) { const char* username = linphone_auth_info_get_username((LinphoneAuthInfo*)auth_info); if (username) { @@ -3084,7 +3083,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getUsernam * Method: setPassword * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setPassword +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setPassword (JNIEnv *env, jobject, jlong auth_info, jstring jpassword) { const char* password = GetStringUTFChars(env, jpassword); linphone_auth_info_set_passwd((LinphoneAuthInfo*)auth_info,password); @@ -3096,7 +3095,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setPassword * Method: setRealm * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setRealm +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setRealm (JNIEnv *env, jobject, jlong auth_info, jstring jrealm) { const char* realm = GetStringUTFChars(env, jrealm); linphone_auth_info_set_realm((LinphoneAuthInfo*)auth_info,realm); @@ -3108,7 +3107,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setRealm * Method: setDomain * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setDomain +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setDomain (JNIEnv *env, jobject, jlong auth_info, jstring jdomain) { const char* domain = GetStringUTFChars(env, jdomain); linphone_auth_info_set_domain((LinphoneAuthInfo*)auth_info, domain); @@ -3120,7 +3119,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setDomain * Method: setUsername * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setUsername +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setUsername (JNIEnv *env, jobject, jlong auth_info, jstring jusername) { const char* username = GetStringUTFChars(env, jusername); linphone_auth_info_set_username((LinphoneAuthInfo*)auth_info,username); @@ -3132,7 +3131,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setUsername * Method: setAuthUserId * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setUserId +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setUserId (JNIEnv *env, jobject, jlong auth_info, jstring juserid) { const char* userid = GetStringUTFChars(env, juserid); linphone_auth_info_set_userid((LinphoneAuthInfo*)auth_info,userid); @@ -3144,7 +3143,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setUserId * Method: getAuthUserId * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getUserId +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getUserId (JNIEnv *env , jobject, jlong auth_info) { const char* userid = linphone_auth_info_get_userid((LinphoneAuthInfo*)auth_info); if (userid) { @@ -3159,7 +3158,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getUserId * Method: setHa1 * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setHa1 +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setHa1 (JNIEnv *env, jobject, jlong auth_info, jstring jha1) { const char* ha1 = GetStringUTFChars(env, jha1); linphone_auth_info_set_ha1((LinphoneAuthInfo*)auth_info,ha1); @@ -3172,7 +3171,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setHa1 * Method: getHa1 * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getHa1 +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getHa1 (JNIEnv *env , jobject, jlong auth_info) { const char* ha1 = linphone_auth_info_get_ha1((LinphoneAuthInfo*)auth_info); if (ha1) { @@ -3182,35 +3181,35 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getHa1 } } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsCertificate +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsCertificate (JNIEnv *env, jobject, jlong auth_info, jstring jcert) { const char* cert = GetStringUTFChars(env, jcert); linphone_auth_info_set_tls_cert((LinphoneAuthInfo*)auth_info,cert); ReleaseStringUTFChars(env, jcert, cert); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsKey +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsKey (JNIEnv *env, jobject, jlong auth_info, jstring jkey) { const char* key = GetStringUTFChars(env, jkey); linphone_auth_info_set_tls_key((LinphoneAuthInfo*)auth_info,key); ReleaseStringUTFChars(env, jkey, key); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsCertificatePath +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsCertificatePath (JNIEnv *env, jobject, jlong auth_info, jstring jpath) { const char* path = GetStringUTFChars(env, jpath); linphone_auth_info_set_tls_cert_path((LinphoneAuthInfo*)auth_info,path); ReleaseStringUTFChars(env, jpath, path); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsKeyPath +extern "C" void Java_org_linphone_core_LinphoneAuthInfoImpl_setTlsKeyPath (JNIEnv *env, jobject, jlong auth_info, jstring jpath) { const char* path = GetStringUTFChars(env, jpath); linphone_auth_info_set_tls_key_path((LinphoneAuthInfo*)auth_info,path); ReleaseStringUTFChars(env, jpath, path); } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsCertificate +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsCertificate (JNIEnv *env , jobject, jlong auth_info) { const char* cert = linphone_auth_info_get_tls_cert((LinphoneAuthInfo*)auth_info); if (cert) { @@ -3220,7 +3219,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsCert } } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsKey +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsKey (JNIEnv *env , jobject, jlong auth_info) { const char* key = linphone_auth_info_get_tls_key((LinphoneAuthInfo*)auth_info); if (key) { @@ -3230,7 +3229,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsKey } } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsCertificatePath +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsCertificatePath (JNIEnv *env , jobject, jlong auth_info) { const char* path = linphone_auth_info_get_tls_cert_path((LinphoneAuthInfo*)auth_info); if (path) { @@ -3240,7 +3239,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsCert } } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsKeyPath +extern "C" jstring Java_org_linphone_core_LinphoneAuthInfoImpl_getTlsKeyPath (JNIEnv *env , jobject, jlong auth_info) { const char* path = linphone_auth_info_get_tls_key_path((LinphoneAuthInfo*)auth_info); if (path) { @@ -3623,7 +3622,7 @@ extern "C" void Java_org_linphone_core_LinphoneCallImpl_finalize(JNIEnv* env linphone_call_unref(call); } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCallImpl_getStats(JNIEnv* env +extern "C" jobject Java_org_linphone_core_LinphoneCallImpl_getStats(JNIEnv* env ,jobject thiz ,jlong ptr, jint type) { LinphoneCall *call=(LinphoneCall*)ptr; @@ -3632,7 +3631,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCallImpl_getStats(JNIEn return stats ? env->NewObject(ljb->callStatsClass, ljb->callStatsId, (jlong)stats) : NULL; } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCallImpl_getCore(JNIEnv* env +extern "C" jobject Java_org_linphone_core_LinphoneCallImpl_getCore(JNIEnv* env ,jobject thiz ,jlong ptr) { LinphoneCall *call=(LinphoneCall*)ptr; @@ -3651,11 +3650,11 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneCoreImpl_getCallLogs(JNIEnv ,jlong lc) { const bctbx_list_t *logs = linphone_core_get_call_logs((LinphoneCore *) lc); size_t logsCount = bctbx_list_size(logs); - jlongArray jLogs = env->NewLongArray(logsCount); + jlongArray jLogs = env->NewLongArray((int)logsCount); jlong *jInternalArray = env->GetLongArrayElements(jLogs, NULL); for (size_t i = 0; i < logsCount; i++) { - jInternalArray[i] = (unsigned long) (logs->data); + jInternalArray[i] = (long) (logs->data); logs = logs->next; } @@ -3735,7 +3734,7 @@ extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getState( JNIEnv* env * Method: getTransferState * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCallImpl_getTransferState(JNIEnv *, jobject jobj, jlong callptr){ +extern "C" jint Java_org_linphone_core_LinphoneCallImpl_getTransferState(JNIEnv *, jobject jobj, jlong callptr){ LinphoneCall *call=(LinphoneCall*)callptr; return linphone_call_get_transfer_state(call); } @@ -3745,7 +3744,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCallImpl_getTransferState( * Method: getTransfererCall * Signature: (J)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCallImpl_getTransfererCall(JNIEnv *env, jobject jCall, jlong callptr){ +extern "C" jobject Java_org_linphone_core_LinphoneCallImpl_getTransfererCall(JNIEnv *env, jobject jCall, jlong callptr){ LinphoneCall *call=(LinphoneCall*)callptr; LinphoneCall *ret=linphone_call_get_transferer_call(call); return getCall(env,ret); @@ -3756,7 +3755,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCallImpl_getTransfererC * Method: getTransferTargetCall * Signature: (J)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCallImpl_getTransferTargetCall(JNIEnv *env, jobject jCall, jlong callptr){ +extern "C" jobject Java_org_linphone_core_LinphoneCallImpl_getTransferTargetCall(JNIEnv *env, jobject jCall, jlong callptr){ LinphoneCall *call=(LinphoneCall*)callptr; LinphoneCall *ret=linphone_call_get_transfer_target_call(call); return getCall(env,ret); @@ -4093,13 +4092,13 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneFriendListImpl_getFriendL size_t friendsSize = bctbx_list_size(friends); LinphoneCore *lc = linphone_friend_list_get_core((LinphoneFriendList *)list); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); - jobjectArray jFriends = env->NewObjectArray(friendsSize,ljb->friendClass,NULL); + jobjectArray jFriends = env->NewObjectArray((int)friendsSize,ljb->friendClass,NULL); for (size_t i = 0; i < friendsSize; i++) { LinphoneFriend* lfriend = (LinphoneFriend*)friends->data; jobject jfriend = getFriend(env,lfriend); if(jfriend != NULL){ - env->SetObjectArrayElement(jFriends, i, jfriend); + env->SetObjectArrayElement(jFriends, (int)i, jfriend); env->DeleteLocalRef(jfriend); } friends = friends->next; @@ -4119,10 +4118,10 @@ extern "C" jlongArray Java_org_linphone_core_LinphoneFriendImpl_getAddresses(JNI ,jlong ptr) { const bctbx_list_t *addresses = linphone_friend_get_addresses((LinphoneFriend*)ptr); size_t size = bctbx_list_size(addresses); - jlongArray jaddresses = env->NewLongArray(size); + jlongArray jaddresses = env->NewLongArray((int)size); jlong *jInternalArray = env->GetLongArrayElements(jaddresses, NULL); for (size_t i = 0; i < size; i++) { - jInternalArray[i] = (unsigned long) (addresses->data); + jInternalArray[i] = (long) (addresses->data); addresses = bctbx_list_next(addresses); } env->ReleaseLongArrayElements(jaddresses, jInternalArray, 0); @@ -4149,10 +4148,10 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneFriendImpl_getPhoneNumber bctbx_list_t *phone_numbers = linphone_friend_get_phone_numbers((LinphoneFriend*)ptr); bctbx_list_t *list = phone_numbers; size_t size = bctbx_list_size(phone_numbers); - jobjectArray jphonenumbers = env->NewObjectArray(size, env->FindClass("java/lang/String"), env->NewStringUTF("")); + jobjectArray jphonenumbers = env->NewObjectArray((int)size, env->FindClass("java/lang/String"), env->NewStringUTF("")); for (size_t i = 0; i < size; i++) { const char *phone = (const char *)phone_numbers->data; - env->SetObjectArrayElement(jphonenumbers, i, env->NewStringUTF(phone)); + env->SetObjectArrayElement(jphonenumbers, (int)i, env->NewStringUTF(phone)); phone_numbers = bctbx_list_next(phone_numbers); } bctbx_list_free(list); @@ -4358,14 +4357,12 @@ extern "C" jobject Java_org_linphone_core_LinphoneFriendImpl_getPresenceModelFor RETURN_USER_DATA_OBJECT("PresenceModelImpl", linphone_presence_model, model); } -extern - /* * Class: org_linphone_core_LinphoneFriendImpl * Method: getPresenceModel * Signature: (J)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneFriendImpl_getPresenceModel(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jobject Java_org_linphone_core_LinphoneFriendImpl_getPresenceModel(JNIEnv *env, jobject jobj, jlong ptr) { LinphoneFriend *lf = (LinphoneFriend *)ptr; LinphonePresenceModel *model = (LinphonePresenceModel *)linphone_friend_get_presence_model(lf); if (model == NULL) return NULL; @@ -4431,13 +4428,13 @@ extern "C" jobjectArray _LinphoneChatRoomImpl_getHistory(JNIEnv* env, jobject th LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); bctbx_list_t *list = history; size_t historySize = bctbx_list_size(history); - jobjectArray jHistory = env->NewObjectArray(historySize, ljb->chatMessageClass, NULL); + jobjectArray jHistory = env->NewObjectArray((int)historySize, ljb->chatMessageClass, NULL); for (size_t i = 0; i < historySize; i++) { LinphoneChatMessage *msg = (LinphoneChatMessage *)history->data; jobject jmsg = getChatMessage(env, msg); if (jmsg != NULL) { - env->SetObjectArrayElement(jHistory, i, jmsg); + env->SetObjectArrayElement(jHistory, (int)i, jmsg); env->DeleteLocalRef(jmsg); } @@ -4495,10 +4492,10 @@ extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_deleteHistory(JNIEnv ,jlong ptr) { linphone_chat_room_delete_history((LinphoneChatRoom*)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneChatRoomImpl_compose(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_compose(JNIEnv *env, jobject thiz, jlong ptr) { linphone_chat_room_compose((LinphoneChatRoom *)ptr); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneChatRoomImpl_isRemoteComposing(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jboolean Java_org_linphone_core_LinphoneChatRoomImpl_isRemoteComposing(JNIEnv *env, jobject thiz, jlong ptr) { return (jboolean)linphone_chat_room_is_remote_composing((LinphoneChatRoom *)ptr); } extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_deleteMessage(JNIEnv* env @@ -4529,7 +4526,7 @@ extern "C" jobject Java_org_linphone_core_LinphoneChatRoomImpl_createFileTransfe linphone_content_set_name(content, tmp = GetStringUTFChars(env, jname)); ReleaseStringUTFChars(env, jname, tmp); - linphone_content_set_size(content, data_size); + linphone_content_set_size(content, (size_t)data_size); message = linphone_chat_room_create_file_transfer_message((LinphoneChatRoom *)ptr, content); @@ -4587,8 +4584,8 @@ extern "C" jbyteArray Java_org_linphone_core_LinphoneChatMessageImpl_getText(JNI const char *message = linphone_chat_message_get_text((LinphoneChatMessage*)ptr); if (message){ size_t length = strlen(message); - jbyteArray array = env->NewByteArray(length); - env->SetByteArrayRegion(array, 0, length, (const jbyte*)message); + jbyteArray array = env->NewByteArray((int)length); + env->SetByteArrayRegion(array, 0, (int)length, (const jbyte*)message); return array; } return NULL; @@ -4642,13 +4639,13 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setExternalBodyUr extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getFrom(JNIEnv* env ,jobject thiz ,jlong ptr) { - return (jlong) linphone_chat_message_get_from((LinphoneChatMessage*)ptr); + return (jlong) linphone_chat_message_get_from_address((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); + return (jlong) linphone_chat_message_get_to_address((LinphoneChatMessage*)ptr); } extern "C" jlong Java_org_linphone_core_LinphoneChatMessageImpl_getPeerAddress(JNIEnv* env @@ -4684,7 +4681,7 @@ extern "C" jboolean Java_org_linphone_core_LinphoneChatMessageImpl_isOutgoing(JN extern "C" jint Java_org_linphone_core_LinphoneChatMessageImpl_getStorageId(JNIEnv* env ,jobject thiz ,jlong ptr) { - return (jint) linphone_chat_message_get_storage_id((LinphoneChatMessage*)ptr); + return 0; } extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setFileTransferFilepath(JNIEnv* env @@ -4695,10 +4692,10 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setFileTransferFi ReleaseStringUTFChars(env, jpath, path); } -extern "C" jint Java_org_linphone_core_LinphoneChatMessageImpl_downloadFile(JNIEnv* env +extern "C" jboolean Java_org_linphone_core_LinphoneChatMessageImpl_downloadFile(JNIEnv* env ,jobject thiz ,jlong ptr) { - return (jint) linphone_chat_message_download_file((LinphoneChatMessage*)ptr); + return linphone_chat_message_download_file((LinphoneChatMessage*)ptr); } extern "C" jboolean Java_org_linphone_core_LinphoneChatMessageImpl_isSecured(JNIEnv* env @@ -4714,7 +4711,7 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_reSend(JNIEnv* e } static jobject getMessageListener(JNIEnv *env, LinphoneChatMessage *msg){ - jobject listener = (jobject) msg->message_state_changed_user_data; + jobject listener = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data(msg); if (listener == NULL) { ms_error("message_state_changed() notification without listener"); @@ -4723,7 +4720,7 @@ static jobject getMessageListener(JNIEnv *env, LinphoneChatMessage *msg){ listener = env->NewLocalRef(listener); //promote the weak ref into a local ref*/ if (listener == NULL){ ms_error("message_state_changed() listener is no longer valid"); - msg->message_state_changed_user_data = NULL; + linphone_chat_message_set_message_state_changed_cb_user_data(msg, NULL); return NULL; } return listener; @@ -4739,6 +4736,7 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS jobject listener = getMessageListener(env, msg); if (!listener) return; + jclass clazz = (jclass) env->GetObjectClass(listener); jmethodID method = env->GetMethodID(clazz, "onLinphoneChatMessageStateChanged","(Lorg/linphone/core/LinphoneChatMessage;Lorg/linphone/core/LinphoneChatMessage$State;)V"); jobject jmessage = getChatMessage(env, msg); @@ -4749,8 +4747,6 @@ static void message_state_changed(LinphoneChatMessage* msg, LinphoneChatMessageS LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); env->CallVoidMethod(listener, method, jmessage, env->CallStaticObjectMethod(ljb->chatMessageStateClass, ljb->chatMessageStateFromIntId, (jint)state)); env->DeleteLocalRef(listener); - - } static void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) { @@ -4848,7 +4844,7 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_setListener(JNIEn LinphoneChatMessage *message = (LinphoneChatMessage *)ptr; LinphoneChatMessageCbs *cbs; - message->message_state_changed_user_data = env->NewWeakGlobalRef(jlistener); + linphone_chat_message_set_message_state_changed_cb_user_data(message, env->NewWeakGlobalRef(jlistener)); cbs = linphone_chat_message_get_callbacks(message); linphone_chat_message_cbs_set_msg_state_changed(cbs, message_state_changed); linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); @@ -4860,13 +4856,13 @@ extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_unref(JNIEnv* en ,jobject thiz ,jlong ptr) { jobject wref = (jobject)linphone_chat_message_get_user_data((LinphoneChatMessage*)ptr); - jobject listener_wref = (jobject) ((LinphoneChatMessage*)ptr)->message_state_changed_user_data; + jobject listener_wref = (jobject) linphone_chat_message_get_message_state_changed_cb_user_data((LinphoneChatMessage*)ptr); linphone_chat_message_set_user_data((LinphoneChatMessage*)ptr, NULL); if (wref){ env->DeleteWeakGlobalRef(wref); } if (listener_wref){ - ((LinphoneChatMessage*)ptr)->message_state_changed_user_data = NULL; + linphone_chat_message_set_message_state_changed_cb_user_data((LinphoneChatMessage*)ptr, NULL); env->DeleteWeakGlobalRef(listener_wref); } linphone_chat_message_unref((LinphoneChatMessage*)ptr); @@ -4879,13 +4875,13 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_getChatRooms(JNI const bctbx_list_t* chats = linphone_core_get_chat_rooms(lc); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); size_t chatsSize = bctbx_list_size(chats); - jobjectArray jChats = env->NewObjectArray(chatsSize, ljb->chatRoomClass, NULL); + jobjectArray jChats = env->NewObjectArray((int)chatsSize, ljb->chatRoomClass, NULL); for (size_t i = 0; i < chatsSize; i++) { LinphoneChatRoom *room = (LinphoneChatRoom *)chats->data; jobject jroom = getChatRoom(env, room); if (jroom != NULL) { - env->SetObjectArrayElement(jChats, i, jroom); + env->SetObjectArrayElement(jChats, (int)i, jroom); env->DeleteLocalRef(jroom); } chats = chats->next; @@ -4983,16 +4979,16 @@ extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getFirewallPolicy(JNIEnv return (jint)linphone_core_get_firewall_policy((LinphoneCore*)lc); } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createNatPolicy(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_createNatPolicy(JNIEnv *env, jobject thiz, jlong lc) { LinphoneNatPolicy *nat_policy = linphone_core_create_nat_policy((LinphoneCore *)lc); return (nat_policy != NULL) ? getNatPolicy(env, nat_policy) : NULL; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setNatPolicy(JNIEnv *env, jobject thiz, jlong lc, jlong jpolicy) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setNatPolicy(JNIEnv *env, jobject thiz, jlong lc, jlong jpolicy) { linphone_core_set_nat_policy((LinphoneCore *)lc, (LinphoneNatPolicy *)jpolicy); } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_getNatPolicy(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_getNatPolicy(JNIEnv *env, jobject thiz, jlong lc) { LinphoneNatPolicy *nat_policy = linphone_core_get_nat_policy((LinphoneCore *)lc); return (nat_policy != NULL) ? getNatPolicy(env, nat_policy) : NULL; } @@ -5053,7 +5049,7 @@ extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_setPrivacy(JNIEnv* ,jobject thiz ,jlong cp ,jint privacy) { - linphone_call_params_set_privacy((LinphoneCallParams*)cp,privacy); + linphone_call_params_set_privacy((LinphoneCallParams*)cp,(unsigned int)privacy); } extern "C" jstring Java_org_linphone_core_LinphoneCallParamsImpl_getSessionName(JNIEnv* env @@ -5117,7 +5113,7 @@ extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_addCustomHeader(JN ReleaseStringUTFChars(env, jheader_value, header_value); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_addCustomSdpAttribute(JNIEnv *env, jobject thiz, jlong ptr, jstring jname, jstring jvalue) { +extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_addCustomSdpAttribute(JNIEnv *env, jobject thiz, jlong ptr, jstring jname, jstring jvalue) { const char *name = GetStringUTFChars(env, jname); const char *value = GetStringUTFChars(env, jvalue); linphone_call_params_add_custom_sdp_attribute((LinphoneCallParams *)ptr, name, value); @@ -5125,7 +5121,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_addCustomSd ReleaseStringUTFChars(env, jvalue, value); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_addCustomSdpMediaAttribute(JNIEnv *env, jobject thiz, jlong ptr, jint jtype, jstring jname, jstring jvalue) { +extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_addCustomSdpMediaAttribute(JNIEnv *env, jobject thiz, jlong ptr, jint jtype, jstring jname, jstring jvalue) { const char *name = GetStringUTFChars(env, jname); const char *value = GetStringUTFChars(env, jvalue); linphone_call_params_add_custom_sdp_media_attribute((LinphoneCallParams *)ptr, (LinphoneStreamType)jtype, name, value); @@ -5133,25 +5129,25 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_addCustomSd ReleaseStringUTFChars(env, jvalue, value); } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_getCustomSdpAttribute(JNIEnv *env, jobject thiz, jlong ptr, jstring jname) { +extern "C" jstring Java_org_linphone_core_LinphoneCallParamsImpl_getCustomSdpAttribute(JNIEnv *env, jobject thiz, jlong ptr, jstring jname) { const char *name = GetStringUTFChars(env, jname); const char *value = linphone_call_params_get_custom_sdp_attribute((LinphoneCallParams *)ptr, name); ReleaseStringUTFChars(env, jname, name); return value ? env->NewStringUTF(value) : NULL; } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_getCustomSdpMediaAttribute(JNIEnv *env, jobject thiz, jlong ptr, jint jtype, jstring jname) { +extern "C" jstring Java_org_linphone_core_LinphoneCallParamsImpl_getCustomSdpMediaAttribute(JNIEnv *env, jobject thiz, jlong ptr, jint jtype, jstring jname) { const char *name = GetStringUTFChars(env, jname); const char *value = linphone_call_params_get_custom_sdp_media_attribute((LinphoneCallParams *)ptr, (LinphoneStreamType)jtype, name); ReleaseStringUTFChars(env, jname, name); return value ? env->NewStringUTF(value) : NULL; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_clearCustomSdpAttributes(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_clearCustomSdpAttributes(JNIEnv *env, jobject thiz, jlong ptr) { linphone_call_params_clear_custom_sdp_attributes((LinphoneCallParams *)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_clearCustomSdpMediaAttributes(JNIEnv *env, jobject thiz, jlong ptr, jint jtype) { +extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_clearCustomSdpMediaAttributes(JNIEnv *env, jobject thiz, jlong ptr, jint jtype) { linphone_call_params_clear_custom_sdp_media_attributes((LinphoneCallParams *)ptr, (LinphoneStreamType)jtype); } @@ -5191,19 +5187,19 @@ extern "C" jfloat Java_org_linphone_core_LinphoneCallParamsImpl_getReceivedFrame return (jfloat)linphone_call_params_get_received_framerate(params); } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_getAudioDirection(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jint Java_org_linphone_core_LinphoneCallParamsImpl_getAudioDirection(JNIEnv *env, jobject thiz, jlong ptr) { return (jint)linphone_call_params_get_audio_direction((LinphoneCallParams *)ptr); } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_getVideoDirection(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jint Java_org_linphone_core_LinphoneCallParamsImpl_getVideoDirection(JNIEnv *env, jobject thiz, jlong ptr) { return (jint)linphone_call_params_get_video_direction((LinphoneCallParams *)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_setAudioDirection(JNIEnv *env, jobject thiz, jlong ptr, jint jdir) { +extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_setAudioDirection(JNIEnv *env, jobject thiz, jlong ptr, jint jdir) { linphone_call_params_set_audio_direction((LinphoneCallParams *)ptr, (LinphoneMediaDirection)jdir); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCallParamsImpl_setVideoDirection(JNIEnv *env, jobject thiz, jlong ptr, jint jdir) { +extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_setVideoDirection(JNIEnv *env, jobject thiz, jlong ptr, jint jdir) { linphone_call_params_set_video_direction((LinphoneCallParams *)ptr, (LinphoneMediaDirection)jdir); } @@ -5217,7 +5213,7 @@ extern "C" void Java_org_linphone_core_LinphoneCallParamsImpl_destroy(JNIEnv *en * Method: createCallParams * Signature: (JJ)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneCoreImpl_createCallParams(JNIEnv *env, jobject jcore, jlong coreptr, jlong callptr){ +extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createCallParams(JNIEnv *env, jobject jcore, jlong coreptr, jlong callptr){ return (jlong)linphone_core_create_call_params((LinphoneCore*)coreptr, (LinphoneCall*)callptr); } @@ -5275,7 +5271,7 @@ extern "C" float Java_org_linphone_core_LinphoneCoreImpl_getPreferredFramerate(J return linphone_core_get_preferred_framerate((LinphoneCore *)lc); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setPreferredVideoSizeByName(JNIEnv *env, jobject thiz, jlong lc, jstring jName) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setPreferredVideoSizeByName(JNIEnv *env, jobject thiz, jlong lc, jstring jName) { const char* cName = GetStringUTFChars(env, jName); linphone_core_set_preferred_video_size_by_name((LinphoneCore *)lc, cName); ReleaseStringUTFChars(env, jName, cName); @@ -5289,7 +5285,7 @@ extern "C" jintArray Java_org_linphone_core_LinphoneCoreImpl_getPreferredVideoSi return arr; } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getDownloadBandwidth(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getDownloadBandwidth(JNIEnv *env, jobject thiz, jlong lc) { return (jint) linphone_core_get_download_bandwidth((LinphoneCore *)lc); } @@ -5297,7 +5293,7 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDownloadBandwidth(JNI linphone_core_set_download_bandwidth((LinphoneCore *)lc, (int) bw); } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getUploadBandwidth(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getUploadBandwidth(JNIEnv *env, jobject thiz, jlong lc) { return (jint) linphone_core_get_upload_bandwidth((LinphoneCore *)lc); } @@ -5342,48 +5338,48 @@ extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getExpires(JNIEnv } extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setPrivacy(JNIEnv* env,jobject thiz,jlong ptr,jint privacy) { - linphone_proxy_config_set_privacy((LinphoneProxyConfig *) ptr, (int) privacy); + linphone_proxy_config_set_privacy((LinphoneProxyConfig *) ptr, (unsigned int) privacy); } extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getPrivacy(JNIEnv* env,jobject thiz,jlong ptr) { - return linphone_proxy_config_get_privacy((LinphoneProxyConfig *) ptr); + return (int) linphone_proxy_config_get_privacy((LinphoneProxyConfig *) ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_enableAvpf(JNIEnv *env, jobject thiz, jlong ptr, jboolean enable) { +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_enableAvpf(JNIEnv *env, jobject thiz, jlong ptr, jboolean enable) { linphone_proxy_config_enable_avpf((LinphoneProxyConfig *)ptr, (bool)enable); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_avpfEnabled(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_avpfEnabled(JNIEnv *env, jobject thiz, jlong ptr) { return linphone_proxy_config_avpf_enabled((LinphoneProxyConfig *)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setAvpfRRInterval(JNIEnv *env, jobject thiz, jlong ptr, jint interval) { +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setAvpfRRInterval(JNIEnv *env, jobject thiz, jlong ptr, jint interval) { linphone_proxy_config_set_avpf_rr_interval((LinphoneProxyConfig *)ptr, (uint8_t)interval); } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getAvpfRRInterval(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getAvpfRRInterval(JNIEnv *env, jobject thiz, jlong ptr) { return (jint)linphone_proxy_config_get_avpf_rr_interval((LinphoneProxyConfig *)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_enableQualityReporting(JNIEnv *env, jobject thiz, jlong ptr, jboolean enable) { +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_enableQualityReporting(JNIEnv *env, jobject thiz, jlong ptr, jboolean enable) { linphone_proxy_config_enable_quality_reporting((LinphoneProxyConfig *)ptr, (bool)enable); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_quality_reportingEnabled(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_quality_reportingEnabled(JNIEnv *env, jobject thiz, jlong ptr) { return linphone_proxy_config_quality_reporting_enabled((LinphoneProxyConfig *)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setQualityReportingInterval(JNIEnv *env, jobject thiz, jlong ptr, jint interval) { +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setQualityReportingInterval(JNIEnv *env, jobject thiz, jlong ptr, jint interval) { linphone_proxy_config_set_quality_reporting_interval((LinphoneProxyConfig *)ptr, (uint8_t)interval); } -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getQualityReportingInterval(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jint Java_org_linphone_core_LinphoneProxyConfigImpl_getQualityReportingInterval(JNIEnv *env, jobject thiz, jlong ptr) { return (jint)linphone_proxy_config_get_quality_reporting_interval((LinphoneProxyConfig *)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setQualityReportingCollector(JNIEnv *env, jobject thiz, jlong ptr, jstring jcollector) { +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setQualityReportingCollector(JNIEnv *env, jobject thiz, jlong ptr, jstring jcollector) { if (jcollector){ const char *collector = GetStringUTFChars(env, jcollector); linphone_proxy_config_set_quality_reporting_collector((LinphoneProxyConfig *)ptr, collector); @@ -5391,12 +5387,12 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setQuality } } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getQualityReportingCollector(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jstring Java_org_linphone_core_LinphoneProxyConfigImpl_getQualityReportingCollector(JNIEnv *env, jobject thiz, jlong ptr) { jstring jvalue = env->NewStringUTF(linphone_proxy_config_get_quality_reporting_collector((LinphoneProxyConfig *)ptr)); return jvalue; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setRealm(JNIEnv *env, jobject thiz, jlong ptr, jstring jrealm) { +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setRealm(JNIEnv *env, jobject thiz, jlong ptr, jstring jrealm) { if (jrealm){ const char *realm = GetStringUTFChars(env, jrealm); linphone_proxy_config_set_realm((LinphoneProxyConfig *)ptr, realm); @@ -5404,12 +5400,12 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setRealm(J } } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getRealm(JNIEnv *env, jobject thiz, jlong ptr) { +extern "C" jstring 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; } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_isPhoneNumber(JNIEnv *env, jobject thiz, jlong ptr, jstring jusername) { +extern "C" jboolean Java_org_linphone_core_LinphoneProxyConfigImpl_isPhoneNumber(JNIEnv *env, jobject thiz, jlong ptr, jstring jusername) { if(jusername){ const char *username = GetStringUTFChars(env, jusername); bool_t res = linphone_proxy_config_is_phone_number((LinphoneProxyConfig *)ptr, username); @@ -5420,7 +5416,7 @@ JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_isPhon } } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setCustomHeader(JNIEnv *env, jobject thiz, jlong prt, jstring jname, jstring jvalue) { +extern "C" void Java_org_linphone_core_LinphoneProxyConfigImpl_setCustomHeader(JNIEnv *env, jobject thiz, jlong prt, jstring jname, jstring jvalue) { const char *name = GetStringUTFChars(env, jname); const char *value = GetStringUTFChars(env, jvalue); linphone_proxy_config_set_custom_header((LinphoneProxyConfig*) prt, name, value); @@ -5428,7 +5424,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_setCustomH ReleaseStringUTFChars(env, jvalue, value); } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneProxyConfigImpl_getCustomHeader(JNIEnv *env, jobject thiz, jlong ptr, jstring jname) { +extern "C" jstring Java_org_linphone_core_LinphoneProxyConfigImpl_getCustomHeader(JNIEnv *env, jobject thiz, jlong ptr, jstring jname) { const char *name = GetStringUTFChars(env, jname); const char *value = linphone_proxy_config_get_custom_header((LinphoneProxyConfig *)ptr, name); ReleaseStringUTFChars(env, jname, name); @@ -5710,12 +5706,12 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_soundResourcesLocked // Needed by Galaxy S (can't switch to/from speaker while playing and still keep mic working) // Implemented directly in msandroid.cpp (sound filters for Android). extern "C" void Java_org_linphone_core_LinphoneCoreImpl_forceSpeakerState(JNIEnv *env, jobject thiz, jlong ptr, jboolean speakerOn) { - LinphoneCore *lc = (LinphoneCore *)ptr; + /*LinphoneCore *lc = (LinphoneCore *)ptr; LinphoneCall *call = linphone_core_get_current_call(lc); if (call && call->audiostream && call->audiostream->soundread) { bool_t on = speakerOn; ms_filter_call_method(call->audiostream->soundread, MS_AUDIO_CAPTURE_FORCE_SPEAKER_STATE, &on); - } + }*/ } // End Galaxy S hack functions @@ -5766,7 +5762,7 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneCoreImpl_tunnelGetServers const bctbx_list_t *it; int i; - tunnelConfigArray = env->NewObjectArray(bctbx_list_size(servers), tunnelConfigClass, NULL); + tunnelConfigArray = env->NewObjectArray((int)bctbx_list_size(servers), tunnelConfigClass, NULL); for(it = servers, i=0; it != NULL; it = it->next, i++) { LinphoneTunnelConfig *conf = (LinphoneTunnelConfig *)it->data; jobject elt = getTunnelConfig(env, conf); @@ -5892,7 +5888,7 @@ extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setStaticPicture(JNIEnv extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setCpuCountNative(JNIEnv *env, jobject thiz, jlong coreptr, jint count) { MSFactory *factory = linphone_core_get_ms_factory((LinphoneCore*)coreptr); - ms_factory_set_cpu_count(factory, count); + ms_factory_set_cpu_count(factory, (unsigned int)count); } extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setAudioJittcomp(JNIEnv *env, jobject thiz, jlong lc, jint value) { @@ -6010,7 +6006,7 @@ static LinphoneContent *create_content_from_java_args(JNIEnv *env, LinphoneCore ReleaseStringUTFChars(env, jencoding, tmp); } - linphone_content_set_buffer(content, data, env->GetArrayLength(jdata)); + linphone_content_set_buffer(content, (const uint8_t *)data, (size_t)env->GetArrayLength(jdata)); env->ReleaseByteArrayElements(jdata,(jbyte*)data,JNI_ABORT); } return content; @@ -6021,7 +6017,7 @@ static LinphoneContent *create_content_from_java_args(JNIEnv *env, LinphoneCore * Method: subscribe * Signature: (JJLjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIEnv *env, jobject jcore, jlong coreptr, jlong addrptr, +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIEnv *env, jobject jcore, jlong coreptr, jlong addrptr, jstring jevname, jint expires, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ LinphoneCore *lc=(LinphoneCore*)coreptr; LinphoneAddress *addr=(LinphoneAddress*)addrptr; @@ -6045,7 +6041,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_subscribe(JNIE * Method: publish * Signature: (JJLjava/lang/String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_publish(JNIEnv *env, jobject jobj, jlong coreptr, jlong addrptr, jstring jevname, jint expires, +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_publish(JNIEnv *env, jobject jobj, jlong coreptr, jlong addrptr, jstring jevname, jint expires, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ LinphoneCore *lc=(LinphoneCore*)coreptr; LinphoneAddress *addr=(LinphoneAddress*)addrptr; @@ -6211,7 +6207,7 @@ static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent * jbyteArray jdata = NULL; jint jsize = 0; const char *tmp; - void *data; + const uint8_t *data; contentClass = (jclass)env->FindClass("org/linphone/core/LinphoneContentImpl"); ctor = env->GetMethodID(contentClass,"", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[BLjava/lang/String;I)V"); @@ -6224,8 +6220,8 @@ static jobject create_java_linphone_content(JNIEnv *env, const LinphoneContent * data = (!linphone_content_is_multipart(icontent) ? linphone_content_get_buffer(icontent) : NULL); if (data){ - jdata = env->NewByteArray(linphone_content_get_size(icontent)); - env->SetByteArrayRegion(jdata, 0, linphone_content_get_size(icontent), (jbyte*)data); + jdata = env->NewByteArray((int)linphone_content_get_size(icontent)); + env->SetByteArrayRegion(jdata, 0, (int)linphone_content_get_size(icontent), (jbyte*)data); } jobject jobj = env->NewObject(contentClass, ctor, jname, jtype, jsubtype, jdata, jencoding, jsize); @@ -6257,8 +6253,8 @@ static jobject create_java_linphone_buffer(JNIEnv *env, const LinphoneBuffer *bu jsize = buffer ? (jint) buffer->size : 0; if (buffer && buffer->content) { - jdata = env->NewByteArray(buffer->size); - env->SetByteArrayRegion(jdata, 0, buffer->size, (jbyte*)buffer->content); + jdata = env->NewByteArray((int)buffer->size); + env->SetByteArrayRegion(jdata, 0, (int)buffer->size, (jbyte*)buffer->content); } jobject jobj = env->NewObject(bufferClass, ctor, jdata, jsize); @@ -6298,7 +6294,7 @@ static LinphoneBuffer* create_c_linphone_buffer_from_java_linphone_buffer(JNIEnv * Method: getContent * Signature: (J)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getContent(JNIEnv *env, jobject jobj, jlong infoptr){ +extern "C" jobject Java_org_linphone_core_LinphoneInfoMessageImpl_getContent(JNIEnv *env, jobject jobj, jlong infoptr){ const LinphoneContent *content=linphone_info_message_get_content((LinphoneInfoMessage*)infoptr); if (content){ return create_java_linphone_content(env,content); @@ -6311,7 +6307,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getCont * Method: setContent * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_setContent(JNIEnv *env, jobject jobj, jlong infoptr, jstring jtype, jstring jsubtype, jstring jdata){ +extern "C" void Java_org_linphone_core_LinphoneInfoMessageImpl_setContent(JNIEnv *env, jobject jobj, jlong infoptr, jstring jtype, jstring jsubtype, jstring jdata){ LinphoneInfoMessage *infomsg = (LinphoneInfoMessage*) infoptr; LinphoneContent * content = linphone_content_new(); const char *tmp; @@ -6334,7 +6330,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_setContent * Method: addHeader * Signature: (JLjava/lang/String;Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_addHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname, jstring jvalue){ +extern "C" void Java_org_linphone_core_LinphoneInfoMessageImpl_addHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname, jstring jvalue){ const char *name = GetStringUTFChars(env, jname); const char *value = GetStringUTFChars(env, jvalue); linphone_info_message_add_header((LinphoneInfoMessage*)infoptr,name,value); @@ -6347,7 +6343,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_addHeader( * Method: getHeader * Signature: (JLjava/lang/String;)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname){ +extern "C" jstring Java_org_linphone_core_LinphoneInfoMessageImpl_getHeader(JNIEnv *env, jobject jobj, jlong infoptr, jstring jname){ const char *name = GetStringUTFChars(env, jname); const char *ret=linphone_info_message_get_header((LinphoneInfoMessage*)infoptr,name); ReleaseStringUTFChars(env, jname, name); @@ -6359,11 +6355,11 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_getHead * Method: delete * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneInfoMessageImpl_delete(JNIEnv *env, jobject jobj , jlong infoptr){ +extern "C" void Java_org_linphone_core_LinphoneInfoMessageImpl_delete(JNIEnv *env, jobject jobj , jlong infoptr){ linphone_info_message_destroy((LinphoneInfoMessage*)infoptr); } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneEventImpl_getCore(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jobject Java_org_linphone_core_LinphoneEventImpl_getCore(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneCore *lc=linphone_event_get_core((LinphoneEvent*)evptr); LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); jobject core = ljb->getCore(); @@ -6375,7 +6371,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneEventImpl_getCore(JNIEn * Method: getEventName * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneEventImpl_getEventName(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jstring Java_org_linphone_core_LinphoneEventImpl_getEventName(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; const char *evname=linphone_event_get_name(ev); return evname ? env->NewStringUTF(evname) : NULL; @@ -6386,7 +6382,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneEventImpl_getEventName( * Method: acceptSubscription * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_acceptSubscription(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_acceptSubscription(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; return linphone_event_accept_subscription(ev); } @@ -6396,7 +6392,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_acceptSubscripti * Method: denySubscription * Signature: (JI)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_denySubscription(JNIEnv *env, jobject jobj, jlong evptr, int reason){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_denySubscription(JNIEnv *env, jobject jobj, jlong evptr, int reason){ LinphoneEvent *ev=(LinphoneEvent*)evptr; return linphone_event_deny_subscription(ev,(LinphoneReason)reason); } @@ -6406,7 +6402,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_denySubscription * Method: notify * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ LinphoneContent * content = create_content_from_java_args(env, linphone_event_get_core((LinphoneEvent *)evptr), jtype, jsubtype, jdata, jencoding, NULL); LinphoneEvent *ev=(LinphoneEvent*)evptr; @@ -6425,7 +6421,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_notify(JNIEnv *e * Method: updateSubscribe * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_updateSubscribe(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ LinphoneContent * content = create_content_from_java_args(env, linphone_event_get_core((LinphoneEvent *)evptr), jtype, jsubtype, jdata, jencoding, NULL); LinphoneEvent *ev=(LinphoneEvent*)evptr; @@ -6442,7 +6438,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updateSubscribe( * Method: updatePublish * Signature: (JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_updatePublish(JNIEnv *env, jobject jobj, jlong evptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding){ LinphoneContent * content = create_content_from_java_args(env, linphone_event_get_core((LinphoneEvent *)evptr), jtype, jsubtype, jdata, jencoding, NULL); LinphoneEvent *ev=(LinphoneEvent*)evptr; @@ -6459,7 +6455,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_updatePublish(JN * Method: terminate * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_terminate(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_terminate(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; linphone_event_terminate(ev); return 0; @@ -6470,12 +6466,12 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_terminate(JNIEnv * Method: getReason * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_getReason(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_getReason(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; return linphone_event_get_reason(ev); } -JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneEventImpl_getErrorInfo(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jlong Java_org_linphone_core_LinphoneEventImpl_getErrorInfo(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; return (jlong)linphone_event_get_error_info(ev); } @@ -6485,7 +6481,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_LinphoneEventImpl_getErrorInfo(JN * Method: getSubscriptionDir * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_getSubscriptionDir(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_getSubscriptionDir(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; return linphone_event_get_subscription_dir(ev); } @@ -6495,12 +6491,12 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_getSubscriptionD * Method: getSubscriptionState * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneEventImpl_getSubscriptionState(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" jint Java_org_linphone_core_LinphoneEventImpl_getSubscriptionState(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; return linphone_event_get_subscription_state(ev); } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createSubscribe(JNIEnv *env, jobject thiz, jlong jcore, jlong jaddr, jstring jeventname, jint expires) { +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_createSubscribe(JNIEnv *env, jobject thiz, jlong jcore, jlong jaddr, jstring jeventname, jint expires) { LinphoneCore *lc = (LinphoneCore*) jcore; LinphoneAddress *addr = (LinphoneAddress*) jaddr; LinphoneEvent *event; @@ -6515,7 +6511,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createSubscrib return jevent; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_sendSubscribe(JNIEnv *env, jobject thiz, jlong eventptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) { +extern "C" void Java_org_linphone_core_LinphoneEventImpl_sendSubscribe(JNIEnv *env, jobject thiz, jlong eventptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) { LinphoneContent *content = create_content_from_java_args(env, linphone_event_get_core((LinphoneEvent*)eventptr), jtype, jsubtype, jdata, jencoding, NULL); @@ -6523,7 +6519,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_sendSubscribe(JN if (content) linphone_content_unref(content); } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createPublish(JNIEnv *env, jobject thiz, jlong jcore, jlong jaddr, jstring jeventname, jint expires) { +extern "C" jobject Java_org_linphone_core_LinphoneCoreImpl_createPublish(JNIEnv *env, jobject thiz, jlong jcore, jlong jaddr, jstring jeventname, jint expires) { LinphoneCore *lc = (LinphoneCore*) jcore; LinphoneAddress *addr = (LinphoneAddress*) jaddr; LinphoneEvent *event; @@ -6538,14 +6534,14 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneCoreImpl_createPublish( return jevent; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_sendPublish(JNIEnv *env, jobject thiz, jlong eventptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) { +extern "C" void Java_org_linphone_core_LinphoneEventImpl_sendPublish(JNIEnv *env, jobject thiz, jlong eventptr, jstring jtype, jstring jsubtype, jbyteArray jdata, jstring jencoding) { LinphoneContent *content = create_content_from_java_args(env, linphone_event_get_core((LinphoneEvent*)eventptr), jtype, jsubtype, jdata, jencoding, NULL); linphone_event_send_publish((LinphoneEvent*) eventptr, content); if (content) linphone_content_unref(content); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_addCustomHeader(JNIEnv *env, jobject thiz, jlong jevent, jstring jname, jstring jvalue) { +extern "C" void Java_org_linphone_core_LinphoneEventImpl_addCustomHeader(JNIEnv *env, jobject thiz, jlong jevent, jstring jname, jstring jvalue) { const char *name = GetStringUTFChars(env, jname); const char *value = GetStringUTFChars(env, jvalue); linphone_event_add_custom_header((LinphoneEvent*) jevent, name, value); @@ -6553,7 +6549,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_addCustomHeader( ReleaseStringUTFChars(env, jvalue, value); } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneEventImpl_getCustomHeader(JNIEnv *env, jobject thiz, jlong jevent, jstring jname) { +extern "C" jstring Java_org_linphone_core_LinphoneEventImpl_getCustomHeader(JNIEnv *env, jobject thiz, jlong jevent, jstring jname) { const char *name = GetStringUTFChars(env, jname); const char *header = linphone_event_get_custom_header((LinphoneEvent*) jevent, name); jstring jheader = header ? env->NewStringUTF(header) : NULL; @@ -6566,7 +6562,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneEventImpl_getCustomHead * Method: unref * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_unref(JNIEnv *env, jobject jobj, jlong evptr){ +extern "C" void Java_org_linphone_core_LinphoneEventImpl_unref(JNIEnv *env, jobject jobj, jlong evptr){ LinphoneEvent *ev=(LinphoneEvent*)evptr; linphone_event_unref(ev); } @@ -6576,7 +6572,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneEventImpl_unref(JNIEnv *en * Method: newPresenceModelImpl * Signature: ()J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_newPresenceModelImpl__(JNIEnv *env, jobject jobj) { +extern "C" jlong Java_org_linphone_core_PresenceModelImpl_newPresenceModelImpl__(JNIEnv *env, jobject jobj) { LinphonePresenceModel *model = linphone_presence_model_new(); model = linphone_presence_model_ref(model); return (jlong)model; @@ -6587,7 +6583,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_newPresenceMode * Method: newPresenceModelImpl * Signature: (ILjava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_newPresenceModelImpl__ILjava_lang_String_2(JNIEnv *env, jobject jobj, jint type, jstring description) { +extern "C" jlong Java_org_linphone_core_PresenceModelImpl_newPresenceModelImpl__ILjava_lang_String_2(JNIEnv *env, jobject jobj, jint type, jstring description) { LinphonePresenceModel *model; const char *cdescription = GetStringUTFChars(env, description); model = linphone_presence_model_new_with_activity((LinphonePresenceActivityType)type, cdescription); @@ -6601,7 +6597,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_newPresenceMode * Method: newPresenceModelImpl * Signature: (ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_newPresenceModelImpl__ILjava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2( +extern "C" jlong Java_org_linphone_core_PresenceModelImpl_newPresenceModelImpl__ILjava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2( JNIEnv *env, jobject jobj, jint type, jstring description, jstring note, jstring lang) { LinphonePresenceModel *model; const char *cdescription = GetStringUTFChars(env, description); @@ -6620,7 +6616,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_newPresenceMode * Method: unref * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PresenceModelImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" void Java_org_linphone_core_PresenceModelImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; linphone_presence_model_unref(model); } @@ -6630,7 +6626,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PresenceModelImpl_unref(JNIEnv *en * Method: getBasicStatus * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_getBasicStatus(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_getBasicStatus(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jint)linphone_presence_model_get_basic_status(model); } @@ -6640,7 +6636,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_getBasicStatus(J * Method: setBasicStatus * Signature: (JI)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_setBasicStatus(JNIEnv *env, jobject jobj, jlong ptr, jint basic_status) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_setBasicStatus(JNIEnv *env, jobject jobj, jlong ptr, jint basic_status) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jint)linphone_presence_model_set_basic_status(model, (LinphonePresenceBasicStatus)basic_status); } @@ -6651,7 +6647,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_setBasicStatus(J * Method: getTimestamp * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getTimestamp(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresenceModelImpl_getTimestamp(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jlong)linphone_presence_model_get_timestamp(model); } @@ -6661,7 +6657,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getTimestamp(JN * Method: getContact * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceModelImpl_getContact(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresenceModelImpl_getContact(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; char *ccontact = linphone_presence_model_get_contact(model); jstring jcontact = ccontact ? env->NewStringUTF(ccontact) : NULL; @@ -6674,7 +6670,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceModelImpl_getContact(JN * Method: setContact * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PresenceModelImpl_setContact(JNIEnv *env, jobject jobj, jlong ptr, jstring contact) { +extern "C" void Java_org_linphone_core_PresenceModelImpl_setContact(JNIEnv *env, jobject jobj, jlong ptr, jstring contact) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; const char *ccontact = GetStringUTFChars(env, contact); linphone_presence_model_set_contact(model, ccontact); @@ -6686,7 +6682,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PresenceModelImpl_setContact(JNIEn * Method: getActivity * Signature: (J)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getActivity(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jobject Java_org_linphone_core_PresenceModelImpl_getActivity(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; LinphonePresenceActivity *activity = linphone_presence_model_get_activity(model); if (activity == NULL) return NULL; @@ -6698,7 +6694,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getActivity(J * Method: setActivity * Signature: (JILjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_setActivity(JNIEnv *env, jobject jobj, jlong ptr, jint acttype, jstring description) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_setActivity(JNIEnv *env, jobject jobj, jlong ptr, jint acttype, jstring description) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; const char *cdescription = GetStringUTFChars(env, description); jint res = (jint)linphone_presence_model_set_activity(model, (LinphonePresenceActivityType)acttype, cdescription); @@ -6711,7 +6707,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_setActivity(JNIE * Method: getNbActivities * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getNbActivities(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresenceModelImpl_getNbActivities(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jlong)linphone_presence_model_get_nb_activities(model); } @@ -6721,7 +6717,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getNbActivities * Method: getNthActivity * Signature: (JJ)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNthActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { +extern "C" jobject Java_org_linphone_core_PresenceModelImpl_getNthActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; LinphonePresenceActivity *activity = linphone_presence_model_get_nth_activity(model, (unsigned int)idx); if (activity == NULL) return NULL; @@ -6733,7 +6729,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNthActivit * Method: addActivity * Signature: (JILjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong activityPtr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_addActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong activityPtr) { return (jint)linphone_presence_model_add_activity((LinphonePresenceModel *)ptr, (LinphonePresenceActivity *)activityPtr); } @@ -6742,7 +6738,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addActivity(JNIE * Method: clearActivities * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearActivities(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_clearActivities(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jint)linphone_presence_model_clear_activities(model); } @@ -6752,7 +6748,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearActivities( * Method: getNote * Signature: (JLjava/lang/String;)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNote(JNIEnv *env , jobject jobj, jlong ptr, jstring lang) { +extern "C" jobject Java_org_linphone_core_PresenceModelImpl_getNote(JNIEnv *env , jobject jobj, jlong ptr, jstring lang) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; const char *clang = GetStringUTFChars(env, lang); LinphonePresenceNote *note = linphone_presence_model_get_note(model, clang); @@ -6766,7 +6762,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNote(JNIEn * Method: addNote * Signature: (JLjava/lang/String;Ljava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addNote(JNIEnv *env, jobject jobj, jlong ptr, jstring description, jstring lang) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_addNote(JNIEnv *env, jobject jobj, jlong ptr, jstring description, jstring lang) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; const char *cdescription = GetStringUTFChars(env, description); const char *clang = GetStringUTFChars(env, lang); @@ -6781,7 +6777,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addNote(JNIEnv * * Method: clearNotes * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearNotes(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_clearNotes(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jint)linphone_presence_model_clear_notes(model); } @@ -6791,7 +6787,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearNotes(JNIEn * Method: getNbServices * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getNbServices(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresenceModelImpl_getNbServices(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jlong)linphone_presence_model_get_nb_services(model); } @@ -6801,7 +6797,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getNbServices(J * Method: getNthService * Signature: (JJ)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNthService(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { +extern "C" jobject Java_org_linphone_core_PresenceModelImpl_getNthService(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; LinphonePresenceService *service = linphone_presence_model_get_nth_service(model, (unsigned int)idx); if (service == NULL) return NULL; @@ -6813,7 +6809,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNthService * Method: addService * Signature: (JJ)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addService(JNIEnv *env, jobject jobj, jlong ptr, jlong servicePtr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_addService(JNIEnv *env, jobject jobj, jlong ptr, jlong servicePtr) { return (jint)linphone_presence_model_add_service((LinphonePresenceModel *)ptr, (LinphonePresenceService *)servicePtr); } @@ -6822,7 +6818,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addService(JNIEn * Method: clearServices * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearServices(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_clearServices(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jint)linphone_presence_model_clear_services(model); } @@ -6832,7 +6828,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearServices(JN * Method: getNbPersons * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getNbPersons(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresenceModelImpl_getNbPersons(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jlong)linphone_presence_model_get_nb_persons(model); } @@ -6842,7 +6838,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceModelImpl_getNbPersons(JN * Method: getNthPerson * Signature: (JJ)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNthPerson(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { +extern "C" jobject Java_org_linphone_core_PresenceModelImpl_getNthPerson(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; LinphonePresencePerson *person = linphone_presence_model_get_nth_person(model, (unsigned int)idx); if (person == NULL) return NULL; @@ -6854,7 +6850,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceModelImpl_getNthPerson( * Method: addPerson * Signature: (JJ)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addPerson(JNIEnv *env, jobject jobj, jlong ptr, jlong personPtr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_addPerson(JNIEnv *env, jobject jobj, jlong ptr, jlong personPtr) { return (jint)linphone_presence_model_add_person((LinphonePresenceModel *)ptr, (LinphonePresencePerson *)personPtr); } @@ -6863,7 +6859,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_addPerson(JNIEnv * Method: clearPersons * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearPersons(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceModelImpl_clearPersons(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceModel *model = (LinphonePresenceModel *)ptr; return (jint)linphone_presence_model_clear_persons(model); } @@ -6873,7 +6869,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceModelImpl_clearPersons(JNI * Method: newPresenceActivityImpl * Signature: (ILjava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceActivityImpl_newPresenceActivityImpl(JNIEnv *env, jobject jobj, jint type, jstring description) { +extern "C" jlong Java_org_linphone_core_PresenceActivityImpl_newPresenceActivityImpl(JNIEnv *env, jobject jobj, jint type, jstring description) { LinphonePresenceActivity *activity; const char *cdescription = GetStringUTFChars(env, description); activity = linphone_presence_activity_new((LinphonePresenceActivityType)type, cdescription); @@ -6887,7 +6883,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceActivityImpl_newPresenceA * Method: unref * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PresenceActivityImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" void Java_org_linphone_core_PresenceActivityImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceActivity *activity = (LinphonePresenceActivity *)ptr; linphone_presence_activity_unref(activity); } @@ -6897,7 +6893,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PresenceActivityImpl_unref(JNIEnv * Method: toString * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceActivityImpl_toString(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresenceActivityImpl_toString(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceActivity *activity = (LinphonePresenceActivity *)ptr; char *cactstr = linphone_presence_activity_to_string(activity); jstring jactstr = cactstr ? env->NewStringUTF(cactstr) : NULL; @@ -6910,7 +6906,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceActivityImpl_toString(J * Method: getType * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_getType(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceActivityImpl_getType(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceActivity *activity = (LinphonePresenceActivity *)ptr; return (jint)linphone_presence_activity_get_type(activity); } @@ -6920,7 +6916,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_getType(JNIEn * Method: setType * Signature: (JI)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_setType(JNIEnv *env, jobject jobj, jlong ptr, jint type) { +extern "C" jint Java_org_linphone_core_PresenceActivityImpl_setType(JNIEnv *env, jobject jobj, jlong ptr, jint type) { LinphonePresenceActivity *activity = (LinphonePresenceActivity *)ptr; return (jint)linphone_presence_activity_set_type(activity, (LinphonePresenceActivityType)type); } @@ -6930,7 +6926,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_setType(JNIEn * Method: getDescription * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceActivityImpl_getDescription(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresenceActivityImpl_getDescription(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceActivity *activity = (LinphonePresenceActivity *)ptr; const char *cdescription = linphone_presence_activity_get_description(activity); return cdescription ? env->NewStringUTF(cdescription) : NULL; @@ -6941,7 +6937,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceActivityImpl_getDescrip * Method: setDescription * Signature: (JLjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_setDescription(JNIEnv *env, jobject jobj, jlong ptr, jstring description) { +extern "C" jint Java_org_linphone_core_PresenceActivityImpl_setDescription(JNIEnv *env, jobject jobj, jlong ptr, jstring description) { LinphonePresenceActivity *activity = (LinphonePresenceActivity *)ptr; const char *cdescription = GetStringUTFChars(env, description); linphone_presence_activity_set_description(activity, cdescription); @@ -6954,7 +6950,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceActivityImpl_setDescriptio * Method: newPresenceServiceImpl * Signature: (Ljava/lang/String;ILjava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceServiceImpl_newPresenceServiceImpl(JNIEnv *env, jobject jobj, jstring id, jint basic_status, jstring contact) { +extern "C" jlong Java_org_linphone_core_PresenceServiceImpl_newPresenceServiceImpl(JNIEnv *env, jobject jobj, jstring id, jint basic_status, jstring contact) { LinphonePresenceService *service; const char *cid = GetStringUTFChars(env, id); const char *ccontact = GetStringUTFChars(env, contact); @@ -6970,7 +6966,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceServiceImpl_newPresenceSe * Method: unref * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PresenceServiceImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" void Java_org_linphone_core_PresenceServiceImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; linphone_presence_service_unref(service); } @@ -6980,7 +6976,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PresenceServiceImpl_unref(JNIEnv * * Method: getId * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceServiceImpl_getId(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresenceServiceImpl_getId(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; char *cid = linphone_presence_service_get_id(service); jstring jid = cid ? env->NewStringUTF(cid) : NULL; @@ -6993,7 +6989,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceServiceImpl_getId(JNIEn * Method: setId * Signature: (JLjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setId(JNIEnv *env, jobject jobj, jlong ptr, jstring id) { +extern "C" jint Java_org_linphone_core_PresenceServiceImpl_setId(JNIEnv *env, jobject jobj, jlong ptr, jstring id) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; const char *cid = GetStringUTFChars(env, id); linphone_presence_service_set_id(service, cid); @@ -7006,7 +7002,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setId(JNIEnv * * Method: getBasicStatus * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_getBasicStatus(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceServiceImpl_getBasicStatus(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; return (jint)linphone_presence_service_get_basic_status(service); } @@ -7016,7 +7012,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_getBasicStatus * Method: setBasicStatus * Signature: (JI)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setBasicStatus(JNIEnv *env, jobject jobj, jlong ptr, jint basic_status) { +extern "C" jint Java_org_linphone_core_PresenceServiceImpl_setBasicStatus(JNIEnv *env, jobject jobj, jlong ptr, jint basic_status) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; return (jint)linphone_presence_service_set_basic_status(service, (LinphonePresenceBasicStatus)basic_status); } @@ -7026,7 +7022,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setBasicStatus * Method: getContact * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceServiceImpl_getContact(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresenceServiceImpl_getContact(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; char *ccontact = linphone_presence_service_get_contact(service); jstring jcontact = ccontact ? env->NewStringUTF(ccontact) : NULL; @@ -7039,7 +7035,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceServiceImpl_getContact( * Method: setContact * Signature: (JLjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setContact(JNIEnv *env, jobject jobj, jlong ptr, jstring contact) { +extern "C" jint Java_org_linphone_core_PresenceServiceImpl_setContact(JNIEnv *env, jobject jobj, jlong ptr, jstring contact) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; const char *ccontact = GetStringUTFChars(env, contact); linphone_presence_service_set_contact(service, ccontact); @@ -7052,7 +7048,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_setContact(JNI * Method: getNbNotes * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceServiceImpl_getNbNotes(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresenceServiceImpl_getNbNotes(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; return (jlong)linphone_presence_service_get_nb_notes(service); } @@ -7062,7 +7058,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceServiceImpl_getNbNotes(JN * Method: getNthNote * Signature: (JJ)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceServiceImpl_getNthNote(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { +extern "C" jobject Java_org_linphone_core_PresenceServiceImpl_getNthNote(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; LinphonePresenceNote *note = linphone_presence_service_get_nth_note(service, (unsigned int)idx); if (note == NULL) return NULL; @@ -7074,7 +7070,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresenceServiceImpl_getNthNote( * Method: addNote * Signature: (JJ)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_addNote(JNIEnv *env, jobject jobj, jlong ptr, jlong notePtr) { +extern "C" jint Java_org_linphone_core_PresenceServiceImpl_addNote(JNIEnv *env, jobject jobj, jlong ptr, jlong notePtr) { return (jint)linphone_presence_service_add_note((LinphonePresenceService *)ptr, (LinphonePresenceNote *)notePtr); } @@ -7083,7 +7079,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_addNote(JNIEnv * Method: clearNotes * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_clearNotes(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresenceServiceImpl_clearNotes(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceService *service = (LinphonePresenceService *)ptr; return (jint)linphone_presence_service_clear_notes(service); } @@ -7093,7 +7089,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceServiceImpl_clearNotes(JNI * Method: newPresencePersonImpl * Signature: (Ljava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_newPresencePersonImpl(JNIEnv *env, jobject jobj, jstring id) { +extern "C" jlong Java_org_linphone_core_PresencePersonImpl_newPresencePersonImpl(JNIEnv *env, jobject jobj, jstring id) { LinphonePresencePerson *person; const char *cid = GetStringUTFChars(env, id); person = linphone_presence_person_new(cid); @@ -7107,7 +7103,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_newPresencePer * Method: unref * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PresencePersonImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" void Java_org_linphone_core_PresencePersonImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; linphone_presence_person_unref(person); } @@ -7117,7 +7113,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PresencePersonImpl_unref(JNIEnv *e * Method: getId * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresencePersonImpl_getId(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresencePersonImpl_getId(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; char *cid = linphone_presence_person_get_id(person); jstring jid = cid ? env->NewStringUTF(cid) : NULL; @@ -7130,7 +7126,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresencePersonImpl_getId(JNIEnv * Method: setId * Signature: (JLjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_setId(JNIEnv *env, jobject jobj, jlong ptr, jstring id) { +extern "C" jint Java_org_linphone_core_PresencePersonImpl_setId(JNIEnv *env, jobject jobj, jlong ptr, jstring id) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; const char *cid = GetStringUTFChars(env, id); linphone_presence_person_set_id(person, cid); @@ -7143,7 +7139,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_setId(JNIEnv *e * Method: getNbActivities * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_getNbActivities(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresencePersonImpl_getNbActivities(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; return (jlong)linphone_presence_person_get_nb_activities(person); } @@ -7153,7 +7149,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_getNbActivitie * Method: getNthActivity * Signature: (JJ)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresencePersonImpl_getNthActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { +extern "C" jobject Java_org_linphone_core_PresencePersonImpl_getNthActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; LinphonePresenceActivity *activity = linphone_presence_person_get_nth_activity(person, (unsigned int)idx); if (activity == NULL) return NULL; @@ -7165,7 +7161,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresencePersonImpl_getNthActivi * Method: addActivity * Signature: (JJ)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_addActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong activityPtr) { +extern "C" jint Java_org_linphone_core_PresencePersonImpl_addActivity(JNIEnv *env, jobject jobj, jlong ptr, jlong activityPtr) { return (jint)linphone_presence_person_add_activity((LinphonePresencePerson *)ptr, (LinphonePresenceActivity *)activityPtr); } @@ -7174,7 +7170,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_addActivity(JNI * Method: clearActivities * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_clearActivities(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresencePersonImpl_clearActivities(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; return (jint)linphone_presence_person_clear_activities(person); } @@ -7184,7 +7180,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_clearActivities * Method: getNbNotes * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_getNbNotes(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresencePersonImpl_getNbNotes(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; return (jlong)linphone_presence_person_get_nb_notes(person); } @@ -7194,7 +7190,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_getNbNotes(JNI * Method: getNthNote * Signature: (JJ)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresencePersonImpl_getNthNote(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { +extern "C" jobject Java_org_linphone_core_PresencePersonImpl_getNthNote(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; LinphonePresenceNote *note = linphone_presence_person_get_nth_note(person, (unsigned int)idx); if (note == NULL) return NULL; @@ -7206,7 +7202,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresencePersonImpl_getNthNote(J * Method: addNote * Signature: (JJ)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_addNote(JNIEnv *env, jobject jobj, jlong ptr, jlong notePtr) { +extern "C" jint Java_org_linphone_core_PresencePersonImpl_addNote(JNIEnv *env, jobject jobj, jlong ptr, jlong notePtr) { return (jint)linphone_presence_person_add_note((LinphonePresencePerson *)ptr, (LinphonePresenceNote *)notePtr); } @@ -7215,7 +7211,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_addNote(JNIEnv * Method: clearNotes * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_clearNotes(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresencePersonImpl_clearNotes(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; return (jint)linphone_presence_person_clear_notes(person); } @@ -7225,7 +7221,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_clearNotes(JNIE * Method: getNbActivitiesNotes * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_getNbActivitiesNotes(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jlong Java_org_linphone_core_PresencePersonImpl_getNbActivitiesNotes(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; return (jlong)linphone_presence_person_get_nb_activities_notes(person); } @@ -7235,7 +7231,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresencePersonImpl_getNbActivitie * Method: getNthActivitiesNote * Signature: (JJ)Ljava/lang/Object; */ -JNIEXPORT jobject JNICALL Java_org_linphone_core_PresencePersonImpl_getNthActivitiesNote(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { +extern "C" jobject Java_org_linphone_core_PresencePersonImpl_getNthActivitiesNote(JNIEnv *env, jobject jobj, jlong ptr, jlong idx) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; LinphonePresenceNote *note = linphone_presence_person_get_nth_activities_note(person, (unsigned int)idx); if (note == NULL) return NULL; @@ -7247,7 +7243,7 @@ JNIEXPORT jobject JNICALL Java_org_linphone_core_PresencePersonImpl_getNthActivi * Method: addActivitiesNote * Signature: (JJ)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_addActivitiesNote(JNIEnv *env, jobject jobj, jlong ptr, jlong notePtr) { +extern "C" jint Java_org_linphone_core_PresencePersonImpl_addActivitiesNote(JNIEnv *env, jobject jobj, jlong ptr, jlong notePtr) { return (jint)linphone_presence_person_add_activities_note((LinphonePresencePerson *)ptr, (LinphonePresenceNote *)notePtr); } @@ -7256,7 +7252,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_addActivitiesNo * Method: clearActivitesNotes * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_clearActivitesNotes(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jint Java_org_linphone_core_PresencePersonImpl_clearActivitesNotes(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresencePerson *person = (LinphonePresencePerson *)ptr; return (jint)linphone_presence_person_clear_activities_notes(person); } @@ -7266,7 +7262,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresencePersonImpl_clearActivitesN * Method: newPresenceNoteImpl * Signature: (Ljava/lang/String;Ljava/lang/String;)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceNoteImpl_newPresenceNoteImpl(JNIEnv *env, jobject jobj, jstring content, jstring lang) { +extern "C" jlong Java_org_linphone_core_PresenceNoteImpl_newPresenceNoteImpl(JNIEnv *env, jobject jobj, jstring content, jstring lang) { LinphonePresenceNote *note; const char *ccontent = GetStringUTFChars(env, content); const char *clang = GetStringUTFChars(env, lang); @@ -7282,7 +7278,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_PresenceNoteImpl_newPresenceNoteI * Method: unref * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PresenceNoteImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" void Java_org_linphone_core_PresenceNoteImpl_unref(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceNote *note = (LinphonePresenceNote *)ptr; linphone_presence_note_unref(note); } @@ -7292,7 +7288,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PresenceNoteImpl_unref(JNIEnv *env * Method: getContent * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceNoteImpl_getContent(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresenceNoteImpl_getContent(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceNote *note = (LinphonePresenceNote *)ptr; const char *ccontent = linphone_presence_note_get_content(note); return ccontent ? env->NewStringUTF(ccontent) : NULL; @@ -7303,7 +7299,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceNoteImpl_getContent(JNI * Method: setContent * Signature: (JLjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setContent(JNIEnv *env, jobject jobj, jlong ptr, jstring content) { +extern "C" jint Java_org_linphone_core_PresenceNoteImpl_setContent(JNIEnv *env, jobject jobj, jlong ptr, jstring content) { LinphonePresenceNote *note = (LinphonePresenceNote *)ptr; const char *ccontent = GetStringUTFChars(env, content); linphone_presence_note_set_content(note, ccontent); @@ -7316,7 +7312,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setContent(JNIEnv * Method: getLang * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceNoteImpl_getLang(JNIEnv *env, jobject jobj, jlong ptr) { +extern "C" jstring Java_org_linphone_core_PresenceNoteImpl_getLang(JNIEnv *env, jobject jobj, jlong ptr) { LinphonePresenceNote *note = (LinphonePresenceNote *)ptr; const char *clang = linphone_presence_note_get_lang(note); return clang ? env->NewStringUTF(clang) : NULL; @@ -7327,7 +7323,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PresenceNoteImpl_getLang(JNIEnv * Method: setLang * Signature: (JLjava/lang/String;)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setLang(JNIEnv *env, jobject jobj, jlong ptr, jstring lang) { +extern "C" jint Java_org_linphone_core_PresenceNoteImpl_setLang(JNIEnv *env, jobject jobj, jlong ptr, jstring lang) { LinphonePresenceNote *note = (LinphonePresenceNote *)ptr; const char *clang = GetStringUTFChars(env, lang); linphone_presence_note_set_lang(note, clang); @@ -7340,7 +7336,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_PresenceNoteImpl_setLang(JNIEnv *e * Method: setRecvFmtp * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PayloadTypeImpl_setRecvFmtp(JNIEnv *env, jobject jobj, jlong ptr, jstring jfmtp){ +extern "C" void Java_org_linphone_core_PayloadTypeImpl_setRecvFmtp(JNIEnv *env, jobject jobj, jlong ptr, jstring jfmtp){ PayloadType *pt=(PayloadType *)ptr; const char *fmtp = GetStringUTFChars(env, jfmtp); payload_type_set_recv_fmtp(pt,fmtp); @@ -7352,7 +7348,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PayloadTypeImpl_setRecvFmtp(JNIEnv * Method: getRecvFmtp * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PayloadTypeImpl_getRecvFmtp(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" jstring Java_org_linphone_core_PayloadTypeImpl_getRecvFmtp(JNIEnv *env, jobject jobj, jlong ptr){ PayloadType *pt=(PayloadType *)ptr; const char *fmtp=pt->recv_fmtp; return fmtp ? env->NewStringUTF(fmtp) : NULL; @@ -7363,7 +7359,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_PayloadTypeImpl_getRecvFmtp(JNI * Method: setSendFmtp * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_PayloadTypeImpl_setSendFmtp(JNIEnv *env, jobject jobj, jlong ptr , jstring jfmtp){ +extern "C" void Java_org_linphone_core_PayloadTypeImpl_setSendFmtp(JNIEnv *env, jobject jobj, jlong ptr , jstring jfmtp){ PayloadType *pt=(PayloadType *)ptr; const char *fmtp = GetStringUTFChars(env, jfmtp); payload_type_set_send_fmtp(pt,fmtp); @@ -7375,21 +7371,21 @@ JNIEXPORT void JNICALL Java_org_linphone_core_PayloadTypeImpl_setSendFmtp(JNIEnv * Method: getSendFmtp * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_PayloadTypeImpl_getSendFmtp(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" jstring Java_org_linphone_core_PayloadTypeImpl_getSendFmtp(JNIEnv *env, jobject jobj, jlong ptr){ PayloadType *pt=(PayloadType *)ptr; const char *fmtp=pt->send_fmtp; return fmtp ? env->NewStringUTF(fmtp) : NULL; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableSdp200Ack(JNIEnv* env +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableSdp200Ack(JNIEnv* env ,jobject thiz ,jlong lc ,jboolean enable) { linphone_core_enable_sdp_200_ack((LinphoneCore*)lc,enable); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_isSdp200AckEnabled(JNIEnv* env +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_isSdp200AckEnabled(JNIEnv* env ,jobject thiz ,jlong lc) { return (jboolean)linphone_core_sdp_200_ack_enabled((const LinphoneCore*)lc); @@ -7404,7 +7400,7 @@ extern "C" { * Method: getReason * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_ErrorInfoImpl_getReason(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" jint Java_org_linphone_core_ErrorInfoImpl_getReason(JNIEnv *env, jobject jobj, jlong ei){ return linphone_error_info_get_reason((const LinphoneErrorInfo*)ei); } @@ -7413,7 +7409,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_ErrorInfoImpl_getReason(JNIEnv *en * Method: getProtocolCode * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_ErrorInfoImpl_getProtocolCode(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" jint Java_org_linphone_core_ErrorInfoImpl_getProtocolCode(JNIEnv *env, jobject jobj, jlong ei){ return linphone_error_info_get_protocol_code((const LinphoneErrorInfo*)ei); } @@ -7422,7 +7418,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_ErrorInfoImpl_getProtocolCode(JNIE * Method: getPhrase * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getPhrase(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" jstring Java_org_linphone_core_ErrorInfoImpl_getPhrase(JNIEnv *env, jobject jobj, jlong ei){ const char *tmp=linphone_error_info_get_phrase((const LinphoneErrorInfo*)ei); return tmp ? env->NewStringUTF(tmp) : NULL; } @@ -7432,7 +7428,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getPhrase(JNIEnv * Method: getProtocol * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getProtocol(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" jstring Java_org_linphone_core_ErrorInfoImpl_getProtocol(JNIEnv *env, jobject jobj, jlong ei){ const char *tmp=linphone_error_info_get_protocol((const LinphoneErrorInfo*)ei); return tmp ? env->NewStringUTF(tmp) : NULL; } @@ -7442,7 +7438,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getProtocol(JNIEn * Method: getSubErrorInfo * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_org_linphone_core_ErrorInfoImpl_getSubErrorInfo(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" jlong Java_org_linphone_core_ErrorInfoImpl_getSubErrorInfo(JNIEnv *env, jobject jobj, jlong ei){ return (jlong)linphone_error_info_get_sub_error_info((LinphoneErrorInfo*)ei); } @@ -7451,7 +7447,7 @@ JNIEXPORT jlong JNICALL Java_org_linphone_core_ErrorInfoImpl_getSubErrorInfo(JNI * Method: setReason * Signature: (JI) */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setReason(JNIEnv *env, jobject jobj, jlong ei, jint reason){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_setReason(JNIEnv *env, jobject jobj, jlong ei, jint reason){ linphone_error_info_set_reason((LinphoneErrorInfo*)ei, (LinphoneReason)reason); } @@ -7460,7 +7456,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setReason(JNIEnv *en * Method: getProtocolCode * Signature: (JI) */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setProtocolCode(JNIEnv *env, jobject jobj, jlong ei, jint code){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_setProtocolCode(JNIEnv *env, jobject jobj, jlong ei, jint code){ return linphone_error_info_set_protocol_code((LinphoneErrorInfo*)ei, code); } @@ -7469,7 +7465,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setProtocolCode(JNIE * Method: setPhrase * Signature: (JLjava/lang/String;) */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setPhrase(JNIEnv *env, jobject jobj, jlong ei, jstring phrase){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_setPhrase(JNIEnv *env, jobject jobj, jlong ei, jstring phrase){ const char *tmp = GetStringUTFChars(env,phrase); linphone_error_info_set_phrase((LinphoneErrorInfo*)ei, tmp); if (phrase) ReleaseStringUTFChars(env, phrase, tmp); @@ -7480,7 +7476,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setPhrase(JNIEnv *en * Method: setProtocol * Signature: (JLjava/lang/String;) */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setProtocol(JNIEnv *env, jobject jobj, jlong ei, jstring protocol){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_setProtocol(JNIEnv *env, jobject jobj, jlong ei, jstring protocol){ const char *tmp = GetStringUTFChars(env, protocol); linphone_error_info_set_protocol((LinphoneErrorInfo*)ei, tmp); if (protocol) ReleaseStringUTFChars(env, protocol, tmp); @@ -7492,7 +7488,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setProtocol(JNIEnv * * Method: setWarnings * Signature: (JLjava/lang/String;) */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setWarnings(JNIEnv *env, jobject jobj, jlong ei, jstring warnings){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_setWarnings(JNIEnv *env, jobject jobj, jlong ei, jstring warnings){ const char *tmp = GetStringUTFChars(env, warnings); linphone_error_info_set_warnings((LinphoneErrorInfo*)ei, tmp); if (warnings) ReleaseStringUTFChars(env, warnings, tmp); @@ -7503,7 +7499,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setWarnings(JNIEnv * * Method: setSubErrorInfo * Signature: (JLjava/lang/String;) */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setSubErrorInfo(JNIEnv *env, jobject jobj, jlong ei, jlong sub_ei){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_setSubErrorInfo(JNIEnv *env, jobject jobj, jlong ei, jlong sub_ei){ linphone_error_info_set_sub_error_info((LinphoneErrorInfo*)ei, (LinphoneErrorInfo*)sub_ei); } @@ -7512,7 +7508,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_setSubErrorInfo(JNIE * Method: getDetails * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getDetails(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" jstring Java_org_linphone_core_ErrorInfoImpl_getDetails(JNIEnv *env, jobject jobj, jlong ei){ const char *tmp=linphone_error_info_get_warnings((const LinphoneErrorInfo*)ei); return tmp ? env->NewStringUTF(tmp) : NULL; } @@ -7522,7 +7518,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getDetails(JNIEnv * Method: getDetails * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getWarnings(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" jstring Java_org_linphone_core_ErrorInfoImpl_getWarnings(JNIEnv *env, jobject jobj, jlong ei){ const char *tmp=linphone_error_info_get_warnings((const LinphoneErrorInfo*)ei); return tmp ? env->NewStringUTF(tmp) : NULL; } @@ -7532,7 +7528,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_ErrorInfoImpl_getWarnings(JNIEn * Method: ref * Signature: (J); */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_ref(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_ref(JNIEnv *env, jobject jobj, jlong ei){ linphone_error_info_ref((LinphoneErrorInfo*)ei); } @@ -7541,7 +7537,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_ref(JNIEnv *env, job * Method: unref * Signature: (J); */ -JNIEXPORT void JNICALL Java_org_linphone_core_ErrorInfoImpl_unref(JNIEnv *env, jobject jobj, jlong ei){ +extern "C" void Java_org_linphone_core_ErrorInfoImpl_unref(JNIEnv *env, jobject jobj, jlong ei){ linphone_error_info_unref((LinphoneErrorInfo*)ei); } @@ -7567,7 +7563,7 @@ extern "C" jlong Java_org_linphone_core_LinphoneCoreImpl_createLocalPlayer(JNIEn * Method: setAudioMulticastAddr * Signature: (JLjava/lang/String;)I */ -extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setAudioMulticastAddr +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_setAudioMulticastAddr (JNIEnv * env , jobject, jlong ptr, jstring value) { const char *char_value = GetStringUTFChars(env, value); LinphoneCore *lc=(LinphoneCore*)ptr; @@ -7581,7 +7577,7 @@ extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setAudioMulticas * Method: setVideoMulticastAddr * Signature: (JLjava/lang/String;)I */ -extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setVideoMulticastAddr +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_setVideoMulticastAddr (JNIEnv * env, jobject, jlong ptr, jstring value) { const char *char_value = GetStringUTFChars(env, value); LinphoneCore *lc=(LinphoneCore*)ptr; @@ -7595,7 +7591,7 @@ extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setVideoMulticas * Method: getAudioMulticastAddr * Signature: (J)Ljava/lang/String; */ -extern "C" jstring JNICALL Java_org_linphone_core_LinphoneCoreImpl_getAudioMulticastAddr +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getAudioMulticastAddr (JNIEnv *env , jobject, jlong ptr) { const char *tmp=linphone_core_get_audio_multicast_addr((LinphoneCore*)ptr); return tmp ? env->NewStringUTF(tmp) : NULL; @@ -7606,7 +7602,7 @@ extern "C" jstring JNICALL Java_org_linphone_core_LinphoneCoreImpl_getAudioMulti * Method: getVideoMulticastAddr * Signature: (J)Ljava/lang/String; */ -extern "C" jstring JNICALL Java_org_linphone_core_LinphoneCoreImpl_getVideoMulticastAddr +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getVideoMulticastAddr (JNIEnv * env, jobject, jlong ptr) { const char *tmp=linphone_core_get_video_multicast_addr((LinphoneCore*)ptr); return tmp ? env->NewStringUTF(tmp) : NULL; @@ -7617,7 +7613,7 @@ extern "C" jstring JNICALL Java_org_linphone_core_LinphoneCoreImpl_getVideoMulti * Method: setAudioMulticastTtl * Signature: (JI)I */ -extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setAudioMulticastTtl +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_setAudioMulticastTtl (JNIEnv *, jobject, jlong ptr, jint value) { return linphone_core_set_audio_multicast_ttl((LinphoneCore*)ptr,value); } @@ -7627,7 +7623,7 @@ extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setAudioMulticas * Method: setVideoMulticastTtl * Signature: (JI)I */ -extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setVideoMulticastTtl +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_setVideoMulticastTtl (JNIEnv *, jobject, jlong ptr, jint value) { return linphone_core_set_video_multicast_ttl((LinphoneCore*)ptr,value); } @@ -7637,7 +7633,7 @@ extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_setVideoMulticas * Method: getAudioMulticastTtl * Signature: (J)I */ -extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getAudioMulticastTtl +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getAudioMulticastTtl (JNIEnv *, jobject, jlong ptr) { return linphone_core_get_audio_multicast_ttl((LinphoneCore*)ptr); } @@ -7647,7 +7643,7 @@ extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getAudioMulticas * Method: getVideoMulticastTtl * Signature: (J)I */ -extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getVideoMulticastTtl +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getVideoMulticastTtl (JNIEnv *, jobject, jlong ptr) { return linphone_core_get_video_multicast_ttl((LinphoneCore*)ptr); } @@ -7657,7 +7653,7 @@ extern "C" jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getVideoMulticas * Method: enableAudioMulticast * Signature: (JZ)V */ -extern "C" void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableAudioMulticast +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableAudioMulticast (JNIEnv *, jobject, jlong ptr, jboolean yesno) { return linphone_core_enable_audio_multicast((LinphoneCore*)ptr,yesno); } @@ -7667,7 +7663,7 @@ extern "C" void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableAudioMulti * Method: audioMulticastEnabled * Signature: (J)Z */ -extern "C" jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_audioMulticastEnabled +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_audioMulticastEnabled (JNIEnv *, jobject, jlong ptr) { return linphone_core_audio_multicast_enabled((LinphoneCore*)ptr); } @@ -7677,7 +7673,7 @@ extern "C" jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_audioMultica * Method: enableVideoMulticast * Signature: (JZ)V */ -extern "C" void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableVideoMulticast +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableVideoMulticast (JNIEnv *, jobject, jlong ptr, jboolean yesno) { return linphone_core_enable_video_multicast((LinphoneCore*)ptr,yesno); } @@ -7687,12 +7683,12 @@ extern "C" void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableVideoMulti * Method: videoMulticastEnabled * Signature: (J)Z */ -extern "C" jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_videoMulticastEnabled +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_videoMulticastEnabled (JNIEnv *, jobject, jlong ptr) { return linphone_core_video_multicast_enabled((LinphoneCore*)ptr); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setDnsServers(JNIEnv *env, jobject thiz, jlong lc, jobjectArray servers){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setDnsServers(JNIEnv *env, jobject thiz, jlong lc, jobjectArray servers){ bctbx_list_t *l = NULL; if (servers != NULL){ @@ -7711,21 +7707,21 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setDnsServers(JNI bctbx_list_free_with_data(l, ms_free); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_enableDnsSrv(JNIEnv *env, jobject thiz, jlong lc, jboolean yesno) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_enableDnsSrv(JNIEnv *env, jobject thiz, jlong lc, jboolean yesno) { linphone_core_enable_dns_srv((LinphoneCore *)lc, yesno); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneCoreImpl_dnsSrvEnabled(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jboolean Java_org_linphone_core_LinphoneCoreImpl_dnsSrvEnabled(JNIEnv *env, jobject thiz, jlong lc) { return linphone_core_dns_srv_enabled((LinphoneCore *)lc); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setVideoPreset(JNIEnv *env, jobject thiz, jlong lc, jstring preset) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setVideoPreset(JNIEnv *env, jobject thiz, jlong lc, jstring preset) { const char *char_preset = GetStringUTFChars(env, preset); linphone_core_set_video_preset((LinphoneCore *)lc, char_preset); ReleaseStringUTFChars(env, preset, char_preset); } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneCoreImpl_getVideoPreset(JNIEnv *env, jobject thiz, jlong lc) { +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getVideoPreset(JNIEnv *env, jobject thiz, jlong lc) { const char *tmp = linphone_core_get_video_preset((LinphoneCore *)lc); return tmp ? env->NewStringUTF(tmp) : NULL; } @@ -7743,7 +7739,7 @@ extern "C" jboolean Java_org_linphone_core_LinphoneCallParamsImpl_realTimeTextEn } extern "C" void Java_org_linphone_core_LinphoneChatMessageImpl_putChar(JNIEnv* env ,jobject thiz, jlong ptr, jlong character) { - linphone_chat_message_put_char((LinphoneChatMessage *)ptr, character); + linphone_chat_message_put_char((LinphoneChatMessage *)ptr, (unsigned int)character); } extern "C" void Java_org_linphone_core_LinphoneChatRoomImpl_finalize(JNIEnv* env, jobject thiz, jlong ptr) { @@ -7862,7 +7858,7 @@ static jobject getTunnelConfig(JNIEnv *env, LinphoneTunnelConfig *cfg){ * Method: getHost * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_TunnelConfigImpl_getHost(JNIEnv *env, jobject obj, jlong ptr){ +extern "C" jstring Java_org_linphone_core_TunnelConfigImpl_getHost(JNIEnv *env, jobject obj, jlong ptr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; const char *host = linphone_tunnel_config_get_host(cfg); if (host){ @@ -7876,7 +7872,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_TunnelConfigImpl_getHost(JNIEnv * Method: setHost * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setHost(JNIEnv *env, jobject obj, jlong ptr, jstring jstr){ +extern "C" void Java_org_linphone_core_TunnelConfigImpl_setHost(JNIEnv *env, jobject obj, jlong ptr, jstring jstr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; const char* host = GetStringUTFChars(env, jstr); linphone_tunnel_config_set_host(cfg, host); @@ -7888,7 +7884,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setHost(JNIEnv *e * Method: getPort * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getPort(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" jint Java_org_linphone_core_TunnelConfigImpl_getPort(JNIEnv *env, jobject jobj, jlong ptr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; return linphone_tunnel_config_get_port(cfg); } @@ -7898,7 +7894,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getPort(JNIEnv *e * Method: setPort * Signature: (JI)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setPort(JNIEnv *env, jobject jobj, jlong ptr, jint port){ +extern "C" void Java_org_linphone_core_TunnelConfigImpl_setPort(JNIEnv *env, jobject jobj, jlong ptr, jint port){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; linphone_tunnel_config_set_port(cfg, port); } @@ -7908,7 +7904,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setPort(JNIEnv *e * Method: getHost * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_TunnelConfigImpl_getHost2(JNIEnv *env, jobject obj, jlong ptr){ +extern "C" jstring Java_org_linphone_core_TunnelConfigImpl_getHost2(JNIEnv *env, jobject obj, jlong ptr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; const char *host = linphone_tunnel_config_get_host2(cfg); if (host){ @@ -7922,7 +7918,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_TunnelConfigImpl_getHost2(JNIEn * Method: setHost * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setHost2(JNIEnv *env, jobject obj, jlong ptr, jstring jstr){ +extern "C" void Java_org_linphone_core_TunnelConfigImpl_setHost2(JNIEnv *env, jobject obj, jlong ptr, jstring jstr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; const char* host = GetStringUTFChars(env, jstr); linphone_tunnel_config_set_host2(cfg, host); @@ -7934,7 +7930,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setHost2(JNIEnv * * Method: getPort * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getPort2(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" jint Java_org_linphone_core_TunnelConfigImpl_getPort2(JNIEnv *env, jobject jobj, jlong ptr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; return linphone_tunnel_config_get_port2(cfg); } @@ -7944,7 +7940,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getPort2(JNIEnv * * Method: setPort * Signature: (JI)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setPort2(JNIEnv *env, jobject jobj, jlong ptr, jint port){ +extern "C" void Java_org_linphone_core_TunnelConfigImpl_setPort2(JNIEnv *env, jobject jobj, jlong ptr, jint port){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; linphone_tunnel_config_set_port2(cfg, port); } @@ -7954,7 +7950,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setPort2(JNIEnv * * Method: getRemoteUdpMirrorPort * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getRemoteUdpMirrorPort(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" jint Java_org_linphone_core_TunnelConfigImpl_getRemoteUdpMirrorPort(JNIEnv *env, jobject jobj, jlong ptr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; return linphone_tunnel_config_get_remote_udp_mirror_port(cfg); } @@ -7964,7 +7960,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getRemoteUdpMirro * Method: setRemoteUdpMirrorPort * Signature: (JI)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setRemoteUdpMirrorPort(JNIEnv *env, jobject jobj, jlong ptr, jint port){ +extern "C" void Java_org_linphone_core_TunnelConfigImpl_setRemoteUdpMirrorPort(JNIEnv *env, jobject jobj, jlong ptr, jint port){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; linphone_tunnel_config_set_remote_udp_mirror_port(cfg, port); } @@ -7974,7 +7970,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setRemoteUdpMirro * Method: getDelay * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getDelay(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" jint Java_org_linphone_core_TunnelConfigImpl_getDelay(JNIEnv *env, jobject jobj, jlong ptr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; return linphone_tunnel_config_get_delay(cfg); } @@ -7984,7 +7980,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_TunnelConfigImpl_getDelay(JNIEnv * * Method: setDelay * Signature: (JI)I */ -JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setDelay(JNIEnv *env, jobject jobj, jlong ptr, jint delay){ +extern "C" void Java_org_linphone_core_TunnelConfigImpl_setDelay(JNIEnv *env, jobject jobj, jlong ptr, jint delay){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; linphone_tunnel_config_set_delay(cfg, delay); } @@ -7994,7 +7990,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_setDelay(JNIEnv * * Method: destroy * Signature: (J)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_destroy(JNIEnv *env, jobject jobj, jlong ptr){ +extern "C" void Java_org_linphone_core_TunnelConfigImpl_destroy(JNIEnv *env, jobject jobj, jlong ptr){ LinphoneTunnelConfig *cfg = (LinphoneTunnelConfig *)ptr; linphone_tunnel_config_set_user_data(cfg, NULL); linphone_tunnel_config_unref(cfg); @@ -8006,7 +8002,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_TunnelConfigImpl_destroy(JNIEnv *e * Method: getCallId * Signature: (J)I */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneCallLogImpl_getCallId(JNIEnv *env, jobject jobj, jlong pcl){ +extern "C" jstring Java_org_linphone_core_LinphoneCallLogImpl_getCallId(JNIEnv *env, jobject jobj, jlong pcl){ const char *str = linphone_call_log_get_call_id((LinphoneCallLog*)pcl); return str ? env->NewStringUTF(str) : NULL; } @@ -8016,7 +8012,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneCallLogImpl_getCallId(J * Method: setHttpProxyHost * Signature: (JLjava/lang/String;)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setHttpProxyHost(JNIEnv *env, jobject jobj, jlong core, jstring jhost){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setHttpProxyHost(JNIEnv *env, jobject jobj, jlong core, jstring jhost){ const char *host = GetStringUTFChars(env, jhost); linphone_core_set_http_proxy_host((LinphoneCore*)core, host); ReleaseStringUTFChars(env, jhost, host); @@ -8027,7 +8023,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setHttpProxyHost( * Method: setHttpProxyPort * Signature: (JI)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setHttpProxyPort(JNIEnv *env, jobject jobj, jlong core, jint port){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setHttpProxyPort(JNIEnv *env, jobject jobj, jlong core, jint port){ linphone_core_set_http_proxy_port((LinphoneCore*)core, port); } @@ -8036,7 +8032,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setHttpProxyPort( * Method: getHttpProxyHost * Signature: (J)Ljava/lang/String; */ -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneCoreImpl_getHttpProxyHost(JNIEnv *env , jobject jobj, jlong core){ +extern "C" jstring Java_org_linphone_core_LinphoneCoreImpl_getHttpProxyHost(JNIEnv *env , jobject jobj, jlong core){ const char * host = linphone_core_get_http_proxy_host((LinphoneCore *)core); return host ? env->NewStringUTF(host) : NULL; } @@ -8046,7 +8042,7 @@ JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneCoreImpl_getHttpProxyHo * Method: getHttpProxyPort * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getHttpProxyPort(JNIEnv *env, jobject jobj, jlong core){ +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getHttpProxyPort(JNIEnv *env, jobject jobj, jlong core){ return linphone_core_get_http_proxy_port((LinphoneCore *)core); } @@ -8056,7 +8052,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getHttpProxyPort( * Method: setSipTransportTimeout * Signature: (JI)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setSipTransportTimeout(JNIEnv *env, jobject jobj, jlong pcore, jint timeout){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setSipTransportTimeout(JNIEnv *env, jobject jobj, jlong pcore, jint timeout){ linphone_core_set_sip_transport_timeout((LinphoneCore*)pcore, timeout); } @@ -8065,7 +8061,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setSipTransportTi * Method: getSipTransportTimeout * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getSipTransportTimeout(JNIEnv *env, jobject jobj, jlong pcore){ +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getSipTransportTimeout(JNIEnv *env, jobject jobj, jlong pcore){ return linphone_core_get_sip_transport_timeout((LinphoneCore*)pcore); } @@ -8074,7 +8070,7 @@ JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getSipTransportTi * Method: setNortpTimeout * Signature: (JI)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setNortpTimeout(JNIEnv *env, jobject obj, jlong core, jint timeout){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setNortpTimeout(JNIEnv *env, jobject obj, jlong core, jint timeout){ linphone_core_set_nortp_timeout((LinphoneCore*)core, timeout); } @@ -8083,7 +8079,7 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setNortpTimeout(J * Method: getNortpTimeout * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_org_linphone_core_LinphoneCoreImpl_getNortpTimeout(JNIEnv *env, jobject obj, jlong core){ +extern "C" jint Java_org_linphone_core_LinphoneCoreImpl_getNortpTimeout(JNIEnv *env, jobject obj, jlong core){ return linphone_core_get_nortp_timeout((LinphoneCore*)core); } @@ -8121,11 +8117,11 @@ extern "C" jobjectArray Java_org_linphone_core_LinphoneConferenceImpl_getPartici int i; participants = linphone_conference_get_participants((LinphoneConference *)pconference); - jaddr_list = env->NewObjectArray(bctbx_list_size(participants), addr_class, NULL); + jaddr_list = env->NewObjectArray((int)bctbx_list_size(participants), addr_class, NULL); for(it=participants, i=0; it; it=bctbx_list_next(it), i++) { LinphoneAddress *addr = (LinphoneAddress *)it->data; jobject jaddr = env->NewObject(addr_class, addr_constructor, (jlong)addr); - env->SetObjectArrayElement(jaddr_list, i, jaddr); + env->SetObjectArrayElement(jaddr_list, (int)i, jaddr); } bctbx_list_free(participants); return jaddr_list; @@ -8142,7 +8138,7 @@ extern "C" jint Java_org_linphone_core_LinphoneConferenceImpl_removeParticipant( * Method: setSipNetworkReachable * Signature: (JZ)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setSipNetworkReachable(JNIEnv *env, jobject jobj, jlong pcore, jboolean reachable){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setSipNetworkReachable(JNIEnv *env, jobject jobj, jlong pcore, jboolean reachable){ linphone_core_set_sip_network_reachable((LinphoneCore*)pcore, (bool_t) reachable); } @@ -8151,97 +8147,97 @@ JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setSipNetworkReac * Method: setMediaNetworkReachable * Signature: (JZ)V */ -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setMediaNetworkReachable(JNIEnv *env, jobject jobj, jlong pcore, jboolean reachable){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setMediaNetworkReachable(JNIEnv *env, jobject jobj, jlong pcore, jboolean reachable){ linphone_core_set_media_network_reachable((LinphoneCore*)pcore, (bool_t) reachable); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_setUserCertificatesPath(JNIEnv *env, jobject jobj, jlong pcore, jstring jpath){ +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_setUserCertificatesPath(JNIEnv *env, jobject jobj, jlong pcore, jstring jpath){ const char *path = GetStringUTFChars(env, jpath); linphone_core_set_user_certificates_path((LinphoneCore*)pcore, path); ReleaseStringUTFChars(env, jpath, path); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_reloadMsPlugins(JNIEnv *env, jobject jobj, jlong pcore, jstring jpath) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_reloadMsPlugins(JNIEnv *env, jobject jobj, jlong pcore, jstring jpath) { const char *path = GetStringUTFChars(env, jpath); linphone_core_reload_ms_plugins((LinphoneCore*)pcore, path); ReleaseStringUTFChars(env, jpath, path); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneCoreImpl_reloadSoundDevices(JNIEnv *env, jobject jobj, jlong pcore) { +extern "C" void Java_org_linphone_core_LinphoneCoreImpl_reloadSoundDevices(JNIEnv *env, jobject jobj, jlong pcore) { linphone_core_reload_sound_devices((LinphoneCore*)pcore); } -JNIEXPORT jobject JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_getCore(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" jobject Java_org_linphone_core_LinphoneNatPolicyImpl_getCore(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneCore *lc = ((LinphoneNatPolicy *)jNatPolicy)->lc; LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_core_get_user_data(lc); return ljb->getCore(); } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_clear(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" void Java_org_linphone_core_LinphoneNatPolicyImpl_clear(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; linphone_nat_policy_clear(nat_policy); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_stunEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" jboolean Java_org_linphone_core_LinphoneNatPolicyImpl_stunEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; return (linphone_nat_policy_stun_enabled(nat_policy) == FALSE) ? JNI_FALSE : JNI_TRUE; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_enableStun(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { +extern "C" void Java_org_linphone_core_LinphoneNatPolicyImpl_enableStun(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; linphone_nat_policy_enable_stun(nat_policy, (jEnable == JNI_FALSE) ? FALSE : TRUE); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_turnEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" jboolean Java_org_linphone_core_LinphoneNatPolicyImpl_turnEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; return (linphone_nat_policy_turn_enabled(nat_policy) == FALSE) ? JNI_FALSE : JNI_TRUE; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_enableTurn(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { +extern "C" void Java_org_linphone_core_LinphoneNatPolicyImpl_enableTurn(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; linphone_nat_policy_enable_turn(nat_policy, (jEnable == JNI_FALSE) ? FALSE : TRUE); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_iceEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" jboolean Java_org_linphone_core_LinphoneNatPolicyImpl_iceEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; return (linphone_nat_policy_ice_enabled(nat_policy) == FALSE) ? JNI_FALSE : JNI_TRUE; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_enableIce(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { +extern "C" void Java_org_linphone_core_LinphoneNatPolicyImpl_enableIce(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; linphone_nat_policy_enable_ice(nat_policy, (jEnable == JNI_FALSE) ? FALSE : TRUE); } -JNIEXPORT jboolean JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_upnpEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" jboolean Java_org_linphone_core_LinphoneNatPolicyImpl_upnpEnabled(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; return (linphone_nat_policy_upnp_enabled(nat_policy) == FALSE) ? JNI_FALSE : JNI_TRUE; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_enableUpnp(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { +extern "C" void Java_org_linphone_core_LinphoneNatPolicyImpl_enableUpnp(JNIEnv *env, jobject thiz, jlong jNatPolicy, jboolean jEnable) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; linphone_nat_policy_enable_upnp(nat_policy, (jEnable == JNI_FALSE) ? FALSE : TRUE); } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_getStunServer(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" jstring Java_org_linphone_core_LinphoneNatPolicyImpl_getStunServer(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; const char *stun_server = linphone_nat_policy_get_stun_server(nat_policy); return (stun_server != NULL) ? env->NewStringUTF(stun_server) : NULL; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_setStunServer(JNIEnv *env, jobject thiz, jlong jNatPolicy, jstring jStunServer) { +extern "C" void Java_org_linphone_core_LinphoneNatPolicyImpl_setStunServer(JNIEnv *env, jobject thiz, jlong jNatPolicy, jstring jStunServer) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; const char *stun_server = GetStringUTFChars(env, jStunServer); linphone_nat_policy_set_stun_server(nat_policy, stun_server); ReleaseStringUTFChars(env, jStunServer, stun_server); } -JNIEXPORT jstring JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_getStunServerUsername(JNIEnv *env, jobject thiz, jlong jNatPolicy) { +extern "C" jstring Java_org_linphone_core_LinphoneNatPolicyImpl_getStunServerUsername(JNIEnv *env, jobject thiz, jlong jNatPolicy) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; const char *stun_server = linphone_nat_policy_get_stun_server_username(nat_policy); return (stun_server != NULL) ? env->NewStringUTF(stun_server) : NULL; } -JNIEXPORT void JNICALL Java_org_linphone_core_LinphoneNatPolicyImpl_setStunServerUsername(JNIEnv *env, jobject thiz, jlong jNatPolicy, jstring jStunServerUsername) { +extern "C" void Java_org_linphone_core_LinphoneNatPolicyImpl_setStunServerUsername(JNIEnv *env, jobject thiz, jlong jNatPolicy, jstring jStunServerUsername) { LinphoneNatPolicy *nat_policy = (LinphoneNatPolicy *)jNatPolicy; const char *stun_server_username = GetStringUTFChars(env, jStunServerUsername); linphone_nat_policy_set_stun_server_username(nat_policy, stun_server_username); diff --git a/coreapi/localplayer.c b/coreapi/localplayer.c index 88ecc06a8..8984eda1d 100644 --- a/coreapi/localplayer.c +++ b/coreapi/localplayer.c @@ -88,7 +88,6 @@ static int _local_player_get_current_position(LinphonePlayer *obj) { static void _local_player_destroy(LinphonePlayer *obj) { ms_media_player_free((MSMediaPlayer *)obj->impl); - _linphone_player_destroy(obj); } static void _local_player_close(LinphonePlayer *obj) { diff --git a/coreapi/logging.c b/coreapi/logging.c index 47da6b514..f707a37dc 100644 --- a/coreapi/logging.c +++ b/coreapi/logging.c @@ -17,13 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include #include -#include -#include +#include + #include +#include +#include + #include "linphone/logging.h" -#include "private.h" + +#include "c-wrapper/c-wrapper.h" #include "logging-private.h" @@ -69,7 +72,7 @@ LinphoneLogLevel _bctbx_log_level_to_linphone_log_level(BctbxLogLevel level) { if (response != tmap.cend()) { return response->first; } else { - ms_fatal("%s(): invalid argument [%d]", __FUNCTION__, level); + ms_warning("%s(): invalid argurement [%d]", __FUNCTION__, level); return LinphoneLogLevelDebug; } } @@ -84,7 +87,7 @@ unsigned int _bctbx_log_mask_to_linphone_log_mask(unsigned int mask) { } } if (mask != 0) { - ms_warning("%s(): invalid flag set in mask [%x]", __FUNCTION__, mask); + ms_fatal("%s(): invalid flag set in mask [%x]", __FUNCTION__, mask); } return res; } @@ -124,6 +127,7 @@ static void _log_handler_on_message_written_cb(void *info,const char *domain, Bc static void _log_handler_destroy_cb(bctbx_log_handler_t *handler) { LinphoneLoggingService *service = (LinphoneLoggingService *)bctbx_log_handler_get_user_data(handler); + bctbx_free(service->log_handler); service->log_handler = NULL; } @@ -132,7 +136,6 @@ static LinphoneLoggingService *_linphone_logging_service_new(void) { service->log_handler = bctbx_create_log_handler(_log_handler_on_message_written_cb, _log_handler_destroy_cb, service); service->cbs = _linphone_logging_service_cbs_new(); bctbx_add_log_handler(service->log_handler); - return service; } @@ -156,11 +159,12 @@ LinphoneLoggingService *linphone_logging_service_ref(LinphoneLoggingService *ser } void linphone_logging_service_unref(LinphoneLoggingService *service) { - belle_sip_object_ref(service); + belle_sip_object_unref(service); } static void _linphone_logging_service_uninit(LinphoneLoggingService *log_service) { - if (log_service->log_handler) bctbx_remove_log_handler(log_service->log_handler); + if (log_service->log_handler) + bctbx_remove_log_handler(log_service->log_handler); linphone_logging_service_cbs_unref(log_service->cbs); } @@ -177,11 +181,11 @@ LinphoneLoggingServiceCbs *linphone_logging_service_get_callbacks(const Linphone static const char *_linphone_logging_service_log_domains[] = { "bctbx", + "belle-sip", "ortp", - "bzrtp", "mediastreamer", - BELLE_SIP_LOG_DOMAIN, - BCTBX_LOG_DOMAIN, + "bzrtp", + BCTBX_LOG_DOMAIN, /* which is "liblinphone", set from CMakeList.txt*/ NULL }; @@ -195,7 +199,7 @@ void linphone_logging_service_set_log_level(LinphoneLoggingService *log_service, void linphone_logging_service_set_log_level_mask(LinphoneLoggingService *log_service, unsigned int mask) { const char **domain; for (domain=_linphone_logging_service_log_domains; *domain; domain++) { - bctbx_set_log_level_mask(*domain, _linphone_log_mask_to_bctbx_log_mask(mask)); + bctbx_set_log_level_mask(*domain, (int)_linphone_log_mask_to_bctbx_log_mask(mask)); } } @@ -236,10 +240,9 @@ void linphone_logging_service_cbs_unref(LinphoneLoggingServiceCbs *cbs) { } void linphone_logging_service_cbs_set_log_message_written(LinphoneLoggingServiceCbs *cbs, LinphoneLoggingServiceCbsLogMessageWrittenCb cb) { - /* We need to set the legacy log handler to NULL here - because LinphoneCore have a default log handler that dump - all messages into the standard output. */ + because LinphoneCore have a default log handler that dump + all messages into the standard output. */ /*this function is moved here to make sure default log handler is only removed when user defined logging cbs is set*/ _linphone_core_set_log_handler(NULL); cbs->message_event_cb = cb; @@ -253,6 +256,10 @@ void linphone_logging_service_cbs_set_user_data(LinphoneLoggingServiceCbs *cbs, cbs->user_data = user_data; } +void *linphone_logging_service_cbs_get_user_data(const LinphoneLoggingServiceCbs *cbs) { + return cbs->user_data; +} + BELLE_SIP_INSTANCIATE_VPTR(LinphoneLoggingServiceCbs, belle_sip_object_t, NULL, // uninit NULL, // clone diff --git a/coreapi/lpc2xml.c b/coreapi/lpc2xml.c index b15186027..52f1f2dd8 100644 --- a/coreapi/lpc2xml.c +++ b/coreapi/lpc2xml.c @@ -31,8 +31,8 @@ static xmlChar* convert_iso_to_utf8(const char *in) { int ret, size, out_size, temp; xmlCharEncodingHandlerPtr handler; - size = (int)strlen(in) + 1; - out_size = size * 2 - 1; + size = (int)strlen(in) + 1; + out_size = size * 2 - 1; out = reinterpret_cast(ms_malloc((size_t)out_size)); if (out) { @@ -41,19 +41,19 @@ static xmlChar* convert_iso_to_utf8(const char *in) { ms_free(out); return NULL; } - + temp = size-1; ret = handler->input(out, &out_size, (const xmlChar *)in, &temp); if (ret < 0 || temp - size + 1) { ms_free(out); return NULL; } else { - out = reinterpret_cast(ms_realloc(out, out_size + 1)); + out = reinterpret_cast(ms_realloc(out, (size_t)out_size + 1)); out[out_size] = '\0'; } } return out; -} +} struct _lpc2xml_context { const LpConfig *lpc; @@ -131,7 +131,7 @@ static int processEntry(const char *section, const char *entry, xmlNode *node, l } lpc2xml_log(ctx, LPC2XML_MESSAGE, "Set %s|%s = %s", section, entry, content); converted_content = convert_iso_to_utf8(content); - + if (converted_content) { // xmlNodeSetContent expects special characters to be escaped, xmlNodeAddContent doesn't (and escapes what needs to be) xmlNodeSetContent(node, (const xmlChar *) ""); @@ -142,7 +142,7 @@ static int processEntry(const char *section, const char *entry, xmlNode *node, l xmlNodeSetContent(node, (const xmlChar *) ""); xmlNodeAddContent(node, (const xmlChar *) content); } - + if (lp_config_get_overwrite_flag_for_entry(ctx->lpc, section, entry) || lp_config_get_overwrite_flag_for_section(ctx->lpc, section)) { xmlSetProp(node, (const xmlChar *)"overwrite", (const xmlChar *) "true"); } @@ -166,7 +166,7 @@ static void processSection_cb(const char *entry, struct __processSectionCtx *ctx ctx->ret = 0; return; } - + if (lp_config_get_skip_flag_for_entry(ctx->ctx->lpc, ctx->section, entry)) { lpc2xml_log(ctx->ctx, LPC2XML_WARNING, "Skipped entry %s", entry); ctx->ret = 0; @@ -208,13 +208,13 @@ static void processConfig_cb(const char *section, struct __processConfigCtx *ctx if(ctx->ret == 0) { xmlNode *node; xmlAttr *name_attr; - + if (lp_config_get_skip_flag_for_section(ctx->ctx->lpc, section)) { lpc2xml_log(ctx->ctx, LPC2XML_WARNING, "Skipped section %s", section); ctx->ret = 0; return; } - + node = xmlNewChild(ctx->node, NULL, (const xmlChar *)"section", NULL); if(node == NULL) { lpc2xml_log(ctx->ctx, LPC2XML_ERROR, "Can't create \"section\" element"); @@ -299,7 +299,7 @@ int lpc2xml_convert_file(lpc2xml_context* context, const char *filename) { if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { - ret = xmlSaveDoc(save_ctx, context->doc); + ret = (int)xmlSaveDoc(save_ctx, context->doc); if(ret != 0) { lpc2xml_log(context, LPC2XML_ERROR, "Can't save document"); lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); @@ -322,7 +322,7 @@ int lpc2xml_convert_fd(lpc2xml_context* context, int fd) { if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { - ret = xmlSaveDoc(save_ctx, context->doc); + ret = (int)xmlSaveDoc(save_ctx, context->doc); if(ret != 0) { lpc2xml_log(context, LPC2XML_ERROR, "Can't save document"); lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); @@ -346,7 +346,7 @@ int lpc2xml_convert_string(lpc2xml_context* context, char **content) { if(save_ctx != NULL) { ret = internal_convert_lpc2xml(context); if(ret == 0) { - ret = xmlSaveDoc(save_ctx, context->doc); + ret = (int)xmlSaveDoc(save_ctx, context->doc); if(ret != 0) { lpc2xml_log(context, LPC2XML_ERROR, "Can't save document"); lpc2xml_log(context, LPC2XML_ERROR, "%s", context->errorBuffer); diff --git a/coreapi/lpconfig.c b/coreapi/lpconfig.c index 4c496a423..66c8c6e67 100644 --- a/coreapi/lpconfig.c +++ b/coreapi/lpconfig.c @@ -24,7 +24,6 @@ #define MAX_LEN 16384 -#include "private.h" #include "bctoolbox/vfs.h" #include "belle-sip/object.h" #include "xml2lpc.h" @@ -61,6 +60,8 @@ #include "linphone/lpconfig.h" #include "lpc2xml.h" +#include "c-wrapper/c-wrapper.h" + typedef struct _LpItem{ char *key; char *value; @@ -647,7 +648,6 @@ bool_t linphone_config_get_range(const LpConfig *lpconfig, const char *section, } } - int linphone_config_get_int(const LpConfig *lpconfig,const char *section, const char *key, int default_value){ const char *str=linphone_config_get_string(lpconfig,section,key,NULL); if (str!=NULL) { @@ -662,6 +662,16 @@ int linphone_config_get_int(const LpConfig *lpconfig,const char *section, const else return default_value; } +bool_t linphone_config_get_bool(const LpConfig *lpconfig, const char *section, const char *key, bool_t default_value) { + const char *str = linphone_config_get_string(lpconfig, section, key, NULL); + if (str != NULL) { + int ret = 0; + sscanf(str, "%i", &ret); + return ret != 0; + } + return default_value; +} + int64_t linphone_config_get_int64(const LpConfig *lpconfig,const char *section, const char *key, int64_t default_value){ const char *str=linphone_config_get_string(lpconfig,section,key,NULL); if (str!=NULL) { @@ -774,6 +784,14 @@ void linphone_config_set_int(LpConfig *lpconfig,const char *section, const char linphone_config_set_string(lpconfig,section,key,tmp); } +void linphone_config_set_bool(LpConfig *lpconfig, const char *section, const char *key, bool_t value) { + if (value) { + linphone_config_set_int(lpconfig, section, key, 1); + } else { + linphone_config_set_int(lpconfig, section, key, 0); + } +} + void linphone_config_set_int_hex(LpConfig *lpconfig,const char *section, const char *key, int value){ char tmp[30]; snprintf(tmp,sizeof(tmp),"0x%x",value); @@ -832,11 +850,11 @@ void linphone_config_set_skip_flag_for_section(LpConfig *lpconfig, const char *s void lp_item_write(LpItem *item, LpConfig *lpconfig){ int ret =-1 ; if (item->is_comment){ - ret =bctbx_file_fprintf(lpconfig->pFile, 0, "%s\n",item->value); + ret = (int)bctbx_file_fprintf(lpconfig->pFile, 0, "%s\n",item->value); } else if (item->value && item->value[0] != '\0' ){ - ret =bctbx_file_fprintf(lpconfig->pFile, 0, "%s=%s\n",item->key,item->value); + ret = (int)bctbx_file_fprintf(lpconfig->pFile, 0, "%s=%s\n",item->key,item->value); } else { @@ -1126,6 +1144,19 @@ const char** linphone_config_get_sections_names(LpConfig *lpconfig) { return sections_names; } +const bctbx_list_t * linphone_config_get_sections_names_list(LpConfig *lpconfig) { + const bctbx_list_t *sections = lpconfig->sections; + bctbx_list_t *sections_names = NULL; + int i; + + for (i = 0; sections != NULL; sections = sections->next, i++) { + LpSection *section = (LpSection *)sections->data; + sections_names = bctbx_list_append(sections_names, section->name); + } + + return sections_names; +} + char* linphone_config_dump_as_xml(const LpConfig *lpconfig) { char *buffer; diff --git a/coreapi/message_storage.c b/coreapi/message_storage.c deleted file mode 100644 index 2060f57ed..000000000 --- a/coreapi/message_storage.c +++ /dev/null @@ -1,950 +0,0 @@ -/* -message_storage.c -Copyright (C) 2012 Belledonne Communications, Grenoble, France - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "private.h" -#include "linphone/core.h" -#include "bctoolbox/charconv.h" - -#ifdef SQLITE_STORAGE_ENABLED - -#include "sqlite3.h" -#include - - -int _linphone_sqlite3_open(const char *db_file, sqlite3 **db) { - char* errmsg = NULL; - int ret; - int flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE; - -#if TARGET_OS_IPHONE - /* the secured filesystem of the iPHone doesn't allow writing while the app is in background mode, which is problematic. - * We workaround by asking that the open is made with no protection*/ - flags |= SQLITE_OPEN_FILEPROTECTION_NONE; -#endif - - /*since we plug our vfs into sqlite, we convert to UTF-8. - * On Windows, the filename has to be converted back to windows native charset.*/ - char *utf8_filename = bctbx_locale_to_utf8(db_file); - ret = sqlite3_open_v2(utf8_filename, db, flags, LINPHONE_SQLITE3_VFS); - ms_free(utf8_filename); - - if (ret != SQLITE_OK) return ret; - // Some platforms do not provide a way to create temporary files which are needed - // for transactions... so we work in memory only - // see http ://www.sqlite.org/compile.html#temp_store - ret = sqlite3_exec(*db, "PRAGMA temp_store=MEMORY", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - ms_error("Cannot set sqlite3 temporary store to memory: %s.", errmsg); - sqlite3_free(errmsg); - } - - /* the lines below have been disabled because they are likely an - * outdated hack */ -#if 0 && TARGET_OS_IPHONE - ret = sqlite3_exec(*db, "PRAGMA journal_mode = OFF", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - ms_error("Cannot set sqlite3 journal_mode to off: %s.", errmsg); - sqlite3_free(errmsg); - } -#endif - return ret; -} -#endif - - - -#ifdef SQLITE_STORAGE_ENABLED - - -static LinphoneChatMessage * get_weak_message(LinphoneChatRoom *cr, unsigned int storage_id) { - LinphoneChatMessage *cm; - bctbx_list_t *item; - for (item = cr->weak_messages; item != NULL; item = bctbx_list_next(item)) { - cm = (LinphoneChatMessage *)bctbx_list_get_data(item); - if (linphone_chat_message_get_storage_id(cm) == storage_id) - return linphone_chat_message_ref(cm); - } - return NULL; -} - -static ORTP_INLINE LinphoneChatMessage* get_transient_message(LinphoneChatRoom* cr, unsigned int storage_id){ - bctbx_list_t* transients = cr->transient_messages; - LinphoneChatMessage* chat; - while( transients ){ - chat = (LinphoneChatMessage*)transients->data; - if(chat->storage_id == storage_id){ - return linphone_chat_message_ref(chat); - } - transients = transients->next; - } - return NULL; -} - -/* DB layout: - * | 0 | storage_id - * | 1 | type - * | 2 | subtype - * | 3 | name - * | 4 | encoding - * | 5 | size - * | 6 | data (currently not stored) - * | 7 | key size - * | 8 | key - */ -// 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_unref(message->file_transfer_information); - message->file_transfer_information = NULL; - } - message->file_transfer_information = linphone_content_new(); - if (argv[1]) linphone_content_set_type(message->file_transfer_information, argv[1]); - if (argv[2]) linphone_content_set_subtype(message->file_transfer_information, argv[2]); - if (argv[3]) linphone_content_set_name(message->file_transfer_information, argv[3]); - if (argv[4]) linphone_content_set_encoding(message->file_transfer_information, argv[4]); - linphone_content_set_size(message->file_transfer_information, (size_t)atoi(argv[5])); - if (argv[8]) linphone_content_set_key(message->file_transfer_information, argv[8], (size_t)atol(argv[7])); - - 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); -} - - - -// Called when fetching all conversations from database -static int callback_all(void *data, int argc, char **argv, char **colName){ - LinphoneCore* lc = (LinphoneCore*) data; - char* address = argv[0]; - LinphoneAddress *addr = linphone_address_new(address); - if (addr){ - linphone_core_get_chat_room(lc, addr); - linphone_address_unref(addr); - } - return 0; -} - -/* DB layout: - * | 0 | storage_id - * | 1 | localContact - * | 2 | remoteContact - * | 3 | direction flag (LinphoneChatMessageDir) - * | 4 | message (text content of the message) - * | 5 | time (unused now, used to be string-based timestamp, replaced by the utc timestamp) - * | 6 | read flag (no longer used, replaced by the LinphoneChatMessageStateDisplayed state) - * | 7 | status (LinphoneChatMessageState) - * | 8 | external body url (deprecated file transfer system) - * | 9 | utc timestamp - * | 10 | app data text - * | 11 | linphone content id (LinphoneContent describing a file transfer) - * | 12 | message id (used for IMDN) - * | 13 | content type (of the message field [must be text representable]) - * | 14 | secured flag - */ -static int create_chat_message(void *data, int argc, char **argv, char **colName){ - LinphoneChatRoom *cr = (LinphoneChatRoom *)data; - unsigned int storage_id = (unsigned int)atoi(argv[0]); - LinphoneChatMessage* new_message; - - /* Check if the message exists in the weak messages list, in which case we should return that one. */ - new_message = get_weak_message(cr, storage_id); - if (new_message == NULL) { - /* Check if the message exists in the transient list, in which case we should return that one. */ - new_message = get_transient_message(cr, storage_id); - } - if (new_message == NULL) { - new_message = linphone_chat_room_create_message_without_conversion(cr, argv[4]); - - if(atoi(argv[3])==LinphoneChatMessageIncoming){ - new_message->dir=LinphoneChatMessageIncoming; - linphone_chat_message_set_from(new_message,linphone_chat_room_get_peer_address(cr)); - new_message->to = NULL; /*will be filled at the end */ - } else { - new_message->dir=LinphoneChatMessageOutgoing; - new_message->from = NULL; /*will be filled at the end */ - linphone_chat_message_set_to(new_message,linphone_chat_room_get_peer_address(cr)); - } - - new_message->time = (time_t)atol(argv[9]); - new_message->is_read=atoi(argv[6]); - new_message->state=static_cast(atoi(argv[7])); - new_message->storage_id=storage_id; - new_message->external_body_url= ms_strdup(argv[8]); - new_message->appdata = ms_strdup(argv[10]); - new_message->message_id = ms_strdup(argv[12]); - linphone_chat_message_set_content_type(new_message, argv[13]); - new_message->is_secured = (bool_t)atoi(argv[14]); - - if (argv[11] != NULL) { - int id = atoi(argv[11]); - if (id >= 0) { - fetch_content_from_database(cr->lc->db, new_message, id); - } - } - - /* Fix content type for old messages that were stored without it */ - if (new_message->content_type == NULL) { - if (new_message->file_transfer_information != NULL) { - new_message->content_type = ms_strdup("application/vnd.gsma.rcs-ft-http+xml"); - } else if (new_message->external_body_url != NULL) { - new_message->content_type = ms_strdup("message/external-body"); - } else { - new_message->content_type = ms_strdup("text/plain"); - } - } - - /* Add the new message to the weak messages list. */ - linphone_chat_room_add_weak_message(cr, new_message); - } - cr->messages_hist=bctbx_list_prepend(cr->messages_hist,new_message); - - return 0; -} - -void linphone_sql_request_message(sqlite3 *db,const char *stmt,LinphoneChatRoom *cr){ - char* errmsg=NULL; - int ret; - ret=sqlite3_exec(db,stmt,create_chat_message,cr,&errmsg); - if(ret != SQLITE_OK) { - ms_error("Error in creation: %s.", errmsg); - sqlite3_free(errmsg); - } -} - -int linphone_sql_request(sqlite3* db,const char *stmt){ - char* errmsg=NULL; - int ret; - ret=sqlite3_exec(db,stmt,NULL,NULL,&errmsg); - if(ret != SQLITE_OK) { - ms_error("linphone_sql_request: statement %s -> error sqlite3_exec(): %s.", stmt, errmsg); - sqlite3_free(errmsg); - } - return ret; -} - -// Process the request to fetch all chat contacts -void linphone_sql_request_all(sqlite3* db,const char *stmt, LinphoneCore* lc){ - char* errmsg=NULL; - 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.", errmsg); - sqlite3_free(errmsg); - } -} - -static int linphone_chat_message_store_content(LinphoneChatMessage *msg) { - LinphoneCore *lc = linphone_chat_room_get_core(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,%lld,%Q);", - linphone_content_get_type(content), - linphone_content_get_subtype(content), - linphone_content_get_name(content), - linphone_content_get_encoding(content), - linphone_content_get_size(content), - NULL, - (int64_t)linphone_content_get_key_size(content), - linphone_content_get_key(content) - ); - 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_core(msg->chat_room); - int id = 0; - - if (lc->db){ - 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,%lld,%Q,%i,%Q,%Q,%i);", - local_contact, - peer, - msg->dir, - msg->message, - "-1", /* use UTC field now */ - FALSE, /* use state == LinphoneChatMessageStateDisplayed now */ - msg->state, - msg->external_body_url, - (int64_t)msg->time, - msg->appdata, - content_id, - msg->message_id, - msg->content_type, - (int)msg->is_secured - ); - linphone_sql_request(lc->db,buf); - sqlite3_free(buf); - ms_free(local_contact); - ms_free(peer); - id = (unsigned int) sqlite3_last_insert_rowid (lc->db); - } - return id; -} - -void linphone_chat_message_store_update(LinphoneChatMessage *msg) { - LinphoneCore *lc = linphone_chat_room_get_core(msg->chat_room); - - if (lc->db) { - char *peer; - char *local_contact; - char *buf; - - 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("UPDATE history SET" - " localContact = %Q," - " remoteContact = %Q," - " message = %Q," - " status = %i," - " appdata = %Q," - " messageId = %Q," - " content_type = %Q" - " WHERE (id = %u);", - local_contact, - peer, - msg->message, - msg->state, - msg->appdata, - msg->message_id, - msg->content_type, - msg->storage_id - ); - linphone_sql_request(lc->db, buf); - sqlite3_free(buf); - ms_free(local_contact); - ms_free(peer); - } -} - -void linphone_chat_message_store_state(LinphoneChatMessage *msg){ - LinphoneCore *lc=msg->chat_room->lc; - if (lc->db){ - char *buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE (id = %u);", - msg->state,msg->storage_id); - linphone_sql_request(lc->db,buf); - sqlite3_free(buf); - } -} - -void linphone_chat_message_store_appdata(LinphoneChatMessage* msg){ - LinphoneCore *lc=msg->chat_room->lc; - if (lc->db){ - char *buf=sqlite3_mprintf("UPDATE history SET appdata=%Q WHERE id=%u;", - msg->appdata,msg->storage_id); - linphone_sql_request(lc->db,buf); - sqlite3_free(buf); - } -} - -void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ - LinphoneCore *lc=linphone_chat_room_get_core(cr); - bctbx_list_t *item; - char *peer; - char *buf; - - if (lc->db==NULL) return ; - - // optimization: do not modify the database if no message is marked as unread - if(linphone_chat_room_get_unread_messages_count(cr) == 0) return; - - peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND direction = %i AND status != %i", peer, LinphoneChatMessageIncoming, LinphoneChatMessageStateDisplayed); - linphone_sql_request_message(lc->db, buf, cr); - sqlite3_free(buf); - for (item = cr->messages_hist; item != NULL; item = bctbx_list_next(item)) { - LinphoneChatMessage *cm = (LinphoneChatMessage *)bctbx_list_get_data(item); - linphone_chat_message_send_display_notification(cm); - } - bctbx_list_free_with_data(cr->messages_hist, (bctbx_list_free_func)linphone_chat_message_unref); - cr->messages_hist = NULL; - buf=sqlite3_mprintf("UPDATE history SET status=%i WHERE remoteContact=%Q AND direction=%i;", - LinphoneChatMessageStateDisplayed, peer, LinphoneChatMessageIncoming); - linphone_sql_request(lc->db,buf); - sqlite3_free(buf); - ms_free(peer); - - if (cr->pending_message) { - linphone_chat_message_set_state(cr->pending_message, LinphoneChatMessageStateDisplayed); - linphone_chat_message_send_display_notification(cr->pending_message); - } - - cr->unread_count = 0; -} - -void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { - LinphoneCore *lc=linphone_chat_room_get_core(cr); - char *buf; - - if (lc->db==NULL) return ; - - buf=sqlite3_mprintf("UPDATE history SET url=%Q WHERE id=%u;",msg->external_body_url,msg->storage_id); - linphone_sql_request(lc->db,buf); - sqlite3_free(buf); -} - -static int linphone_chat_room_get_messages_count(LinphoneChatRoom *cr, bool_t unread_only){ - LinphoneCore *lc=linphone_chat_room_get_core(cr); - int numrows=0; - char *peer; - char *buf; - char *option = NULL; - sqlite3_stmt *selectStatement; - int returnValue; - - if (lc->db==NULL) return 0; - - // optimization: do not read database if the count is already available in memory - if(unread_only && cr->unread_count >= 0) return cr->unread_count; - - peer=linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - if (unread_only) { - option = bctbx_strdup_printf("AND status!=%i AND direction=%i", LinphoneChatMessageStateDisplayed, LinphoneChatMessageIncoming); - } - buf=sqlite3_mprintf("SELECT count(*) FROM history WHERE remoteContact = %Q %s;",peer,unread_only?option:""); - returnValue = sqlite3_prepare_v2(lc->db,buf,-1,&selectStatement,NULL); - if (returnValue == SQLITE_OK){ - if(sqlite3_step(selectStatement) == SQLITE_ROW){ - numrows= sqlite3_column_int(selectStatement, 0); - } - } - sqlite3_finalize(selectStatement); - sqlite3_free(buf); - ms_free(peer); - - /* no need to test the sign of cr->unread_count here - * because it has been tested above */ - if(unread_only) { - cr->unread_count = numrows; - if (option) bctbx_free(option); - } - - 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 ; - - buf=sqlite3_mprintf("DELETE FROM history WHERE id = %u;", msg->storage_id); - linphone_sql_request(lc->db,buf); - sqlite3_free(buf); - - /* Invalidate unread_count when we modify the database, so that next - time we need it it will be recomputed from latest database state */ - cr->unread_count = -1; -} - -void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ - LinphoneCore *lc=cr->lc; - char *peer; - char *buf; - - if (lc->db==NULL) return ; - - 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); - - if(cr->unread_count > 0) cr->unread_count = 0; -} - -bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int startm, int endm){ - LinphoneCore *lc=linphone_chat_room_get_core(cr); - bctbx_list_t *ret; - char *buf,*buf2; - 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)); - - cr->messages_hist = NULL; - - /*since we want to append query parameters depending on arguments given, we use malloc instead of sqlite3_mprintf*/ - buf=reinterpret_cast(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) || (startm == 0 && endm == 0) ){ - buf2=ms_strdup_printf("%s LIMIT %i ",buf,endm+1-startm); - ms_free(buf); - buf = buf2; - }else if(startm>0){ - ms_message("%s(): end is lower than start (%d < %d). Assuming no end limit.",__FUNCTION__,endm,startm); - buf2=ms_strdup_printf("%s LIMIT -1",buf); - ms_free(buf); - buf = buf2; - } - - if (startm>0){ - buf2=ms_strdup_printf("%s OFFSET %i ",buf,startm); - ms_free(buf); - buf = buf2; - } - - begin=ortp_get_cur_time_ms(); - linphone_sql_request_message(lc->db,buf,cr); - end=ortp_get_cur_time_ms(); - - if (endm+1-startm > 1) { - //display message only if at least 2 messages are loaded - ms_message("%s(): completed in %i ms",__FUNCTION__, (int)(end-begin)); - } - ms_free(buf); - - if (cr->messages_hist) { - //fill local addr with core identity instead of per message - LinphoneAddress* local_addr = linphone_address_new(linphone_core_get_identity(cr->lc)); - bctbx_list_t* it = cr->messages_hist; - while (it) { - LinphoneChatMessage* msg = reinterpret_cast(it->data); - if (msg->dir == LinphoneChatMessageOutgoing) { - if (msg->from != NULL) linphone_address_unref(msg->from); - msg->from = linphone_address_ref(local_addr); - } else { - msg->to = linphone_address_ref(local_addr); - } - it = it->next; - } - linphone_address_unref(local_addr); - } - - ret=cr->messages_hist; - cr->messages_hist=NULL; - ms_free(peer); - return ret; -} - -bctbx_list_t *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ - return linphone_chat_room_get_history_range(cr, 0, nb_message-1); -} - - -bctbx_list_t* linphone_chat_room_find_messages(LinphoneChatRoom *cr, const char *message_id) { - LinphoneCore *lc = linphone_chat_room_get_core(cr); - char *buf; - char *peer; - bctbx_list_t* messages; - - if (lc->db == NULL) return NULL; - peer = linphone_address_as_string_uri_only(linphone_chat_room_get_peer_address(cr)); - cr->messages_hist = NULL; - buf = sqlite3_mprintf("SELECT * FROM history WHERE remoteContact = %Q AND messageId = %Q", peer, message_id); - linphone_sql_request_message(lc->db, buf, cr); - sqlite3_free(buf); - ms_free(peer); - messages = cr->messages_hist; - cr->messages_hist = NULL; - return messages; -} - -LinphoneChatMessage * linphone_chat_room_find_message_with_dir(LinphoneChatRoom *cr, const char *message_id, LinphoneChatMessageDir dir) { - bctbx_list_t* messages = linphone_chat_room_find_messages(cr, message_id); - bctbx_list_t* it; - LinphoneChatMessage *ret = NULL; - for (it = messages; it != NULL; it = it->next) { - LinphoneChatMessage * cm = (LinphoneChatMessage*)it->data; - if (cm->dir == dir) { - linphone_chat_message_ref(cm); - ret = cm; - break; - } - } - if (messages) - bctbx_list_free_with_data(messages, (bctbx_list_free_func)linphone_chat_message_unref); - - return ret; - -} - -LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, const char *message_id) { - bctbx_list_t* messages = linphone_chat_room_find_messages(cr, message_id); - LinphoneChatMessage *cm = NULL; - if (messages) { - cm = (LinphoneChatMessage *)bctbx_list_nth_data(messages, 0); - linphone_chat_message_ref(cm); - bctbx_list_free_with_data(messages, (bctbx_list_free_func)linphone_chat_message_unref); - } - return cm; -} - -static void linphone_create_history_table(sqlite3* db){ - char* errmsg=NULL; - int ret; - ret=sqlite3_exec(db,"CREATE TABLE IF NOT EXISTS history (" - "id INTEGER PRIMARY KEY AUTOINCREMENT," - "localContact TEXT NOT NULL," - "remoteContact TEXT NOT NULL," - "direction INTEGER," - "message TEXT," - "time TEXT NOT NULL," - "read INTEGER," - "status INTEGER" - ");", - 0,0,&errmsg); - if(ret != SQLITE_OK) { - ms_error("Error in creation: %s.\n", errmsg); - sqlite3_free(errmsg); - } -} - - -static const char *days[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; -static const char *months[]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; -static time_t parse_time_from_db( const char* time ){ - /* messages used to be stored in the DB by using string-based time */ - struct tm ret={0}; - char tmp1[80]={0}; - char tmp2[80]={0}; - int i,j; - time_t parsed = 0; - - if( sscanf(time,"%3c %3c%d%d:%d:%d %d",tmp1,tmp2,&ret.tm_mday, - &ret.tm_hour,&ret.tm_min,&ret.tm_sec,&ret.tm_year) == 7 ){ - ret.tm_year-=1900; - for(i=0;i<7;i++) { - if(strcmp(tmp1,days[i])==0) ret.tm_wday=i; - } - for(j=0;j<12;j++) { - if(strcmp(tmp2,months[j])==0) ret.tm_mon=j; - } - ret.tm_isdst=-1; - parsed = mktime(&ret); - } - return parsed; -} - - -static int migrate_messages_timestamp(void* data,int argc, char** argv, char** column_names) { - time_t new_time = parse_time_from_db(argv[1]); - if( new_time ){ - /* replace 'time' by -1 and set 'utc' to the timestamp */ - char *buf = sqlite3_mprintf("UPDATE history SET utc=%lld,time='-1' WHERE id=%i;", (int64_t)new_time, atoi(argv[0])); - if( buf) { - linphone_sql_request((sqlite3*)data, buf); - sqlite3_free(buf); - } - } else { - ms_warning("Cannot parse time %s from id %s", argv[1], argv[0]); - } - return 0; -} - -static void linphone_migrate_timestamps(sqlite3* db){ - int ret; - char* errmsg = NULL; - uint64_t begin=ortp_get_cur_time_ms(); - - linphone_sql_request(db,"BEGIN TRANSACTION"); - - ret = sqlite3_exec(db,"SELECT id,time,direction FROM history WHERE time != '-1';", migrate_messages_timestamp, db, &errmsg); - if( ret != SQLITE_OK ){ - ms_warning("Error migrating outgoing messages: %s.\n", errmsg); - sqlite3_free(errmsg); - linphone_sql_request(db, "ROLLBACK"); - } else { - uint64_t end; - linphone_sql_request(db, "COMMIT"); - end=ortp_get_cur_time_ms(); - ms_message("Migrated message timestamps to UTC in %lu ms",(unsigned long)(end-begin)); - } -} - -static void linphone_update_history_table(sqlite3* db) { - char* errmsg=NULL; - char *buf; - int ret; - - // for image url storage - ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN url TEXT;",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 URL."); - } - - // for UTC timestamp storage - ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN utc 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 UTC."); - // migrate from old text-based timestamps to unix time-based timestamps - linphone_migrate_timestamps(db); - } - - // new field for app-specific storage - ret=sqlite3_exec(db,"ALTER TABLE history ADD COLUMN appdata TEXT;",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 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."); - } - } - - // new fields for content key storage when using lime - ret=sqlite3_exec(db,"ALTER TABLE content ADD COLUMN key_size INTEGER;",NULL,NULL,&errmsg); - if(ret != SQLITE_OK) { - ms_message("Table already up to date: %s.", errmsg); - sqlite3_free(errmsg); - } else { - ret=sqlite3_exec(db,"ALTER TABLE content ADD COLUMN key TEXT;",NULL,NULL,&errmsg); - if(ret != SQLITE_OK) { - ms_message("Table already up to date: %s.", errmsg); - sqlite3_free(errmsg); - } else { - ms_debug("Table history content successfully for lime key storage data."); - } - } - - // new field for message_id - ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN messageId TEXT;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - ms_message("Table already up to date: %s", errmsg); - sqlite3_free(errmsg); - } else { - ms_message("Table history updated successfully for messageId data."); - } - - // Convert is_read to LinphoneChatMessageStateDisplayed - buf = sqlite3_mprintf("UPDATE history SET status=%i WHERE read=1 AND direction=%i;", LinphoneChatMessageStateDisplayed, LinphoneChatMessageIncoming); - linphone_sql_request(db, buf); - sqlite3_free(buf); - - /* New field for content type */ - ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN content_type TEXT;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - ms_message("Table already up to date: %s", errmsg); - sqlite3_free(errmsg); - } else { - ms_message("Table history updated successfully for content_type data."); - } - - // new field for secured flag - ret = sqlite3_exec(db, "ALTER TABLE history ADD COLUMN is_secured INTEGER DEFAULT 0;", NULL, NULL, &errmsg); - if (ret != SQLITE_OK) { - ms_message("Table already up to date: %s", errmsg); - sqlite3_free(errmsg); - } else { - ms_message("Table history updated successfully for is_secured data."); - } -} - -static void linphone_fix_outgoing_messages_state(sqlite3* db) { - /* Convert Idle and InProgress states of outgoing messages to NotDelivered */ - char *buf = sqlite3_mprintf("UPDATE history SET status=%i WHERE direction=%i AND (status=%i OR status=%i);", - LinphoneChatMessageStateNotDelivered, LinphoneChatMessageOutgoing, LinphoneChatMessageStateIdle, LinphoneChatMessageStateInProgress); - linphone_sql_request(db, buf); - sqlite3_free(buf); -} - -void linphone_message_storage_init_chat_rooms(LinphoneCore *lc) { - char *buf; - - if (lc->db==NULL) return; - buf=sqlite3_mprintf("SELECT remoteContact FROM history GROUP BY remoteContact;"); - linphone_sql_request_all(lc->db,buf,lc); - sqlite3_free(buf); -} - -static void _linphone_message_storage_profile(void*data,const char*statement, sqlite3_uint64 duration){ - ms_warning("SQL statement '%s' took %llu microseconds", statement, (unsigned long long)(duration / 1000LL) ); -} - -static void linphone_message_storage_activate_debug(sqlite3* db, bool_t debug){ - if( debug ){ - sqlite3_profile(db, _linphone_message_storage_profile, NULL ); - } else { - sqlite3_profile(db, NULL, NULL ); - } -} - -void linphone_core_message_storage_set_debug(LinphoneCore *lc, bool_t debug){ - - lc->debug_storage = debug; - - if( lc->db ){ - linphone_message_storage_activate_debug(lc->db, debug); - } -} - -void linphone_core_message_storage_init(LinphoneCore *lc){ - int ret; - const char *errmsg; - sqlite3 *db = NULL; - - linphone_core_message_storage_close(lc); - - ret=_linphone_sqlite3_open(lc->chat_db_file,&db); - if(ret != SQLITE_OK) { - errmsg=sqlite3_errmsg(db); - ms_error("Error in the opening: %s.\n", errmsg); - sqlite3_close(db); - return; - } - - linphone_message_storage_activate_debug(db, lc->debug_storage); - - linphone_create_history_table(db); - linphone_update_history_table(db); - linphone_fix_outgoing_messages_state(db); - lc->db=db; - - // Create a chatroom for each contact in the chat history - linphone_message_storage_init_chat_rooms(lc); -} - -void linphone_core_message_storage_close(LinphoneCore *lc){ - if (lc->db){ - sqlite3_close(lc->db); - lc->db=NULL; - } -} - -#else - -unsigned int linphone_chat_message_store(LinphoneChatMessage *cr){ - return 0; -} - -void linphone_chat_message_store_state(LinphoneChatMessage *cr){ -} - -void linphone_chat_message_store_appdata(LinphoneChatMessage *msg){ -} - -void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr){ -} - -bctbx_list_t *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message){ - return NULL; -} - -bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end){ - return NULL; -} - -LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, const char *message_id) { - return NULL; -} - -void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { -} - -void linphone_chat_room_delete_history(LinphoneChatRoom *cr){ -} - -void linphone_message_storage_init_chat_rooms(LinphoneCore *lc) { -} - -void linphone_core_message_storage_init(LinphoneCore *lc){ -} - -void linphone_core_message_storage_close(LinphoneCore *lc){ -} - -void linphone_chat_room_update_url(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { -} - -int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr){ - return 0; -} - -int linphone_chat_room_get_history_size(LinphoneChatRoom *cr){ - return 0; -} - -void linphone_chat_message_store_update(LinphoneChatMessage *msg){ -} - -LinphoneChatMessage * linphone_chat_room_find_message_with_dir(LinphoneChatRoom *cr, const char *message_id, LinphoneChatMessageDir dir) { - return NULL; -} - -#endif diff --git a/coreapi/misc.c b/coreapi/misc.c index 2486410b4..a7fcd57d3 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -18,7 +18,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "private.h" #include "linphone/lpconfig.h" #include "linphone/wrapper_utils.h" #include "mediastreamer2/mediastream.h" @@ -56,88 +55,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define pclose _pclose #endif +#include "nat/stun-client.h" +#include "utils/payload-type-handler.h" -#define UDP_HDR_SZ 8 -#define RTP_HDR_SZ 12 -#define IP4_HDR_SZ 20 /*20 is the minimum, but there may be some options*/ +#include "c-wrapper/c-wrapper.h" -static void clear_ice_check_list(LinphoneCall *call, IceCheckList *removed); - - -/* - *((codec-birate*ptime/8) + RTP header + UDP header + IP header)*8/ptime; - *ptime=1/npacket - */ - -static double get_audio_payload_bandwidth_from_codec_bitrate(const PayloadType *pt){ - double npacket=50; - double packet_size; - int bitrate; - - if (strcmp(payload_type_get_mime(&payload_type_aaceld_44k), payload_type_get_mime(pt))==0) { - /*special case of aac 44K because ptime= 10ms*/ - npacket=100; - }else if (strcmp(payload_type_get_mime(&payload_type_ilbc), payload_type_get_mime(pt))==0) { - npacket=1000/30.0; - } - - bitrate=pt->normal_bitrate; - packet_size= (((double)bitrate)/(npacket*8))+UDP_HDR_SZ+RTP_HDR_SZ+IP4_HDR_SZ; - return packet_size*8.0*npacket; -} - -typedef struct vbr_codec_bitrate{ - int max_avail_bitrate; - int min_rate; - int recomended_bitrate; -}vbr_codec_bitrate_t; - -static vbr_codec_bitrate_t defauls_vbr[]={ - //{ 100, 44100, 100 }, - { 64, 44100, 50 }, - { 64, 16000, 40 }, - { 32, 16000, 32 }, - { 32, 8000, 32 }, - { 0 , 8000, 24 }, - { 0 , 0, 0 } -}; - -static int lookup_vbr_typical_bitrate(int maxbw, int clock_rate){ - vbr_codec_bitrate_t *it; - if (maxbw<=0) maxbw=defauls_vbr[0].max_avail_bitrate; - for(it=defauls_vbr;it->min_rate!=0;it++){ - if (maxbw>=it->max_avail_bitrate && clock_rate>=it->min_rate) - return it->recomended_bitrate; - } - ms_error("lookup_vbr_typical_bitrate(): should not happen."); - return 32; -} - -int get_audio_payload_bandwidth(const LinphoneCore *lc, const PayloadType *pt, int maxbw) { - if (payload_type_is_vbr(pt)) { - if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE){ - ms_debug("PayloadType %s/%i has bitrate override",pt->mime_type,pt->clock_rate); - return pt->normal_bitrate/1000; - } - return lookup_vbr_typical_bitrate(maxbw,pt->clock_rate); - }else return (int)ceil(get_audio_payload_bandwidth_from_codec_bitrate(pt)/1000.0);/*rounding codec bandwidth should be avoid, specially for AMR*/ -} - -void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt, int maxbw){ - call->audio_bw=get_audio_payload_bandwidth(call->core,pt,maxbw); - ms_message("Audio bandwidth for this call is %i",call->audio_bw); -} +// TODO: From coreapi. Remove me later. +#include "private.h" void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc){ const bctbx_list_t *elem; - int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), + int maxbw=LinphonePrivate::PayloadTypeHandler::getMinBandwidth(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)){ - int pt_bitrate=get_audio_payload_bandwidth(lc,pt,maxbw); + int pt_bitrate=LinphonePrivate::PayloadTypeHandler::getAudioPayloadTypeBandwidth(pt,maxbw); if (max_codec_bitrate==0) { max_codec_bitrate=pt_bitrate; }else if (max_codec_bitratetype){ case PAYLOAD_AUDIO_CONTINUOUS: case PAYLOAD_AUDIO_PACKETIZED: - codec_band=get_audio_payload_bandwidth(lc,pt,bandwidth_limit); - ret=bandwidth_is_greater(bandwidth_limit,(int)codec_band); + codec_band=LinphonePrivate::PayloadTypeHandler::getAudioPayloadTypeBandwidth(pt,bandwidth_limit); + ret=LinphonePrivate::PayloadTypeHandler::bandwidthIsGreater(bandwidth_limit,(int)codec_band); /*ms_message("Payload %s: codec_bandwidth=%g, bandwidth_limit=%i",pt->mime_type,codec_band,bandwidth_limit);*/ break; case PAYLOAD_VIDEO: @@ -196,59 +131,6 @@ bool_t lp_spawn_command_line_sync(const char *command, char **result,int *comman return FALSE; } -static ortp_socket_t create_socket(int local_port){ - struct sockaddr_in laddr; - ortp_socket_t sock; - int optval; - sock=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP); - if (sock<0) { - ms_error("Fail to create socket"); - return -1; - } - memset (&laddr,0,sizeof(laddr)); - laddr.sin_family=AF_INET; - laddr.sin_addr.s_addr=INADDR_ANY; - laddr.sin_port=htons(local_port); - if (bind(sock,(struct sockaddr*)&laddr,sizeof(laddr))<0){ - ms_error("Bind socket to 0.0.0.0:%i failed: %s",local_port,getSocketError()); - close_socket(sock); - return -1; - } - optval=1; - if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, - (SOCKET_OPTION_VALUE)&optval, sizeof (optval))<0){ - ms_warning("Fail to set SO_REUSEADDR"); - } - set_non_blocking_socket(sock); - return sock; -} - -static int send_stun_request(int sock, const struct sockaddr *server, socklen_t addrlen, int id, bool_t change_addr){ - char *buf = NULL; - size_t len; - int err = 0; - MSStunMessage *req = ms_stun_binding_request_create(); - UInt96 tr_id = ms_stun_message_get_tr_id(req); - tr_id.octet[0] = id; - ms_stun_message_set_tr_id(req, tr_id); - ms_stun_message_enable_change_ip(req, change_addr); - ms_stun_message_enable_change_port(req, change_addr); - len = ms_stun_message_encode(req, &buf); - if (len <= 0) { - ms_error("Fail to encode stun message."); - err = -1; - } else { - err = bctbx_sendto(sock, buf, len, 0, server, addrlen); - if (err < 0) { - ms_error("sendto failed: %s",strerror(errno)); - err = -1; - } - } - if (buf != NULL) ms_free(buf); - ms_free(req); - return err; -} - int linphone_parse_host_port(const char *input, char *host, size_t hostlen, int *port){ char tmphost[NI_MAXHOST]={0}; @@ -288,162 +170,25 @@ int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, sock return -1; } if (!res) return -1; - memcpy(ss,res->ai_addr,res->ai_addrlen); + memcpy(ss,res->ai_addr,(size_t)res->ai_addrlen); *socklen=(socklen_t)res->ai_addrlen; freeaddrinfo(res); return 0; } -static int recv_stun_response(ortp_socket_t sock, char *ipaddr, int *port, int *id) { - char buf[MS_STUN_MAX_MESSAGE_SIZE]; - int len = MS_STUN_MAX_MESSAGE_SIZE; - MSStunMessage *resp; - - len = recv(sock, buf, len, 0); - if (len > 0) { - struct in_addr ia; - resp = ms_stun_message_create_from_buffer_parsing((uint8_t *)buf, (ssize_t)len); - if (resp != NULL) { - const MSStunAddress *stun_addr; - UInt96 tr_id = ms_stun_message_get_tr_id(resp); - *id = tr_id.octet[0]; - stun_addr = ms_stun_message_get_xor_mapped_address(resp); - if (stun_addr != NULL) { - *port = stun_addr->ip.v4.port; - ia.s_addr = htonl(stun_addr->ip.v4.addr); - } else { - stun_addr = ms_stun_message_get_mapped_address(resp); - if (stun_addr != NULL) { - *port = stun_addr->ip.v4.port; - ia.s_addr = htonl(stun_addr->ip.v4.addr); - } else len = -1; - } - if (len > 0) strncpy(ipaddr, inet_ntoa(ia), LINPHONE_IPADDR_SIZE); - } - } - return len; -} - /* this functions runs a simple stun test and return the number of milliseconds to complete the tests, or -1 if the test were failed.*/ -int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call){ - const char *server=linphone_core_get_stun_server(lc); - StunCandidate *ac=&call->ac; - StunCandidate *vc=&call->vc; - StunCandidate *tc=&call->tc; - - if (lc->sip_conf.ipv6_enabled){ - ms_warning("stun support is not implemented for ipv6"); - return -1; - } - if (call->media_ports[call->main_audio_stream_index].rtp_port==-1){ - ms_warning("Stun-only support not available for system random port"); - return -1; - } - if (server!=NULL){ - const struct addrinfo *ai=linphone_core_get_stun_server_addrinfo(lc); - ortp_socket_t sock1=-1, sock2=-1, sock3=-1; - int loops=0; - bool_t video_enabled=linphone_core_video_enabled(lc); - bool_t got_audio,got_video,got_text; - bool_t cone_audio=FALSE,cone_video=FALSE,cone_text=FALSE; - struct timeval init,cur; - double elapsed; - int ret=0; - - if (ai==NULL){ - ms_error("Could not obtain stun server addrinfo."); - return -1; - } - 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[call->main_audio_stream_index].rtp_port); - if (sock1==-1) return -1; - if (video_enabled){ - sock2=create_socket(call->media_ports[call->main_video_stream_index].rtp_port); - if (sock2==-1) return -1; - } - sock3=create_socket(call->media_ports[call->main_text_stream_index].rtp_port); - if (sock3==-1) return -1; - - got_audio=FALSE; - got_video=FALSE; - got_text=FALSE; - ortp_gettimeofday(&init,NULL); - do{ - - int id; - if (loops%20==0){ - ms_message("Sending stun requests..."); - send_stun_request((int)sock1,ai->ai_addr,(socklen_t)ai->ai_addrlen,11,TRUE); - send_stun_request((int)sock1,ai->ai_addr,(socklen_t)ai->ai_addrlen,1,FALSE); - if (sock2!=-1){ - send_stun_request((int)sock2,ai->ai_addr,(socklen_t)ai->ai_addrlen,22,TRUE); - send_stun_request((int)sock2,ai->ai_addr,(socklen_t)ai->ai_addrlen,2,FALSE); - } - if (sock3!=-1){ - send_stun_request((int)sock3,ai->ai_addr,(socklen_t)ai->ai_addrlen,33,TRUE); - send_stun_request((int)sock3,ai->ai_addr,(socklen_t)ai->ai_addrlen,3,FALSE); - } - } - ms_usleep(10000); - - if (recv_stun_response(sock1, ac->addr, &ac->port, &id) > 0) { - ms_message("STUN test result: local audio port maps to %s:%i", ac->addr, ac->port); - if (id==11) cone_audio=TRUE; - got_audio=TRUE; - } - if (recv_stun_response(sock2, vc->addr, &vc->port, &id) > 0) { - ms_message("STUN test result: local video port maps to %s:%i", vc->addr, vc->port); - if (id==22) cone_video=TRUE; - got_video=TRUE; - } - if (recv_stun_response(sock3, tc->addr, &tc->port, &id)>0) { - ms_message("STUN test result: local text port maps to %s:%i", tc->addr, tc->port); - if (id==33) cone_text=TRUE; - got_text=TRUE; - } - ortp_gettimeofday(&cur,NULL); - elapsed=((cur.tv_sec-init.tv_sec)*1000.0) + ((cur.tv_usec-init.tv_usec)/1000.0); - if (elapsed>2000) { - ms_message("Stun responses timeout, going ahead."); - ret=-1; - break; - } - loops++; - }while(!(got_audio && (got_video||sock2==-1) && (got_text||sock3==-1) ) ); - if (ret==0) ret=(int)elapsed; - if (!got_audio){ - ms_error("No stun server response for audio port."); - }else{ - if (!cone_audio) { - ms_message("NAT is symmetric for audio port"); - } - } - if (sock2!=-1){ - if (!got_video){ - ms_error("No stun server response for video port."); - }else{ - if (!cone_video) { - ms_message("NAT is symmetric for video port."); - } - } - } - if (sock3!=-1){ - if (!got_text){ - ms_error("No stun server response for text port."); - }else{ - if (!cone_text) { - ms_message("NAT is symmetric for text port."); - } - } - } - close_socket(sock1); - if (sock2!=-1) close_socket(sock2); - if (sock3!=-1) close_socket(sock3); - return ret; - } - return -1; +int linphone_run_stun_tests(LinphoneCore *lc, int audioPort, int videoPort, int textPort, + char *audioCandidateAddr, int *audioCandidatePort, char *videoCandidateAddr, int *videoCandidatePort, char *textCandidateAddr, int *textCandidatePort) { + LinphonePrivate::StunClient *client = new LinphonePrivate::StunClient(L_GET_CPP_PTR_FROM_C_OBJECT(lc)); + int ret = client->run(audioPort, videoPort, textPort); + strncpy(audioCandidateAddr, client->getAudioCandidate().address.c_str(), LINPHONE_IPADDR_SIZE); + *audioCandidatePort = client->getAudioCandidate().port; + strncpy(videoCandidateAddr, client->getVideoCandidate().address.c_str(), LINPHONE_IPADDR_SIZE); + *videoCandidatePort = client->getVideoCandidate().port; + strncpy(textCandidateAddr, client->getTextCandidate().address.c_str(), LINPHONE_IPADDR_SIZE); + *textCandidatePort = client->getTextCandidate().port; + delete client; + return ret; } int linphone_core_get_edge_bw(LinphoneCore *lc){ @@ -456,31 +201,16 @@ int linphone_core_get_edge_ptime(LinphoneCore *lc){ return edge_ptime; } -void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, LinphoneCallParams *params){ - int threshold; - if (ping_time_ms>0 && lp_config_get_int(lc->config,"net","activate_edge_workarounds",0)==1){ - ms_message("Stun server ping time is %i ms",ping_time_ms); - threshold=lp_config_get_int(lc->config,"net","edge_ping_time",500); - - if (ping_time_ms>threshold){ - /* we might be in a 2G network*/ - params->low_bandwidth=TRUE; - }/*else use default settings */ +void linphone_core_resolve_stun_server(LinphoneCore *lc) { + auto proxies = linphone_core_get_proxy_config_list(lc); + for (auto item = proxies; item; item = bctbx_list_next(item)) { + auto proxy = reinterpret_cast(bctbx_list_get_data(item)); + auto policy = linphone_proxy_config_get_nat_policy(proxy); + if (policy) + linphone_nat_policy_resolve_stun_server(policy); } - if (params->low_bandwidth){ - params->up_bw=params->down_bw=linphone_core_get_edge_bw(lc); - params->up_ptime=params->down_ptime=linphone_core_get_edge_ptime(lc); - params->has_video=FALSE; - } -} - - -void linphone_core_resolve_stun_server(LinphoneCore *lc){ - if (lc->nat_policy != NULL) { + if (lc->nat_policy) linphone_nat_policy_resolve_stun_server(lc->nat_policy); - } else { - ms_error("linphone_core_resolve_stun_server(): called without nat_policy, this should not happen."); - } } const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc){ @@ -500,180 +230,6 @@ void linphone_core_enable_short_turn_refresh(LinphoneCore *lc, bool_t enable) { lc->short_turn_refresh = enable; } -static void stun_auth_requested_cb(LinphoneCall *call, const char *realm, const char *nonce, const char **username, const char **password, const char **ha1) { - LinphoneProxyConfig *proxy = NULL; - const LinphoneNatPolicy *nat_policy = NULL; - const LinphoneAddress *addr = NULL; - const LinphoneAuthInfo *auth_info = NULL; - LinphoneCore *lc = call->core; - const char *user = NULL; - - // Get the username from the nat policy or the proxy config - if (call->dest_proxy != NULL) proxy = call->dest_proxy; - else proxy = linphone_core_get_default_proxy_config(call->core); - if (proxy == NULL) return; - nat_policy = linphone_proxy_config_get_nat_policy(proxy); - if (nat_policy != NULL) { - user = linphone_nat_policy_get_stun_server_username(nat_policy); - } else { - nat_policy = call->nat_policy; - if (nat_policy != NULL) { - user = linphone_nat_policy_get_stun_server_username(nat_policy); - } - } - if (user == NULL) { - /* If the username has not been found in the nat_policy, take the username from the currently used proxy config. */ - addr = linphone_proxy_config_get_identity_address(proxy); - if (addr == NULL) return; - user = linphone_address_get_username(addr); - } - if (user == NULL) return; - - auth_info = linphone_core_find_auth_info(lc, realm, user, NULL); - if (auth_info != NULL) { - const char *hash = linphone_auth_info_get_ha1(auth_info); - if (hash != NULL) { - *ha1 = hash; - } else { - *password = linphone_auth_info_get_passwd(auth_info); - } - *username = user; - } else { - ms_warning("No auth info found for STUN auth request"); - } -} - -static void linphone_core_add_local_ice_candidates(LinphoneCall *call, int family, const char *addr, IceCheckList *audio_cl, IceCheckList *video_cl, IceCheckList *text_cl) { - if ((ice_check_list_state(audio_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(audio_cl) == FALSE)) { - ice_add_local_candidate(audio_cl, "host", family, addr, call->media_ports[call->main_audio_stream_index].rtp_port, 1, NULL); - ice_add_local_candidate(audio_cl, "host", family, addr, call->media_ports[call->main_audio_stream_index].rtcp_port, 2, NULL); - call->audio_stats->ice_state = LinphoneIceStateInProgress; - } - if (linphone_core_video_enabled(call->core) && (video_cl != NULL) - && (ice_check_list_state(video_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(video_cl) == FALSE)) { - ice_add_local_candidate(video_cl, "host", family, addr, call->media_ports[call->main_video_stream_index].rtp_port, 1, NULL); - ice_add_local_candidate(video_cl, "host", family, addr, call->media_ports[call->main_video_stream_index].rtcp_port, 2, NULL); - call->video_stats->ice_state = LinphoneIceStateInProgress; - } - if (call->params->realtimetext_enabled && (text_cl != NULL) - && (ice_check_list_state(text_cl) != ICL_Completed) && (ice_check_list_candidates_gathered(text_cl) == FALSE)) { - ice_add_local_candidate(text_cl, "host", family, addr, call->media_ports[call->main_text_stream_index].rtp_port, 1, NULL); - ice_add_local_candidate(text_cl, "host", family, addr, call->media_ports[call->main_text_stream_index].rtcp_port, 2, NULL); - call->text_stats->ice_state = LinphoneIceStateInProgress; - } -} - -static const struct addrinfo * find_nat64_addrinfo(const struct addrinfo *ai) { - while (ai != NULL) { - if (ai->ai_family == AF_INET6) { - struct sockaddr_storage ss; - socklen_t sslen = sizeof(ss); - bctbx_sockaddr_remove_nat64_mapping(ai->ai_addr, (struct sockaddr *)&ss, &sslen); - if (ss.ss_family == AF_INET) break; - } - ai = ai->ai_next; - } - return ai; -} - -static const struct addrinfo * find_ipv4_addrinfo(const struct addrinfo *ai) { - while (ai != NULL) { - if (ai->ai_family == AF_INET) break; - if (ai->ai_family == AF_INET6 && ai->ai_flags & AI_V4MAPPED) break; - ai = ai->ai_next; - } - return ai; -} - -static const struct addrinfo * find_ipv6_addrinfo(const struct addrinfo *ai) { - while (ai != NULL) { - if (ai->ai_family == AF_INET6) break; - ai = ai->ai_next; - } - return ai; -} - -/** - * Choose the preferred IP address to use to contact the STUN server from the list of IP addresses - * the DNS resolution returned. If a NAT64 address is present, use it, otherwise if an IPv4 address - * is present, use it, otherwise use an IPv6 address if it is present. - */ -static const struct addrinfo * get_preferred_stun_server_addrinfo(const struct addrinfo *ai) { - const struct addrinfo *preferred_ai = find_nat64_addrinfo(ai); - if (!preferred_ai) preferred_ai = find_ipv4_addrinfo(ai); - if (!preferred_ai) preferred_ai = find_ipv6_addrinfo(ai); - return preferred_ai; -} - -/* Return values: - * 1 : STUN gathering is started - * 0 : no STUN gathering is started, but it's ok to proceed with ICE anyway (with local candidates only or because STUN gathering was already done before) - * -1: no gathering started and something went wrong with local candidates. There is no way to start the ICE session. - */ -int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call){ - char local_addr[64]; - const struct addrinfo *ai = NULL; - IceCheckList *audio_cl; - IceCheckList *video_cl; - IceCheckList *text_cl; - LinphoneNatPolicy *nat_policy = call->nat_policy; - - if (call->ice_session == NULL) return -1; - audio_cl = ice_session_check_list(call->ice_session, call->main_audio_stream_index); - video_cl = ice_session_check_list(call->ice_session, call->main_video_stream_index); - text_cl = ice_session_check_list(call->ice_session, call->main_text_stream_index); - if ((audio_cl == NULL) && (video_cl == NULL) && (text_cl == NULL)) return -1; - - if ((nat_policy != NULL) && linphone_nat_policy_stun_server_activated(nat_policy)) { - ai=linphone_nat_policy_get_stun_server_addrinfo(nat_policy); - if (ai==NULL){ - ms_warning("Fail to resolve STUN server for ICE gathering, continuing without stun."); - } else { - ai = get_preferred_stun_server_addrinfo(ai); - } - }else{ - ms_warning("Ice is used without stun server."); - } - linphone_core_notify_display_status(lc, _("ICE local candidates gathering in progress...")); - - ice_session_enable_forced_relay(call->ice_session, lc->forced_ice_relay); - ice_session_enable_short_turn_refresh(call->ice_session, lc->short_turn_refresh); - - /* Gather local host candidates. */ - if (call->af == AF_INET6) { - if (linphone_core_get_local_ip_for(AF_INET6, NULL, local_addr) < 0) { - ms_error("Fail to get local IPv6"); - return -1; - } else { - linphone_core_add_local_ice_candidates(call, AF_INET6, local_addr, audio_cl, video_cl, text_cl); - } - } - if (linphone_core_get_local_ip_for(AF_INET, NULL, local_addr) < 0) { - if (call->af != AF_INET6) { - ms_error("Fail to get local IPv4"); - return -1; - } - } else { - linphone_core_add_local_ice_candidates(call, AF_INET, local_addr, audio_cl, video_cl, text_cl); - } - if ((ai != NULL) && (nat_policy != NULL) && linphone_nat_policy_stun_server_activated(nat_policy)) { - bool_t gathering_in_progress; - const char *server = linphone_nat_policy_get_stun_server(nat_policy); - ms_message("ICE: gathering candidate from [%s] using %s", server, linphone_nat_policy_turn_enabled(nat_policy) ? "TURN" : "STUN"); - /* Gather local srflx candidates. */ - ice_session_enable_turn(call->ice_session, linphone_nat_policy_turn_enabled(nat_policy)); - ice_session_set_stun_auth_requested_cb(call->ice_session, (MSStunAuthRequestedCb)stun_auth_requested_cb, call); - gathering_in_progress = ice_session_gather_candidates(call->ice_session, ai->ai_addr, (socklen_t)ai->ai_addrlen); - return (gathering_in_progress == FALSE) ? 0 : 1; - } else { - ms_message("ICE: bypass candidates gathering"); - ice_session_compute_candidates_foundations(call->ice_session); - ice_session_eliminate_redundant_candidates(call->ice_session); - ice_session_choose_default_candidates(call->ice_session); - } - return 0; -} - const char *linphone_ice_state_to_string(LinphoneIceState state){ switch(state){ case LinphoneIceStateFailed: @@ -692,283 +248,6 @@ const char *linphone_ice_state_to_string(LinphoneIceState state){ return "invalid"; } -void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call) { - IceCheckList *audio_check_list; - IceCheckList *video_check_list; - IceCheckList *text_check_list; - IceSessionState session_state; - - if (call->ice_session == NULL) { - call->audio_stats->ice_state = LinphoneIceStateNotActivated; - call->video_stats->ice_state = LinphoneIceStateNotActivated; - call->text_stats->ice_state = LinphoneIceStateNotActivated; - return; - } - audio_check_list = ice_session_check_list(call->ice_session, call->main_audio_stream_index); - video_check_list = ice_session_check_list(call->ice_session, call->main_video_stream_index); - text_check_list = ice_session_check_list(call->ice_session, call->main_text_stream_index); - if ((audio_check_list == NULL) && (video_check_list == NULL) && (text_check_list == NULL)) return; - - session_state = ice_session_state(call->ice_session); - if ((session_state == IS_Completed) || ((session_state == IS_Failed) && (ice_session_has_completed_check_list(call->ice_session) == TRUE))) { - if (call->params->has_audio && (audio_check_list != NULL)) { - if (ice_check_list_state(audio_check_list) == ICL_Completed) { - switch (ice_check_list_selected_valid_candidate_type(audio_check_list)) { - case ICT_HostCandidate: - call->audio_stats->ice_state = LinphoneIceStateHostConnection; - break; - case ICT_ServerReflexiveCandidate: - case ICT_PeerReflexiveCandidate: - call->audio_stats->ice_state = LinphoneIceStateReflexiveConnection; - break; - case ICT_RelayedCandidate: - call->audio_stats->ice_state = LinphoneIceStateRelayConnection; - break; - case ICT_CandidateInvalid: - case ICT_CandidateTypeMax: - /*shall not happen*/ - break; - } - } else { - call->audio_stats->ice_state = LinphoneIceStateFailed; - } - }else call->audio_stats->ice_state = LinphoneIceStateNotActivated; - - 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: - call->video_stats->ice_state = LinphoneIceStateHostConnection; - break; - case ICT_ServerReflexiveCandidate: - case ICT_PeerReflexiveCandidate: - call->video_stats->ice_state = LinphoneIceStateReflexiveConnection; - break; - case ICT_RelayedCandidate: - call->video_stats->ice_state = LinphoneIceStateRelayConnection; - break; - case ICT_CandidateInvalid: - case ICT_CandidateTypeMax: - /*shall not happen*/ - break; - } - } else { - call->video_stats->ice_state = LinphoneIceStateFailed; - } - }else call->video_stats->ice_state = LinphoneIceStateNotActivated; - - if (call->params->realtimetext_enabled && (text_check_list != NULL)) { - if (ice_check_list_state(text_check_list) == ICL_Completed) { - switch (ice_check_list_selected_valid_candidate_type(text_check_list)) { - case ICT_HostCandidate: - call->text_stats->ice_state = LinphoneIceStateHostConnection; - break; - case ICT_ServerReflexiveCandidate: - case ICT_PeerReflexiveCandidate: - call->text_stats->ice_state = LinphoneIceStateReflexiveConnection; - break; - case ICT_RelayedCandidate: - call->text_stats->ice_state = LinphoneIceStateRelayConnection; - break; - case ICT_CandidateInvalid: - case ICT_CandidateTypeMax: - /*shall not happen*/ - break; - } - } else { - call->text_stats->ice_state = LinphoneIceStateFailed; - } - }else call->text_stats->ice_state = LinphoneIceStateNotActivated; - } else if (session_state == IS_Running) { - call->audio_stats->ice_state = LinphoneIceStateInProgress; - if (call->params->has_video && (video_check_list != NULL)) { - call->video_stats->ice_state = LinphoneIceStateInProgress; - } - if (call->params->realtimetext_enabled && (text_check_list != NULL)) { - call->text_stats->ice_state = LinphoneIceStateInProgress; - } - } else { - call->audio_stats->ice_state = LinphoneIceStateFailed; - if (call->params->has_video && (video_check_list != NULL)) { - call->video_stats->ice_state = LinphoneIceStateFailed; - } - if (call->params->realtimetext_enabled && (text_check_list != NULL)) { - call->text_stats->ice_state = LinphoneIceStateFailed; - } - } - ms_message("Call [%p] New ICE state: audio: [%s] video: [%s] text: [%s]", call, - linphone_ice_state_to_string(call->audio_stats->ice_state), linphone_ice_state_to_string(call->video_stats->ice_state), linphone_ice_state_to_string(call->text_stats->ice_state)); -} - -void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDescription *desc) { - int i; - IceSession *session = call->ice_session; - - if (session == NULL) return; - if (ice_session_state(session) == IS_Completed) return; - - for (i = 0; i < desc->nb_streams; i++) { - IceCheckList *cl = ice_session_check_list(session, i); - if (!sal_stream_description_active(&desc->streams[i]) && cl) { - ice_session_remove_check_list(session, cl); - clear_ice_check_list(call, cl); - } - } - - linphone_call_update_ice_state_in_call_stats(call); -} - - -void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session, bool_t use_nortpproxy) { - IceCandidate *rtp_candidate = NULL; - IceCandidate *rtcp_candidate = NULL; - IceSessionState session_state = ice_session_state(session); - int nb_candidates; - int i; - int j; - bool_t result = FALSE; - - if (session_state == IS_Completed) { - IceCheckList *first_cl = NULL; - for (i = 0; i < desc->nb_streams; i++) { - IceCheckList *cl = ice_session_check_list(session, i); - if (cl != NULL) { - first_cl = cl; - break; - } - } - if (first_cl != NULL) { - result = ice_check_list_selected_valid_local_candidate(first_cl, &rtp_candidate, NULL); - } - if (result == TRUE) { - strncpy(desc->addr, rtp_candidate->taddr.ip, sizeof(desc->addr)); - } else { - ms_warning("If ICE has completed successfully, rtp_candidate should be set!"); - ice_dump_valid_list(first_cl); - } - } - - strncpy(desc->ice_pwd, ice_session_local_pwd(session), sizeof(desc->ice_pwd)); - strncpy(desc->ice_ufrag, ice_session_local_ufrag(session), sizeof(desc->ice_ufrag)); - for (i = 0; i < desc->nb_streams; i++) { - SalStreamDescription *stream = &desc->streams[i]; - IceCheckList *cl = ice_session_check_list(session, i); - nb_candidates = 0; - rtp_candidate = rtcp_candidate = NULL; - if (!sal_stream_description_active(stream) || (cl == NULL)) continue; - if (ice_check_list_state(cl) == ICL_Completed) { - if (use_nortpproxy) stream->set_nortpproxy = TRUE; - result = ice_check_list_selected_valid_local_candidate(ice_session_check_list(session, i), &rtp_candidate, &rtcp_candidate); - } else { - stream->set_nortpproxy = FALSE; - result = ice_check_list_default_local_candidate(ice_session_check_list(session, i), &rtp_candidate, &rtcp_candidate); - } - if (result == TRUE) { - strncpy(stream->rtp_addr, rtp_candidate->taddr.ip, sizeof(stream->rtp_addr)); - strncpy(stream->rtcp_addr, rtcp_candidate->taddr.ip, sizeof(stream->rtcp_addr)); - stream->rtp_port = rtp_candidate->taddr.port; - stream->rtcp_port = rtcp_candidate->taddr.port; - } else { - memset(stream->rtp_addr, 0, sizeof(stream->rtp_addr)); - memset(stream->rtcp_addr, 0, sizeof(stream->rtcp_addr)); - } - if ((strlen(ice_check_list_local_pwd(cl)) != strlen(desc->ice_pwd)) || (strcmp(ice_check_list_local_pwd(cl), desc->ice_pwd))) - strncpy(stream->ice_pwd, ice_check_list_local_pwd(cl), sizeof(stream->ice_pwd)); - else - memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd)); - if ((strlen(ice_check_list_local_ufrag(cl)) != strlen(desc->ice_ufrag)) || (strcmp(ice_check_list_local_ufrag(cl), desc->ice_ufrag))) - strncpy(stream->ice_ufrag, ice_check_list_local_ufrag(cl), sizeof(stream->ice_ufrag)); - else - memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd)); - stream->ice_mismatch = ice_check_list_is_mismatch(cl); - if ((ice_check_list_state(cl) == ICL_Running) || (ice_check_list_state(cl) == ICL_Completed)) { - memset(stream->ice_candidates, 0, sizeof(stream->ice_candidates)); - for (j = 0; j < MIN((int)bctbx_list_size(cl->local_candidates), SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES); j++) { - SalIceCandidate *sal_candidate = &stream->ice_candidates[nb_candidates]; - IceCandidate *ice_candidate = reinterpret_cast(bctbx_list_nth_data(cl->local_candidates, j)); - const char *default_addr = NULL; - int default_port = 0; - if (ice_candidate->componentID == 1) { - default_addr = stream->rtp_addr; - default_port = stream->rtp_port; - } else if (ice_candidate->componentID == 2) { - default_addr = stream->rtcp_addr; - default_port = stream->rtcp_port; - } else continue; - if (default_addr[0] == '\0') default_addr = desc->addr; - /* Only include the candidates matching the default destination for each component of the stream if the state is Completed as specified in RFC5245 section 9.1.2.2. */ - if ((ice_check_list_state(cl) == ICL_Completed) - && !((ice_candidate->taddr.port == default_port) && (strlen(ice_candidate->taddr.ip) == strlen(default_addr)) && (strcmp(ice_candidate->taddr.ip, default_addr) == 0))) - continue; - strncpy(sal_candidate->foundation, ice_candidate->foundation, sizeof(sal_candidate->foundation)); - sal_candidate->componentID = ice_candidate->componentID; - sal_candidate->priority = ice_candidate->priority; - strncpy(sal_candidate->type, ice_candidate_type(ice_candidate), sizeof(sal_candidate->type)); - strncpy(sal_candidate->addr, ice_candidate->taddr.ip, sizeof(sal_candidate->addr)); - sal_candidate->port = ice_candidate->taddr.port; - if ((ice_candidate->base != NULL) && (ice_candidate->base != ice_candidate)) { - strncpy(sal_candidate->raddr, ice_candidate->base->taddr.ip, sizeof(sal_candidate->raddr)); - sal_candidate->rport = ice_candidate->base->taddr.port; - } - nb_candidates++; - } - } - if ((ice_check_list_state(cl) == ICL_Completed) && (ice_session_role(session) == IR_Controlling)) { - memset(stream->ice_remote_candidates, 0, sizeof(stream->ice_remote_candidates)); - if (ice_check_list_selected_valid_remote_candidate(cl, &rtp_candidate, &rtcp_candidate) == TRUE) { - strncpy(stream->ice_remote_candidates[0].addr, rtp_candidate->taddr.ip, sizeof(stream->ice_remote_candidates[0].addr)); - stream->ice_remote_candidates[0].port = rtp_candidate->taddr.port; - strncpy(stream->ice_remote_candidates[1].addr, rtcp_candidate->taddr.ip, sizeof(stream->ice_remote_candidates[1].addr)); - stream->ice_remote_candidates[1].port = rtcp_candidate->taddr.port; - } else { - ms_error("ice: Selected valid remote candidates should be present if the check list is in the Completed state"); - } - } else { - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) { - stream->ice_remote_candidates[j].addr[0] = '\0'; - stream->ice_remote_candidates[j].port = 0; - } - } - } -} - -static void get_default_addr_and_port(uint16_t componentID, const SalMediaDescription *md, const SalStreamDescription *stream, const char **addr, int *port) -{ - if (componentID == 1) { - *addr = stream->rtp_addr; - *port = stream->rtp_port; - } else if (componentID == 2) { - *addr = stream->rtcp_addr; - *port = stream->rtcp_port; - } else return; - if ((*addr)[0] == '\0') *addr = md->addr; -} - -static void clear_ice_check_list(LinphoneCall *call, IceCheckList *removed){ - if (call->audiostream && call->audiostream->ms.ice_check_list==removed) - call->audiostream->ms.ice_check_list=NULL; - if (call->videostream && call->videostream->ms.ice_check_list==removed) - call->videostream->ms.ice_check_list=NULL; - if (call->textstream && call->textstream->ms.ice_check_list==removed) - call->textstream->ms.ice_check_list=NULL; -} - -void linphone_call_clear_unused_ice_candidates(LinphoneCall *call, const SalMediaDescription *md){ - int i; - - if (!call->localdesc) return; - for (i = 0; i < md->nb_streams; i++) { - const SalStreamDescription *local_stream = &call->localdesc->streams[i]; - const SalStreamDescription *stream = &md->streams[i]; - IceCheckList *cl = ice_session_check_list(call->ice_session, i); - if (!cl || !local_stream) continue; - - if (stream->rtcp_mux && local_stream->rtcp_mux){ - ice_check_list_remove_rtcp_candidates(cl); - } - } -} - bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md){ int i; @@ -1014,13 +293,13 @@ unsigned int linphone_core_get_audio_features(LinphoneCore *lc){ if (ret==AUDIO_STREAM_FEATURE_ALL){ /*since call recording is specified before creation of the stream in linphonecore, * it will be requested on demand. It is not necessary to include it all the time*/ - ret&=~AUDIO_STREAM_FEATURE_MIXED_RECORDING; + ret&=(unsigned int) ~AUDIO_STREAM_FEATURE_MIXED_RECORDING; } return ret; } bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc){ - return lp_config_get_int(lc->config,"sound","tone_indications",1); + return !!lp_config_get_int(lc->config,"sound","tone_indications",1); } int linphone_core_get_local_ip_for(int type, const char *dest, char *result){ @@ -1201,7 +480,7 @@ const char * linphone_core_get_echo_canceller_filter_name(const LinphoneCore *lc * task_fun must return BELLE_SIP_STOP when job is finished. **/ void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description){ - belle_sip_source_t *s=sal_create_timer(lc->sal,task_fun,data, 20, task_description); + belle_sip_source_t *s=lc->sal->createTimer(task_fun,data, 20, task_description); belle_sip_object_unref(s); } @@ -1334,7 +613,7 @@ const MSCryptoSuite * linphone_core_get_srtp_crypto_suites(LinphoneCore *lc){ char *pos; char *nextpos; char *params; - int found=0; + unsigned long found=0; MSCryptoSuite *result=NULL; pos=tmp; do{ @@ -1517,6 +796,15 @@ const char ** linphone_core_get_supported_file_formats(LinphoneCore *core){ return core->supported_formats; } +bctbx_list_t * linphone_core_get_supported_file_formats_list(LinphoneCore *core){ + bctbx_list_t *file_formats = NULL; + file_formats = bctbx_list_append(file_formats, ms_strdup("wav")); + if (ms_factory_lookup_filter_by_id(core->factory,MS_MKV_RECORDER_ID)){ + file_formats = bctbx_list_append(file_formats, ms_strdup("mkv")); + } + return file_formats; +} + bool_t linphone_core_file_format_supported(LinphoneCore *lc, const char *fmt){ const char **formats=linphone_core_get_supported_file_formats(lc); for(;*formats!=NULL;++formats){ @@ -1529,7 +817,7 @@ bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc){ /* Clients don't really need rtp symmetric, unless they have a public IP address and want * to interoperate with natted client. This case is not frequent with client apps. */ - return lp_config_get_int(lc->config,"rtp","symmetric",0); + return !!lp_config_get_int(lc->config,"rtp","symmetric",0); } LinphoneStatus linphone_core_set_network_simulator_params(LinphoneCore *lc, const OrtpNetworkSimulatorParams *params){ @@ -1618,223 +906,31 @@ void linphone_task_list_free(LinphoneTaskList *t){ t->hooks = bctbx_list_free_with_data(t->hooks, (void (*)(void*))ms_free); } -static bool_t _ice_params_found_in_remote_media_description(IceSession *ice_session, const SalMediaDescription *md) { - const SalStreamDescription *stream; - IceCheckList *cl = NULL; - int i; - bool_t ice_params_found = FALSE; - if ((md->ice_pwd[0] != '\0') && (md->ice_ufrag[0] != '\0')) { - ice_params_found=TRUE; - } else { - for (i = 0; i < md->nb_streams; i++) { - stream = &md->streams[i]; - cl = ice_session_check_list(ice_session, i); - if (cl) { - if ((stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) { - ice_params_found=TRUE; - } else { - ice_params_found=FALSE; - break; - } - } - } - } - return ice_params_found; -} - -static bool_t _check_for_ice_restart_and_set_remote_credentials(IceSession *ice_session, const SalMediaDescription *md, bool_t is_offer) { - const SalStreamDescription *stream; - IceCheckList *cl = NULL; - bool_t ice_restarted = FALSE; - int i; - - if ((strcmp(md->addr, "0.0.0.0") == 0) || (strcmp(md->addr, "::0") == 0)) { - ice_session_restart(ice_session, is_offer ? IR_Controlled : IR_Controlling); - ice_restarted = TRUE; - } else { - for (i = 0; i < md->nb_streams; i++) { - stream = &md->streams[i]; - cl = ice_session_check_list(ice_session, i); - if (cl && (strcmp(stream->rtp_addr, "0.0.0.0") == 0)) { - ice_session_restart(ice_session, is_offer ? IR_Controlled : IR_Controlling); - ice_restarted = TRUE; - break; - } - } - } - if ((ice_session_remote_ufrag(ice_session) == NULL) && (ice_session_remote_pwd(ice_session) == NULL)) { - ice_session_set_remote_credentials(ice_session, md->ice_ufrag, md->ice_pwd); - } else if (ice_session_remote_credentials_changed(ice_session, md->ice_ufrag, md->ice_pwd)) { - if (ice_restarted == FALSE) { - ice_session_restart(ice_session, is_offer ? IR_Controlled : IR_Controlling); - ice_restarted = TRUE; - } - ice_session_set_remote_credentials(ice_session, md->ice_ufrag, md->ice_pwd); - } - for (i = 0; i < md->nb_streams; i++) { - stream = &md->streams[i]; - cl = ice_session_check_list(ice_session, i); - if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) { - if (ice_check_list_remote_credentials_changed(cl, stream->ice_ufrag, stream->ice_pwd)) { - if (ice_restarted == FALSE - && ice_check_list_get_remote_ufrag(cl) - && ice_check_list_get_remote_pwd(cl)) { - /* restart only if remote ufrag/paswd was already set*/ - ice_session_restart(ice_session, is_offer ? IR_Controlled : IR_Controlling); - ice_restarted = TRUE; - } - ice_check_list_set_remote_credentials(cl, stream->ice_ufrag, stream->ice_pwd); - break; - } - } - } - return ice_restarted; -} - -/*the purpose of this function is to detect a situation where a check list is still running while a reINVITE -with remote-candidates is received*/ -bool_t check_ice_reinvite_needs_defered_response(LinphoneCall *call){ - SalMediaDescription *md = sal_call_get_remote_media_description(call->op); - int i,j; - IceCheckList *cl; - - if (ice_session_state(call->ice_session) != IS_Running ) return FALSE; - - for (i = 0; i < md->nb_streams; i++) { - SalStreamDescription *stream = &md->streams[i]; - cl = ice_session_check_list(call->ice_session, i); - - if (cl==NULL) continue; - if (stream->ice_mismatch == TRUE) { - return FALSE; - } - if (stream->rtp_port == 0) { - continue; - } - - if (ice_check_list_state(cl) != ICL_Running) continue; - - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) { - const SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[j]; - if (remote_candidate->addr[0] != '\0') return TRUE; - else break; - } - } - return FALSE; -} - -static void _create_ice_check_lists_and_parse_ice_attributes(LinphoneCall *call, const SalMediaDescription *md, bool_t ice_restarted) { - const SalStreamDescription *stream; - IceCheckList *cl = NULL; - bool_t default_candidate = FALSE; - const char *addr = NULL; - int port = 0; - int componentID = 0; - int remote_family; - int family; - int i, j; - - for (i = 0; i < md->nb_streams; i++) { - stream = &md->streams[i]; - cl = ice_session_check_list(call->ice_session, i); - - if (cl==NULL) continue; - if (stream->ice_mismatch == TRUE) { - ice_check_list_set_state(cl, ICL_Failed); - continue; - } - if (stream->rtp_port == 0) { - ice_session_remove_check_list(call->ice_session, cl); - clear_ice_check_list(call,cl); - continue; - } - - if ((stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) - ice_check_list_set_remote_credentials(cl, stream->ice_ufrag, stream->ice_pwd); - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES; j++) { - const SalIceCandidate *candidate = &stream->ice_candidates[j]; - default_candidate = FALSE; - addr = NULL; - port = 0; - if (candidate->addr[0] == '\0') break; - if ((candidate->componentID == 0) || (candidate->componentID > 2)) continue; - get_default_addr_and_port(candidate->componentID, md, stream, &addr, &port); - if (addr && (candidate->port == port) && (strlen(candidate->addr) == strlen(addr)) && (strcmp(candidate->addr, addr) == 0)) - default_candidate = TRUE; - if (strchr(candidate->addr, ':') != NULL) family = AF_INET6; - else family = AF_INET; - ice_add_remote_candidate(cl, candidate->type, family, candidate->addr, candidate->port, candidate->componentID, - candidate->priority, candidate->foundation, default_candidate); - } - if (ice_restarted == FALSE) { - bool_t losing_pairs_added = FALSE; - for (j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) { - const SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[j]; - addr = NULL; - port = 0; - componentID = j + 1; - if (remote_candidate->addr[0] == '\0') break; - get_default_addr_and_port(componentID, md, stream, &addr, &port); - if (j == 0) { - /* If we receive a re-invite and we finished ICE processing on our side, use the candidates given by the remote. */ - ice_check_list_unselect_valid_pairs(cl); - } - if (strchr(remote_candidate->addr, ':') != NULL) remote_family = AF_INET6; - else remote_family = AF_INET; - if (strchr(addr, ':') != NULL) family = AF_INET6; - else family = AF_INET; - - ice_add_losing_pair(cl, j + 1, remote_family, remote_candidate->addr, remote_candidate->port, family, addr, port); - losing_pairs_added = TRUE; - } - if (losing_pairs_added == TRUE) ice_check_list_check_completed(cl); - } - } -} - -static void _update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md, bool_t is_offer) { - const SalStreamDescription *stream; - IceCheckList *cl = NULL; - bool_t ice_restarted = FALSE; - int i; - - /* Check for ICE restart and set remote credentials. */ - ice_restarted = _check_for_ice_restart_and_set_remote_credentials(call->ice_session, md, is_offer); - - /* Create ICE check lists if needed and parse ICE attributes. */ - _create_ice_check_lists_and_parse_ice_attributes(call, md, ice_restarted); - for (i = 0; i < md->nb_streams; i++) { - stream = &md->streams[i]; - cl = ice_session_check_list(call->ice_session, i); - if (!cl) continue; - - if (!sal_stream_description_active(stream)) { - ice_session_remove_check_list_from_idx(call->ice_session, i); - clear_ice_check_list(call, cl); - } - } - linphone_call_clear_unused_ice_candidates(call, md); - ice_session_check_mismatch(call->ice_session); -} - -void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md, bool_t is_offer){ - if (_ice_params_found_in_remote_media_description(call->ice_session, md) == TRUE) { - _update_ice_from_remote_media_description(call, md, is_offer); - } else { - /* Response from remote does not contain mandatory ICE attributes, delete the session. */ - linphone_call_delete_ice_session(call); - linphone_call_set_symmetric_rtp(call, linphone_core_symmetric_rtp_enabled(linphone_call_get_core(call))); - return; - } - if (ice_session_nb_check_lists(call->ice_session) == 0) { - linphone_call_delete_ice_session(call); - linphone_call_set_symmetric_rtp(call, linphone_core_symmetric_rtp_enabled(linphone_call_get_core(call))); - } -} - void linphone_core_report_call_log(LinphoneCore *lc, LinphoneCallLog *call_log){ bool_t call_logs_sqlite_db_found = FALSE; + // TODO: This is a workaround that has to be removed ASAP + // Do not add calls made to the conference factory in the history + const char *conference_factory_uri = nullptr; + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(lc, call_log->to); + if (proxy) + conference_factory_uri = linphone_proxy_config_get_conference_factory_uri(proxy); + if (conference_factory_uri) { + LinphoneAddress *conference_factory_addr = linphone_address_new(conference_factory_uri); + if (linphone_address_weak_equal(call_log->to, conference_factory_addr)) { + linphone_address_unref(conference_factory_addr); + return; + } + linphone_address_unref(conference_factory_addr); + } + const char *usernameFrom = linphone_address_get_username(call_log->from); + const char *usernameTo = linphone_address_get_username(call_log->to); + if ((usernameFrom && (strstr(usernameFrom, "chatroom-") == usernameFrom)) + || (usernameTo && (strstr(usernameTo, "chatroom-") == usernameTo)) + ) + return; + // End of workaround + #ifdef SQLITE_STORAGE_ENABLED if (lc->logs_db) { call_logs_sqlite_db_found = TRUE; diff --git a/coreapi/nat_policy.c b/coreapi/nat_policy.c index dcd0b2d75..6a969b375 100644 --- a/coreapi/nat_policy.c +++ b/coreapi/nat_policy.c @@ -18,8 +18,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/core.h" -#include "private.h" +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" static LinphoneNatPolicy * _linphone_nat_policy_new_with_ref(LinphoneCore *lc, const char *ref) { LinphoneNatPolicy *policy = belle_sip_object_new(LinphoneNatPolicy); @@ -163,12 +166,7 @@ bool_t linphone_nat_policy_upnp_enabled(const LinphoneNatPolicy *policy) { void linphone_nat_policy_enable_upnp(LinphoneNatPolicy *policy, bool_t enable) { policy->upnp_enabled = enable; if (enable) { -#ifdef BUILD_UPNP - policy->stun_enabled = policy->turn_enabled = policy->ice_enabled = FALSE; - ms_warning("Enabling uPnP NAT policy has disabled any other previously enabled policies"); -#else - ms_warning("Cannot enable the uPnP NAT policy because the uPnP support is not compiled in"); -#endif + ms_warning("uPnP NAT policy is no longer supported"); } } @@ -187,6 +185,17 @@ void linphone_nat_policy_set_stun_server(LinphoneNatPolicy *policy, const char * if (new_stun_server != NULL) { policy->stun_server = new_stun_server; } + if (policy->stun_addrinfo) { + bctbx_freeaddrinfo(policy->stun_addrinfo); + policy->stun_addrinfo = NULL; + } + if (policy->stun_resolver_context){ + belle_sip_resolver_context_cancel(policy->stun_resolver_context); + belle_sip_object_unref(policy->stun_resolver_context); + policy->stun_resolver_context = NULL; + + } + linphone_nat_policy_resolve_stun_server(policy); } const char * linphone_nat_policy_get_stun_server_username(const LinphoneNatPolicy *policy) { @@ -227,7 +236,7 @@ void linphone_nat_policy_resolve_stun_server(LinphoneNatPolicy *policy) { if (linphone_nat_policy_stun_server_activated(policy) && (policy->lc->sal != NULL) && !policy->stun_resolver_context) { char host[NI_MAXHOST]; - int port = 3478; + int port = 0; linphone_parse_host_port(policy->stun_server, host, sizeof(host), &port); if (linphone_nat_policy_turn_enabled(policy)) service = "turn"; else if (linphone_nat_policy_stun_enabled(policy)) service = "stun"; @@ -235,7 +244,12 @@ void linphone_nat_policy_resolve_stun_server(LinphoneNatPolicy *policy) { int family = AF_INET; if (linphone_core_ipv6_enabled(policy->lc) == TRUE) family = AF_INET6; ms_message("Starting stun server resolution [%s]", host); - policy->stun_resolver_context = sal_resolve(policy->lc->sal, service, "udp", host, port, family, stun_server_resolved, policy); + if (port == 0) { + port = 3478; + policy->stun_resolver_context = policy->lc->sal->resolve(service, "udp", host, port, family, stun_server_resolved, policy); + } else { + policy->stun_resolver_context = policy->lc->sal->resolveA(host, port, family, stun_server_resolved, policy); + } if (policy->stun_resolver_context) belle_sip_object_ref(policy->stun_resolver_context); } } @@ -257,7 +271,7 @@ const struct addrinfo * linphone_nat_policy_get_stun_server_addrinfo(LinphoneNat int wait_limit = 1000; linphone_nat_policy_resolve_stun_server(policy); while ((policy->stun_addrinfo == NULL) && (policy->stun_resolver_context != NULL) && (wait_ms < wait_limit)) { - sal_iterate(policy->lc->sal); + policy->lc->sal->iterate(); ms_usleep(50000); wait_ms += 50; } @@ -279,7 +293,7 @@ LinphoneNatPolicy * linphone_config_create_nat_policy_from_section(const Linphon policy = _linphone_nat_policy_new_with_ref(NULL, config_ref); else policy = linphone_nat_policy_new(NULL); - + if (server != NULL) linphone_nat_policy_set_stun_server(policy, server); if (username != NULL) linphone_nat_policy_set_stun_server_username(policy, username); if (l != NULL) { @@ -303,7 +317,7 @@ LinphoneNatPolicy * linphone_core_create_nat_policy_from_config(LinphoneCore *lc char *section; int index; bool_t finished = FALSE; - + for (index = 0; finished != TRUE; index++) { section = belle_sip_strdup_printf("nat_policy_%i", index); if (lp_config_has_section(config, section)) { @@ -318,3 +332,7 @@ LinphoneNatPolicy * linphone_core_create_nat_policy_from_config(LinphoneCore *lc } return policy; } + +LinphoneCore *linphone_nat_policy_get_core(const LinphoneNatPolicy *policy) { + return policy->lc; +} diff --git a/coreapi/offeranswer.c b/coreapi/offeranswer.c index d3e7b2ab1..d76f1c68e 100644 --- a/coreapi/offeranswer.c +++ b/coreapi/offeranswer.c @@ -17,10 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "c-wrapper/internal/c-sal.h" #include "sal/sal.h" #include "offeranswer.h" #include "private.h" +#include "utils/payload-type-handler.h" + static bool_t only_telephone_event(const bctbx_list_t *l){ for(;l!=NULL;l=l->next){ PayloadType *p=(PayloadType*)l->data; diff --git a/coreapi/payload_type.c b/coreapi/payload_type.c index 20e2bc949..75ccc1f94 100644 --- a/coreapi/payload_type.c +++ b/coreapi/payload_type.c @@ -19,7 +19,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include + #include "linphone/payload_type.h" + +#include "c-wrapper/c-wrapper.h" +#include "utils/payload-type-handler.h" + +// TODO: From coreapi. Remove me later. #include "private.h" struct _LinphonePayloadType { @@ -104,11 +110,7 @@ char *linphone_payload_type_get_description(const LinphonePayloadType *pt) { static const char *_linphone_core_get_payload_type_codec_description(const LinphoneCore *lc, const OrtpPayloadType *pt) { if (ms_factory_codec_supported(lc->factory, pt->mime_type)){ MSFilterDesc *desc=ms_factory_get_encoder(lc->factory, pt->mime_type); -#ifdef ENABLE_NLS - return dgettext("mediastreamer",desc->text); -#else return desc->text; -#endif } return NULL; } @@ -134,16 +136,16 @@ const char *linphone_payload_type_get_encoder_description(const LinphonePayloadT } static int _linphone_core_get_payload_type_normal_bitrate(const LinphoneCore *lc, const OrtpPayloadType *pt) { - int maxbw = get_min_bandwidth(linphone_core_get_download_bandwidth(lc), + int maxbw = LinphonePrivate::PayloadTypeHandler::getMinBandwidth(linphone_core_get_download_bandwidth(lc), linphone_core_get_upload_bandwidth(lc)); if (pt->type==PAYLOAD_AUDIO_CONTINUOUS || pt->type==PAYLOAD_AUDIO_PACKETIZED){ - return get_audio_payload_bandwidth(lc, pt, maxbw); + return LinphonePrivate::PayloadTypeHandler::getAudioPayloadTypeBandwidth(pt, maxbw); }else if (pt->type==PAYLOAD_VIDEO){ int video_bw; if (maxbw<=0) { video_bw=1500; /*default bitrate for video stream when no bandwidth limit is set, around 1.5 Mbit/s*/ }else{ - video_bw=get_remaining_bandwidth_for_video(maxbw,lc->audio_bw); + video_bw=LinphonePrivate::PayloadTypeHandler::getRemainingBandwidthForVideo(maxbw,lc->audio_bw); } return video_bw; } @@ -258,7 +260,7 @@ bool_t linphone_payload_type_is_vbr(const LinphonePayloadType *pt) { } bool_t _linphone_core_check_payload_type_usability(const LinphoneCore *lc, const OrtpPayloadType *pt) { - int maxbw=get_min_bandwidth(linphone_core_get_download_bandwidth(lc), + int maxbw=LinphonePrivate::PayloadTypeHandler::getMinBandwidth(linphone_core_get_download_bandwidth(lc), linphone_core_get_upload_bandwidth(lc)); return linphone_core_is_payload_type_usable_for_bandwidth(lc, pt, maxbw); } @@ -293,3 +295,15 @@ BELLE_SIP_INSTANCIATE_VPTR(LinphonePayloadType, belle_sip_object_t, NULL, // marshale TRUE // unown ); + + +void payload_type_set_enable(OrtpPayloadType *pt, bool_t value) { + if (value) + payload_type_set_flag(pt, PAYLOAD_TYPE_ENABLED); + else + payload_type_unset_flag(pt, PAYLOAD_TYPE_ENABLED); +} + +bool_t payload_type_enabled(const OrtpPayloadType *pt) { + return (pt->flags & PAYLOAD_TYPE_ENABLED); +} diff --git a/coreapi/platform-helpers.h b/coreapi/platform-helpers.h deleted file mode 100644 index a067c354c..000000000 --- a/coreapi/platform-helpers.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -linphone -Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef platform_helpers_h -#define platform_helpers_h - - -namespace LinphonePrivate{ - -/** - * This interface aims at abstracting some features offered by the platform, most often mobile platforms. - * A per platform implementation is to be made to implement these features, if available on the platform - */ -class PlatformHelpers{ - public: - //This method shall retrieve DNS server list from the platform and assign it to the core. - virtual void setDnsServers() = 0; - virtual void acquireWifiLock() = 0; - virtual void releaseWifiLock() = 0; - virtual void acquireMcastLock() = 0; - virtual void releaseMcastLock() = 0; - virtual void acquireCpuLock() = 0; - virtual void releaseCpuLock() = 0; - virtual ~PlatformHelpers(); - protected: - PlatformHelpers(LinphoneCore *lc) : mCore(lc){ - } - LinphoneCore *mCore; -}; - -class StubbedPlatformHelpers : public PlatformHelpers{ -public: - StubbedPlatformHelpers(LinphoneCore *lc); - virtual void setDnsServers(); - virtual void acquireWifiLock(); - virtual void releaseWifiLock(); - virtual void acquireMcastLock(); - virtual void releaseMcastLock(); - virtual void acquireCpuLock(); - virtual void releaseCpuLock(); - virtual ~StubbedPlatformHelpers(); -}; - -PlatformHelpers *createAndroidPlatformHelpers(LinphoneCore *lc, void *system_context); -PlatformHelpers *createIosPlatformHelpers(LinphoneCore *lc, void *system_context); - -}//end of namespace - -#endif diff --git a/coreapi/player.c b/coreapi/player.c index aee053ead..ac9e3f5ab 100644 --- a/coreapi/player.c +++ b/coreapi/player.c @@ -18,6 +18,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. #include "private.h" BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePlayer); @@ -97,10 +100,11 @@ void linphone_player_close(LinphonePlayer *obj){ } void linphone_player_destroy(LinphonePlayer *obj) { - if(obj->destroy) obj->destroy(obj); + _linphone_player_destroy(obj); } void _linphone_player_destroy(LinphonePlayer *player) { + if(player->destroy) player->destroy(player); linphone_player_cbs_unref(player->callbacks); } @@ -112,15 +116,16 @@ void _linphone_player_destroy(LinphonePlayer *player) { 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)); + if (linphone_call_get_state(call)!=LinphoneCallStreamsRunning){ + ms_warning("Call [%p]: in-call player not usable in state [%s]",call,linphone_call_state_to_string(linphone_call_get_state(call))); return FALSE; } - if (call->audiostream==NULL) { + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + if (astream==NULL) { ms_error("call_player_check_state(): no audiostream."); return FALSE; } - if (check_player && call->audiostream->av_player.player==NULL){ + if (check_player && astream->av_player.player==NULL){ ms_error("call_player_check_state(): no player."); return FALSE; } @@ -142,7 +147,8 @@ 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); + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + filter=audio_stream_open_remote_play(astream,filename); if (!filter) return -1; ms_filter_add_notify_callback(filter,&on_eof,player,FALSE); return 0; @@ -151,34 +157,39 @@ static int call_player_open(LinphonePlayer* player, const char *filename){ 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); + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + return ms_filter_call_method_noarg(astream->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); + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + return ms_filter_call_method_noarg(astream->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); + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + ms_filter_call_method(astream->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); + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + return ms_filter_call_method(astream->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; - audio_stream_close_remote_play(call->audiostream); - + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + audio_stream_close_remote_play(astream); + } static void on_call_destroy(void *obj, belle_sip_object_t *call_being_destroyed){ @@ -198,6 +209,9 @@ LinphonePlayer *linphone_call_build_player(LinphoneCall *call){ return obj; } +LinphoneCore *linphone_player_get_core(const LinphonePlayer *player){ + return linphone_call_get_core((LinphoneCall *)player->impl); +} BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePlayerCbs); diff --git a/coreapi/presence.c b/coreapi/presence.c index bf076fca5..bb4ffa087 100644 --- a/coreapi/presence.c +++ b/coreapi/presence.c @@ -18,16 +18,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "linphone/core.h" -#include "private.h" #include "linphone/lpconfig.h" #include "linphone/presence.h" +#include "c-wrapper/c-wrapper.h" +// TODO: From coreapi. Remove me later. +#include "private.h" + +using namespace LinphonePrivate; extern const char *__policy_enum_to_str(LinphoneSubscribePolicy pol); - - struct _LinphonePresenceNote { belle_sip_object_t base; void *user_data; @@ -371,6 +373,7 @@ LinphoneStatus linphone_presence_model_set_contact(LinphonePresenceModel *model, service = linphone_presence_service_new(NULL, LinphonePresenceBasicStatusClosed, NULL); if (service == NULL) return -1; linphone_presence_model_add_service(model, service); + linphone_presence_service_unref(service); } return linphone_presence_service_set_contact(service, contact); } @@ -389,7 +392,7 @@ static void presence_model_get_activity(const LinphonePresencePerson *person, st if (st->current_idx != (unsigned)-1) { unsigned int size = (unsigned int)bctbx_list_size(person->activities); if (st->requested_idx < (st->current_idx + size)) { - st->activity = (LinphonePresenceActivity *)bctbx_list_nth_data(person->activities, st->requested_idx - st->current_idx); + st->activity = (LinphonePresenceActivity *)bctbx_list_nth_data(person->activities, (int)(st->requested_idx - st->current_idx)); st->current_idx = (unsigned)-1; } else { st->current_idx += size; @@ -641,7 +644,7 @@ LinphonePresenceService * linphone_presence_model_get_nth_service(const Linphone if ((model == NULL) || (idx >= linphone_presence_model_get_nb_services(model))) return NULL; - return (LinphonePresenceService *)bctbx_list_nth_data(model->services, idx); + return (LinphonePresenceService *)bctbx_list_nth_data(model->services, (int)idx); } LinphoneStatus linphone_presence_model_add_service(LinphonePresenceModel *model, LinphonePresenceService *service) { @@ -667,7 +670,7 @@ LinphonePresencePerson * linphone_presence_model_get_nth_person(const LinphonePr if ((model == NULL) || (idx >= linphone_presence_model_get_nb_persons(model))) return NULL; - return (LinphonePresencePerson *)bctbx_list_nth_data(model->persons, idx); + return (LinphonePresencePerson *)bctbx_list_nth_data(model->persons, (int)idx); } LinphoneStatus linphone_presence_model_add_person(LinphonePresenceModel *model, LinphonePresencePerson *person) { @@ -803,7 +806,7 @@ LinphonePresenceNote * linphone_presence_service_get_nth_note(const LinphonePres if ((service == NULL) || (idx >= linphone_presence_service_get_nb_notes(service))) return NULL; - return (LinphonePresenceNote *)bctbx_list_nth_data(service->notes, idx); + return (LinphonePresenceNote *)bctbx_list_nth_data(service->notes, (int)idx); } LinphoneStatus linphone_presence_service_add_note(LinphonePresenceService *service, LinphonePresenceNote *note) { @@ -864,7 +867,7 @@ unsigned int linphone_presence_person_get_nb_activities(const LinphonePresencePe LinphonePresenceActivity * linphone_presence_person_get_nth_activity(const LinphonePresencePerson *person, unsigned int idx) { if ((person == NULL) || (idx >= linphone_presence_person_get_nb_activities(person))) return NULL; - return (LinphonePresenceActivity *)bctbx_list_nth_data(person->activities, idx); + return (LinphonePresenceActivity *)bctbx_list_nth_data(person->activities, (int)idx); } LinphoneStatus linphone_presence_person_add_activity(LinphonePresencePerson *person, LinphonePresenceActivity *activity) { @@ -890,7 +893,7 @@ unsigned int linphone_presence_person_get_nb_notes(const LinphonePresencePerson LinphonePresenceNote * linphone_presence_person_get_nth_note(const LinphonePresencePerson *person, unsigned int idx) { if ((person == NULL) || (idx >= linphone_presence_person_get_nb_notes(person))) return NULL; - return (LinphonePresenceNote *)bctbx_list_nth_data(person->notes, idx); + return (LinphonePresenceNote *)bctbx_list_nth_data(person->notes, (int)idx); } LinphoneStatus linphone_presence_person_add_note(LinphonePresencePerson *person, LinphonePresenceNote *note) { @@ -915,7 +918,7 @@ unsigned int linphone_presence_person_get_nb_activities_notes(const LinphonePres LinphonePresenceNote * linphone_presence_person_get_nth_activities_note(const LinphonePresencePerson *person, unsigned int idx) { if ((person == NULL) || (idx >= linphone_presence_person_get_nb_activities_notes(person))) return NULL; - return (LinphonePresenceNote *)bctbx_list_nth_data(person->activities_notes, idx); + return (LinphonePresenceNote *)bctbx_list_nth_data(person->activities_notes, (int)idx); } LinphoneStatus linphone_presence_person_add_activities_note(LinphonePresencePerson *person, LinphonePresenceNote *note) { @@ -1295,7 +1298,7 @@ static int process_pidf_xml_presence_services(xmlparsing_context_t *xml_ctx, Lin if (service != NULL) { if (timestamp_str != NULL) presence_service_set_timestamp(service, parse_timestamp(timestamp_str)); if (contact_str != NULL) linphone_presence_service_set_contact(service, contact_str); - process_pidf_xml_presence_service_notes(xml_ctx, service, i); + process_pidf_xml_presence_service_notes(xml_ctx, service, (unsigned int)i); linphone_presence_model_add_service(model, service); linphone_presence_service_unref(service); } @@ -1435,9 +1438,9 @@ static int process_pidf_xml_presence_persons(xmlparsing_context_t *xml_ctx, Linp person = presence_person_new(person_id_str, timestamp); if (person != NULL) { - err = process_pidf_xml_presence_person_activities(xml_ctx, person, i); + err = process_pidf_xml_presence_person_activities(xml_ctx, person, (unsigned int)i); if (err == 0) { - err = process_pidf_xml_presence_person_notes(xml_ctx, person, i); + err = process_pidf_xml_presence_person_notes(xml_ctx, person, (unsigned int)i); } if (err == 0) { presence_model_add_person(model, person); @@ -1563,7 +1566,7 @@ void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *p } } -void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ +void linphone_subscription_new(LinphoneCore *lc, SalSubscribeOp *op, const char *from){ LinphoneFriend *lf=NULL; char *tmp; LinphoneAddress *uri; @@ -1580,12 +1583,12 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ linphone_friend_add_incoming_subscription(lf, op); lf->inc_subscribe_pending=TRUE; if (lp_config_get_int(lc->config,"sip","notify_pending_state",0)) { - sal_notify_pending_state(op); + op->notifyPendingState(); } - sal_subscribe_accept(op); + op->accept(); } else { ms_message("%s is not authorized to subscribe", from); - sal_subscribe_decline(op, SalReasonDeclined); + op->decline(SalReasonDeclined); } linphone_friend_done(lf); /*this will do all necessary actions */ }else{ @@ -1593,14 +1596,14 @@ void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from){ if (linphone_find_friend_by_address(lc->subscribers,uri,&lf)){ if (lf->pol==LinphoneSPDeny){ ms_message("Rejecting %s because we already rejected it once.",from); - sal_subscribe_decline(op,SalReasonDeclined); + op->decline(SalReasonDeclined); } else { /* else it is in wait for approval state, because otherwise it is in the friend list.*/ ms_message("New subscriber found in subscriber list, in %s state.",__policy_enum_to_str(lf->pol)); } }else { - sal_subscribe_accept(op); + op->accept(); linphone_core_add_subscriber(lc,tmp,op); } } @@ -1953,8 +1956,11 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa if (linphone_core_get_default_friend_list(lc) != NULL) lf=linphone_core_find_friend_by_out_subscribe(lc, op); if (lf==NULL && lp_config_get_int(lc->config,"sip","allow_out_of_subscribe_presence",0)){ - const SalAddress *addr=sal_op_get_from_address(op); - lf = linphone_core_find_friend(lc, (LinphoneAddress *)addr); + char *buf = sal_address_as_string_uri_only(op->getFromAddress()); + LinphoneAddress *addr = linphone_address_new(buf); + lf = linphone_core_find_friend(lc, addr); + ms_free(buf); + linphone_address_unref(addr); } if (lf!=NULL){ LinphonePresenceActivity *activity = NULL; @@ -1979,27 +1985,27 @@ void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, Sa linphone_core_notify_notify_presence_received(lc,(LinphoneFriend*)lf); if (op != lf->outsub){ /*case of a NOTIFY received out of any dialog*/ - sal_op_release(op); + op->release(); return; } }else{ ms_message("But this person is not part of our friend list, so we don't care."); linphone_presence_model_unref(presence); - sal_op_release(op); + op->release(); return ; } if (ss==SalSubscribeTerminated){ if (lf){ if (lf->outsub != op){ - sal_op_release(op); + op->release(); } if (lf->outsub){ - sal_op_release(lf->outsub); + lf->outsub->release(); lf->outsub=NULL; } lf->subscribe_active=FALSE; }else{ - sal_op_release(op); + op->release(); } } } @@ -2014,7 +2020,7 @@ void linphone_subscription_closed(LinphoneCore *lc, SalOp *op){ linphone_friend_remove_incoming_subscription(lf, op); }else{ /*case of an op that we already released because the friend was destroyed*/ - ms_message("Receiving unsuscribe for unknown in-subscribtion from %s", sal_op_get_from(op)); + ms_message("Receiving unsuscribe for unknown in-subscribtion from %s", op->getFrom().c_str()); } } diff --git a/coreapi/private.h b/coreapi/private.h index 54c18b7e5..bc33c4184 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -25,22 +25,48 @@ #ifndef _PRIVATE_H #define _PRIVATE_H +#include + #include "linphone/core.h" #include "linphone/friend.h" #include "linphone/friendlist.h" #include "linphone/tunnel.h" -#include "linphone/core_utils.h" -#include "linphone/conference.h" -#include "sal/sal.h" -#ifdef __cplusplus -#include "platform-helpers.h" + +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic push #endif +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#else +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif +#include "linphone/core_utils.h" +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic pop +#endif + +#include "linphone/conference.h" + +#include "address/address.h" +#include "c-wrapper/internal/c-sal.h" +#include "sal/call-op.h" +#include "sal/event-op.h" +#include "sal/message-op.h" +#include "sal/presence-op.h" +#include "sal/register-op.h" + +#ifdef __cplusplus +#include "core/platform-helpers/platform-helpers.h" +#endif + #include "linphone/sipsetup.h" #include "quality_reporting.h" #include "linphone/ringtoneplayer.h" #include "vcard_private.h" #include "carddav.h" #include "linphone/player.h" +#include "account_creator_private.h" +#include "tester_utils.h" #include "bctoolbox/port.h" #include "bctoolbox/map.h" @@ -57,41 +83,12 @@ #include "mediastreamer2/ice.h" #include "mediastreamer2/mediastream.h" #include "mediastreamer2/msconference.h" -#ifdef BUILD_UPNP -#include "upnp.h" -#endif //BUILD_UPNP #ifndef LIBLINPHONE_VERSION #define LIBLINPHONE_VERSION LINPHONE_VERSION #endif -#ifdef ENABLE_NLS - -#ifdef _MSC_VER -// prevent libintl.h from re-defining fprintf and vfprintf -#ifndef fprintf -#define fprintf fprintf -#endif -#ifndef vfprintf -#define vfprintf vfprintf -#endif -#define _GL_STDIO_H -#endif - -#include - -#ifndef _ -#define _(String) dgettext(GETTEXT_PACKAGE,String) -#endif -#else -#ifndef _ -#define _(something) (something) -#endif -#ifndef ngettext -#define ngettext(singular, plural, number) (((number)==1)?(singular):(plural)) -#endif -#endif #ifdef __ANDROID__ #include #endif @@ -115,1156 +112,26 @@ #endif #endif -#include -#include -#include -#include - #ifdef SQLITE_STORAGE_ENABLED #include #endif -#ifdef __cplusplus -extern "C" { -#endif + +#include "private_structs.h" +#include "private_functions.h" +#include "core_private.h" #define STRING_RESET(field) if (field) bctbx_free(field); (field) = NULL #define STRING_SET(field, value) do{ if (field){bctbx_free(field);field=NULL;}; field=bctbx_strdup(value); }while(0) #define STRING_TRANSFER(field, newvalue) do{ if (field){bctbx_free(field);field=NULL;}; field=newvalue; }while(0) -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; - PayloadType *audio_codec; /*audio codec currently in use */ - PayloadType *video_codec; /*video codec currently in use */ - PayloadType *text_codec; /*text codec currently in use */ - MSVideoSize sent_vsize; /* DEPRECATED: Size of the video currently being sent */ - MSVideoSize recv_vsize; /* DEPRECATED: Size of the video currently being received */ - LinphoneVideoDefinition *sent_vdef; /* Definition of the video currently being sent */ - LinphoneVideoDefinition *recv_vdef; /* Definition of the video currrently being received */ - float received_fps,sent_fps; - int down_bw; - int up_bw; - int down_ptime; - int up_ptime; - char *record_file; - char *session_name; - SalCustomHeader *custom_headers; - SalCustomSdpAttribute *custom_sdp_attributes; - SalCustomSdpAttribute *custom_sdp_media_attributes[LinphoneStreamTypeUnknown]; - LinphonePrivacyMask privacy; - LinphoneMediaDirection audio_dir; - LinphoneMediaDirection video_dir; - bool_t has_audio; - bool_t has_video; - bool_t avpf_enabled; /* RTCP feedback messages are enabled */ - bool_t implicit_rtcp_fb; - - 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*/ - bool_t internal_call_update; /*use mark that call update was requested internally (might be by ice) - unused for the moment*/ - bool_t video_multicast_enabled; - - bool_t audio_multicast_enabled; - bool_t realtimetext_enabled; - bool_t update_call_when_ice_completed; - bool_t encryption_mandatory; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCallParams); - - -struct _LinphoneQualityReporting{ - reporting_session_report_t * reports[3]; /**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*/ - LinphoneQualityReportingReportSendCb on_report_sent; -}; - -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*/ - LinphoneAddress *from; /**= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#if defined(__clang__) || defined(__GNUC__) -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif -#ifdef _MSC_VER -#pragma deprecated(message_state_changed_cb) -#endif - LinphoneChatMessageStateChangedCb message_state_changed_cb; -#if defined(__clang__) || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif -}; - -/* - *Gets a Message with a given message id and direction. - */ -LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_room_find_message_with_dir(LinphoneChatRoom *cr, const char *message_id,LinphoneChatMessageDir dir); - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessage); - -typedef struct StunCandidate{ - char addr[64]; - int port; -}StunCandidate; - - -typedef struct _PortConfig{ - char multicast_ip[LINPHONE_IPADDR_SIZE]; - char multicast_bind_ip[LINPHONE_IPADDR_SIZE]; - int rtp_port; - int rtcp_port; -}PortConfig; - -struct _LinphoneCallCbs { - belle_sip_object_t base; - void *user_data; - LinphoneCallCbsDtmfReceivedCb dtmf_received_cb; - LinphoneCallCbsEncryptionChangedCb encryption_changed_cb; - LinphoneCallCbsInfoMessageReceivedCb info_message_received_cb; - LinphoneCallCbsStateChangedCb state_changed_cb; - LinphoneCallCbsStatsUpdatedCb stats_updated_cb; - LinphoneCallCbsTransferStateChangedCb transfer_state_changed_cb; - LinphoneCallCbsAckProcessingCb ack_processing; - LinphoneCallCbsTmmbrReceivedCb tmmbr_received_cb; - LinphoneCallCbsSnapshotTakenCb snapshot_taken_cb; - LinphoneCallCbsNextVideoFrameDecodedCb next_video_frame_decoded_cb; -}; - -LinphoneCallCbs * _linphone_call_cbs_new(void); - -struct _LinphoneCall{ - belle_sip_object_t base; - void *user_data; - struct _LinphoneCore *core; - LinphoneErrorInfo *ei; - int af; /*the address family to prefer for RTP path, guessed from signaling path*/ - LinphoneCallDir dir; - SalMediaDescription *biggestdesc; /*media description with all already proposed streams, used to remember the mapping of streams*/ - SalMediaDescription *localdesc; - SalMediaDescription *resultdesc; - struct _RtpProfile *audio_profile; - struct _RtpProfile *video_profile; - struct _RtpProfile *text_profile; - struct _RtpProfile *rtp_io_audio_profile; - struct _RtpProfile *rtp_io_video_profile; - struct _LinphoneCallLog *log; - LinphoneAddress *me; /*Either from or to based on call dir*/ - LinphoneAddress *diversion_address; - SalOp *op; - SalOp *ping_op; - char media_localip[LINPHONE_IPADDR_SIZE]; /* our best guess for local media ipaddress for this call */ - LinphoneCallState state; - LinphoneCallState prevstate; - LinphoneCallState transfer_state; /*idle if no transfer*/ - LinphoneProxyConfig *dest_proxy; - int main_audio_stream_index, main_video_stream_index, main_text_stream_index; - PortConfig media_ports[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; - MSMediaStreamSessions sessions[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; /*the rtp, srtp, zrtp contexts for each stream*/ - StunCandidate ac, vc, tc; /*audio video text ip/port discovered by STUN*/ - struct _AudioStream *audiostream; /**/ - struct _VideoStream *videostream; - struct _TextStream *textstream; - void *video_window_id; - MSAudioEndpoint *endpoint; /*used for conferencing*/ - char *refer_to; - LinphoneCallParams *params; - LinphoneCallParams *current_params; - LinphoneCallParams *remote_params; - int up_bw; /*upload bandwidth setting at the time the call is started. Used to detect if it changes during a call */ - int audio_bw; /*upload bandwidth used by audio */ - OrtpEvQueue *audiostream_app_evq; - char *auth_token; - OrtpEvQueue *videostream_app_evq; - OrtpEvQueue *textstream_app_evq; - CallCallbackObj nextVideoFrameDecoded; - LinphoneCallStats *audio_stats; - LinphoneCallStats *video_stats; - LinphoneCallStats *text_stats; -#ifdef BUILD_UPNP - UpnpSession *upnp_session; -#endif //BUILD_UPNP - IceSession *ice_session; - int ping_time; - unsigned int remote_session_id; - unsigned int remote_session_ver; - LinphoneCall *referer; /*when this call is the result of a transfer, referer is set to the original call that caused the transfer*/ - LinphoneCall *transfer_target;/*if this call received a transfer request, then transfer_target points to the new call created to the refer target */ - int localdesc_changed;/*not a boolean, contains a mask representing changes*/ - LinphonePlayer *player; - unsigned long bg_task_id; /*used to prevent device to suspend app while a call is received in background*/ - unsigned int nb_media_starts; - - char *dtmf_sequence; /*DTMF sequence needed to be sent using #dtmfs_timer*/ - belle_sip_source_t *dtmfs_timer; /*DTMF timer needed to send a DTMF sequence*/ - - char *dtls_certificate_fingerprint; /**> This fingerprint is computed during stream init and is stored in call to be used when making local media description */ - char *onhold_file; /*set if a on-hold file is to be played*/ - LinphoneChatRoom *chat_room; - LinphoneConference *conf_ref; /**> Point on the associated conference if this call is part of a conference. NULL instead. */ - bool_t refer_pending; - bool_t expect_media_in_ack; - bool_t audio_muted; - bool_t camera_enabled; - - bool_t all_muted; /*this flag is set during early medias*/ - bool_t playing_ringbacktone; - bool_t ringing_beep; /* whether this call is ringing through an already existent current call*/ - bool_t auth_token_verified; - - bool_t defer_update; - bool_t was_automatically_paused; - bool_t ping_replied; - bool_t record_active; - - bool_t paused_by_app; - bool_t broken; /*set to TRUE when the call is in broken state due to network disconnection or transport */ - bool_t defer_notify_incoming; - bool_t need_localip_refresh; - - bool_t reinvite_on_cancel_response_requested; - bool_t non_op_error; /*set when the LinphoneErrorInfo was set at higher level than sal*/ - bool_t incoming_ice_reinvite_pending; - - bctbx_list_t *callbacks; /* A list of LinphoneCallCbs object */ - LinphoneCallCbs *current_cbs; /* The current LinphoneCallCbs object used to call a callback */ - LinphoneNatPolicy *nat_policy; /*nat policy for this call, either from proxy nor from core*/ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCall); - - -void linphone_call_notify_state_changed(LinphoneCall *call, LinphoneCallState cstate, const char *message); -void linphone_call_notify_dtmf_received(LinphoneCall *call, int dtmf); -void linphone_call_notify_encryption_changed(LinphoneCall *call, bool_t on, const char *authentication_token); -void linphone_call_notify_transfer_state_changed(LinphoneCall *call, LinphoneCallState cstate); -void linphone_call_notify_stats_updated(LinphoneCall *call, const LinphoneCallStats *stats); -void linphone_call_notify_info_message_received(LinphoneCall *call, const LinphoneInfoMessage *msg); -void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received); -void linphone_call_notify_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr); -void linphone_call_notify_snapshot_taken(LinphoneCall *call, const char *file_path); -void linphone_call_notify_next_video_frame_decoded(LinphoneCall *call); - -LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); -LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op); -void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params); -void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); -void linphone_call_set_contact_op(LinphoneCall* call); -void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, SalMediaDescription *md); -void linphone_call_set_symmetric_rtp(LinphoneCall *call, bool_t val); -/* private: */ -LinphoneCallLog * linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress * to); -void linphone_call_log_completed(LinphoneCall *call); -void linphone_call_set_transfer_state(LinphoneCall* call, LinphoneCallState state); -LinphonePlayer *linphone_call_build_player(LinphoneCall*call); -void linphone_call_refresh_sockets(LinphoneCall *call); -void linphone_call_replace_op(LinphoneCall *call, SalOp *op); -void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call); - -LinphoneCallParams * linphone_call_params_new(void); -SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params); -SalStreamDir get_audio_dir_from_call_params(const LinphoneCallParams *params); -SalStreamDir get_video_dir_from_call_params(const LinphoneCallParams *params); -void linphone_call_params_set_custom_headers(LinphoneCallParams *params, const SalCustomHeader *ch); -void linphone_call_params_set_custom_sdp_attributes(LinphoneCallParams *params, const SalCustomSdpAttribute *csa); -void linphone_call_params_set_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa); - -void linphone_auth_info_write_config(LinphoneConfig *config, LinphoneAuthInfo *obj, int pos); -LinphoneAuthInfo * linphone_auth_info_new_from_config_file(LpConfig *config, int pos); -void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai); -const LinphoneAuthInfo *_linphone_core_find_tls_auth_info(LinphoneCore *lc); -const LinphoneAuthInfo *_linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain, bool_t ignore_realm); - -void linphone_core_update_proxy_register(LinphoneCore *lc); -int linphone_call_abort(LinphoneCall *call, const char *error); -const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); - -int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphonePresenceModel *presence); -void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message); -void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig *obj); -void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc); -void _linphone_proxy_config_release(LinphoneProxyConfig *cfg); -void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj); -void linphone_proxy_config_notify_publish_state_changed(LinphoneProxyConfig *cfg, LinphonePublishState state); -LinphoneEvent *linphone_proxy_config_create_publish(LinphoneProxyConfig *cfg, const char *event, int expires); -/* - * returns service route as defined in as defined by rfc3608, might be a list instead of just one. - * Can be NULL - * */ -const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg); - -void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list); -void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body); -void linphone_friend_list_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state); -void _linphone_friend_list_release(LinphoneFriendList *list); -/*get rls either from list or core if any*/ -const LinphoneAddress * _linphone_friend_list_get_rls_address(const LinphoneFriendList *list); - -LINPHONE_PUBLIC void linphone_friend_invalidate_subscription(LinphoneFriend *lf); -void linphone_friend_close_subscriptions(LinphoneFriend *lf); -void _linphone_friend_release(LinphoneFriend *lf); -LINPHONE_PUBLIC void linphone_friend_update_subscribes(LinphoneFriend *fr, bool_t only_when_registered); -void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence); -void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc); -void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, SalOp *op); -void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, SalOp *op); -const char * linphone_friend_phone_number_to_sip_uri(LinphoneFriend *lf, const char *phone_number); -const char * linphone_friend_sip_uri_to_phone_number(LinphoneFriend *lf, const char *uri); -void linphone_friend_clear_presence_models(LinphoneFriend *lf); -LinphoneFriend *linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, SalOp *op); -LinphoneFriend *linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, SalOp *op); -LinphoneFriend *linphone_core_find_friend_by_out_subscribe(const LinphoneCore *lc, SalOp *op); -LinphoneFriend *linphone_core_find_friend_by_inc_subscribe(const LinphoneCore *lc, SalOp *op); -MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf); -bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc); -void linphone_core_update_friends_subscriptions(LinphoneCore *lc); -void _linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered); -void linphone_core_friends_storage_init(LinphoneCore *lc); -void linphone_core_friends_storage_close(LinphoneCore *lc); -void linphone_core_store_friend_in_db(LinphoneCore *lc, LinphoneFriend *lf); -void linphone_core_remove_friend_from_db(LinphoneCore *lc, LinphoneFriend *lf); -void linphone_core_store_friends_list_in_db(LinphoneCore *lc, LinphoneFriendList *list); -void linphone_core_remove_friends_list_from_db(LinphoneCore *lc, LinphoneFriendList *list); -LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_from_db(LinphoneCore *lc, LinphoneFriendList *list); -LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_lists_from_db(LinphoneCore *lc); -LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_import_friend(LinphoneFriendList *list, LinphoneFriend *lf, bool_t synchronize); - -int linphone_parse_host_port(const char *input, char *host, size_t hostlen, int *port); -int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, socklen_t *socklen, int default_port); - -bool_t host_has_ipv6_network(void); -bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret); - -static MS2_INLINE int get_min_bandwidth(int dbw, int ubw){ - if (dbw<=0) return ubw; - if (ubw<=0) return dbw; - return MIN(dbw,ubw); -} - -static MS2_INLINE bool_t bandwidth_is_greater(int bw1, int bw2){ - if (bw1<=0) return TRUE; - else if (bw2<=0) return FALSE; - else return bw1>=bw2; -} - -static MS2_INLINE int get_remaining_bandwidth_for_video(int total, int audio){ - int ret = total-audio-10; - if (ret < 0) ret = 0; - return ret; -} - -static MS2_INLINE void set_string(char **dest, const char *src, bool_t lowercase){ - if (*dest){ - ms_free(*dest); - *dest=NULL; - } - if (src) { - *dest=ms_strdup(src); - if (lowercase) { - char *cur = *dest; - for (; *cur; cur++) *cur = tolower(*cur); - } - } -} - -#define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0 -#define PAYLOAD_TYPE_BITRATE_OVERRIDE PAYLOAD_TYPE_USER_FLAG_3 -#define PAYLOAD_TYPE_FROZEN_NUMBER PAYLOAD_TYPE_USER_FLAG_4 - -void linphone_process_authentication(LinphoneCore* lc, SalOp *op); -void linphone_authentication_ok(LinphoneCore *lc, SalOp *op); -void linphone_subscription_new(LinphoneCore *lc, SalOp *op, const char *from); -void linphone_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presence); -void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result); -void linphone_notify_convert_presence_to_xml(SalOp *op, SalPresenceModel *presence, const char *contact, char **content); -void linphone_notify_recv(LinphoneCore *lc, SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model); -void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, SalOp *op); -void linphone_core_soundcard_hint_check(LinphoneCore* lc); - - -void linphone_subscription_answered(LinphoneCore *lc, SalOp *op); -void linphone_subscription_closed(LinphoneCore *lc, SalOp *op); - -void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc); -void linphone_core_update_allocated_audio_bandwidth_in_call(LinphoneCall *call, const PayloadType *pt, int maxbw); - -LINPHONE_PUBLIC int linphone_core_run_stun_tests(LinphoneCore *lc, LinphoneCall *call); -void linphone_core_resolve_stun_server(LinphoneCore *lc); -LINPHONE_PUBLIC const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc); -void linphone_core_adapt_to_network(LinphoneCore *lc, int ping_time_ms, LinphoneCallParams *params); -int linphone_core_gather_ice_candidates(LinphoneCore *lc, LinphoneCall *call); -LINPHONE_PUBLIC void linphone_core_enable_forced_ice_relay(LinphoneCore *lc, bool_t enable); -LINPHONE_PUBLIC void linphone_core_enable_short_turn_refresh(LinphoneCore *lc, bool_t enable); -void linphone_call_update_ice_state_in_call_stats(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev); -void linphone_call_stop_ice_for_inactive_streams(LinphoneCall *call, SalMediaDescription *result); -void _update_local_media_description_from_ice(SalMediaDescription *desc, IceSession *session, bool_t use_nortpproxy); -void linphone_call_update_local_media_description_from_ice_or_upnp(LinphoneCall *call); -void linphone_call_update_ice_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md, bool_t is_offer); -void linphone_call_clear_unused_ice_candidates(LinphoneCall *call, const SalMediaDescription *md); -bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md); - -void linphone_core_send_initial_subscribes(LinphoneCore *lc); -void linphone_core_write_friends_config(LinphoneCore* lc); -void linphone_friend_write_to_config_file(LinphoneConfig *config, LinphoneFriend *lf, int index); -LinphoneFriend * linphone_friend_new_from_config_file(struct _LinphoneCore *lc, int index); - -void linphone_proxy_config_update(LinphoneProxyConfig *cfg); -LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri); -const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to); -int linphone_core_get_local_ip_for(int type, const char *dest, char *result); -LINPHONE_PUBLIC void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result); - -LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore *lc, int index); -void linphone_proxy_config_write_to_config_file(LinphoneConfig* config,LinphoneProxyConfig *obj, int index); - -LinphoneReason linphone_core_message_received(LinphoneCore *lc, SalOp *op, const SalMessage *msg); -void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call); - -void linphone_call_init_stats(LinphoneCallStats *stats, LinphoneStreamType type); -void linphone_call_fix_call_parameters(LinphoneCall *call, SalMediaDescription *rmd); -void linphone_call_init_audio_stream(LinphoneCall *call); -void linphone_call_init_video_stream(LinphoneCall *call); -void linphone_call_init_text_stream(LinphoneCall *call); -void linphone_call_init_media_streams(LinphoneCall *call); -void linphone_call_start_media_streams(LinphoneCall *call, LinphoneCallState target_state); -void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call); -void linphone_call_stop_media_streams(LinphoneCall *call); -void linphone_call_delete_ice_session(LinphoneCall *call); -void linphone_call_delete_upnp_session(LinphoneCall *call); -void linphone_call_stop_media_streams_for_ice_gathering(LinphoneCall *call); -void linphone_call_update_crypto_parameters(LinphoneCall *call, SalMediaDescription *old_md, SalMediaDescription *new_md); -void linphone_call_update_remote_session_id_and_ver(LinphoneCall *call); -int _linphone_core_apply_transports(LinphoneCore *lc); -const char * linphone_core_get_identity(LinphoneCore *lc); - -void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose); -void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses); -void linphone_core_stop_waiting(LinphoneCore *lc); - -int linphone_call_proceed_with_invite_if_ready(LinphoneCall *call, LinphoneProxyConfig *dest_proxy); -int linphone_call_start_invite(LinphoneCall *call, const LinphoneAddress *destination/* = NULL if to be taken from the call log */); -int linphone_call_restart_invite(LinphoneCall *call); -/* - * param automatic_offering aims is to take into account previous answer for video in case of automatic re-invite. - * Purpose is to avoid to re-ask video previously declined */ -int linphone_call_start_update(LinphoneCall *call); -int linphone_call_start_accept_update(LinphoneCall *call, LinphoneCallState next_state, const char *state_info); -void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call); -bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md); -extern SalCallbacks linphone_sal_callbacks; -LINPHONE_PUBLIC bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); -LINPHONE_PUBLIC bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc); - -void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description); - -typedef enum _LinphoneProxyConfigAddressComparisonResult{ - LinphoneProxyConfigAddressDifferent, - LinphoneProxyConfigAddressEqual, - LinphoneProxyConfigAddressWeakEqual -} LinphoneProxyConfigAddressComparisonResult; - -LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b); -LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj); -/** - * unregister without moving the register_enable flag - */ -void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj); -void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj); - -/*chat*/ -void linphone_chat_room_release(LinphoneChatRoom *cr); -void linphone_chat_room_add_weak_message(LinphoneChatRoom *cr, LinphoneChatMessage *cm); -void linphone_chat_message_destroy(LinphoneChatMessage* msg); -void linphone_chat_message_update_state(LinphoneChatMessage *msg, LinphoneChatMessageState new_state); -void linphone_chat_message_set_state(LinphoneChatMessage *msg, LinphoneChatMessageState state); -void linphone_chat_message_set_is_secured(LinphoneChatMessage *msg, bool_t secured); -void linphone_chat_message_send_delivery_notification(LinphoneChatMessage *cm, LinphoneReason reason); -void linphone_chat_message_send_display_notification(LinphoneChatMessage *cm); -void _linphone_chat_message_cancel_file_transfer(LinphoneChatMessage *msg, bool_t unref); -int linphone_chat_room_upload_file(LinphoneChatMessage *msg); -void _linphone_chat_room_send_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); -LinphoneChatMessageCbs *linphone_chat_message_cbs_new(void); -LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call); -void linphone_chat_room_add_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); -void linphone_chat_room_remove_transient_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); -/**/ - -struct _LinphoneProxyConfig -{ - belle_sip_object_t base; - void *user_data; - struct _LinphoneCore *lc; - LinphoneErrorInfo *ei; - char *reg_proxy; - char *reg_identity; - LinphoneAddress* identity_address; - char *reg_route; - char *quality_reporting_collector; - char *realm; - char *contact_params; - char *contact_uri_params; - int expires; - int publish_expires; - SalOp *op; - SalCustomHeader *sent_headers; - char *type; - struct _SipSetupContext *ssctx; - int auth_failures; - char *dial_prefix; - LinphoneRegistrationState state; - LinphoneAVPFMode avpf_mode; - LinphoneNatPolicy *nat_policy; - - bool_t commit; - bool_t reg_sendregister; - bool_t publish; - bool_t dial_escape_plus; - - bool_t send_publish; - bool_t quality_reporting_enabled; - uint8_t avpf_rr_interval; - uint8_t quality_reporting_interval; - - time_t deletion_date; - LinphonePrivacyMask privacy; - /*use to check if server config has changed between edit() and done()*/ - LinphoneAddress *saved_proxy; - LinphoneAddress *saved_identity; - bool_t register_changed; - bool_t unused[3]; - /*---*/ - LinphoneAddress *pending_contact; /*use to store previous contact in case of network failure*/ - LinphoneEvent *presence_publish_event; - unsigned long long previous_publish_config_hash[2]; - - char *refkey; - char *sip_etag; /*publish context*/ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneProxyConfig); - -struct _LinphoneAuthInfo -{ - belle_sip_object_t base; - char *username; - char *realm; - char *userid; - char *passwd; - char *ha1; - char *domain; - char *tls_cert; - char *tls_key; - char *tls_cert_path; - char *tls_key_path; -}; - -typedef enum _LinphoneIsComposingState { - LinphoneIsComposingIdle, - LinphoneIsComposingActive -} LinphoneIsComposingState; - -struct _LinphoneChatRoom{ - belle_sip_object_t base; - void *user_data; - struct _LinphoneCore *lc; - char *peer; - LinphoneAddress *peer_url; - MSList *messages_hist; - MSList *transient_messages; - bctbx_list_t *weak_messages; - int unread_count; - LinphoneIsComposingState remote_is_composing; - LinphoneIsComposingState is_composing; - belle_sip_source_t *remote_composing_refresh_timer; - belle_sip_source_t *composing_idle_timer; - belle_sip_source_t *composing_refresh_timer; - LinphoneCall *call; - LinphoneChatMessage *pending_message; - MSList *received_rtt_characters; -}; - -typedef struct _LinphoneChatMessageCharacter { - uint32_t value; - bool_t has_been_read; -} LinphoneChatMessageCharacter; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatRoom); - - -typedef struct _LinphoneFriendPresence { - char *uri_or_tel; - LinphonePresenceModel *presence; -} LinphoneFriendPresence; - -typedef struct _LinphoneFriendPhoneNumberSipUri { - char *number; - char *uri; -} LinphoneFriendPhoneNumberSipUri; - -struct _LinphoneFriend{ - belle_sip_object_t base; - void *user_data; - LinphoneAddress *uri; - MSList *insubs; /*list of SalOp. There can be multiple instances of a same Friend that subscribe to our presence*/ - SalOp *outsub; - LinphoneSubscribePolicy pol; - MSList *presence_models; /* list of LinphoneFriendPresence. It associates SIP URIs and phone numbers with their respective presence models. */ - MSList *phone_number_sip_uri_map; /* list of LinphoneFriendPhoneNumberSipUri. It associates phone numbers with their corresponding SIP URIs. */ - struct _LinphoneCore *lc; - BuddyInfo *info; - char *refkey; - bool_t subscribe; - bool_t subscribe_active; - bool_t inc_subscribe_pending; - bool_t commit; - bool_t initial_subscribes_sent; /*used to know if initial subscribe message was sent or not*/ - bool_t presence_received; - LinphoneVcard *vcard; - unsigned int storage_id; - LinphoneFriendList *friend_list; - LinphoneSubscriptionState out_sub_state; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneFriend); - -struct _LinphoneFriendListCbs { - belle_sip_object_t base; - void *user_data; - LinphoneFriendListCbsContactCreatedCb contact_created_cb; - LinphoneFriendListCbsContactDeletedCb contact_deleted_cb; - LinphoneFriendListCbsContactUpdatedCb contact_updated_cb; - LinphoneFriendListCbsSyncStateChangedCb sync_state_changed_cb; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneFriendListCbs); - -struct _LinphoneFriendList { - belle_sip_object_t base; - void *user_data; - LinphoneCore *lc; - LinphoneEvent *event; - char *display_name; - char *rls_uri; /*this field is take in sync with rls_addr*/ - LinphoneAddress *rls_addr; - MSList *friends; - bctbx_map_t *friends_map; - bctbx_map_t *friends_map_uri; - unsigned char *content_digest; - int expected_notification_version; - unsigned int storage_id; - char *uri; - MSList *dirty_friends_to_update; - int revision; - LinphoneFriendListCbs *cbs; - bool_t enable_subscriptions; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneFriendList); - - - -typedef struct sip_config -{ - char *contact; - char *guessed_contact; - MSList *proxies; - MSList *deleted_proxies; - int inc_timeout; /*timeout after an un-answered incoming call is rejected*/ - int in_call_timeout; /*timeout after a call is hangup */ - int delayed_timeout; /*timeout after a delayed call is resumed */ - unsigned int keepalive_period; /* interval in ms between keep alive messages sent to the proxy server*/ - LinphoneSipTransports transports; - bool_t guess_hostname; - bool_t loopback_only; - bool_t ipv6_enabled; - bool_t sdp_200_ack; - bool_t register_only_when_network_is_up; - bool_t register_only_when_upnp_is_ok; - bool_t ping_with_options; - bool_t auto_net_state_mon; - bool_t tcp_tls_keepalive; - bool_t vfu_with_info; /*use to enable vfu request using sip info*/ - bool_t save_auth_info; // if true, auth infos will be write in the config file when they are added to the list -} sip_config_t; - -typedef struct rtp_config -{ - int audio_rtp_min_port; - int audio_rtp_max_port; - int video_rtp_min_port; - int video_rtp_max_port; - int audio_jitt_comp; /*jitter compensation*/ - int video_jitt_comp; /*jitter compensation*/ - int nortp_timeout; - int disable_upnp; - MSCryptoSuite *srtp_suites; - LinphoneAVPFMode avpf_mode; - bool_t rtp_no_xmit_on_audio_mute; - /* stop rtp xmit when audio muted */ - bool_t audio_adaptive_jitt_comp_enabled; - bool_t video_adaptive_jitt_comp_enabled; - bool_t pad; - char* audio_multicast_addr; - bool_t audio_multicast_enabled; - int audio_multicast_ttl; - char* video_multicast_addr; - int video_multicast_ttl; - bool_t video_multicast_enabled; - int text_rtp_min_port; - int text_rtp_max_port; -}rtp_config_t; - - - -typedef struct net_config -{ - char *nat_address; /* may be IP or host name */ - char *nat_address_ip; /* ip translated from nat_address */ - struct addrinfo *stun_addrinfo; - int download_bw; - int upload_bw; - int mtu; - OrtpNetworkSimulatorParams netsim_params; - bool_t nat_sdp_only; -}net_config_t; - - -typedef struct sound_config -{ - struct _MSSndCard * ring_sndcard; /* the playback sndcard currently used */ - struct _MSSndCard * play_sndcard; /* the playback sndcard currently used */ - struct _MSSndCard * capt_sndcard; /* the capture sndcard currently used */ - struct _MSSndCard * lsd_card; /* dummy playback card for Linphone Sound Daemon extension */ - const char **cards; - int latency; /* latency in samples of the current used sound device */ - float soft_play_lev; /*playback gain in db.*/ - float soft_mic_lev; /*mic gain in db.*/ - char rec_lev; - char play_lev; - char ring_lev; - char source; - char *local_ring; - char *remote_ring; - char *ringback_tone; - bool_t ec; - bool_t ea; - bool_t agc; -} sound_config_t; - -typedef struct codecs_config -{ - MSList *audio_codecs; /* list of audio codecs in order of preference*/ - MSList *video_codecs; - MSList *text_codecs; - int dyn_pt; - int telephone_event_pt; -}codecs_config_t; - -typedef struct video_config{ - struct _MSWebCam *device; - const char **cams; - MSVideoSize vsize; - MSVideoSize preview_vsize; /*is 0,0 if no forced preview size is set, in which case vsize field above is used.*/ - LinphoneVideoDefinition *vdef; - LinphoneVideoDefinition *preview_vdef; - float fps; - bool_t capture; - bool_t show_local; - bool_t display; - bool_t selfview; /*during calls*/ - bool_t reuse_preview_source; -}video_config_t; - -typedef struct text_config{ - bool_t enabled; -}text_config_t; - -typedef struct ui_config -{ - int is_daemon; - int is_applet; - unsigned int timer_id; /* the timer id for registration */ -}ui_config_t; - - - -typedef struct autoreplier_config -{ - int enabled; - int after_seconds; /* accept the call after x seconds*/ - int max_users; /* maximum number of user that can call simultaneously */ - int max_rec_time; /* the max time of incoming voice recorded */ - int max_rec_msg; /* maximum number of recorded messages */ - const char *message; /* the path of the file to be played */ -}autoreplier_config_t; - - -typedef struct _LinphoneToneDescription{ - LinphoneReason reason; /*the call error code*/ - LinphoneToneID toneid; /*A tone type to play when this error arrives. This is played using tone generator*/ - char *audiofile; /*An override audio file to play instead, when this error arrives*/ - /*Note that some tones are not affected to any error, in which case it is affected LinphoneReasonNone*/ -}LinphoneToneDescription; - -LinphoneToneDescription * linphone_tone_description_new(LinphoneReason reason, LinphoneToneID id, const char *audiofile); -void linphone_tone_description_destroy(LinphoneToneDescription *obj); -LinphoneToneDescription *linphone_core_get_call_error_tone(const LinphoneCore *lc, LinphoneReason reason); -void linphone_core_play_call_error_tone(LinphoneCore *lc, LinphoneReason reason); -void _linphone_core_set_tone(LinphoneCore *lc, LinphoneReason reason, LinphoneToneID id, const char *audiofile); -LINPHONE_PUBLIC const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID id); -int _linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params, LinphoneCallState next_state, const char *state_info); - -typedef struct _LinphoneTaskList{ - MSList *hooks; -}LinphoneTaskList; - -void linphone_task_list_init(LinphoneTaskList *t); -void linphone_task_list_add(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data); -void linphone_task_list_remove(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data); -void linphone_task_list_run(LinphoneTaskList *t); -void linphone_task_list_free(LinphoneTaskList *t); - - -struct _LinphoneCoreCbs { - belle_sip_object_t base; - LinphoneCoreVTable *vtable; - bool_t autorelease; -}; - -LinphoneCoreCbs * _linphone_core_cbs_new(void); -void _linphone_core_cbs_set_v_table(LinphoneCoreCbs *cbs, LinphoneCoreVTable *vtable, bool_t autorelease); - -typedef struct _LCCallbackObj { - LinphoneCoreCbFunc _func; - void *_user_data; -} LCCallbackObj; - -struct _LinphoneCore -{ - belle_sip_object_t base; - MSFactory* factory; - MSList* vtable_refs; - int vtable_notify_recursion; - Sal *sal; - void *platform_helper; /*is a LinphonePrivate::PlatformHelpers but cannot be used as is because private.h is compiled as C in testers.*/ - LinphoneGlobalState state; - struct _LpConfig *config; - MSList *default_audio_codecs; - MSList *default_video_codecs; - MSList *default_text_codecs; - net_config_t net_conf; - sip_config_t sip_conf; - rtp_config_t rtp_conf; - sound_config_t sound_conf; - video_config_t video_conf; - text_config_t text_conf; - codecs_config_t codecs_conf; - ui_config_t ui_conf; - autoreplier_config_t autoreplier_conf; - LinphoneProxyConfig *default_proxy; - MSList *friends_lists; - MSList *auth_info; - struct _RingStream *ringstream; - time_t dmfs_playing_start_time; - LCCallbackObj preview_finished_cb; - LinphoneCall *current_call; /* the current call */ - MSList *calls; /* all the processed calls */ - MSList *queued_calls; /* used by the autoreplier */ - MSList *call_logs; - MSList *chatrooms; - int max_call_logs; - int missed_calls; - VideoPreview *previewstream; - struct _MSEventQueue *msevq; - LinphoneRtpTransportFactories *rtptf; - MSList *bl_reqs; - MSList *subscribers; /* unknown subscribers */ - int minutes_away; - LinphonePresenceModel *presence_model; - void *data; - char *play_file; - char *rec_file; - uint64_t prevtime_ms; - int audio_bw; /*IP bw consumed by audio codec, set as soon as used codec is known, its purpose is to know the remaining bw for video*/ - LinphoneCoreWaitingCallback wait_cb; - void *wait_ctx; - void *video_window_id; - void *preview_window_id; - time_t netup_time; /*time when network went reachable */ - struct _EcCalibrator *ecc; - struct _EchoTester *ect; - LinphoneTaskList hooks; /*tasks periodically executed in linphone_core_iterate()*/ - LinphoneConference *conf_ctx; - char* zrtp_secrets_cache; /**< zrtp cache filename */ - char* user_certificates_path; - LinphoneVideoPolicy video_policy; - time_t network_last_check; - LinphoneNatPolicy *nat_policy; - LinphoneImNotifPolicy *im_notif_policy; - - bool_t use_files; - bool_t apply_nat_settings; - bool_t initial_subscribes_sent; - bool_t bl_refresh; - - bool_t preview_finished; - bool_t auto_net_state_mon; - bool_t sip_network_reachable; - bool_t media_network_reachable; - - bool_t network_reachable_to_be_notified; /*set to true when state must be notified in next iterate*/ - bool_t use_preview_window; - bool_t network_last_status; - bool_t ringstream_autorelease; - - bool_t vtables_running; - bool_t send_call_stats_periodical_updates; - bool_t forced_ice_relay; - bool_t short_turn_refresh; - - char localip[LINPHONE_IPADDR_SIZE]; - int device_rotation; - int max_calls; - LinphoneTunnel *tunnel; - char* device_id; - char *chat_db_file; - char *logs_db_file; - char *friends_db_file; -#ifdef SQLITE_STORAGE_ENABLED - sqlite3 *zrtp_cache_db; /**< zrtp sqlite cache, used by both zrtp and lime */ - sqlite3 *db; - sqlite3 *logs_db; - sqlite3 *friends_db; - bool_t debug_storage; -#endif -#ifdef BUILD_UPNP - UpnpContext *upnp; -#endif //BUILD_UPNP - belle_http_provider_t *http_provider; - belle_tls_crypto_config_t *http_crypto_config; - belle_http_request_listener_t *provisioning_http_listener; -#ifdef ENABLE_UPDATE_CHECK - belle_http_request_listener_t *update_check_http_listener; - char *update_check_current_version; -#endif - MSList *tones; - LinphoneReason chat_deny_code; - char *file_transfer_server; - const char **supported_formats; - LinphoneContent *log_collection_upload_information; - LinphoneCoreCbs *current_cbs; // the latest LinphoneCoreCbs object to call a callback, see linphone_core_get_current_cbs() - LinphoneRingtonePlayer *ringtoneplayer; - LinphoneVcardContext *vcard_context; - - /*for tests only*/ - bool_t zrtp_not_available_simulation; - - /* string for TLS auth instead of path to files */ - char *tls_cert; - char *tls_key; - - LinphoneAddress *default_rls_addr; /*default resource list server*/ - LinphoneImEncryptionEngine *im_encryption_engine; - struct _LinphoneAccountCreatorService *default_ac_service; - MSBandwidthController *bw_controller; - bool_t dns_set_by_app; -}; - #ifdef __cplusplus #define getPlatformHelpers(lc) static_cast(lc->platform_helper) #endif -struct _LinphoneEvent{ - belle_sip_object_t base; - LinphoneErrorInfo *ei; - LinphoneSubscriptionDir dir; - LinphoneCore *lc; - SalOp *op; - SalCustomHeader *send_custom_headers; - LinphoneSubscriptionState subscription_state; - LinphonePublishState publish_state; - void *userdata; - char *name; - int expires; - bool_t terminating; - bool_t is_out_of_dialog_op; /*used for out of dialog notify*/ - bool_t internal; - bool_t oneshot; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneEvent); - -LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc); -void linphone_tunnel_configure(LinphoneTunnel *tunnel); -void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler); - -/** - * Check if we do not have exceed the number of simultaneous call - * - * @ingroup call_control -**/ -bool_t linphone_core_can_we_add_call(LinphoneCore *lc); - -int linphone_core_add_call( LinphoneCore *lc, LinphoneCall *call); -int linphone_core_del_call( LinphoneCore *lc, LinphoneCall *call); -int linphone_core_get_calls_nb(const LinphoneCore *lc); - -void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); -void linphone_call_update_biggest_desc(LinphoneCall *call, SalMediaDescription *md); -void linphone_call_make_local_media_description(LinphoneCall *call); -void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params); -void linphone_call_increment_local_media_description(LinphoneCall *call); -void linphone_call_fill_media_multicast_addr(LinphoneCall *call); -void linphone_call_update_streams(LinphoneCall *call, SalMediaDescription *new_md, LinphoneCallState target_state); - -bool_t linphone_core_is_payload_type_usable_for_bandwidth(const LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit); - -#define linphone_core_ready(lc) ((lc)->state==LinphoneGlobalOn || (lc)->state==LinphoneGlobalShutdown) -void _linphone_core_configure_resolver(void); - -void linphone_core_initialize_supported_content_types(LinphoneCore *lc); - -struct _EcCalibrator{ - MSFactory *factory; - ms_thread_t thread; - MSSndCard *play_card,*capt_card; - MSFilter *sndread,*det,*rec; - MSFilter *play, *gen, *sndwrite; - MSFilter *read_resampler,*write_resampler; - MSTicker *ticker; - LinphoneEcCalibrationCallback cb; - void *cb_data; - LinphoneEcCalibrationAudioInit audio_init_cb; - LinphoneEcCalibrationAudioUninit audio_uninit_cb; - int64_t acc; - int delay; - unsigned int rate; - LinphoneEcCalibratorStatus status; - bool_t freq1,freq2,freq3; - bool_t play_cool_tones; -}; - -typedef struct _EcCalibrator EcCalibrator; - -LinphoneEcCalibratorStatus ec_calibrator_get_status(EcCalibrator *ecc); - -void ec_calibrator_destroy(EcCalibrator *ecc); - -struct _EchoTester { - MSFactory *factory; - MSFilter *in,*out; - MSSndCard *capture_card; - MSSndCard *playback_card; - MSTicker *ticker; - unsigned int rate; -}; - -typedef struct _EchoTester EchoTester; - -void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapsed); -void linphone_call_set_broken(LinphoneCall *call); -void linphone_call_repair_if_broken(LinphoneCall *call); -void linphone_core_repair_calls(LinphoneCore *lc); -int linphone_core_preempt_sound_resources(LinphoneCore *lc); -int _linphone_call_pause(LinphoneCall *call); - -/*conferencing subsystem*/ -void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted); -bool_t linphone_core_sound_resources_available(LinphoneCore *lc); -void linphone_core_notify_refer_state(LinphoneCore *lc, LinphoneCall *referer, LinphoneCall *newcall); -LINPHONE_PUBLIC unsigned int linphone_core_get_audio_features(LinphoneCore *lc); - -void _linphone_core_codec_config_write(LinphoneCore *lc); - #define HOLD_OFF (0) #define HOLD_ON (1) @@ -1281,766 +148,6 @@ void _linphone_core_codec_config_write(LinphoneCore *lc); #endif #endif -LINPHONE_PUBLIC bctbx_list_t * call_logs_read_from_config_file(LinphoneCore *lc); -void call_logs_write_to_config_file(LinphoneCore *lc); -void linphone_core_call_log_storage_init(LinphoneCore *lc); -void linphone_core_call_log_storage_close(LinphoneCore *lc); -void linphone_core_store_call_log(LinphoneCore *lc, LinphoneCallLog *log); -LINPHONE_PUBLIC const MSList *linphone_core_get_call_history(LinphoneCore *lc); -LINPHONE_PUBLIC void linphone_core_delete_call_history(LinphoneCore *lc); -LINPHONE_PUBLIC void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log); -LINPHONE_PUBLIC int linphone_core_get_call_history_size(LinphoneCore *lc); - -int linphone_core_get_edge_bw(LinphoneCore *lc); -int linphone_core_get_edge_ptime(LinphoneCore *lc); - -LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context); - -int linphone_upnp_init(LinphoneCore *lc); -void linphone_upnp_destroy(LinphoneCore *lc); - -#ifdef SQLITE_STORAGE_ENABLED -int _linphone_sqlite3_open(const char *db_file, sqlite3 **db); -sqlite3 * linphone_message_storage_init(void); -void linphone_message_storage_init_chat_rooms(LinphoneCore *lc); -#endif -void linphone_chat_message_store_update(LinphoneChatMessage *msg); -void linphone_chat_message_store_state(LinphoneChatMessage *msg); -void linphone_chat_message_store_appdata(LinphoneChatMessage* msg); -void linphone_core_message_storage_init(LinphoneCore *lc); -void linphone_core_message_storage_close(LinphoneCore *lc); -void linphone_core_message_storage_set_debug(LinphoneCore *lc, bool_t debug); - -void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID id); -bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc); -const char *linphone_core_create_uuid(LinphoneCore *lc); -void linphone_configure_op(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); -void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact, LinphoneProxyConfig *proxy); -void linphone_call_create_op_to(LinphoneCall *call, LinphoneAddress *to); -void linphone_call_create_op(LinphoneCall *call); -int linphone_call_prepare_ice(LinphoneCall *call, bool_t incoming_offer); -void linphone_core_notify_info_message(LinphoneCore* lc,SalOp *op, SalBodyHandler *body); -LinphoneContent * linphone_content_new(void); -LinphoneContent * linphone_content_copy(const LinphoneContent *ref); -SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content); -SalReason linphone_reason_to_sal(LinphoneReason reason); -LinphoneReason linphone_reason_from_sal(SalReason reason); -void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei); -LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires); -LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); -void linphone_event_unpublish(LinphoneEvent *lev); -/** - * Useful for out of dialog notify - * */ -LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, SalOp *op, LinphoneSubscriptionDir dir, const char *name); -void linphone_event_set_internal(LinphoneEvent *lev, bool_t internal); -bool_t linphone_event_is_internal(LinphoneEvent *lev); -void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); -void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state); -LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); -LinphoneContent *linphone_content_from_sal_body_handler(SalBodyHandler *ref); -void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); -void linphone_core_register_offer_answer_providers(LinphoneCore *lc); - - -struct _LinphoneContent { - belle_sip_object_t base; - void *user_data; - SalBodyHandler *body_handler; - char *name; /**< used by RCS File transfer messages to store the original filename of the file to be downloaded from server */ - char *key; /**< used by RCS File transfer messages to store the key to encrypt file if needed */ - size_t keyLength; /**< Length of key in bytes */ - void *cryptoContext; /**< crypto context used to encrypt file for RCS file transfer */ - bool_t owned_fields; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneContent); - -struct _LinphoneBuffer { - belle_sip_object_t base; - void *user_data; - uint8_t *content; /**< A pointer to the buffer content */ - size_t size; /**< The size of the buffer content */ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneBuffer); - -struct _LinphoneNatPolicy { - belle_sip_object_t base; - void *user_data; - LinphoneCore *lc; - belle_sip_resolver_context_t *stun_resolver_context; - struct addrinfo *stun_addrinfo; - char *stun_server; - char *stun_server_username; - char *ref; - bool_t stun_enabled; - bool_t turn_enabled; - bool_t ice_enabled; - bool_t upnp_enabled; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneNatPolicy); - -bool_t linphone_nat_policy_stun_server_activated(LinphoneNatPolicy *policy); -void linphone_nat_policy_save_to_config(const LinphoneNatPolicy *policy); - -struct _LinphoneImNotifPolicy { - belle_sip_object_t base; - void *user_data; - LinphoneCore *lc; - bool_t send_is_composing; - bool_t recv_is_composing; - bool_t send_imdn_delivered; - bool_t recv_imdn_delivered; - bool_t send_imdn_displayed; - bool_t recv_imdn_displayed; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneImNotifPolicy); - -void linphone_core_create_im_notif_policy(LinphoneCore *lc); - - -/***************************************************************************** - * XML-RPC interface * - ****************************************************************************/ - -typedef struct _LinphoneXmlRpcArg { - LinphoneXmlRpcArgType type; - union { - int i; - char *s; - } data; -} LinphoneXmlRpcArg; - -struct _LinphoneXmlRpcRequestCbs { - belle_sip_object_t base; - void *user_data; - LinphoneXmlRpcRequestCbsResponseCb response; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneXmlRpcRequestCbs); - -struct _LinphoneXmlRpcRequest { - belle_sip_object_t base; - void *user_data; - LinphoneXmlRpcRequestCbs *callbacks; - belle_sip_list_t *arg_list; - char *content; /**< The string representation of the XML-RPC request */ - char *method; - LinphoneXmlRpcStatus status; - LinphoneXmlRpcArg response; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneXmlRpcRequest); - -struct _LinphoneXmlRpcSession { - belle_sip_object_t base; - void *user_data; - LinphoneCore *core; - char *url; - bool_t released; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneXmlRpcSession); - - -/***************************************************************************** - * Account creator interface * - ****************************************************************************/ - -struct _LinphoneAccountCreatorService { - belle_sip_object_t base; - void *user_data; - - LinphoneAccountCreatorRequestFunc account_creator_service_constructor_cb; /**< Constructor */ - LinphoneAccountCreatorRequestFunc account_creator_service_destructor_cb; /**< Destructor */ - - LinphoneAccountCreatorRequestFunc create_account_request_cb; /**< Request to create account */ - LinphoneAccountCreatorRequestFunc is_account_exist_request_cb; /**< Request to know if account exist */ - - LinphoneAccountCreatorRequestFunc activate_account_request_cb; /**< Request to activate account */ - LinphoneAccountCreatorRequestFunc is_account_activated_request_cb; /**< Request to know if account is activated */ - - LinphoneAccountCreatorRequestFunc link_account_request_cb; /**< Request to link account with an alias */ - LinphoneAccountCreatorRequestFunc activate_alias_request_cb; /**< Request to activate the link of alias */ - LinphoneAccountCreatorRequestFunc is_alias_used_request_cb; /**< Request to know if alias is used */ - LinphoneAccountCreatorRequestFunc is_account_linked_request_cb; /**< Request to know if account is linked with an alias */ - - LinphoneAccountCreatorRequestFunc recover_account_request_cb; /**< Request to recover account */ - LinphoneAccountCreatorRequestFunc update_account_request_cb; /**< Request to update account */ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorService); - -struct _LinphoneAccountCreatorCbs { - belle_sip_object_t base; - void *user_data; - - LinphoneAccountCreatorCbsStatusCb create_account_response_cb; /**< Response of create_account request */ - LinphoneAccountCreatorCbsStatusCb is_account_exist_response_cb; /**< Response of is_account_exist request */ - - LinphoneAccountCreatorCbsStatusCb activate_account_response_cb; /**< Response of activate_account request */ - LinphoneAccountCreatorCbsStatusCb is_account_activated_response_cb; /**< Response of is_account_activated request */ - - LinphoneAccountCreatorCbsStatusCb link_account_response_cb; /**< Response of link_account request */ - LinphoneAccountCreatorCbsStatusCb activate_alias_response_cb; /**< Response of activation alias */ - LinphoneAccountCreatorCbsStatusCb is_alias_used_response_cb; /**< Response of is_alias_used request */ - LinphoneAccountCreatorCbsStatusCb is_account_linked_response_cb; /**< Response of is_account_linked request */ - - LinphoneAccountCreatorCbsStatusCb recover_account_response_cb; /**< Response of recover_account request */ - LinphoneAccountCreatorCbsStatusCb update_account_response_cb; /**< Response of update_account request */ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreatorCbs); - -struct _LinphoneAccountCreator { - belle_sip_object_t base; - void *user_data; - LinphoneCore *core; - - /* AccountCreator */ - LinphoneAccountCreatorService *service; /**< Account creator service */ - LinphoneAccountCreatorCbs *cbs; /**< Account creator cbs */ - LinphoneXmlRpcSession *xmlrpc_session; /**< XML-RPC session */ - LinphoneProxyConfig *proxy_cfg; /**< Default proxy config */ - - /* User */ - char *username; /**< Username */ - char *display_name; /**< Display name */ - /* Password */ - char *password; /**< Plain text password */ - char *ha1; /**< Hash password */ - /* Phone Number(Alias) */ - char *phone_number; /**< User phone number*/ - char *phone_country_code; /**< User phone number country code */ - /* Email(Alias) */ - char *email; /**< User email */ - /* Misc */ - char *language; /**< User language */ - char *activation_code; /**< Account validation code */ - char *domain; /**< Domain */ - LinphoneTransportType transport; /**< Transport used */ - - /* Deprecated */ - char *route; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneAccountCreator); - -/** - * Account creator custom to set Linphone default values - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_constructor_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to test the existence of a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to create a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to activate a Linphone account with phone number. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to activate a Linphone account with email. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_email_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to test the validation of a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to test the existence a phone number with a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_phone_number_used_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to link a phone number with a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_link_phone_number_with_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to activate the link of a phone number with a Linphone account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_phone_number_link_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to a Linphone account with the phone number. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_recover_phone_account_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to ask if an account is linked with a phone number - * @param[in] creator LinphoneAccountCreator object - * @return if this account is linked with a phone number -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked_linphone(LinphoneAccountCreator *creator); - -/** - * Send an XML-RPC request to ask if an account is linked with a phone number - * @param[in] creator LinphoneAccountCreator object - * @param[in] new_pwd const char * : new password for the account creator - * @return LinphoneAccountCreatorStatusRequestOk if everything is OK, or a specific error otherwise. -**/ -LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_update_password_linphone(LinphoneAccountCreator *creator); - - -/***************************************************************************** - * CardDAV interface * - ****************************************************************************/ - -struct _LinphoneCardDavContext { - LinphoneFriendList *friend_list; - int ctag; - void *user_data; - LinphoneCardDavContactCreatedCb contact_created_cb; - LinphoneCardDavContactUpdatedCb contact_updated_cb; - LinphoneCardDavContactRemovedCb contact_removed_cb; - LinphoneCardDavSynchronizationDoneCb sync_done_cb; - LinphoneAuthInfo *auth_info; -}; - -struct _LinphoneCardDavQuery { - LinphoneCardDavContext *context; - char *url; - const char *method; - char *body; - const char *depth; - const char *ifmatch; - belle_http_request_listener_t *http_request_listener; - void *user_data; - LinphoneCardDavQueryType type; -}; - -struct _LinphoneCardDavResponse { - char *etag; - char *url; - char *vcard; -}; - -/***************************************************************************** - * REMOTE PROVISIONING FUNCTIONS * - ****************************************************************************/ - -void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message); -int linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri); -LINPHONE_PUBLIC int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path); - -/***************************************************************************** - * Player interface * - ****************************************************************************/ - -struct _LinphonePlayerCbs { - belle_sip_object_t base; - void *user_data; - LinphonePlayerCbsEofReachedCb eof; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphonePlayerCbs); - -LinphonePlayerCbs *linphone_player_cbs_new(void); - -struct _LinphonePlayer{ - belle_sip_object_t base; - void *user_data; - int (*open)(LinphonePlayer* player, const char *filename); - int (*start)(LinphonePlayer* player); - int (*pause)(LinphonePlayer* player); - int (*seek)(LinphonePlayer* player, int time_ms); - MSPlayerState (*get_state)(LinphonePlayer* player); - int (*get_duration)(LinphonePlayer *player); - int (*get_position)(LinphonePlayer *player); - void (*close)(LinphonePlayer* player); - void (*destroy)(LinphonePlayer *player); - void *impl; - LinphonePlayerCbs *callbacks; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphonePlayer); - -LinphonePlayer * linphone_player_new(void); -void _linphone_player_destroy(LinphonePlayer *player); - - -/***************************************************************************** - * XML UTILITY FUNCTIONS * - ****************************************************************************/ - -#define XMLPARSING_BUFFER_LEN 2048 -#define MAX_XPATH_LENGTH 256 - -typedef struct _xmlparsing_context { - xmlDoc *doc; - xmlXPathContextPtr xpath_ctx; - char errorBuffer[XMLPARSING_BUFFER_LEN]; - char warningBuffer[XMLPARSING_BUFFER_LEN]; -} xmlparsing_context_t; - -xmlparsing_context_t * linphone_xmlparsing_context_new(void); -void linphone_xmlparsing_context_destroy(xmlparsing_context_t *ctx); -void linphone_xmlparsing_genericxml_error(void *ctx, const char *fmt, ...); -int linphone_create_xml_xpath_context(xmlparsing_context_t *xml_ctx); -void linphone_xml_xpath_context_set_node(xmlparsing_context_t *xml_ctx, xmlNodePtr node); -char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression); -char * linphone_get_xml_attribute_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression, const char *attribute_name); -void linphone_free_xml_text_content(char *text); -xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression); -void linphone_xml_xpath_context_init_carddav_ns(xmlparsing_context_t *xml_ctx); - -/***************************************************************************** - * OTHER UTILITY FUNCTIONS * - ****************************************************************************/ -char * linphone_timestamp_to_rfc3339_string(time_t timestamp); - - -void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op); - -static MS2_INLINE void payload_type_set_enable(OrtpPayloadType *pt,int value) -{ - if ((value)!=0) payload_type_set_flag(pt,PAYLOAD_TYPE_ENABLED); \ - else payload_type_unset_flag(pt,PAYLOAD_TYPE_ENABLED); -} - -static MS2_INLINE bool_t payload_type_enabled(const OrtpPayloadType *pt) { - return (((pt)->flags & PAYLOAD_TYPE_ENABLED)!=0); -} - -bool_t is_payload_type_number_available(const MSList *l, int number, const OrtpPayloadType *ignore); -int get_audio_payload_bandwidth(const LinphoneCore *lc, const PayloadType *pt, int maxbw); -LinphonePayloadType *linphone_payload_type_new(LinphoneCore *lc, OrtpPayloadType *ortp_pt); -bool_t _linphone_core_check_payload_type_usability(const LinphoneCore *lc, const OrtpPayloadType *pt); -OrtpPayloadType *linphone_payload_type_get_ortp_pt(const LinphonePayloadType *pt); - - -const MSCryptoSuite * linphone_core_get_srtp_crypto_suites(LinphoneCore *lc); -MsZrtpCryptoTypesCount linphone_core_get_zrtp_key_agreement_suites(LinphoneCore *lc, MSZrtpKeyAgreement keyAgreements[MS_MAX_ZRTP_CRYPTO_TYPES]); -MsZrtpCryptoTypesCount linphone_core_get_zrtp_cipher_suites(LinphoneCore *lc, MSZrtpCipher ciphers[MS_MAX_ZRTP_CRYPTO_TYPES]); -MsZrtpCryptoTypesCount linphone_core_get_zrtp_hash_suites(LinphoneCore *lc, MSZrtpHash hashes[MS_MAX_ZRTP_CRYPTO_TYPES]); -MsZrtpCryptoTypesCount linphone_core_get_zrtp_auth_suites(LinphoneCore *lc, MSZrtpAuthTag authTags[MS_MAX_ZRTP_CRYPTO_TYPES]); -MsZrtpCryptoTypesCount linphone_core_get_zrtp_sas_suites(LinphoneCore *lc, MSZrtpSasType sasTypes[MS_MAX_ZRTP_CRYPTO_TYPES]); - -struct _LinphoneImEncryptionEngineCbs { - belle_sip_object_t base; - void *user_data; - LinphoneImEncryptionEngineCbsIncomingMessageCb process_incoming_message; - LinphoneImEncryptionEngineCbsOutgoingMessageCb process_outgoing_message; - LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer; - LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key; - LinphoneImEncryptionEngineCbsDownloadingFileCb process_downlading_file; - LinphoneImEncryptionEngineCbsUploadingFileCb process_uploading_file; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneImEncryptionEngineCbs); - -LinphoneImEncryptionEngineCbs * linphone_im_encryption_engine_cbs_new(void); - -struct _LinphoneImEncryptionEngine { - belle_sip_object_t base; - void *user_data; - LinphoneCore *lc; - LinphoneImEncryptionEngineCbs *callbacks; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneImEncryptionEngine); - -struct _LinphoneRange { - belle_sip_object_t base; - void *user_data; - int min; - int max; -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneRange); - -LinphoneRange *linphone_range_new(void); - -struct _LinphoneTransports { - belle_sip_object_t base; - void *user_data; - int udp_port; /**< SIP/UDP port */ - int tcp_port; /**< SIP/TCP port */ - int dtls_port; /**< SIP/DTLS port */ - int tls_port; /**< SIP/TLS port */ -}; - -BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneTransports); - -LINPHONE_PUBLIC LinphoneTransports *linphone_transports_new(void); - -struct _LinphoneVideoActivationPolicy { - belle_sip_object_t base; - void *user_data; - bool_t automatically_initiate; /** +#include +#include +#include + +#include + +#include "private_types.h" +#include "tester_utils.h" +#include "conference/participant-imdn-state.h" +#include "sal/op.h" +#include "sal/event-op.h" + +#include "linphone/core_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +LinphoneCallCbs *_linphone_call_cbs_new(void); + +void linphone_call_notify_state_changed(LinphoneCall *call, LinphoneCallState cstate, const char *message); +void linphone_call_notify_dtmf_received(LinphoneCall *call, int dtmf); +void linphone_call_notify_encryption_changed(LinphoneCall *call, bool_t on, const char *authentication_token); +void linphone_call_notify_transfer_state_changed(LinphoneCall *call, LinphoneCallState cstate); +void linphone_call_notify_stats_updated(LinphoneCall *call, const LinphoneCallStats *stats); +void linphone_call_notify_info_message_received(LinphoneCall *call, const LinphoneInfoMessage *msg); +void linphone_call_notify_ack_processing(LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received); +void linphone_call_notify_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr); +void linphone_call_notify_snapshot_taken(LinphoneCall *call, const char *file_path); +void linphone_call_notify_next_video_frame_decoded(LinphoneCall *call); + +LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); +LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LinphonePrivate::SalCallOp *op); +LINPHONE_PUBLIC LinphoneCallLog *linphone_call_log_new(LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress * to); +LinphonePlayer *linphone_call_build_player(LinphoneCall*call); + +LinphonePrivate::SalCallOp *linphone_call_get_op(const LinphoneCall *call); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC LinphoneProxyConfig *linphone_call_get_dest_proxy(const LinphoneCall *call); + +LINPHONE_PUBLIC MediaStream * linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC LinphoneCallLog * linphone_call_get_log(const LinphoneCall *call); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC IceSession *linphone_call_get_ice_session(const LinphoneCall *call); + +bool_t linphone_call_get_audio_muted(const LinphoneCall *call); +void linphone_call_set_audio_muted(LinphoneCall *call, bool_t value); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC bool_t linphone_call_get_all_muted(const LinphoneCall *call); + +void _linphone_call_set_conf_ref (LinphoneCall *call, LinphoneConference *ref); +MSAudioEndpoint *_linphone_call_get_endpoint (const LinphoneCall *call); +void _linphone_call_set_endpoint (LinphoneCall *call, MSAudioEndpoint *endpoint); + +LinphoneCallParams * linphone_call_params_new(LinphoneCore *core); +SalMediaProto get_proto_from_call_params(const LinphoneCallParams *params); +SalStreamDir get_audio_dir_from_call_params(const LinphoneCallParams *params); +SalStreamDir get_video_dir_from_call_params(const LinphoneCallParams *params); +void linphone_call_params_set_custom_headers(LinphoneCallParams *params, const SalCustomHeader *ch); +void linphone_call_params_set_custom_sdp_attributes(LinphoneCallParams *params, const SalCustomSdpAttribute *csa); +void linphone_call_params_set_custom_sdp_media_attributes(LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa); +bool_t linphone_call_params_get_in_conference(const LinphoneCallParams *params); +void linphone_call_params_set_in_conference(LinphoneCallParams *params, bool_t value); +bool_t linphone_call_params_get_internal_call_update(const LinphoneCallParams *params); +void linphone_call_params_set_internal_call_update(LinphoneCallParams *params, bool_t value); +bool_t linphone_call_params_implicit_rtcp_fb_enabled(const LinphoneCallParams *params); +void linphone_call_params_enable_implicit_rtcp_fb(LinphoneCallParams *params, bool_t value); +int linphone_call_params_get_down_bandwidth(const LinphoneCallParams *params); +void linphone_call_params_set_down_bandwidth(LinphoneCallParams *params, int value); +int linphone_call_params_get_up_bandwidth(const LinphoneCallParams *params); +void linphone_call_params_set_up_bandwidth(LinphoneCallParams *params, int value); +int linphone_call_params_get_down_ptime(const LinphoneCallParams *params); +void linphone_call_params_set_down_ptime(LinphoneCallParams *params, int value); +int linphone_call_params_get_up_ptime(const LinphoneCallParams *params); +void linphone_call_params_set_up_ptime(LinphoneCallParams *params, int value); +SalCustomHeader * linphone_call_params_get_custom_headers(const LinphoneCallParams *params); +SalCustomSdpAttribute * linphone_call_params_get_custom_sdp_attributes(const LinphoneCallParams *params); +SalCustomSdpAttribute * linphone_call_params_get_custom_sdp_media_attributes(const LinphoneCallParams *params, LinphoneStreamType type); +LinphoneCall * linphone_call_params_get_referer(const LinphoneCallParams *params); +void linphone_call_params_set_referer(LinphoneCallParams *params, LinphoneCall *referer); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC bool_t linphone_call_params_get_update_call_when_ice_completed(const LinphoneCallParams *params); + +void linphone_call_params_set_update_call_when_ice_completed(LinphoneCallParams *params, bool_t value); +void linphone_call_params_set_sent_vsize(LinphoneCallParams *params, MSVideoSize vsize); +void linphone_call_params_set_recv_vsize(LinphoneCallParams *params, MSVideoSize vsize); +void linphone_call_params_set_sent_video_definition(LinphoneCallParams *params, LinphoneVideoDefinition *vdef); +void linphone_call_params_set_received_video_definition(LinphoneCallParams *params, LinphoneVideoDefinition *vdef); +void linphone_call_params_set_sent_fps(LinphoneCallParams *params, float value); +void linphone_call_params_set_received_fps(LinphoneCallParams *params, float value); +void linphone_call_params_set_used_audio_codec(LinphoneCallParams *params, OrtpPayloadType *codec); +void linphone_call_params_set_used_video_codec(LinphoneCallParams *params, OrtpPayloadType *codec); +void linphone_call_params_set_used_text_codec(LinphoneCallParams *params, OrtpPayloadType *codec); +bool_t linphone_call_params_get_no_user_consent(const LinphoneCallParams *params); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC void linphone_call_params_set_no_user_consent(LinphoneCallParams *params, bool_t value); + +void linphone_auth_info_write_config(LinphoneConfig *config, LinphoneAuthInfo *obj, int pos); +LinphoneAuthInfo * linphone_auth_info_new_from_config_file(LpConfig *config, int pos); +void _linphone_core_uninit(LinphoneCore *lc); +void linphone_core_write_auth_info(LinphoneCore *lc, LinphoneAuthInfo *ai); +const LinphoneAuthInfo *_linphone_core_find_tls_auth_info(LinphoneCore *lc); +const LinphoneAuthInfo *_linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *domain, bool_t ignore_realm); + +void linphone_core_update_proxy_register(LinphoneCore *lc); +const char *linphone_core_get_nat_address_resolved(LinphoneCore *lc); + +int linphone_proxy_config_send_publish(LinphoneProxyConfig *cfg, LinphonePresenceModel *presence); +void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState rstate, const char *message); +void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig *obj); +void linphone_proxy_config_write_all_to_config_file(LinphoneCore *lc); +void _linphone_proxy_config_release(LinphoneProxyConfig *cfg); +void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj); +void linphone_proxy_config_notify_publish_state_changed(LinphoneProxyConfig *cfg, LinphonePublishState state); +LinphoneEvent *linphone_proxy_config_create_publish(LinphoneProxyConfig *cfg, const char *event, int expires); +/* + * returns service route as defined in as defined by rfc3608, might be a list instead of just one. + * Can be NULL + * */ +const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg); +const LinphoneAddress *_linphone_proxy_config_get_contact_without_params (const LinphoneProxyConfig *cfg); + +void linphone_friend_list_invalidate_subscriptions(LinphoneFriendList *list); +void linphone_friend_list_notify_presence_received(LinphoneFriendList *list, LinphoneEvent *lev, const LinphoneContent *body); +void linphone_friend_list_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state); +void _linphone_friend_list_release(LinphoneFriendList *list); +/*get rls either from list or core if any*/ +const LinphoneAddress * _linphone_friend_list_get_rls_address(const LinphoneFriendList *list); + +LINPHONE_PUBLIC void linphone_friend_invalidate_subscription(LinphoneFriend *lf); +void linphone_friend_close_subscriptions(LinphoneFriend *lf); +void _linphone_friend_release(LinphoneFriend *lf); +LINPHONE_PUBLIC void linphone_friend_update_subscribes(LinphoneFriend *fr, bool_t only_when_registered); +void linphone_friend_notify(LinphoneFriend *lf, LinphonePresenceModel *presence); +void linphone_friend_apply(LinphoneFriend *fr, LinphoneCore *lc); +void linphone_friend_add_incoming_subscription(LinphoneFriend *lf, LinphonePrivate::SalOp *op); +void linphone_friend_remove_incoming_subscription(LinphoneFriend *lf, LinphonePrivate::SalOp *op); +const char * linphone_friend_phone_number_to_sip_uri(LinphoneFriend *lf, const char *phone_number); +const char * linphone_friend_sip_uri_to_phone_number(LinphoneFriend *lf, const char *uri); +void linphone_friend_clear_presence_models(LinphoneFriend *lf); +LinphoneFriend *linphone_friend_list_find_friend_by_inc_subscribe(const LinphoneFriendList *list, LinphonePrivate::SalOp *op); +LinphoneFriend *linphone_friend_list_find_friend_by_out_subscribe(const LinphoneFriendList *list, LinphonePrivate::SalOp *op); +LinphoneFriend *linphone_core_find_friend_by_out_subscribe(const LinphoneCore *lc, LinphonePrivate::SalOp *op); +LinphoneFriend *linphone_core_find_friend_by_inc_subscribe(const LinphoneCore *lc, LinphonePrivate::SalOp *op); +MSList *linphone_find_friend_by_address(MSList *fl, const LinphoneAddress *addr, LinphoneFriend **lf); +bool_t linphone_core_should_subscribe_friends_only_when_registered(const LinphoneCore *lc); +void linphone_core_update_friends_subscriptions(LinphoneCore *lc); +void _linphone_friend_list_update_subscriptions(LinphoneFriendList *list, LinphoneProxyConfig *cfg, bool_t only_when_registered); +void linphone_core_friends_storage_init(LinphoneCore *lc); +void linphone_core_friends_storage_close(LinphoneCore *lc); +void linphone_core_store_friend_in_db(LinphoneCore *lc, LinphoneFriend *lf); +void linphone_core_remove_friend_from_db(LinphoneCore *lc, LinphoneFriend *lf); +void linphone_core_store_friends_list_in_db(LinphoneCore *lc, LinphoneFriendList *list); +void linphone_core_remove_friends_list_from_db(LinphoneCore *lc, LinphoneFriendList *list); +LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_from_db(LinphoneCore *lc, LinphoneFriendList *list); +LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_lists_from_db(LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_import_friend(LinphoneFriendList *list, LinphoneFriend *lf, bool_t synchronize); + +int linphone_parse_host_port(const char *input, char *host, size_t hostlen, int *port); +int parse_hostname_to_addr(const char *server, struct sockaddr_storage *ss, socklen_t *socklen, int default_port); + +bool_t host_has_ipv6_network(void); +bool_t lp_spawn_command_line_sync(const char *command, char **result,int *command_ret); + +static MS2_INLINE void set_string(char **dest, const char *src, bool_t lowercase){ + if (*dest){ + ms_free(*dest); + *dest=NULL; + } + if (src) { + *dest=ms_strdup(src); + if (lowercase) { + char *cur = *dest; + for (; *cur; cur++) *cur = (char)tolower(*cur); + } + } +} + +void linphone_process_authentication(LinphoneCore* lc, LinphonePrivate::SalOp *op); +void linphone_authentication_ok(LinphoneCore *lc, LinphonePrivate::SalOp *op); +void linphone_subscription_new(LinphoneCore *lc, LinphonePrivate::SalSubscribeOp *op, const char *from); +void linphone_core_send_presence(LinphoneCore *lc, LinphonePresenceModel *presence); +void linphone_notify_parse_presence(const char *content_type, const char *content_subtype, const char *body, SalPresenceModel **result); +void linphone_notify_convert_presence_to_xml(LinphonePrivate::SalOp *op, SalPresenceModel *presence, const char *contact, char **content); +void linphone_notify_recv(LinphoneCore *lc, LinphonePrivate::SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model); +void linphone_proxy_config_process_authentication_failure(LinphoneCore *lc, LinphonePrivate::SalOp *op); +void linphone_core_soundcard_hint_check(LinphoneCore* lc); + + +void linphone_subscription_answered(LinphoneCore *lc, LinphonePrivate::SalOp *op); +void linphone_subscription_closed(LinphoneCore *lc, LinphonePrivate::SalOp *op); + +void linphone_core_update_allocated_audio_bandwidth(LinphoneCore *lc); + +LINPHONE_PUBLIC int linphone_run_stun_tests(LinphoneCore *lc, int audioPort, int videoPort, int textPort, + char *audioCandidateAddr, int *audioCandidatePort, char *videoCandidateAddr, int *videoCandidatePort, char *textCandidateAddr, int *textCandidatePort); +void linphone_core_resolve_stun_server(LinphoneCore *lc); +LINPHONE_PUBLIC const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_enable_forced_ice_relay(LinphoneCore *lc, bool_t enable); +LINPHONE_PUBLIC void linphone_core_enable_short_turn_refresh(LinphoneCore *lc, bool_t enable); +LINPHONE_PUBLIC void linphone_call_stats_fill(LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev); +void linphone_call_stats_update(LinphoneCallStats *stats, MediaStream *stream); +LinphoneCallStats *_linphone_call_stats_new(void); +void _linphone_call_stats_uninit(LinphoneCallStats *stats); +void _linphone_call_stats_clone(LinphoneCallStats *dst, const LinphoneCallStats *src); +void _linphone_call_stats_set_ice_state (LinphoneCallStats *stats, LinphoneIceState state); +void _linphone_call_stats_set_type (LinphoneCallStats *stats, LinphoneStreamType type); +void _linphone_call_stats_set_received_rtcp (LinphoneCallStats *stats, mblk_t *m); +mblk_t *_linphone_call_stats_get_sent_rtcp (const LinphoneCallStats *stats); +void _linphone_call_stats_set_sent_rtcp (LinphoneCallStats *stats, mblk_t *m); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC int _linphone_call_stats_get_updated (const LinphoneCallStats *stats); + +void _linphone_call_stats_set_updated (LinphoneCallStats *stats, int updated); +void _linphone_call_stats_set_rtp_stats (LinphoneCallStats *stats, const rtp_stats_t *rtpStats); +void _linphone_call_stats_set_download_bandwidth (LinphoneCallStats *stats, float bandwidth); +void _linphone_call_stats_set_upload_bandwidth (LinphoneCallStats *stats, float bandwidth); +void _linphone_call_stats_set_rtcp_download_bandwidth (LinphoneCallStats *stats, float bandwidth); +void _linphone_call_stats_set_rtcp_upload_bandwidth (LinphoneCallStats *stats, float bandwidth); +void _linphone_call_stats_set_ip_family_of_remote (LinphoneCallStats *stats, LinphoneAddressFamily family); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC bool_t _linphone_call_stats_rtcp_received_via_mux (const LinphoneCallStats *stats); + +bool_t linphone_core_media_description_contains_video_stream(const SalMediaDescription *md); + +void linphone_core_send_initial_subscribes(LinphoneCore *lc); +void linphone_core_write_friends_config(LinphoneCore* lc); +void linphone_friend_write_to_config_file(LinphoneConfig *config, LinphoneFriend *lf, int index); +LinphoneFriend * linphone_friend_new_from_config_file(struct _LinphoneCore *lc, int index); + +void linphone_proxy_config_update(LinphoneProxyConfig *cfg); +LinphoneProxyConfig * linphone_core_lookup_known_proxy(LinphoneCore *lc, const LinphoneAddress *uri); +const char *linphone_core_find_best_identity(LinphoneCore *lc, const LinphoneAddress *to); +LINPHONE_PUBLIC void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result); + +LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore *lc, int index); +void linphone_proxy_config_write_to_config_file(LinphoneConfig* config,LinphoneProxyConfig *obj, int index); + +int linphone_core_message_received(LinphoneCore *lc, LinphonePrivate::SalOp *op, const SalMessage *msg); +void linphone_core_real_time_text_received(LinphoneCore *lc, LinphoneChatRoom *cr, uint32_t character, LinphoneCall *call); + +void linphone_call_init_media_streams(LinphoneCall *call); +void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call); +void linphone_call_stop_media_streams(LinphoneCall *call); +int _linphone_core_apply_transports(LinphoneCore *lc); + +void linphone_core_start_waiting(LinphoneCore *lc, const char *purpose); +void linphone_core_update_progress(LinphoneCore *lc, const char *purpose, float progresses); +void linphone_core_stop_waiting(LinphoneCore *lc); + +void linphone_core_notify_incoming_call(LinphoneCore *lc, LinphoneCall *call); +bool_t linphone_core_incompatible_security(LinphoneCore *lc, SalMediaDescription *md); +extern LinphonePrivate::Sal::Callbacks linphone_sal_callbacks; +LINPHONE_PUBLIC bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); +LINPHONE_PUBLIC bool_t linphone_core_symmetric_rtp_enabled(LinphoneCore*lc); +bool_t _linphone_core_is_conference_creation (const LinphoneCore *lc, const LinphoneAddress *addr); +LinphoneChatRoom *_linphone_core_create_server_group_chat_room (LinphoneCore *lc, LinphonePrivate::SalCallOp *op); + +void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description); + + +LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b); +LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj); +/** + * unregister without moving the register_enable flag + */ +void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj); +void _linphone_proxy_config_release_ops(LinphoneProxyConfig *obj); + +/*chat*/ +LinphoneChatRoom *_linphone_server_group_chat_room_new (LinphoneCore *core, LinphonePrivate::SalCallOp *op); +void linphone_chat_room_set_call(LinphoneChatRoom *cr, LinphoneCall *call); +LinphoneChatRoomCbs * _linphone_chat_room_cbs_new (void); +void _linphone_chat_room_notify_is_composing_received(LinphoneChatRoom *cr, const LinphoneAddress *remoteAddr, bool_t isComposing); +void _linphone_chat_room_notify_message_received(LinphoneChatRoom *cr, LinphoneChatMessage *msg); +void _linphone_chat_room_notify_participant_added(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_participant_removed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_participant_device_added(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_participant_device_removed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_participant_admin_status_changed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState); +void _linphone_chat_room_notify_subject_changed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_conference_joined(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_conference_left(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_undecryptable_message_received(LinphoneChatRoom *cr, LinphoneChatMessage *msg); +void _linphone_chat_room_notify_chat_message_received(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_chat_message_sent(LinphoneChatRoom *cr, const LinphoneEventLog *event_log); +void _linphone_chat_room_notify_conference_address_generation(LinphoneChatRoom *cr); +void _linphone_chat_room_notify_participant_device_fetch_requested(LinphoneChatRoom *cr, const LinphoneAddress *participantAddr); +void _linphone_chat_room_notify_participants_capabilities_checked(LinphoneChatRoom *cr, const LinphoneAddress *deviceAddr, const bctbx_list_t *participantsAddr); +void _linphone_chat_room_notify_participant_registration_subscription_requested(LinphoneChatRoom *cr, const LinphoneAddress *participantAddr); +void _linphone_chat_room_notify_participant_registration_unsubscription_requested(LinphoneChatRoom *cr, const LinphoneAddress *participantAddr); +void _linphone_chat_room_notify_chat_message_should_be_stored(LinphoneChatRoom *cr, LinphoneChatMessage *msg); +void _linphone_chat_room_clear_callbacks (LinphoneChatRoom *cr); +const LinphoneParticipantImdnState *_linphone_participant_imdn_state_from_cpp_obj (const LinphonePrivate::ParticipantImdnState &state); + +LinphoneToneDescription * linphone_tone_description_new(LinphoneReason reason, LinphoneToneID id, const char *audiofile); +void linphone_tone_description_destroy(LinphoneToneDescription *obj); +LinphoneToneDescription *linphone_core_get_call_error_tone(const LinphoneCore *lc, LinphoneReason reason); +void linphone_core_play_call_error_tone(LinphoneCore *lc, LinphoneReason reason); +void _linphone_core_set_tone(LinphoneCore *lc, LinphoneReason reason, LinphoneToneID id, const char *audiofile); +LINPHONE_PUBLIC const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID id); + +void linphone_task_list_init(LinphoneTaskList *t); +void linphone_task_list_add(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data); +void linphone_task_list_remove(LinphoneTaskList *t, LinphoneCoreIterateHook hook, void *hook_data); +void linphone_task_list_run(LinphoneTaskList *t); +void linphone_task_list_free(LinphoneTaskList *t); + +LinphoneCoreCbs * _linphone_core_cbs_new(void); +void _linphone_core_cbs_set_v_table(LinphoneCoreCbs *cbs, LinphoneCoreVTable *vtable, bool_t autorelease); + + +LinphoneTunnel *linphone_core_tunnel_new(LinphoneCore *lc); +void linphone_tunnel_configure(LinphoneTunnel *tunnel); +void linphone_tunnel_enable_logs_with_handler(LinphoneTunnel *tunnel, bool_t enabled, OrtpLogFunc logHandler); + +// FIXME: Remove this declaration, use LINPHONE_PUBLIC as ugly workaround, already defined in tester_utils.h +LINPHONE_PUBLIC int linphone_core_get_calls_nb(const LinphoneCore *lc); + +void linphone_core_set_state(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); +void linphone_call_update_biggest_desc(LinphoneCall *call, SalMediaDescription *md); +void linphone_call_make_local_media_description_with_params(LinphoneCore *lc, LinphoneCall *call, LinphoneCallParams *params); + +bool_t linphone_core_is_payload_type_usable_for_bandwidth(const LinphoneCore *lc, const PayloadType *pt, int bandwidth_limit); + +#define linphone_core_ready(lc) ((lc)->state==LinphoneGlobalOn || (lc)->state==LinphoneGlobalShutdown) +void _linphone_core_configure_resolver(void); + +void linphone_core_initialize_supported_content_types(LinphoneCore *lc); + +LinphoneEcCalibratorStatus ec_calibrator_get_status(EcCalibrator *ecc); + +void ec_calibrator_destroy(EcCalibrator *ecc); + +int linphone_core_preempt_sound_resources(LinphoneCore *lc); +int _linphone_call_pause(LinphoneCall *call); + +/*conferencing subsystem*/ +void _post_configure_audio_stream(AudioStream *st, LinphoneCore *lc, bool_t muted); +bool_t linphone_core_sound_resources_available(LinphoneCore *lc); +LINPHONE_PUBLIC unsigned int linphone_core_get_audio_features(LinphoneCore *lc); + +void _linphone_core_codec_config_write(LinphoneCore *lc); + +LINPHONE_PUBLIC bctbx_list_t * linphone_core_read_call_logs_from_config_file(LinphoneCore *lc); +void call_logs_write_to_config_file(LinphoneCore *lc); +void linphone_core_call_log_storage_init(LinphoneCore *lc); +void linphone_core_call_log_storage_close(LinphoneCore *lc); +void linphone_core_store_call_log(LinphoneCore *lc, LinphoneCallLog *log); +LINPHONE_PUBLIC const MSList *linphone_core_get_call_history(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_delete_call_history(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log); +LINPHONE_PUBLIC int linphone_core_get_call_history_size(LinphoneCore *lc); + +int linphone_core_get_edge_bw(LinphoneCore *lc); +int linphone_core_get_edge_ptime(LinphoneCore *lc); + +LinphoneCore *_linphone_core_new_with_config(LinphoneCoreCbs *cbs, struct _LpConfig *config, void *userdata, void *system_context, bool_t automatically_start); + +int linphone_upnp_init(LinphoneCore *lc); +void linphone_upnp_destroy(LinphoneCore *lc); + +#ifdef SQLITE_STORAGE_ENABLED +int _linphone_sqlite3_open(const char *db_file, sqlite3 **db); +#endif + +LinphoneChatMessageStateChangedCb linphone_chat_message_get_message_state_changed_cb(LinphoneChatMessage* msg); +void linphone_chat_message_set_message_state_changed_cb(LinphoneChatMessage* msg, LinphoneChatMessageStateChangedCb cb); +void linphone_chat_message_set_message_state_changed_cb_user_data(LinphoneChatMessage* msg, void *user_data); +void * linphone_chat_message_get_message_state_changed_cb_user_data(LinphoneChatMessage* msg); +LinphoneChatRoom *_linphone_core_create_chat_room_from_call(LinphoneCall *call); + +void linphone_core_play_named_tone(LinphoneCore *lc, LinphoneToneID id); +bool_t linphone_core_tone_indications_enabled(LinphoneCore*lc); +const char *linphone_core_create_uuid(LinphoneCore *lc); +void linphone_configure_op(LinphoneCore *lc, LinphonePrivate::SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact); +void linphone_configure_op_with_proxy(LinphoneCore *lc, LinphonePrivate::SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact, LinphoneProxyConfig *proxy); +LinphoneContent * linphone_content_new(void); +LinphoneContent * linphone_content_copy(const LinphoneContent *ref); +SalBodyHandler *sal_body_handler_from_content(const LinphoneContent *content, bool parseMultipart = true); +SalReason linphone_reason_to_sal(LinphoneReason reason); +LinphoneReason linphone_reason_from_sal(SalReason reason); +void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei); +LinphoneEvent *linphone_event_new(LinphoneCore *lc, LinphoneSubscriptionDir dir, const char *name, int expires); +LinphoneEvent *linphone_event_new_with_op(LinphoneCore *lc, LinphonePrivate::SalEventOp *op, LinphoneSubscriptionDir dir, const char *name); +void linphone_event_unpublish(LinphoneEvent *lev); +/** + * Useful for out of dialog notify + * */ +LinphoneEvent *linphone_event_new_with_out_of_dialog_op(LinphoneCore *lc, LinphonePrivate::SalEventOp *op, LinphoneSubscriptionDir dir, const char *name); +void linphone_event_set_internal(LinphoneEvent *lev, bool_t internal); +bool_t linphone_event_is_internal(LinphoneEvent *lev); +void linphone_event_set_state(LinphoneEvent *lev, LinphoneSubscriptionState state); +void linphone_event_set_publish_state(LinphoneEvent *lev, LinphonePublishState state); +void _linphone_event_notify_notify_response(const LinphoneEvent *lev); +LinphoneSubscriptionState linphone_subscription_state_from_sal(SalSubscribeStatus ss); +LinphoneContent *linphone_content_from_sal_body_handler(const SalBodyHandler *ref, bool parseMultipart = true); +void linphone_core_invalidate_friend_subscriptions(LinphoneCore *lc); +void linphone_core_register_offer_answer_providers(LinphoneCore *lc); + +bool_t linphone_nat_policy_stun_server_activated(LinphoneNatPolicy *policy); +void linphone_nat_policy_save_to_config(const LinphoneNatPolicy *policy); + +void linphone_core_create_im_notif_policy(LinphoneCore *lc); + + +/***************************************************************************** + * REMOTE PROVISIONING FUNCTIONS * + ****************************************************************************/ + +void linphone_configuring_terminated(LinphoneCore *lc, LinphoneConfiguringState state, const char *message); +int linphone_remote_provisioning_download_and_apply(LinphoneCore *lc, const char *remote_provisioning_uri); +LINPHONE_PUBLIC int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path); + + +/***************************************************************************** + * Player interface * + ****************************************************************************/ + +LinphonePlayerCbs *linphone_player_cbs_new(void); +LinphonePlayer * linphone_player_new(void); +void _linphone_player_destroy(LinphonePlayer *player); + + +/***************************************************************************** + * XML UTILITY FUNCTIONS * + ****************************************************************************/ + +xmlparsing_context_t * linphone_xmlparsing_context_new(void); +void linphone_xmlparsing_context_destroy(xmlparsing_context_t *ctx); +void linphone_xmlparsing_genericxml_error(void *ctx, const char *fmt, ...); +int linphone_create_xml_xpath_context(xmlparsing_context_t *xml_ctx); +void linphone_xml_xpath_context_set_node(xmlparsing_context_t *xml_ctx, xmlNodePtr node); +char * linphone_get_xml_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression); +char * linphone_get_xml_attribute_text_content(xmlparsing_context_t *xml_ctx, const char *xpath_expression, const char *attribute_name); +void linphone_free_xml_text_content(char *text); +xmlXPathObjectPtr linphone_get_xml_xpath_object_for_node_list(xmlparsing_context_t *xml_ctx, const char *xpath_expression); +void linphone_xml_xpath_context_init_carddav_ns(xmlparsing_context_t *xml_ctx); + +/***************************************************************************** + * OTHER UTILITY FUNCTIONS * + ****************************************************************************/ + +char * linphone_timestamp_to_rfc3339_string(time_t timestamp); + +void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const LinphonePrivate::SalOp *op); + +void payload_type_set_enable(OrtpPayloadType *pt, bool_t value); +bool_t payload_type_enabled(const OrtpPayloadType *pt); + +LinphonePayloadType *linphone_payload_type_new(LinphoneCore *lc, OrtpPayloadType *ortp_pt); +bool_t _linphone_core_check_payload_type_usability(const LinphoneCore *lc, const OrtpPayloadType *pt); +OrtpPayloadType *linphone_payload_type_get_ortp_pt(const LinphonePayloadType *pt); + + +const MSCryptoSuite * linphone_core_get_srtp_crypto_suites(LinphoneCore *lc); +MsZrtpCryptoTypesCount linphone_core_get_zrtp_key_agreement_suites(LinphoneCore *lc, MSZrtpKeyAgreement keyAgreements[MS_MAX_ZRTP_CRYPTO_TYPES]); +MsZrtpCryptoTypesCount linphone_core_get_zrtp_cipher_suites(LinphoneCore *lc, MSZrtpCipher ciphers[MS_MAX_ZRTP_CRYPTO_TYPES]); +MsZrtpCryptoTypesCount linphone_core_get_zrtp_hash_suites(LinphoneCore *lc, MSZrtpHash hashes[MS_MAX_ZRTP_CRYPTO_TYPES]); +MsZrtpCryptoTypesCount linphone_core_get_zrtp_auth_suites(LinphoneCore *lc, MSZrtpAuthTag authTags[MS_MAX_ZRTP_CRYPTO_TYPES]); +MsZrtpCryptoTypesCount linphone_core_get_zrtp_sas_suites(LinphoneCore *lc, MSZrtpSasType sasTypes[MS_MAX_ZRTP_CRYPTO_TYPES]); + +LinphoneImEncryptionEngineCbs * linphone_im_encryption_engine_cbs_new(void); + +LinphoneRange *linphone_range_new(void); + +LINPHONE_PUBLIC LinphoneTransports *linphone_transports_new(void); + +LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_video_activation_policy_new(void); + +void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message); +void linphone_core_notify_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message); +void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token); +void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message); +void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url); +void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain); +void linphone_core_notify_authentication_requested(LinphoneCore *lc, LinphoneAuthInfo *auth_info, LinphoneAuthMethod method); +void linphone_core_notify_call_log_updated(LinphoneCore *lc, LinphoneCallLog *newcl); +void linphone_core_notify_text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from, const char *message); +void linphone_core_notify_message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message); +void linphone_core_notify_message_received_unable_decrypt(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message); +void linphone_core_notify_file_transfer_recv(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, const char* buff, size_t size); +void linphone_core_notify_file_transfer_send(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, char* buff, size_t* size); +void linphone_core_notify_file_transfer_progress_indication(LinphoneCore *lc, LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total); +void linphone_core_notify_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room); +void linphone_core_notify_dtmf_received(LinphoneCore* lc, LinphoneCall *call, int dtmf); +/* + * return true if at least a registered vtable has a cb for dtmf received*/ +bool_t linphone_core_dtmf_received_has_listener(const LinphoneCore* lc); +void linphone_core_notify_refer_received(LinphoneCore *lc, const char *refer_to); +void linphone_core_notify_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf); +void linphone_core_notify_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state); +void linphone_core_notify_call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats); +void linphone_core_notify_info_received(LinphoneCore *lc, LinphoneCall *call, const LinphoneInfoMessage *msg); +void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message); +void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable); + +void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *notified_event, const LinphoneContent *body); +void linphone_core_notify_subscribe_received(LinphoneCore *lc, LinphoneEvent *lev, const char *subscribe_event, const LinphoneContent *body); +void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state); +void linphone_core_notify_publish_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphonePublishState state); +void linphone_core_notify_log_collection_upload_state_changed(LinphoneCore *lc, LinphoneCoreLogCollectionUploadState state, const char *info); +void linphone_core_notify_log_collection_upload_progress_indication(LinphoneCore *lc, size_t offset, size_t total); +void linphone_core_notify_friend_list_created(LinphoneCore *lc, LinphoneFriendList *list); +void linphone_core_notify_friend_list_removed(LinphoneCore *lc, LinphoneFriendList *list); +void linphone_core_notify_call_created(LinphoneCore *lc, LinphoneCall *call); +void linphone_core_notify_version_update_check_result_received(LinphoneCore *lc, LinphoneVersionUpdateCheckResult result, const char *version, const char *url); +void linphone_core_notify_chat_room_state_changed (LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatRoomState state); +void linphone_core_notify_qrcode_found(LinphoneCore *lc, const char *result); +void linphone_core_notify_ec_calibration_result(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms); +void linphone_core_notify_ec_calibration_audio_init(LinphoneCore *lc); +void linphone_core_notify_ec_calibration_audio_uninit(LinphoneCore *lc); + +void set_playback_gain_db(AudioStream *st, float gain); + +LinphoneMediaDirection media_direction_from_sal_stream_dir(SalStreamDir dir); +SalStreamDir sal_dir_from_call_params_dir(LinphoneMediaDirection cpdir); + +/***************************************************************************** + * LINPHONE CONTENT PRIVATE ACCESSORS * + ****************************************************************************/ + +/** + * Get the address of the crypto context associated with a RCS file transfer message if encrypted + * @param[in] content LinphoneContent object. + * @return The address of the pointer to the crypto context. Crypto context is managed(alloc/free) + * by the encryption/decryption functions, so we give the address to store/retrieve the pointer + */ +void ** linphone_content_get_cryptoContext_address(LinphoneContent *content); + +void v_table_reference_destroy(VTableReference *ref); + +LINPHONE_PUBLIC void _linphone_core_add_callbacks(LinphoneCore *lc, LinphoneCoreCbs *vtable, bool_t internal); + +MSWebCam *get_nowebcam_device(MSFactory *f); + +LinphoneLimeState linphone_core_lime_for_file_sharing_enabled(const LinphoneCore *lc); + +int linphone_core_get_default_proxy_config_index(LinphoneCore *lc); + +char *linphone_presence_model_to_xml(LinphonePresenceModel *model) ; + +void linphone_core_report_call_log(LinphoneCore *lc, LinphoneCallLog *call_log); +void linphone_core_report_early_failed_call(LinphoneCore *lc, LinphoneCallDir dir, LinphoneAddress *from, LinphoneAddress *to, LinphoneErrorInfo *ei); + +LinphoneVideoDefinition * linphone_video_definition_new(unsigned int width, unsigned int height, const char *name); + +LinphoneVideoDefinition * linphone_factory_find_supported_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height); +LinphoneVideoDefinition * linphone_factory_find_supported_video_definition_by_name(const LinphoneFactory *factory, const char *name); + +const char* _linphone_config_load_from_xml_string(LpConfig *lpc, const char *buffer); +LinphoneNatPolicy * linphone_config_create_nat_policy_from_section(const LinphoneConfig *config, const char* section); + +SalCustomHeader *linphone_info_message_get_headers (const LinphoneInfoMessage *im); +void linphone_info_message_set_headers (LinphoneInfoMessage *im, const SalCustomHeader *headers); + +void _linphone_core_set_log_handler(OrtpLogFunc logfunc); + +#ifdef __cplusplus +} +#endif + +#endif /* _PRIVATE_FUNCTIONS_H_ */ diff --git a/coreapi/private_structs.h b/coreapi/private_structs.h new file mode 100644 index 000000000..f532cbcf9 --- /dev/null +++ b/coreapi/private_structs.h @@ -0,0 +1,833 @@ +/* + * private_structs.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _PRIVATE_STRUCTS_H_ +#define _PRIVATE_STRUCTS_H_ + +#include +#include +#include +#include +#include + +#include "carddav.h" +#include "sal/register-op.h" + +struct _LinphoneQualityReporting{ + reporting_session_report_t * reports[3]; /**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*/ + LinphoneQualityReportingReportSendCb on_report_sent; +}; + +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*/ + LinphoneAddress *from; /**= 6) || __GNUC__ > 4) +#pragma GCC diagnostic push +#endif +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#else +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + LinphoneEcCalibrationCallback cb; + void *cb_data; + LinphoneEcCalibrationAudioInit audio_init_cb; + LinphoneEcCalibrationAudioUninit audio_uninit_cb; +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic pop +#endif + int64_t acc; + int delay; + unsigned int rate; + LinphoneEcCalibratorStatus status; + bool_t freq1,freq2,freq3; + bool_t play_cool_tones; +}; + +struct _EchoTester { + MSFactory *factory; + MSFilter *in,*out; + MSSndCard *capture_card; + MSSndCard *playback_card; + MSTicker *ticker; + unsigned int rate; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneContent); + +struct _LinphoneBuffer { + belle_sip_object_t base; + void *user_data; + uint8_t *content; /**< A pointer to the buffer content */ + size_t size; /**< The size of the buffer content */ +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneBuffer); + +struct _LinphoneNatPolicy { + belle_sip_object_t base; + void *user_data; + LinphoneCore *lc; + belle_sip_resolver_context_t *stun_resolver_context; + struct addrinfo *stun_addrinfo; + char *stun_server; + char *stun_server_username; + char *ref; + bool_t stun_enabled; + bool_t turn_enabled; + bool_t ice_enabled; + bool_t upnp_enabled; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneNatPolicy); + +struct _LinphoneImNotifPolicy { + belle_sip_object_t base; + void *user_data; + LinphoneCore *lc; + bool_t send_is_composing; + bool_t recv_is_composing; + bool_t send_imdn_delivered; + bool_t recv_imdn_delivered; + bool_t send_imdn_displayed; + bool_t recv_imdn_displayed; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneImNotifPolicy); + + +/***************************************************************************** + * XML-RPC interface * + ****************************************************************************/ + +struct _LinphoneXmlRpcArg { + LinphoneXmlRpcArgType type; + union { + int i; + char *s; + } data; +}; + +struct _LinphoneXmlRpcRequestCbs { + belle_sip_object_t base; + void *user_data; + LinphoneXmlRpcRequestCbsResponseCb response; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneXmlRpcRequestCbs); + +struct _LinphoneXmlRpcRequest { + belle_sip_object_t base; + void *user_data; + LinphoneXmlRpcRequestCbs *callbacks; + belle_sip_list_t *arg_list; + char *content; /**< The string representation of the XML-RPC request */ + char *method; + LinphoneXmlRpcStatus status; + struct _LinphoneXmlRpcArg response; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneXmlRpcRequest); + +struct _LinphoneXmlRpcSession { + belle_sip_object_t base; + void *user_data; + LinphoneCore *core; + char *url; + bool_t released; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneXmlRpcSession); + + +/***************************************************************************** + * CardDAV interface * + ****************************************************************************/ + +struct _LinphoneCardDavContext { + LinphoneFriendList *friend_list; + int ctag; + void *user_data; + LinphoneCardDavContactCreatedCb contact_created_cb; + LinphoneCardDavContactUpdatedCb contact_updated_cb; + LinphoneCardDavContactRemovedCb contact_removed_cb; + LinphoneCardDavSynchronizationDoneCb sync_done_cb; + LinphoneAuthInfo *auth_info; +}; + +struct _LinphoneCardDavQuery { + LinphoneCardDavContext *context; + char *url; + const char *method; + char *body; + const char *depth; + const char *ifmatch; + belle_http_request_listener_t *http_request_listener; + void *user_data; + LinphoneCardDavQueryType type; +}; + +struct _LinphoneCardDavResponse { + char *etag; + char *url; + char *vcard; +}; + + +/***************************************************************************** + * Player interface * + ****************************************************************************/ + +struct _LinphonePlayerCbs { + belle_sip_object_t base; + void *user_data; + LinphonePlayerCbsEofReachedCb eof; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphonePlayerCbs); + +struct _LinphonePlayer{ + belle_sip_object_t base; + void *user_data; + int (*open)(LinphonePlayer* player, const char *filename); + int (*start)(LinphonePlayer* player); + int (*pause)(LinphonePlayer* player); + int (*seek)(LinphonePlayer* player, int time_ms); + MSPlayerState (*get_state)(LinphonePlayer* player); + int (*get_duration)(LinphonePlayer *player); + int (*get_position)(LinphonePlayer *player); + void (*close)(LinphonePlayer* player); + void (*destroy)(LinphonePlayer *player); + void *impl; + LinphonePlayerCbs *callbacks; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphonePlayer); + + +/***************************************************************************** + * XML UTILITY FUNCTIONS * + ****************************************************************************/ + +#define XMLPARSING_BUFFER_LEN 2048 +#define MAX_XPATH_LENGTH 256 + +struct _xmlparsing_context { + xmlDoc *doc; + xmlXPathContextPtr xpath_ctx; + char errorBuffer[XMLPARSING_BUFFER_LEN]; + char warningBuffer[XMLPARSING_BUFFER_LEN]; +}; + + +/***************************************************************************** + * OTHER UTILITY FUNCTIONS * + ****************************************************************************/ + +struct _LinphoneImEncryptionEngineCbs { + belle_sip_object_t base; + void *user_data; + LinphoneImEncryptionEngineCbsIncomingMessageCb process_incoming_message; + LinphoneImEncryptionEngineCbsOutgoingMessageCb process_outgoing_message; + LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer; + LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key; + LinphoneImEncryptionEngineCbsDownloadingFileCb process_downlading_file; + LinphoneImEncryptionEngineCbsUploadingFileCb process_uploading_file; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneImEncryptionEngineCbs); + +struct _LinphoneImEncryptionEngine { + belle_sip_object_t base; + void *user_data; + LinphoneCore *lc; + LinphoneImEncryptionEngineCbs *callbacks; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneImEncryptionEngine); + +struct _LinphoneRange { + belle_sip_object_t base; + void *user_data; + int min; + int max; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneRange); + +struct _LinphoneTransports { + belle_sip_object_t base; + void *user_data; + int udp_port; /**< SIP/UDP port */ + int tcp_port; /**< SIP/TCP port */ + int dtls_port; /**< SIP/DTLS port */ + int tls_port; /**< SIP/TLS port */ +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneTransports); + +struct _LinphoneVideoActivationPolicy { + belle_sip_object_t base; + void *user_data; + bool_t automatically_initiate; /** #include +#include +#include "linphone/core_utils.h" +#include "linphone/core.h" +#include "linphone/lpconfig.h" +#include "linphone/sipsetup.h" + +#include "mediastreamer2/mediastream.h" + +#include "enum.h" +#include "private.h" + +// For migration purpose. +#include "address/address-p.h" +#include "c-wrapper/c-wrapper.h" +#include "linphone/api/c-dial-plan.h" + +#include "dial-plan/dial-plan.h" +#include "dial-plan/dial-plan-p.h" + +using namespace LinphonePrivate; + /*store current config related to server location*/ static void linphone_proxy_config_store_server_config(LinphoneProxyConfig* cfg) { if (cfg->saved_identity) linphone_address_unref(cfg->saved_identity); @@ -102,33 +115,35 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cf const char *dial_prefix = lc ? lp_config_get_default_string(lc->config,"proxy","dial_prefix",NULL) : NULL; const char *identity = lc ? lp_config_get_default_string(lc->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 *route = lc ? lp_config_get_default_string(lc->config, "proxy", "reg_route", NULL) : NULL; //TODO return list instead of string 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; const char *refkey = lc ? lp_config_get_default_string(lc->config, "proxy", "refkey", NULL) : NULL; const char *nat_policy_ref = lc ? lp_config_get_default_string(lc->config, "proxy", "nat_policy_ref", NULL):NULL; + const char *conference_factory_uri = lc ? lp_config_get_default_string(lc->config, "proxy", "conference_factory_uri", NULL):NULL; cfg->lc = lc; cfg->expires = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_expires", 3600) : 3600; - cfg->reg_sendregister = lc ? lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1; + cfg->reg_sendregister = lc ? !!lp_config_get_default_int(lc->config, "proxy", "reg_sendregister", 1) : 1; cfg->dial_prefix = dial_prefix ? ms_strdup(dial_prefix) : NULL; - cfg->dial_escape_plus = lc ? lp_config_get_default_int(lc->config, "proxy", "dial_escape_plus", 0) : 0; - cfg->privacy = lc ? lp_config_get_default_int(lc->config, "proxy", "privacy", LinphonePrivacyDefault) : LinphonePrivacyDefault; + cfg->dial_escape_plus = lc ? !!lp_config_get_default_int(lc->config, "proxy", "dial_escape_plus", 0) : 0; + cfg->privacy = lc ? (LinphonePrivacyMask)lp_config_get_default_int(lc->config, "proxy", "privacy", LinphonePrivacyDefault) : (LinphonePrivacyMask)LinphonePrivacyDefault; cfg->identity_address = identity ? linphone_address_new(identity) : NULL; cfg->reg_identity = cfg->identity_address ? linphone_address_as_string(cfg->identity_address) : NULL; cfg->reg_proxy = proxy ? ms_strdup(proxy) : NULL; - cfg->reg_route = route ? ms_strdup(route) : NULL; + cfg->reg_routes = route ? bctbx_list_append(cfg->reg_routes, ms_strdup(route)) : NULL; //TODO get list directly cfg->realm = realm ? ms_strdup(realm) : NULL; - cfg->quality_reporting_enabled = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0; + cfg->quality_reporting_enabled = lc ? !!lp_config_get_default_int(lc->config, "proxy", "quality_reporting_enabled", 0) : 0; cfg->quality_reporting_collector = quality_reporting_collector ? ms_strdup(quality_reporting_collector) : NULL; cfg->quality_reporting_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "quality_reporting_interval", 0) : 0; cfg->contact_params = contact_params ? ms_strdup(contact_params) : NULL; cfg->contact_uri_params = contact_uri_params ? ms_strdup(contact_uri_params) : NULL; cfg->avpf_mode = lc ? static_cast(lp_config_get_default_int(lc->config, "proxy", "avpf", LinphoneAVPFDefault)) : LinphoneAVPFDefault; - cfg->avpf_rr_interval = lc ? lp_config_get_default_int(lc->config, "proxy", "avpf_rr_interval", 5) : 5; + cfg->avpf_rr_interval = lc ? !!lp_config_get_default_int(lc->config, "proxy", "avpf_rr_interval", 5) : 5; cfg->publish_expires= lc ? lp_config_get_default_int(lc->config, "proxy", "publish_expires", -1) : -1; - cfg->publish = lc ? lp_config_get_default_int(lc->config, "proxy", "publish", FALSE) : FALSE; + cfg->publish = lc ? !!lp_config_get_default_int(lc->config, "proxy", "publish", FALSE) : FALSE; + cfg->push_notification_allowed = lc ? !!lp_config_get_default_int(lc->config, "proxy", "push_notification_allowed", TRUE) : TRUE; cfg->refkey = refkey ? ms_strdup(refkey) : NULL; if (nat_policy_ref) { LinphoneNatPolicy *policy = linphone_config_create_nat_policy_from_section(lc->config,nat_policy_ref); @@ -139,6 +154,7 @@ static void linphone_proxy_config_init(LinphoneCore* lc, LinphoneProxyConfig *cf ms_error("Cannot create default nat policy with ref [%s] for proxy config [%p]",nat_policy_ref,cfg); } } + cfg->conference_factory_uri = conference_factory_uri ? ms_strdup(conference_factory_uri) : NULL; } LinphoneProxyConfig *linphone_proxy_config_new() { @@ -170,13 +186,18 @@ bool_t linphone_proxy_config_compute_publish_params_hash(LinphoneProxyConfig * c char hash[33]; char saved; unsigned long long previous_hash[2]; + bctbx_list_t *routes_iterator = cfg->reg_routes; previous_hash[0] = cfg->previous_publish_config_hash[0]; previous_hash[1] = cfg->previous_publish_config_hash[1]; source = ms_strcat_printf(source, "%i",cfg->privacy); source=append_linphone_address(cfg->identity_address, source); source=append_string(cfg->reg_proxy,source); - source=append_string(cfg->reg_route,source); + while (routes_iterator) { + const char *route = (const char *)bctbx_list_get_data(routes_iterator); + source=append_string(route,source); + routes_iterator = bctbx_list_next(routes_iterator); + } source=append_string(cfg->realm,source); source = ms_strcat_printf(source, "%i",cfg->publish_expires); source = ms_strcat_printf(source, "%i",cfg->publish); @@ -208,7 +229,7 @@ LinphoneProxyConfig * linphone_core_create_proxy_config(LinphoneCore *lc) { void _linphone_proxy_config_release_ops(LinphoneProxyConfig *cfg){ if (cfg->op) { - sal_op_release(cfg->op); + cfg->op->release(); cfg->op=NULL; } if (cfg->presence_publish_event){ @@ -222,7 +243,7 @@ void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){ if (cfg->reg_proxy!=NULL) ms_free(cfg->reg_proxy); if (cfg->reg_identity!=NULL) ms_free(cfg->reg_identity); if (cfg->identity_address!=NULL) linphone_address_unref(cfg->identity_address); - if (cfg->reg_route!=NULL) ms_free(cfg->reg_route); + if (cfg->reg_routes!=NULL) bctbx_list_free_with_data(cfg->reg_routes, ms_free); if (cfg->quality_reporting_collector!=NULL) ms_free(cfg->quality_reporting_collector); if (cfg->ssctx!=NULL) sip_setup_context_free(cfg->ssctx); if (cfg->realm!=NULL) ms_free(cfg->realm); @@ -238,9 +259,16 @@ void _linphone_proxy_config_destroy(LinphoneProxyConfig *cfg){ if (cfg->nat_policy != NULL) { linphone_nat_policy_unref(cfg->nat_policy); } + if (cfg->conference_factory_uri) + bctbx_free(cfg->conference_factory_uri); if (cfg->ei){ linphone_error_info_unref(cfg->ei); } + + if (cfg->contact_address) linphone_address_unref(cfg->contact_address); + if (cfg->contact_address_without_params) + linphone_address_unref(cfg->contact_address_without_params); + _linphone_proxy_config_release_ops(cfg); } @@ -328,9 +356,9 @@ const char *linphone_proxy_config_get_domain(const LinphoneProxyConfig *cfg){ LinphoneStatus linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const char *route) { - if (cfg->reg_route!=NULL){ - ms_free(cfg->reg_route); - cfg->reg_route=NULL; + if (cfg->reg_routes != NULL) { + bctbx_list_free_with_data(cfg->reg_routes, ms_free); + cfg->reg_routes = NULL; } if (route!=NULL && route[0] !='\0'){ SalAddress *addr; @@ -342,7 +370,7 @@ LinphoneStatus linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const c addr=sal_address_new(tmp); if (addr!=NULL){ sal_address_destroy(addr); - cfg->reg_route=tmp; + cfg->reg_routes = bctbx_list_append(cfg->reg_routes, tmp); return 0; }else{ ms_free(tmp); @@ -353,19 +381,42 @@ LinphoneStatus linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const c } } +LinphoneStatus linphone_proxy_config_set_routes(LinphoneProxyConfig *cfg, const bctbx_list_t *routes) { + if (cfg->reg_routes != NULL) { + bctbx_list_free_with_data(cfg->reg_routes, ms_free); + cfg->reg_routes = NULL; + } + bctbx_list_t *iterator = (bctbx_list_t *)routes; + while (iterator != NULL) { + char *route = (char *)bctbx_list_get_data(iterator); + if (route != NULL && route[0] !='\0') { + SalAddress *addr; + char *tmp; + /*try to prepend 'sip:' */ + if (strstr(route,"sip:") == NULL && strstr(route,"sips:") == NULL) { + tmp = ms_strdup_printf("sip:%s",route); + } else { + tmp = ms_strdup(route); + } + addr = sal_address_new(tmp); + if (addr != NULL) { + sal_address_destroy(addr); + cfg->reg_routes = bctbx_list_append(cfg->reg_routes, tmp); + } else { + ms_free(tmp); + return -1; + } + } + iterator = bctbx_list_next(iterator); + } + return 0; +} + bool_t linphone_proxy_config_check(LinphoneCore *lc, LinphoneProxyConfig *cfg){ - if (cfg->reg_proxy==NULL){ - 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.")); + if (cfg->reg_proxy==NULL) return FALSE; - } - if (cfg->identity_address==NULL){ - 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")); + if (cfg->identity_address==NULL) return FALSE; - } return TRUE; } @@ -385,7 +436,7 @@ void linphone_proxy_config_enable_publish(LinphoneProxyConfig *cfg, bool_t val){ } void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg){ - if (cfg->op) sal_op_stop_refreshing(cfg->op); + if (cfg->op) cfg->op->stopRefreshing(); } void linphone_proxy_config_edit(LinphoneProxyConfig *cfg){ @@ -405,72 +456,69 @@ void linphone_proxy_config_apply(LinphoneProxyConfig *cfg,LinphoneCore *lc){ } void linphone_proxy_config_stop_refreshing(LinphoneProxyConfig * cfg){ - LinphoneAddress *contact_addr=NULL; - if (cfg->op - && cfg->state == LinphoneRegistrationOk - && (contact_addr = (LinphoneAddress*)sal_op_get_contact_address(cfg->op)) - && linphone_address_get_transport(contact_addr) != LinphoneTransportUdp /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/ - && lp_config_get_int(cfg->lc->config, "sip", "unregister_previous_contact", 0)) { - /*need to save current contact in order to reset it later*/ - linphone_address_ref(contact_addr); - if (cfg->pending_contact) - linphone_address_unref(cfg->pending_contact); - cfg->pending_contact=contact_addr; + LinphoneAddress *contact_addr = NULL; + const SalAddress *sal_addr = cfg->op && cfg->state == LinphoneRegistrationOk ? cfg->op->getContactAddress() : NULL; + if (sal_addr) { + char *buf = sal_address_as_string(sal_addr); + contact_addr = buf ? linphone_address_new(buf) : NULL; + ms_free(buf); + } + /*with udp, there is a risk of port reuse, so I prefer to not do anything for now*/ + if (contact_addr) { + if (linphone_address_get_transport(contact_addr) != LinphoneTransportUdp && lp_config_get_int(cfg->lc->config, "sip", "unregister_previous_contact", 0)) { + if (cfg->pending_contact) + linphone_address_unref(cfg->pending_contact); + cfg->pending_contact=contact_addr; + } else + linphone_address_unref(contact_addr); } if (cfg->presence_publish_event){ /*might probably do better*/ linphone_event_set_publish_state(cfg->presence_publish_event,LinphonePublishNone); linphone_event_unref(cfg->presence_publish_event); /*probably useless as cfg->long_term_event is already unref in linphone_proxy_config_notify_publish_state_changed. To be check with Ghislain*/ cfg->presence_publish_event=NULL; } + if (cfg->op){ - sal_op_release(cfg->op); + cfg->op->release(); cfg->op=NULL; } } -LinphoneAddress *guess_contact_for_register(LinphoneProxyConfig *cfg){ - LinphoneAddress *ret=NULL; - LinphoneAddress *proxy=linphone_address_new(cfg->reg_proxy); - const char *host; +static void guess_contact_for_register (LinphoneProxyConfig *cfg) { + if (cfg->contact_address) + linphone_address_unref(cfg->contact_address); + cfg->contact_address = nullptr; - if (proxy==NULL) return NULL; - host=linphone_address_get_domain(proxy); - if (host!=NULL){ - int localport = -1; - const char *localip = NULL; - LinphoneAddress *contact=linphone_address_clone(cfg->identity_address); - - linphone_address_clean(contact); + if (cfg->contact_address_without_params) + linphone_address_unref(cfg->contact_address_without_params); + cfg->contact_address_without_params = nullptr; + LinphoneAddress *proxy = linphone_address_new(cfg->reg_proxy); + if (!proxy) + return; + const char *host = linphone_address_get_domain(proxy); + if (host) { + cfg->contact_address_without_params = linphone_address_clone(cfg->identity_address); + linphone_address_clean(cfg->contact_address_without_params); + linphone_address_set_port(cfg->contact_address_without_params, -1); + linphone_address_set_domain(cfg->contact_address_without_params, nullptr); + linphone_address_set_display_name(cfg->contact_address_without_params, nullptr); + cfg->contact_address = linphone_address_clone(cfg->contact_address_without_params); if (cfg->contact_params) { // We want to add a list of contacts params to the linphone address - sal_address_set_params(contact,cfg->contact_params); + linphone_address_set_params(cfg->contact_address, cfg->contact_params); } - if (cfg->contact_uri_params){ - sal_address_set_uri_params(contact,cfg->contact_uri_params); - } -#ifdef BUILD_UPNP - if (cfg->lc->upnp != NULL && linphone_core_get_firewall_policy(cfg->lc)==LinphonePolicyUseUpnp && - linphone_upnp_context_get_state(cfg->lc->upnp) == LinphoneUpnpStateOk) { - localip = linphone_upnp_context_get_external_ipaddress(cfg->lc->upnp); - localport = linphone_upnp_context_get_external_port(cfg->lc->upnp); - } -#endif //BUILD_UPNP - linphone_address_set_port(contact,localport); - linphone_address_set_domain(contact,localip); - linphone_address_set_display_name(contact,NULL); - - ret=contact; + if (cfg->contact_uri_params) + linphone_address_set_uri_params(cfg->contact_address, cfg->contact_uri_params); } linphone_address_unref(proxy); - return ret; } void _linphone_proxy_config_unregister(LinphoneProxyConfig *obj) { if (obj->op && (obj->state == LinphoneRegistrationOk || (obj->state == LinphoneRegistrationProgress && obj->expires != 0))) { - sal_unregister(obj->op); + obj->op->unregister(); } } @@ -479,25 +527,26 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){ LinphoneAddress* proxy=linphone_address_new(cfg->reg_proxy); char* proxy_string; char * from = linphone_address_as_string(cfg->identity_address); - LinphoneAddress *contact; ms_message("LinphoneProxyConfig [%p] about to register (LinphoneCore version: %s)",cfg,linphone_core_get_version()); proxy_string=linphone_address_as_string_uri_only(proxy); linphone_address_unref(proxy); if (cfg->op) - sal_op_release(cfg->op); - cfg->op=sal_op_new(cfg->lc->sal); + cfg->op->release(); + cfg->op=new SalRegisterOp(cfg->lc->sal); linphone_configure_op(cfg->lc, cfg->op, cfg->identity_address, cfg->sent_headers, FALSE); - if ((contact=guess_contact_for_register(cfg))) { - sal_op_set_contact_address(cfg->op,contact); - linphone_address_unref(contact); - } + guess_contact_for_register(cfg); + if (cfg->contact_address) + cfg->op->setContactAddress(L_GET_PRIVATE_FROM_C_OBJECT(cfg->contact_address)->getInternalAddress()); + cfg->op->setUserPointer(cfg); - sal_op_set_user_pointer(cfg->op,cfg); - - - if (sal_register(cfg->op,proxy_string, cfg->reg_identity, cfg->expires, cfg->pending_contact)==0) { + if (cfg->op->sendRegister( + proxy_string, + cfg->reg_identity, + cfg->expires, + cfg->pending_contact ? L_GET_PRIVATE_FROM_C_OBJECT(cfg->pending_contact)->getInternalAddress() : NULL + )==0) { if (cfg->pending_contact) { linphone_address_unref(cfg->pending_contact); cfg->pending_contact=NULL; @@ -519,7 +568,7 @@ static void linphone_proxy_config_register(LinphoneProxyConfig *cfg){ void linphone_proxy_config_refresh_register(LinphoneProxyConfig *cfg){ if (cfg->reg_sendregister && cfg->op && cfg->state!=LinphoneRegistrationProgress){ - if (sal_register_refresh(cfg->op,cfg->expires) == 0) { + if (cfg->op->refreshRegister(cfg->expires) == 0) { linphone_proxy_config_set_state(cfg,LinphoneRegistrationProgress, "Refresh registration"); } } @@ -640,7 +689,7 @@ bool_t linphone_proxy_config_normalize_number(LinphoneProxyConfig *proxy, const char* linphone_proxy_config_normalize_phone_number(LinphoneProxyConfig *proxy, const char *username) { LinphoneProxyConfig *tmpproxy = proxy ? proxy : linphone_proxy_config_new(); char* result = NULL; - LinphoneDialPlan dialplan = {0}; + DialPlan dialplan; char * nationnal_significant_number = NULL; int ccc = -1; @@ -648,51 +697,55 @@ char* linphone_proxy_config_normalize_phone_number(LinphoneProxyConfig *proxy, c char * flatten=flatten_number(username); ms_debug("Flattened number is '%s' for '%s'",flatten, username); - ccc = linphone_dial_plan_lookup_ccc_from_e164(flatten); + ccc = DialPlan::lookupCccFromE164(flatten); if (ccc>-1) { /*e164 like phone number*/ - dialplan = *linphone_dial_plan_by_ccc_as_int(ccc); - nationnal_significant_number = strstr(flatten, dialplan.ccc); + dialplan = DialPlan::findByCcc(ccc); + nationnal_significant_number = strstr(flatten, dialplan.getCountryCallingCode().c_str()); if (nationnal_significant_number) { - nationnal_significant_number +=strlen(dialplan.ccc); + nationnal_significant_number +=strlen(dialplan.getCountryCallingCode().c_str()); } } else if (flatten[0] =='+') { ms_message ("Unknown ccc for e164 like number [%s]", flatten); goto end; } else { - dialplan = *linphone_dial_plan_by_ccc(tmpproxy->dial_prefix); //copy dial plan; + if (tmpproxy->dial_prefix) { + dialplan = DialPlan::findByCcc(tmpproxy->dial_prefix); //copy dial plan; + } else { + dialplan = DialPlan::MostCommon; + } if (tmpproxy->dial_prefix){ - if (strcmp(tmpproxy->dial_prefix,dialplan.ccc) != 0){ + if (strcmp(tmpproxy->dial_prefix,dialplan.getCountryCallingCode().c_str()) != 0){ //probably generic dialplan, preserving proxy dial prefix - strncpy(dialplan.ccc,tmpproxy->dial_prefix,sizeof(dialplan.ccc)); + dialplan.setCountryCallingCode(tmpproxy->dial_prefix); } + /*it does not make sens to try replace icp with + if we are not sure from the country we are (I.E tmpproxy->dial_prefix==NULL)*/ - if (strstr(flatten,dialplan.icp)==flatten) { - char *e164 = replace_icp_with_plus(flatten,dialplan.icp); - result = linphone_proxy_config_normalize_phone_number(tmpproxy,e164); + if (strstr(flatten, dialplan.getInternationalCallPrefix().c_str()) == flatten) { + char *e164 = replace_icp_with_plus(flatten, dialplan.getInternationalCallPrefix().c_str()); + result = linphone_proxy_config_normalize_phone_number(tmpproxy, e164); ms_free(e164); goto end; } - } nationnal_significant_number=flatten; } - ms_debug("Using dial plan '%s'",dialplan.country); + ms_debug("Using dial plan '%s'",dialplan.getCountry().c_str()); /*if proxy has a dial prefix, modify phonenumber accordingly*/ - if (dialplan.ccc[0]!='\0') { + if (dialplan.getCountryCallingCode().c_str()[0]!='\0') { /* the number already starts with + or international prefix*/ /*0. keep at most national number significant digits */ char* nationnal_significant_number_start = nationnal_significant_number + MAX(0, (int)strlen(nationnal_significant_number) - - (int)dialplan.nnl); - ms_debug("Prefix not present. Keeping at most %d digits: %s", dialplan.nnl, nationnal_significant_number_start); + - (int)dialplan.getNationalNumberLength()); + ms_debug("Prefix not present. Keeping at most %d digits: %s", dialplan.getNationalNumberLength(), nationnal_significant_number_start); /*1. First prepend international calling prefix or +*/ /*2. Second add prefix*/ /*3. Finally add user digits */ result = ms_strdup_printf("%s%s%s" - , tmpproxy->dial_escape_plus ? dialplan.icp : "+" - , dialplan.ccc + , tmpproxy->dial_escape_plus ? dialplan.getInternationalCallPrefix().c_str() : "+" + , dialplan.getCountryCallingCode().c_str() , nationnal_significant_number_start); ms_debug("Prepended prefix resulted in %s", result); } @@ -726,13 +779,7 @@ LinphoneAddress* linphone_proxy_config_normalize_sip_uri(LinphoneProxyConfig *pr if (!username || *username=='\0') return NULL; if (is_enum(username,&enum_domain)){ - if (proxy) { - linphone_core_notify_display_status(proxy->lc,_("Looking for telephone number destination...")); - } if (enum_lookup(enum_domain,&enumres)<0){ - if (proxy) { - linphone_core_notify_display_status(proxy->lc,_("Could not resolve this number.")); - } ms_free(enum_domain); return NULL; } @@ -803,8 +850,8 @@ LinphoneStatus linphone_proxy_config_done(LinphoneProxyConfig *cfg) if (res == LinphoneProxyConfigAddressDifferent) { _linphone_proxy_config_unregister(cfg); } - sal_op_set_user_pointer(cfg->op,NULL); /*we don't want to receive status for this un register*/ - sal_op_unref(cfg->op); /*but we keep refresher to handle authentication if needed*/ + cfg->op->setUserPointer(NULL); /*we don't want to receive status for this un register*/ + cfg->op->unref(); /*but we keep refresher to handle authentication if needed*/ cfg->op=NULL; } if (cfg->presence_publish_event) { @@ -889,7 +936,7 @@ int linphone_proxy_config_send_publish(LinphoneProxyConfig *proxy, LinphonePrese } content = linphone_content_new(); - linphone_content_set_buffer(content,presence_body,strlen(presence_body)); + linphone_content_set_buffer(content, (const uint8_t *)presence_body,strlen(presence_body)); linphone_content_set_type(content, "application"); linphone_content_set_subtype(content,"pidf+xml"); if (proxy->sip_etag) { @@ -925,8 +972,13 @@ void _linphone_proxy_config_unpublish(LinphoneProxyConfig *obj) { } } -const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *cfg){ - return cfg->reg_route; +const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *cfg) { + if (cfg->reg_routes) return (const char *)bctbx_list_get_data(cfg->reg_routes); + return NULL; +} + +const bctbx_list_t* linphone_proxy_config_get_routes(const LinphoneProxyConfig *cfg) { + return cfg->reg_routes; } const LinphoneAddress *linphone_proxy_config_get_identity_address(const LinphoneProxyConfig *cfg){ @@ -993,7 +1045,7 @@ struct _LinphoneCore * linphone_proxy_config_get_core(const LinphoneProxyConfig const char *linphone_proxy_config_get_custom_header(LinphoneProxyConfig *cfg, const char *header_name){ const SalCustomHeader *ch; if (!cfg->op) return NULL; - ch = sal_op_get_recv_custom_header(cfg->op); + ch = cfg->op->getRecvCustomHeaders(); return sal_custom_header_find(ch, header_name); } @@ -1084,7 +1136,7 @@ int linphone_core_get_default_proxy(LinphoneCore *lc, LinphoneProxyConfig **conf return linphone_core_get_default_proxy_config_index(lc); } -LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc) { +LinphoneProxyConfig * linphone_core_get_default_proxy_config(const LinphoneCore *lc) { return lc->default_proxy; } @@ -1107,8 +1159,8 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC if (cfg->reg_proxy!=NULL){ lp_config_set_string(config,key,"reg_proxy",cfg->reg_proxy); } - if (cfg->reg_route!=NULL){ - lp_config_set_string(config,key,"reg_route",cfg->reg_route); + if (cfg->reg_routes != NULL) { + lp_config_set_string_list(config, key, "reg_route", cfg->reg_routes); } if (cfg->reg_identity!=NULL){ lp_config_set_string(config,key,"reg_identity",cfg->reg_identity); @@ -1134,7 +1186,8 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC lp_config_set_int(config, key, "avpf_rr_interval", cfg->avpf_rr_interval); lp_config_set_int(config,key,"dial_escape_plus",cfg->dial_escape_plus); lp_config_set_string(config,key,"dial_prefix",cfg->dial_prefix); - lp_config_set_int(config,key,"privacy",cfg->privacy); + lp_config_set_int(config,key,"privacy",(int)cfg->privacy); + lp_config_set_int(config,key,"push_notification_allowed",(int)cfg->push_notification_allowed); if (cfg->refkey) lp_config_set_string(config,key,"refkey",cfg->refkey); lp_config_set_int(config, key, "publish_expires", cfg->publish_expires); @@ -1142,6 +1195,8 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC lp_config_set_string(config, key, "nat_policy_ref", cfg->nat_policy->ref); linphone_nat_policy_save_to_config(cfg->nat_policy); } + + lp_config_set_string(config, key, "conference_factory_uri", cfg->conference_factory_uri); } @@ -1153,10 +1208,10 @@ void linphone_proxy_config_write_to_config_file(LpConfig *config, LinphoneProxyC } #define CONFIGURE_BOOL_VALUE(cfg,config,key,param,param_name) \ - linphone_proxy_config_enable_##param(cfg,lp_config_get_int(config,key,param_name,linphone_proxy_config_##param##_enabled(cfg))); + linphone_proxy_config_enable_##param(cfg, !!lp_config_get_int(config,key,param_name,linphone_proxy_config_##param##_enabled(cfg))); -#define CONFIGURE_INT_VALUE(cfg,config,key,param,param_name) \ - linphone_proxy_config_set_##param(cfg,lp_config_get_int(config,key,param_name,linphone_proxy_config_get_##param(cfg))); +#define CONFIGURE_INT_VALUE(cfg,config,key,param,param_name, param_type) \ + linphone_proxy_config_set_##param(cfg, (param_type)lp_config_get_int(config,key,param_name,(int)linphone_proxy_config_get_##param(cfg))); LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc, int index) { @@ -1176,45 +1231,50 @@ LinphoneProxyConfig *linphone_proxy_config_new_from_config_file(LinphoneCore* lc CONFIGURE_STRING_VALUE(cfg,config,key,identity,"reg_identity") CONFIGURE_STRING_VALUE(cfg,config,key,server_addr,"reg_proxy") - CONFIGURE_STRING_VALUE(cfg,config,key,route,"reg_route") + bctbx_list_t *routes = linphone_config_get_string_list(config, key, "reg_route", NULL); + linphone_proxy_config_set_routes(cfg, routes); + if (routes) + bctbx_list_free_with_data(routes, (bctbx_list_free_func)bctbx_free); 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_INT_VALUE(cfg,config,key,quality_reporting_interval,"quality_reporting_interval",int) CONFIGURE_STRING_VALUE(cfg,config,key,contact_parameters,"contact_parameters") CONFIGURE_STRING_VALUE(cfg,config,key,contact_uri_parameters,"contact_uri_parameters") - CONFIGURE_INT_VALUE(cfg,config,key,expires,"reg_expires") + CONFIGURE_INT_VALUE(cfg,config,key,expires,"reg_expires", int) CONFIGURE_BOOL_VALUE(cfg,config,key,register,"reg_sendregister") CONFIGURE_BOOL_VALUE(cfg,config,key,publish,"publish") + linphone_proxy_config_set_push_notification_allowed(cfg, !!lp_config_get_int(config,key,"push_notification_allowed",linphone_proxy_config_is_push_notification_allowed(cfg))); linphone_proxy_config_set_avpf_mode(cfg,static_cast(lp_config_get_int(config,key,"avpf",linphone_proxy_config_get_avpf_mode(cfg)))); - 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_INT_VALUE(cfg,config,key,avpf_rr_interval,"avpf_rr_interval",uint8_t) + CONFIGURE_INT_VALUE(cfg,config,key,dial_escape_plus,"dial_escape_plus",bool_t) CONFIGURE_STRING_VALUE(cfg,config,key,dial_prefix,"dial_prefix") tmp=lp_config_get_string(config,key,"type",NULL); if (tmp!=NULL && strlen(tmp)>0) linphone_proxy_config_set_sip_setup(cfg,tmp); - CONFIGURE_INT_VALUE(cfg,config,key,privacy,"privacy") + CONFIGURE_INT_VALUE(cfg,config,key,privacy,"privacy",LinphonePrivacyMask) CONFIGURE_STRING_VALUE(cfg,config,key,ref_key,"refkey") - CONFIGURE_INT_VALUE(cfg,config,key,publish_expires,"publish_expires") + CONFIGURE_INT_VALUE(cfg,config,key,publish_expires,"publish_expires",int) nat_policy_ref = lp_config_get_string(config, key, "nat_policy_ref", NULL); if (nat_policy_ref != NULL) { cfg->nat_policy = linphone_core_create_nat_policy_from_config(lc, nat_policy_ref); } + CONFIGURE_STRING_VALUE(cfg, config, key, conference_factory_uri, "conference_factory_uri"); + return cfg; } static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){ SipSetupContext *ssc; SipSetup *ss=sip_setup_lookup(cfg->type); - LinphoneCore *lc=linphone_proxy_config_get_core(cfg); unsigned int caps; if (!ss) return ; ssc=sip_setup_context_new(ss,cfg); @@ -1223,16 +1283,10 @@ static void linphone_proxy_config_activate_sip_setup(LinphoneProxyConfig *cfg){ ms_error("Invalid identity for this proxy configuration."); return; } - caps=sip_setup_context_get_capabilities(ssc); + caps=(unsigned int)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){ - { - char *tmp=ms_strdup_printf(_("Could not login as %s"),cfg->reg_identity); - linphone_core_notify_display_warning(lc,tmp); - ms_free(tmp); - } + if (sip_setup_context_login_account(ssc,cfg->reg_identity,NULL,NULL)!=0) return; - } } if (caps & SIP_SETUP_CAP_PROXY_PROVIDER){ char proxy[256]; @@ -1255,14 +1309,6 @@ SipSetup *linphone_proxy_config_get_sip_setup(LinphoneProxyConfig *cfg){ static bool_t can_register(LinphoneProxyConfig *cfg){ LinphoneCore *lc=cfg->lc; -#ifdef BUILD_UPNP - if (linphone_core_get_firewall_policy(lc)==LinphonePolicyUseUpnp){ - if(lc->sip_conf.register_only_when_upnp_is_ok && - (lc->upnp == NULL || !linphone_upnp_context_is_ready_for_register(lc->upnp))) { - return FALSE; - } - } -#endif //BUILD_UPNP if (lc->sip_conf.register_only_when_network_is_up){ return lc->sip_network_reachable; } @@ -1310,14 +1356,6 @@ void * linphone_proxy_config_get_user_data(const LinphoneProxyConfig *cfg) { void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *message){ LinphoneCore *lc=cfg->lc; - - if (state==LinphoneRegistrationProgress) { - char *msg=ortp_strdup_printf(_("Refreshing on %s..."), linphone_proxy_config_get_identity(cfg)); - linphone_core_notify_display_status(lc,msg); - ms_free(msg); - - } - if (cfg->state!=state || state==LinphoneRegistrationOk) { /*allow multiple notification of LinphoneRegistrationOk for refreshing*/ ms_message("Proxy config [%p] for identity [%s] moving from state [%s] to [%s] on core [%p]" , cfg, @@ -1335,10 +1373,8 @@ void linphone_proxy_config_set_state(LinphoneProxyConfig *cfg, LinphoneRegistrat cfg->state=state; } - if (lc){ + if (lc) linphone_core_notify_registration_state_changed(lc,cfg,state,message); - linphone_core_repair_calls(lc); - } } else { /*state already reported*/ } @@ -1380,14 +1416,16 @@ const LinphoneErrorInfo *linphone_proxy_config_get_error_info(const LinphoneProx } const LinphoneAddress* linphone_proxy_config_get_service_route(const LinphoneProxyConfig* cfg) { - return cfg->op?(const LinphoneAddress*) sal_op_get_service_route(cfg->op):NULL; + return cfg->op?(const LinphoneAddress*) cfg->op->getServiceRoute():NULL; } const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) { const char* addr=NULL; const char* ret="udp"; /*default value*/ - SalAddress* route_addr=NULL; + const SalAddress* route_addr=NULL; + bool_t destroy_route_addr = FALSE; + if (linphone_proxy_config_get_service_route(cfg)) { - route_addr=(SalAddress*)linphone_proxy_config_get_service_route(cfg); + route_addr = L_GET_PRIVATE_FROM_C_OBJECT(linphone_proxy_config_get_service_route(cfg))->getInternalAddress(); } else if (linphone_proxy_config_get_route(cfg)) { addr=linphone_proxy_config_get_route(cfg); } else if(linphone_proxy_config_get_addr(cfg)) { @@ -1397,13 +1435,16 @@ const char* linphone_proxy_config_get_transport(const LinphoneProxyConfig *cfg) return NULL; } - if (route_addr || (route_addr=sal_address_new(addr))) { - ret=sal_transport_to_string(sal_address_get_transport(route_addr)); - if (!linphone_proxy_config_get_service_route(cfg)) { - sal_address_destroy(route_addr); - } + if (!route_addr) { + if (!((*(SalAddress **)&route_addr) = sal_address_new(addr))) + return NULL; + destroy_route_addr = TRUE; } + ret=sal_transport_to_string(sal_address_get_transport(route_addr)); + if (destroy_route_addr) + sal_address_destroy((SalAddress *)route_addr); + return ret; } void linphone_proxy_config_set_privacy(LinphoneProxyConfig *params, LinphonePrivacyMask privacy) { @@ -1451,8 +1492,26 @@ uint8_t linphone_proxy_config_get_avpf_rr_interval(const LinphoneProxyConfig *cf return cfg->avpf_rr_interval; } -const LinphoneAddress* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg) { - return sal_op_get_contact_address(cfg->op); +const LinphoneAddress *linphone_proxy_config_get_contact (const LinphoneProxyConfig *cfg) { + // Warning : Do not remove, the op can change its contact_address + if (!cfg->op) + return NULL; + const SalAddress *salAddr = cfg->op->getContactAddress(); + if (!salAddr) + return NULL; + if (cfg->contact_address) + L_GET_PRIVATE_FROM_C_OBJECT(cfg->contact_address)->setInternalAddress(const_cast(salAddr)); + else { + char *buf = sal_address_as_string(salAddr); + const_cast(cfg)->contact_address = linphone_address_new(buf); + ms_free(buf); + } + + return cfg->contact_address; +} + +const LinphoneAddress *_linphone_proxy_config_get_contact_without_params (const LinphoneProxyConfig *cfg) { + return cfg->contact_address_without_params; } const struct _LinphoneAuthInfo* linphone_proxy_config_find_auth_info(const LinphoneProxyConfig *cfg) { @@ -1506,3 +1565,24 @@ void linphone_proxy_config_notify_publish_state_changed(LinphoneProxyConfig *cfg } } } + +void linphone_proxy_config_set_conference_factory_uri(LinphoneProxyConfig *cfg, const char *uri) { + if (cfg->conference_factory_uri) { + bctbx_free(cfg->conference_factory_uri); + cfg->conference_factory_uri = nullptr; + } + if (uri) + cfg->conference_factory_uri = bctbx_strdup(uri); +} + +const char * linphone_proxy_config_get_conference_factory_uri(const LinphoneProxyConfig *cfg) { + return cfg->conference_factory_uri; +} + +bool_t linphone_proxy_config_is_push_notification_allowed(const LinphoneProxyConfig *cfg) { + return cfg->push_notification_allowed; +} + +void linphone_proxy_config_set_push_notification_allowed(LinphoneProxyConfig *cfg, bool_t is_allowed) { + cfg->push_notification_allowed = is_allowed; +} diff --git a/coreapi/quality_reporting.c b/coreapi/quality_reporting.c index 9e8302dda..089077d41 100644 --- a/coreapi/quality_reporting.c +++ b/coreapi/quality_reporting.c @@ -21,8 +21,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "config.h" #endif +#include "linphone/api/c-content.h" #include "linphone/core.h" + #include "private.h" +#include "c-wrapper/internal/c-sal.h" #include "sal/sal.h" #include "ortp/rtpsession.h" @@ -32,6 +35,14 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #endif +#include + +// For migration purpose. +#include "address/address-p.h" +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "conference/session/media-session-p.h" + #define STR_REASSIGN(dest, src) {\ if (dest != NULL) \ ms_free(dest); \ @@ -44,7 +55,7 @@ static char * float_to_one_decimal_string(float f) { float rounded_f = floorf(f * 10 + .5f) / 10; int floor_part = (int) rounded_f; - int one_decimal_part = (int)floorf(10 * (rounded_f - floor_part) + .5f); + int one_decimal_part = (int)floorf(10 * (rounded_f - (float)floor_part) + .5f); return ms_strdup_printf("%d.%d", floor_part, one_decimal_part); } @@ -150,11 +161,12 @@ static uint8_t are_metrics_filled(const reporting_content_metrics_t *rm) { } static bool_t quality_reporting_enabled(const LinphoneCall * call) { - return (call->dest_proxy != NULL && linphone_proxy_config_quality_reporting_enabled(call->dest_proxy)); + return (L_GET_PRIVATE_FROM_C_OBJECT(call)->getDestProxy() + && linphone_proxy_config_quality_reporting_enabled(L_GET_PRIVATE_FROM_C_OBJECT(call)->getDestProxy())); } static bool_t media_report_enabled(LinphoneCall * call, int stats_type){ - if (! quality_reporting_enabled(call)) + if (!quality_reporting_enabled(call)) return FALSE; if (stats_type == LINPHONE_CALL_STATS_VIDEO && !linphone_call_params_video_enabled(linphone_call_get_current_params(call))) @@ -163,7 +175,7 @@ static bool_t media_report_enabled(LinphoneCall * call, int stats_type){ if (stats_type == LINPHONE_CALL_STATS_TEXT && !linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call))) return FALSE; - return (call->log->reporting.reports[stats_type] != NULL); + return (L_GET_CPP_PTR_FROM_C_OBJECT(call)->getLog()->reporting.reports[stats_type] != NULL); } static void append_metrics_to_buffer(char ** buffer, size_t * size, size_t * offset, const reporting_content_metrics_t *rm) { @@ -272,6 +284,7 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, LinphoneAddress *request_uri; const char* collector_uri; char *collector_uri_allocated = NULL; + const SalAddress *salAddress; /*if we are on a low bandwidth network, do not send reports to not overload it*/ if (linphone_call_params_low_bandwidth_enabled(linphone_call_get_current_params(call))){ @@ -343,30 +356,31 @@ static int send_report(LinphoneCall* call, reporting_session_report_t * report, } #endif - linphone_content_set_buffer(content, buffer, strlen(buffer)); + linphone_content_set_buffer(content, (uint8_t *)buffer, strlen(buffer)); ms_free(buffer); - if (call->log->reporting.on_report_sent != NULL) { - SalStreamType type = report == call->log->reporting.reports[0] ? SalAudio : report == call->log->reporting.reports[1] ? SalVideo : SalText; - call->log->reporting.on_report_sent(call, type, content); + if (linphone_call_get_log(call)->reporting.on_report_sent != NULL) { + SalStreamType type = report == linphone_call_get_log(call)->reporting.reports[0] ? SalAudio : report == linphone_call_get_log(call)->reporting.reports[1] ? SalVideo : SalText; + linphone_call_get_log(call)->reporting.on_report_sent(call, type, content); } - collector_uri = linphone_proxy_config_get_quality_reporting_collector(call->dest_proxy); + collector_uri = linphone_proxy_config_get_quality_reporting_collector(linphone_call_get_dest_proxy(call)); if (!collector_uri){ - collector_uri = collector_uri_allocated = ms_strdup_printf("sip:%s", linphone_proxy_config_get_domain(call->dest_proxy)); + collector_uri = collector_uri_allocated = ms_strdup_printf("sip:%s", linphone_proxy_config_get_domain(linphone_call_get_dest_proxy(call))); } request_uri = linphone_address_new(collector_uri); - lev = linphone_core_create_one_shot_publish(call->core, request_uri, "vq-rtcpxr"); + lev = linphone_core_create_one_shot_publish(linphone_call_get_core(call), request_uri, "vq-rtcpxr"); /* Special exception for quality report PUBLISH: if the collector_uri has any transport related parameters * (port, transport, maddr), then it is sent directly. * Otherwise it is routed as any LinphoneEvent publish, following proxy config policy. **/ - if (sal_address_has_uri_param((SalAddress*)request_uri, "transport") || - sal_address_has_uri_param((SalAddress*)request_uri, "maddr") || + salAddress = L_GET_PRIVATE_FROM_C_OBJECT(request_uri)->getInternalAddress(); + if (sal_address_has_uri_param(salAddress, "transport") || + sal_address_has_uri_param(salAddress, "maddr") || linphone_address_get_port(request_uri) != 0) { ms_message("Publishing report with custom route %s", collector_uri); - sal_op_set_route(lev->op, collector_uri); + lev->op->setRoute(collector_uri); } if (linphone_event_send_publish(lev, content) != 0){ @@ -409,27 +423,28 @@ static const SalStreamDescription * get_media_stream_for_desc(const SalMediaDesc static void update_ip(LinphoneCall * call, int stats_type) { SalStreamType sal_stream_type = stats_type == LINPHONE_CALL_STATS_AUDIO ? SalAudio : stats_type == LINPHONE_CALL_STATS_VIDEO ? SalVideo : SalText; - const SalStreamDescription * local_desc = get_media_stream_for_desc(call->localdesc, sal_stream_type); - const SalStreamDescription * remote_desc = get_media_stream_for_desc(sal_call_get_remote_media_description(call->op), sal_stream_type); + const SalStreamDescription * local_desc = get_media_stream_for_desc(_linphone_call_get_local_desc(call), sal_stream_type); + const SalStreamDescription * remote_desc = get_media_stream_for_desc(L_GET_PRIVATE_FROM_C_OBJECT(call)->getOp()->getRemoteMediaDescription(), sal_stream_type); + LinphoneCallLog *log = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getLog(); if (local_desc != NULL) { /*since this function might be called for video stream AFTER it has been uninitialized, local description might be invalid. In any other case, IP/port should be always filled and valid*/ if (strlen(local_desc->rtp_addr) > 0) { - call->log->reporting.reports[stats_type]->info.local_addr.port = local_desc->rtp_port; - STR_REASSIGN(call->log->reporting.reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr)); + log->reporting.reports[stats_type]->info.local_addr.port = local_desc->rtp_port; + STR_REASSIGN(log->reporting.reports[stats_type]->info.local_addr.ip, ms_strdup(local_desc->rtp_addr)); } } if (remote_desc != NULL) { /*port is always stored in stream description struct*/ - call->log->reporting.reports[stats_type]->info.remote_addr.port = remote_desc->rtp_port; + log->reporting.reports[stats_type]->info.remote_addr.port = remote_desc->rtp_port; /*for IP it can be not set if we are using a direct route*/ if (strlen(remote_desc->rtp_addr) > 0) { - STR_REASSIGN(call->log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr)); + STR_REASSIGN(log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(remote_desc->rtp_addr)); } else { - STR_REASSIGN(call->log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(sal_call_get_remote_media_description(call->op)->addr)); + STR_REASSIGN(log->reporting.reports[stats_type]->info.remote_addr.ip, ms_strdup(L_GET_PRIVATE_FROM_C_OBJECT(call)->getOp()->getRemoteMediaDescription()->addr)); } } } @@ -443,7 +458,7 @@ static void qos_analyzer_on_action_suggested(void *user_data, int datac, const c int bitrate[3] = {-1, -1, -1}; int up_bw[3] = {-1, -1, -1}; int down_bw[3] = {-1, -1, -1}; - MediaStream *streams[3] = { (MediaStream*) call->audiostream, (MediaStream *) call->videostream, (MediaStream *) call->textstream }; + MediaStream *streams[3] = { linphone_call_get_stream(call, LinphoneStreamTypeAudio), linphone_call_get_stream(call, LinphoneStreamTypeVideo), linphone_call_get_stream(call, LinphoneStreamTypeText) }; for (i = 0; i < 3; i++){ if (streams[i] != NULL){ if (streams[i]->encoder != NULL){ @@ -456,10 +471,11 @@ static void qos_analyzer_on_action_suggested(void *user_data, int datac, const c down_bw[i] = (int)(media_stream_get_down_bw(streams[i])/1000.f); } } - if (call->audiostream!=NULL){ - if (call->audiostream->ms.encoder!=NULL){ - if(ms_filter_has_method(call->audiostream->ms.encoder,MS_AUDIO_ENCODER_GET_PTIME)){ - ms_filter_call_method(call->audiostream->ms.encoder,MS_AUDIO_ENCODER_GET_PTIME,&ptime); + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + if (astream!=NULL){ + if (astream->ms.encoder!=NULL){ + if(ms_filter_has_method(astream->ms.encoder,MS_AUDIO_ENCODER_GET_PTIME)){ + ms_filter_call_method(astream->ms.encoder,MS_AUDIO_ENCODER_GET_PTIME,&ptime); } } } @@ -487,67 +503,67 @@ void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type) { const PayloadType * local_payload = NULL; const PayloadType * remote_payload = NULL; const LinphoneCallParams * current_params = linphone_call_get_current_params(call); - reporting_session_report_t * report = call->log->reporting.reports[stats_type]; - char * dialog_id; + LinphoneCallLog *log = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getLog(); + reporting_session_report_t * report = log->reporting.reports[stats_type]; // call->op might be already released if hanging up in state LinphoneCallOutgoingInit - if (!media_report_enabled(call, stats_type) || call->op == NULL) + if (!media_report_enabled(call, stats_type) || !L_GET_PRIVATE_FROM_C_OBJECT(call)->getOp()) return; - dialog_id = sal_op_get_dialog_id(call->op); + std::string dialogId = L_GET_PRIVATE_FROM_C_OBJECT(call)->getOp()->getDialogId(); - STR_REASSIGN(report->info.call_id, ms_strdup(call->log->call_id)); + STR_REASSIGN(report->info.call_id, ms_strdup(log->call_id)); - STR_REASSIGN(report->local_metrics.user_agent, ms_strdup(linphone_core_get_user_agent(call->core))); + STR_REASSIGN(report->local_metrics.user_agent, ms_strdup(linphone_core_get_user_agent(linphone_call_get_core(call)))); STR_REASSIGN(report->remote_metrics.user_agent, ms_strdup(linphone_call_get_remote_user_agent(call))); // RFC states: "LocalGroupID provides the identification for the purposes // of aggregation for the local endpoint.". STR_REASSIGN(report->info.local_addr.group, ms_strdup_printf("%s-%s-%s" - , dialog_id ? dialog_id : "" + , dialogId.c_str() , "local" , report->local_metrics.user_agent ? report->local_metrics.user_agent : "" ) ); STR_REASSIGN(report->info.remote_addr.group, ms_strdup_printf("%s-%s-%s" - , dialog_id ? dialog_id : "" + , dialogId.c_str() , "remote" , report->remote_metrics.user_agent ? report->remote_metrics.user_agent : "" ) ); - if (call->dir == LinphoneCallIncoming) { - STR_REASSIGN(report->info.remote_addr.id, linphone_address_as_string(call->log->from)); - STR_REASSIGN(report->info.local_addr.id, linphone_address_as_string(call->log->to)); + if (L_GET_CPP_PTR_FROM_C_OBJECT(call)->getDirection() == LinphoneCallIncoming) { + STR_REASSIGN(report->info.remote_addr.id, linphone_address_as_string(log->from)); + STR_REASSIGN(report->info.local_addr.id, linphone_address_as_string(log->to)); STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.remote_addr.id)); } else { - STR_REASSIGN(report->info.remote_addr.id, linphone_address_as_string(call->log->to)); - STR_REASSIGN(report->info.local_addr.id, linphone_address_as_string(call->log->from)); + STR_REASSIGN(report->info.remote_addr.id, linphone_address_as_string(log->to)); + STR_REASSIGN(report->info.local_addr.id, linphone_address_as_string(log->from)); STR_REASSIGN(report->info.orig_id, ms_strdup(report->info.local_addr.id)); } - report->local_metrics.timestamps.start = call->log->start_date_time; - report->local_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + report->local_metrics.timestamps.start = log->start_date_time; + report->local_metrics.timestamps.stop = log->start_date_time + linphone_call_get_duration(call); /*we use same timestamps for remote too*/ - report->remote_metrics.timestamps.start = call->log->start_date_time; - report->remote_metrics.timestamps.stop = call->log->start_date_time + linphone_call_get_duration(call); + report->remote_metrics.timestamps.start = log->start_date_time; + report->remote_metrics.timestamps.stop = log->start_date_time + linphone_call_get_duration(call); /*yet we use the same payload config for local and remote, since this is the largest use case*/ - if (stats_type == LINPHONE_CALL_STATS_AUDIO && call->audiostream != NULL) { - stream = &call->audiostream->ms; - local_payload = current_params->audio_codec; + if (stats_type == LINPHONE_CALL_STATS_AUDIO && L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio)) { + stream = L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio); + local_payload = linphone_call_params_get_used_audio_codec(current_params); remote_payload = local_payload; - } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && call->videostream != NULL) { - stream = &call->videostream->ms; - local_payload = current_params->video_codec; + } else if (stats_type == LINPHONE_CALL_STATS_VIDEO && L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeVideo)) { + stream = L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeVideo); + local_payload = linphone_call_params_get_used_video_codec(current_params); remote_payload = local_payload; - } else if (stats_type == LINPHONE_CALL_STATS_TEXT && call->textstream != NULL) { - stream = &call->textstream->ms; - local_payload = current_params->text_codec; + } else if (stats_type == LINPHONE_CALL_STATS_TEXT && L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeText)) { + stream = L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeText); + local_payload = linphone_call_params_get_used_text_codec(current_params); remote_payload = local_payload; } @@ -565,7 +581,7 @@ void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type) { } } - STR_REASSIGN(report->dialog_id, ms_strdup_printf("%s;%u", dialog_id ? dialog_id : "", report->info.local_addr.ssrc)); + STR_REASSIGN(report->dialog_id, ms_strdup_printf("%s;%u", dialogId.c_str(), report->info.local_addr.ssrc)); if (local_payload != NULL) { report->local_metrics.session_description.payload_type = local_payload->type; @@ -580,41 +596,39 @@ void linphone_reporting_update_media_info(LinphoneCall * call, int stats_type) { report->remote_metrics.session_description.sample_rate = remote_payload->clock_rate; STR_REASSIGN(report->remote_metrics.session_description.fmtp, ms_strdup(remote_payload->recv_fmtp)); } - - ms_free(dialog_id); } /* generate random float in interval ] 0.9 t ; 1.1 t [*/ static float reporting_rand(float t){ - return t * (.2f * (rand() / (RAND_MAX * 1.0f)) + 0.9f); + return t * (.2f * ((float)rand() / (float)RAND_MAX) + 0.9f); } void linphone_reporting_on_rtcp_update(LinphoneCall *call, SalStreamType stats_type) { - reporting_session_report_t * report = call->log->reporting.reports[stats_type]; + reporting_session_report_t * report = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getLog()->reporting.reports[stats_type]; reporting_content_metrics_t * metrics = NULL; LinphoneCallStats *stats = NULL; mblk_t *block = NULL; int report_interval; if (stats_type == 0) { - stats = call->audio_stats; + stats = L_GET_PRIVATE_FROM_C_OBJECT(call)->getStats(LinphoneStreamTypeAudio); } else if (stats_type == 1) { - stats = call->video_stats; + stats = L_GET_PRIVATE_FROM_C_OBJECT(call)->getStats(LinphoneStreamTypeVideo); } else { - stats = call->text_stats; + stats = L_GET_PRIVATE_FROM_C_OBJECT(call)->getStats(LinphoneStreamTypeText); } if (! media_report_enabled(call,stats_type)) return; - report_interval = linphone_proxy_config_get_quality_reporting_interval(call->dest_proxy); + report_interval = linphone_proxy_config_get_quality_reporting_interval(L_GET_PRIVATE_FROM_C_OBJECT(call)->getDestProxy()); - if (stats->updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { + if (_linphone_call_stats_get_updated(stats) == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { metrics = &report->remote_metrics; - block = stats->received_rtcp; - } else if (stats->updated == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { + block = _linphone_call_stats_get_received_rtcp(stats); + } else if (_linphone_call_stats_get_updated(stats) == LINPHONE_CALL_STATS_SENT_RTCP_UPDATE) { metrics = &report->local_metrics; - block = stats->sent_rtcp; + block = _linphone_call_stats_get_sent_rtcp(stats); } do{ if (rtcp_is_XR(block) && (rtcp_XR_get_block_type(block) == RTCP_XR_VOIP_METRICS)){ @@ -625,7 +639,7 @@ void linphone_reporting_on_rtcp_update(LinphoneCall *call, SalStreamType stats_t // for local mos rating, we'll use the quality indicator directly // because rtcp XR might not be enabled - if (stats->updated == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE){ + if (_linphone_call_stats_get_updated(stats) == LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE){ metrics->quality_estimates.moslq = (rtcp_XR_voip_metrics_get_mos_lq(block)==127) ? 127 : rtcp_XR_voip_metrics_get_mos_lq(block) / 10.f; metrics->quality_estimates.moscq = (rtcp_XR_voip_metrics_get_mos_cq(block)==127) ? @@ -643,7 +657,9 @@ void linphone_reporting_on_rtcp_update(LinphoneCall *call, SalStreamType stats_t metrics->delay.round_trip_delay += rtcp_XR_voip_metrics_get_round_trip_delay(block); }else if (rtcp_is_SR(block)){ - MediaStream *ms=(stats_type==0 ? &call->audiostream->ms : &call->videostream->ms); + MediaStream *ms = (stats_type == 0) + ? L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio) + : L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeVideo); float rtt = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session); if (rtt > 1e-6){ @@ -665,11 +681,11 @@ static int publish_report(LinphoneCall *call, const char *event_type){ int ret = 0; int i; for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++){ - int stream_index = i == call->main_audio_stream_index ? LINPHONE_CALL_STATS_AUDIO : call->main_video_stream_index ? LINPHONE_CALL_STATS_VIDEO : LINPHONE_CALL_STATS_TEXT; + int stream_index = i == _linphone_call_get_main_audio_stream_index(call) ? LINPHONE_CALL_STATS_AUDIO : _linphone_call_get_main_video_stream_index(call) ? LINPHONE_CALL_STATS_VIDEO : LINPHONE_CALL_STATS_TEXT; if (media_report_enabled(call, stream_index)) { int sndret; linphone_reporting_update_media_info(call, stream_index); - sndret=send_report(call, call->log->reporting.reports[stream_index], event_type); + sndret=send_report(call, L_GET_CPP_PTR_FROM_C_OBJECT(call)->getLog()->reporting.reports[stream_index], event_type); if (sndret>0){ ret += 10+(i+1)*sndret; } @@ -704,32 +720,37 @@ static bool_t set_on_action_suggested_cb(MediaStream *stream,void (*on_action_su void linphone_reporting_call_state_updated(LinphoneCall *call){ LinphoneCallState state=linphone_call_get_state(call); + LinphoneCallLog *log = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getLog(); if (state == LinphoneCallReleased||!quality_reporting_enabled(call)){ return; } switch (state){ case LinphoneCallStreamsRunning:{ int i = 0; - MediaStream *streams[3] = { (MediaStream*) call->audiostream, (MediaStream *) call->videostream, (MediaStream *) call->textstream }; + MediaStream *streams[3] = { + L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio), + L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeVideo), + L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeText) + }; for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - int stream_index = i == call->main_audio_stream_index ? LINPHONE_CALL_STATS_AUDIO : call->main_video_stream_index ? LINPHONE_CALL_STATS_VIDEO : LINPHONE_CALL_STATS_TEXT; + int stream_index = i == _linphone_call_get_main_audio_stream_index(call) ? LINPHONE_CALL_STATS_AUDIO : _linphone_call_get_main_video_stream_index(call) ? LINPHONE_CALL_STATS_VIDEO : LINPHONE_CALL_STATS_TEXT; bool_t enabled = media_report_enabled(call, stream_index); - if (enabled && set_on_action_suggested_cb(streams[stream_index], qos_analyzer_on_action_suggested, call->log->reporting.reports[stream_index])) { - call->log->reporting.reports[stream_index]->call=call; - STR_REASSIGN(call->log->reporting.reports[stream_index]->qos_analyzer.name, ms_strdup(ms_qos_analyzer_get_name(ms_bitrate_controller_get_qos_analyzer(streams[stream_index]->rc)))); + if (enabled && set_on_action_suggested_cb(streams[stream_index], qos_analyzer_on_action_suggested, log->reporting.reports[stream_index])) { + log->reporting.reports[stream_index]->call=call; + STR_REASSIGN(log->reporting.reports[stream_index]->qos_analyzer.name, ms_strdup(ms_qos_analyzer_get_name(ms_bitrate_controller_get_qos_analyzer(streams[stream_index]->rc)))); } } linphone_reporting_update_ip(call); - if (!media_report_enabled(call, LINPHONE_CALL_STATS_VIDEO) && call->log->reporting.was_video_running){ - send_report(call, call->log->reporting.reports[LINPHONE_CALL_STATS_VIDEO], "VQSessionReport"); + if (!media_report_enabled(call, LINPHONE_CALL_STATS_VIDEO) && log->reporting.was_video_running){ + send_report(call, log->reporting.reports[LINPHONE_CALL_STATS_VIDEO], "VQSessionReport"); } - call->log->reporting.was_video_running=media_report_enabled(call, LINPHONE_CALL_STATS_VIDEO); + log->reporting.was_video_running=media_report_enabled(call, LINPHONE_CALL_STATS_VIDEO); break; } case LinphoneCallEnd:{ - set_on_action_suggested_cb(&call->audiostream->ms, NULL, NULL); - set_on_action_suggested_cb(&call->videostream->ms, NULL, NULL); - if (call->log->status==LinphoneCallSuccess || call->log->status==LinphoneCallAborted){ + set_on_action_suggested_cb(L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeAudio), NULL, NULL); + set_on_action_suggested_cb(L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(LinphoneStreamTypeVideo), NULL, NULL); + if (log->status==LinphoneCallSuccess || log->status==LinphoneCallAborted){ linphone_reporting_publish_session_report(call, TRUE); } break; @@ -802,5 +823,5 @@ void linphone_reporting_destroy(reporting_session_report_t * report) { void linphone_reporting_set_on_report_send(LinphoneCall *call, LinphoneQualityReportingReportSendCb cb){ - call->log->reporting.on_report_sent = cb; + linphone_call_get_log(call)->reporting.on_report_sent = cb; } diff --git a/coreapi/quality_reporting.h b/coreapi/quality_reporting.h index 155dec2ee..1ee63335d 100644 --- a/coreapi/quality_reporting.h +++ b/coreapi/quality_reporting.h @@ -21,7 +21,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define quality_reporting_h #include "linphone/core.h" -#include "sal/sal.h" +#include "c-wrapper/internal/c-sal.h" #ifdef __cplusplus extern "C"{ diff --git a/coreapi/ringtoneplayer_ios.m b/coreapi/ringtoneplayer_ios.m index 61e73703b..2a7a51a4b 100644 --- a/coreapi/ringtoneplayer_ios.m +++ b/coreapi/ringtoneplayer_ios.m @@ -77,7 +77,7 @@ int linphone_ringtoneplayer_ios_start_with_cb(LinphoneRingtonePlayer* rp, const } bool_t linphone_ringtoneplayer_ios_is_started(LinphoneRingtonePlayer* rp) { - return [rp->player isPlaying]; + return (bool_t)[rp->player isPlaying]; } int linphone_ringtoneplayer_ios_stop(LinphoneRingtonePlayer* rp) { diff --git a/coreapi/siplogin.c b/coreapi/siplogin.c index 8cc115615..d657d7f70 100644 --- a/coreapi/siplogin.c +++ b/coreapi/siplogin.c @@ -35,7 +35,7 @@ static void guess_display_name(LinphoneAddress *from){ bool_t surname=0; for(it=linphone_address_get_username(from);*it!='\0';++it){ if (begin){ - *wptr=toupper(*it); + *wptr = (char)toupper(*it); begin=FALSE; }else if (*it=='.'){ if (surname) break; diff --git a/coreapi/sipsetup.c b/coreapi/sipsetup.c index a1f22f7d7..fbbbd5c59 100644 --- a/coreapi/sipsetup.c +++ b/coreapi/sipsetup.c @@ -121,7 +121,7 @@ unsigned int sip_setup_get_capabilities(SipSetup *s){ } int sip_setup_context_get_capabilities(SipSetupContext *ctx){ - return ctx->funcs->capabilities; + return (int)ctx->funcs->capabilities; } LinphoneStatus sip_setup_context_create_account(SipSetupContext * ctx, const char *uri, const char *passwd, const char *email, int suscribe){ diff --git a/coreapi/sqlite3_bctbx_vfs.c b/coreapi/sqlite3_bctbx_vfs.c index 1c1a5aeb3..629c1b879 100755 --- a/coreapi/sqlite3_bctbx_vfs.c +++ b/coreapi/sqlite3_bctbx_vfs.c @@ -18,10 +18,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef SQLITE_STORAGE_ENABLED - #include "private.h" -#include "bctoolbox/charconv.h" +#include "bctoolbox/charconv.h" #include "sqlite3_bctbx_vfs.h" #include @@ -68,13 +67,13 @@ static int sqlite3bctbx_Read(sqlite3_file *p, void *buf, int count, sqlite_int64 int ret; sqlite3_bctbx_file_t *pFile = (sqlite3_bctbx_file_t*) p; if (pFile){ - ret = bctbx_file_read(pFile->pbctbx_file, buf, count, (off_t)offset); + ret = (int)bctbx_file_read(pFile->pbctbx_file, buf, (size_t)count, (off_t)offset); if( ret==count ){ return SQLITE_OK; } else if( ret >= 0 ){ /*fill in unread portion of buffer, as requested by sqlite3 documentation*/ - memset(((uint8_t*)buf) + ret, 0, count-ret); + memset(((uint8_t*)buf) + ret, 0, (size_t)(count-ret)); return SQLITE_IOERR_SHORT_READ; }else { @@ -97,7 +96,7 @@ static int sqlite3bctbx_Write(sqlite3_file *p, const void *buf, int count, sqlit sqlite3_bctbx_file_t *pFile = (sqlite3_bctbx_file_t*) p; int ret; if (pFile ){ - ret = bctbx_file_write(pFile->pbctbx_file, buf, count, (off_t)offset); + ret = (int)bctbx_file_write(pFile->pbctbx_file, buf, (size_t)count, (off_t)offset); if(ret > 0 ) return SQLITE_OK; else { return SQLITE_IOERR_WRITE; @@ -110,11 +109,11 @@ static int sqlite3bctbx_Write(sqlite3_file *p, const void *buf, int count, sqlit * TRuncates or extends a file depending on the size provided. * @param p sqlite3_file file handle pointer. * @param size New file size. - * @return SQLITE_OK on success, SQLITE_IOERR_TRUNCATE if an error occurred during truncate, - * SQLITE_ERROR if ther was a problem on the file descriptor. + * @return SQLITE_OK on success, SQLITE_IOERR_TRUNCATE if an error occurred during truncate, + * SQLITE_ERROR if ther was a problem on the file descriptor. */ static int sqlite3bctbx_Truncate(sqlite3_file *p, sqlite_int64 size){ - int rc; + int rc; sqlite3_bctbx_file_t *pFile = (sqlite3_bctbx_file_t*) p; if (pFile->pbctbx_file){ rc = bctbx_file_truncate(pFile->pbctbx_file, size); @@ -282,7 +281,7 @@ static int sqlite3bctbx_Open(sqlite3_vfs *pVfs, const char *fName, sqlite3_file if (pFile == NULL || fName == NULL){ return SQLITE_IOERR; } - + /* Set flags to open the file with */ if( flags&SQLITE_OPEN_EXCLUSIVE ) openFlags |= O_EXCL; if( flags&SQLITE_OPEN_CREATE ) openFlags |= O_CREAT; @@ -299,7 +298,7 @@ static int sqlite3bctbx_Open(sqlite3_vfs *pVfs, const char *fName, sqlite3_file } else { pFile->pbctbx_file = NULL; } - + if( pFile->pbctbx_file == NULL){ return SQLITE_CANTOPEN; } @@ -381,7 +380,7 @@ void sqlite3_bctbx_vfs_register( int makeDefault){ sqlite3_vfs* pDefault = sqlite3_vfs_find("unix-none"); #endif pVfsToUse->xCurrentTime = pDefault->xCurrentTime; - + pVfsToUse->xAccess = pDefault->xAccess; pVfsToUse->xFullPathname = pDefault->xFullPathname; diff --git a/coreapi/tester_utils.cpp b/coreapi/tester_utils.cpp new file mode 100644 index 000000000..8b9f89bd7 --- /dev/null +++ b/coreapi/tester_utils.cpp @@ -0,0 +1,177 @@ +/* +tester_utils.cpp +Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "tester_utils.h" +#include "private.h" + +#include "call/call-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "core/core-p.h" +#include "c-wrapper/c-wrapper.h" +#include "conference/session/media-session-p.h" +#include "event-log/conference/conference-chat-message-event.h" + +using namespace std; + +using namespace LinphonePrivate; + +LinphoneVcardContext *linphone_core_get_vcard_context(const LinphoneCore *lc) { + return lc->vcard_context; +} + +void linphone_core_set_zrtp_not_available_simulation(LinphoneCore *lc, bool_t enabled) { + lc->zrtp_not_available_simulation = enabled; +} + +belle_http_provider_t *linphone_core_get_http_provider(const LinphoneCore *lc) { + return lc->http_provider; +} + +void linphone_core_enable_send_call_stats_periodical_updates(LinphoneCore *lc, bool_t enabled) { + lc->send_call_stats_periodical_updates = enabled; +} + +void linphone_core_set_zrtp_cache_db(LinphoneCore *lc, sqlite3 *cache_db) { + lc->zrtp_cache_db = cache_db; +} + +LinphoneCoreCbs *linphone_core_get_first_callbacks(const LinphoneCore *lc) { + return ((VTableReference *)lc->vtable_refs->data)->cbs; +} + +bctbx_list_t **linphone_core_get_call_logs_attribute(LinphoneCore *lc) { + return &lc->call_logs; +} + +void linphone_core_cbs_set_auth_info_requested(LinphoneCoreCbs *cbs, LinphoneCoreAuthInfoRequestedCb cb) { + cbs->vtable->auth_info_requested = cb; +} + +LinphoneQualityReporting *linphone_call_log_get_quality_reporting(LinphoneCallLog *call_log) { + return &call_log->reporting; +} + +reporting_session_report_t **linphone_quality_reporting_get_reports(LinphoneQualityReporting *qreporting) { + return &qreporting->reports[0]; +} + +const bctbx_list_t *linphone_friend_get_insubs(const LinphoneFriend *fr) { + return fr->insubs; +} + +int linphone_friend_list_get_expected_notification_version(const LinphoneFriendList *list) { + return list->expected_notification_version; +} + +unsigned int linphone_friend_list_get_storage_id(const LinphoneFriendList *list) { + return list->storage_id; +} + +unsigned int linphone_friend_get_storage_id(const LinphoneFriend *lf) { + return lf->storage_id; +} + +void linphone_friend_set_core(LinphoneFriend *lf, LinphoneCore *lc) { + lf->lc = lc; +} + +LinphoneFriendList *linphone_friend_get_friend_list(const LinphoneFriend *lf) { + return lf->friend_list; +} + +bctbx_list_t **linphone_friend_list_get_friends_attribute(LinphoneFriendList *lfl) { + return &lfl->friends; +} + +const bctbx_list_t *linphone_friend_list_get_dirty_friends_to_update(const LinphoneFriendList *lfl) { + return lfl->dirty_friends_to_update; +} + +int linphone_friend_list_get_revision(const LinphoneFriendList *lfl) { + return lfl->revision; +} + +unsigned int _linphone_call_get_nb_media_starts (const LinphoneCall *call) { + return L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStartCount(); +} + +belle_sip_source_t *_linphone_call_get_dtmf_timer (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getDtmfTimer(); +} + +bool_t _linphone_call_has_dtmf_sequence (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getDtmfSequence().empty() ? FALSE : TRUE; +} + +SalMediaDescription *_linphone_call_get_local_desc (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getLocalDesc(); +} + +SalMediaDescription *_linphone_call_get_result_desc (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getResultDesc(); +} + +MSWebCam *_linphone_call_get_video_device (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getVideoDevice(); +} + +void _linphone_call_add_local_desc_changed_flag (LinphoneCall *call, int flag) { + L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->addLocalDescChangedFlag(flag); +} + +int _linphone_call_get_main_audio_stream_index (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getMainAudioStreamIndex(); +} + +int _linphone_call_get_main_text_stream_index (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getMainTextStreamIndex(); +} + +int _linphone_call_get_main_video_stream_index (const LinphoneCall *call) { + return L_GET_PRIVATE(static_pointer_cast( + L_GET_PRIVATE_FROM_C_OBJECT(call)->getActiveSession()))->getMainVideoStreamIndex(); +} + +void _linphone_chat_room_enable_migration(LinphoneChatRoom *cr, bool_t enable) { + shared_ptr acr = L_GET_CPP_PTR_FROM_C_OBJECT(cr); + L_GET_PRIVATE(acr->getCore())->mainDb->enableChatRoomMigration(acr->getChatRoomId(), !!enable); +} + +int _linphone_chat_room_get_transient_message_count (const LinphoneChatRoom *cr) { + shared_ptr chatRoom = static_pointer_cast(L_GET_CPP_PTR_FROM_C_OBJECT(cr)); + return (int)L_GET_PRIVATE(chatRoom)->transientEvents.size(); +} + +LinphoneChatMessage * _linphone_chat_room_get_first_transient_message (const LinphoneChatRoom *cr) { + shared_ptr chatRoom = static_pointer_cast(L_GET_CPP_PTR_FROM_C_OBJECT(cr)); + if (L_GET_PRIVATE(chatRoom)->transientEvents.empty()) + return nullptr; + shared_ptr event = static_pointer_cast( + L_GET_PRIVATE(chatRoom)->transientEvents.front() + ); + return L_GET_C_BACK_PTR(event->getChatMessage()); +} \ No newline at end of file diff --git a/coreapi/tester_utils.h b/coreapi/tester_utils.h new file mode 100644 index 000000000..0dd600d72 --- /dev/null +++ b/coreapi/tester_utils.h @@ -0,0 +1,178 @@ +/* +tester_utils.h +Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef _TESTER_UTILS_H_ +#define _TESTER_UTILS_H_ + +#include "account_creator_private.h" +#include "linphone/core.h" +#include "linphone/tunnel.h" +#include "c-wrapper/internal/c-sal.h" +#include +#include "quality_reporting.h" +#include "vcard_private.h" + +#ifndef __cplusplus +typedef struct _Sal Sal; +typedef struct _SalOp SalOp; +#endif + +typedef struct _LinphoneQualityReporting LinphoneQualityReporting; + +typedef enum _LinphoneProxyConfigAddressComparisonResult{ + LinphoneProxyConfigAddressDifferent, + LinphoneProxyConfigAddressEqual, + LinphoneProxyConfigAddressWeakEqual +} LinphoneProxyConfigAddressComparisonResult; + +#ifdef __cplusplus +extern "C" { +#endif + +LINPHONE_PUBLIC LinphoneVcardContext *linphone_core_get_vcard_context(const LinphoneCore *lc); +LINPHONE_PUBLIC bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_get_local_ip(LinphoneCore *lc, int af, const char *dest, char *result); +LINPHONE_PUBLIC int linphone_core_get_local_ip_for(int type, const char *dest, char *result); +LINPHONE_PUBLIC void linphone_core_enable_forced_ice_relay(LinphoneCore *lc, bool_t enable); +LINPHONE_PUBLIC void linphone_core_set_zrtp_not_available_simulation(LinphoneCore *lc, bool_t enabled); +LINPHONE_PUBLIC belle_http_provider_t *linphone_core_get_http_provider(const LinphoneCore *lc); +LINPHONE_PUBLIC const char *linphone_core_get_tone_file(const LinphoneCore *lc, LinphoneToneID id); +LINPHONE_PUBLIC IceSession * linphone_call_get_ice_session(const LinphoneCall *call); +LINPHONE_PUBLIC const struct addrinfo *linphone_core_get_stun_server_addrinfo(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_enable_send_call_stats_periodical_updates(LinphoneCore *lc, bool_t enabled); + +LINPHONE_PUBLIC int linphone_run_stun_tests(LinphoneCore *lc, int audioPort, int videoPort, int textPort, + char *audioCandidateAddr, int *audioCandidatePort, char *videoCandidateAddr, int *videoCandidatePort, char *textCandidateAddr, int *textCandidatePort); +LINPHONE_PUBLIC void linphone_core_enable_short_turn_refresh(LinphoneCore *lc, bool_t enable); + +LINPHONE_PUBLIC void linphone_core_set_zrtp_cache_db(LinphoneCore *lc, sqlite3 *cache_db); + +LINPHONE_PUBLIC LinphoneCoreCbs *linphone_core_get_first_callbacks(const LinphoneCore *lc); +LINPHONE_PUBLIC void _linphone_core_add_callbacks(LinphoneCore *lc, LinphoneCoreCbs *vtable, bool_t internal); + +LINPHONE_PUBLIC bctbx_list_t * linphone_core_read_call_logs_from_config_file(LinphoneCore *lc); +LINPHONE_PUBLIC bctbx_list_t **linphone_core_get_call_logs_attribute(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_delete_call_log(LinphoneCore *lc, LinphoneCallLog *log); + +LINPHONE_PUBLIC const MSList *linphone_core_get_call_history(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_delete_call_history(LinphoneCore *lc); +LINPHONE_PUBLIC int linphone_core_get_call_history_size(LinphoneCore *lc); + +LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_cbs_set_auth_info_requested(LinphoneCoreCbs *cbs, LinphoneCoreAuthInfoRequestedCb cb); + +LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_is_server_config_changed(const LinphoneProxyConfig* obj); +LINPHONE_PUBLIC LinphoneProxyConfigAddressComparisonResult linphone_proxy_config_address_equal(const LinphoneAddress *a, const LinphoneAddress *b); + +LINPHONE_PUBLIC LinphoneCallLog *linphone_call_get_log(const LinphoneCall *call); +LINPHONE_PUBLIC MediaStream * linphone_call_get_stream(LinphoneCall *call, LinphoneStreamType type); +LINPHONE_PUBLIC bool_t linphone_call_get_all_muted(const LinphoneCall *call); +LINPHONE_PUBLIC LinphoneProxyConfig * linphone_call_get_dest_proxy(const LinphoneCall *call); +LINPHONE_PUBLIC unsigned int _linphone_call_get_nb_media_starts (const LinphoneCall *call); +LINPHONE_PUBLIC belle_sip_source_t *_linphone_call_get_dtmf_timer (const LinphoneCall *call); +LINPHONE_PUBLIC bool_t _linphone_call_has_dtmf_sequence (const LinphoneCall *call); +LINPHONE_PUBLIC SalMediaDescription *_linphone_call_get_local_desc (const LinphoneCall *call); +LINPHONE_PUBLIC SalMediaDescription *_linphone_call_get_result_desc (const LinphoneCall *call); +LINPHONE_PUBLIC MSWebCam *_linphone_call_get_video_device (const LinphoneCall *call); +LINPHONE_PUBLIC void _linphone_call_add_local_desc_changed_flag (LinphoneCall *call, int flag); +LINPHONE_PUBLIC int _linphone_call_get_main_audio_stream_index (const LinphoneCall *call); +LINPHONE_PUBLIC int _linphone_call_get_main_text_stream_index (const LinphoneCall *call); +LINPHONE_PUBLIC int _linphone_call_get_main_video_stream_index (const LinphoneCall *call); + +LINPHONE_PUBLIC void linphone_call_params_set_no_user_consent(LinphoneCallParams *params, bool_t value); +LINPHONE_PUBLIC bool_t linphone_call_params_get_update_call_when_ice_completed(const LinphoneCallParams *params); + +LINPHONE_PUBLIC int _linphone_call_stats_get_updated(const LinphoneCallStats *stats); +LINPHONE_PUBLIC bool_t _linphone_call_stats_rtcp_received_via_mux(const LinphoneCallStats *stats); +LINPHONE_PUBLIC mblk_t *_linphone_call_stats_get_received_rtcp (const LinphoneCallStats *stats); + +LINPHONE_PUBLIC LinphoneQualityReporting *linphone_call_log_get_quality_reporting(LinphoneCallLog *call_log); +LINPHONE_PUBLIC reporting_session_report_t **linphone_quality_reporting_get_reports(LinphoneQualityReporting *qreporting); + +LINPHONE_PUBLIC void _linphone_chat_room_enable_migration(LinphoneChatRoom *cr, bool_t enable); +LINPHONE_PUBLIC int _linphone_chat_room_get_transient_message_count (const LinphoneChatRoom *cr); +LINPHONE_PUBLIC LinphoneChatMessage * _linphone_chat_room_get_first_transient_message (const LinphoneChatRoom *cr); + +LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_from_db(LinphoneCore *lc, LinphoneFriendList *list); +LINPHONE_PUBLIC MSList* linphone_core_fetch_friends_lists_from_db(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_friend_invalidate_subscription(LinphoneFriend *lf); +LINPHONE_PUBLIC void linphone_friend_update_subscribes(LinphoneFriend *fr, bool_t only_when_registered); +LINPHONE_PUBLIC const bctbx_list_t *linphone_friend_get_insubs(const LinphoneFriend *fr); +LINPHONE_PUBLIC int linphone_friend_list_get_expected_notification_version(const LinphoneFriendList *list); +LINPHONE_PUBLIC unsigned int linphone_friend_list_get_storage_id(const LinphoneFriendList *list); +LINPHONE_PUBLIC unsigned int linphone_friend_get_storage_id(const LinphoneFriend *lf); +LINPHONE_PUBLIC void linphone_friend_set_core(LinphoneFriend *lf, LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneFriendList *linphone_friend_get_friend_list(const LinphoneFriend *lf); +LINPHONE_PUBLIC bctbx_list_t **linphone_friend_list_get_friends_attribute(LinphoneFriendList *lfl); +LINPHONE_PUBLIC const bctbx_list_t *linphone_friend_list_get_dirty_friends_to_update(const LinphoneFriendList *lfl); +LINPHONE_PUBLIC int linphone_friend_list_get_revision(const LinphoneFriendList *lfl); + +LINPHONE_PUBLIC int linphone_remote_provisioning_load_file( LinphoneCore* lc, const char* file_path); + + +#ifndef __cplusplus +LINPHONE_PUBLIC Sal *linphone_core_get_sal(const LinphoneCore *lc); +LINPHONE_PUBLIC SalOp *linphone_proxy_config_get_sal_op(const LinphoneProxyConfig *cfg); +LINPHONE_PUBLIC SalOp *linphone_call_get_op_as_sal_op(const LinphoneCall *call); + +LINPHONE_PUBLIC Sal * sal_init(MSFactory *factory); +LINPHONE_PUBLIC void sal_uninit(Sal* sal); + +LINPHONE_PUBLIC int sal_create_uuid(Sal *ctx, char *uuid, size_t len); +LINPHONE_PUBLIC char *sal_get_random_token(int size); +LINPHONE_PUBLIC void sal_set_uuid(Sal *ctx, const char *uuid); + +LINPHONE_PUBLIC void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handling_method) ; +LINPHONE_PUBLIC void sal_set_send_error(Sal *sal,int value); +LINPHONE_PUBLIC void sal_set_recv_error(Sal *sal,int value); +LINPHONE_PUBLIC int sal_enable_pending_trans_checking(Sal *sal, bool_t value); +LINPHONE_PUBLIC void sal_enable_unconditional_answer(Sal *sal,int value); +LINPHONE_PUBLIC void sal_set_dns_timeout(Sal* sal,int timeout); +LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file); +LINPHONE_PUBLIC void *sal_get_stack_impl(Sal *sal); +LINPHONE_PUBLIC void sal_set_refresher_retry_after(Sal *sal,int value); +LINPHONE_PUBLIC int sal_get_refresher_retry_after(const Sal *sal); +LINPHONE_PUBLIC void sal_set_transport_timeout(Sal* sal,int timeout); +LINPHONE_PUBLIC void sal_enable_test_features(Sal*ctx, bool_t enabled); +LINPHONE_PUBLIC int sal_transport_available(Sal *ctx, SalTransport t); + +LINPHONE_PUBLIC const SalErrorInfo *sal_op_get_error_info(const SalOp *op); +LINPHONE_PUBLIC bool_t sal_call_dialog_request_pending(const SalOp *op); +LINPHONE_PUBLIC void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling); +LINPHONE_PUBLIC SalMediaDescription * sal_call_get_final_media_description(SalOp *h); + +LINPHONE_PUBLIC belle_sip_resolver_context_t *sal_resolve_a(Sal *sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data); + +LINPHONE_PUBLIC Sal *sal_op_get_sal(SalOp *op); +LINPHONE_PUBLIC SalOp *sal_create_refer_op(Sal *sal); +LINPHONE_PUBLIC void sal_release_op(SalOp *op); +LINPHONE_PUBLIC void sal_op_set_from(SalOp *sal_refer_op, const char* from); +LINPHONE_PUBLIC void sal_op_set_to(SalOp *sal_refer_op, const char* to); +LINPHONE_PUBLIC void sal_op_send_refer(SalOp *sal_refer_op, SalAddress* refer_to); +LINPHONE_PUBLIC void sal_set_user_pointer(Sal *sal, void *user_pointer); +LINPHONE_PUBLIC void *sal_get_user_pointer(Sal *sal); +LINPHONE_PUBLIC void sal_set_call_refer_callback(Sal *sal, void (*OnReferCb)(SalOp *op, const SalAddress *referto)); +#endif + +#ifdef __cplusplus +} +#endif + + + +#endif // _TESTER_UTILS_H_ diff --git a/coreapi/upnp.c b/coreapi/upnp.c deleted file mode 100644 index 642eb24bc..000000000 --- a/coreapi/upnp.c +++ /dev/null @@ -1,1412 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications SARL - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "upnp.h" -#include "private.h" -#include "linphone/lpconfig.h" -#include - -#define UPNP_STRINGIFY(x) #x -#define UPNP_TOSTRING(x) UPNP_STRINGIFY(x) - -#define UPNP_ADD_MAX_RETRY 4 -#define UPNP_REMOVE_MAX_RETRY 4 -#define UPNP_SECTION_NAME "uPnP" -#define UPNP_CORE_READY_CHECK 1 -#define UPNP_CORE_RETRY_DELAY 10 -#define UPNP_CALL_RETRY_DELAY 3 -#define UPNP_UUID_LEN 128 -#define UPNP_UUID_LEN_STR UPNP_TOSTRING(UPNP_UUID_LEN) -/* - * uPnP Definitions - */ - -typedef struct _UpnpPortBinding { - ms_mutex_t mutex; - LinphoneUpnpState state; - upnp_igd_ip_protocol protocol; - char *device_id; - char local_addr[LINPHONE_IPADDR_SIZE]; - int local_port; - char external_addr[LINPHONE_IPADDR_SIZE]; - int external_port; - int retry; - int ref; - bool_t to_remove; - bool_t to_add; - time_t last_update; -} UpnpPortBinding; - -typedef struct _UpnpStream { - UpnpPortBinding *rtp; - UpnpPortBinding *rtcp; - LinphoneUpnpState state; -} UpnpStream; - -struct _UpnpSession { - LinphoneCall *call; - UpnpStream *audio; - UpnpStream *video; - LinphoneUpnpState state; -}; - -struct _UpnpContext { - LinphoneCore *lc; - upnp_igd_context *upnp_igd_ctxt; - UpnpPortBinding *sip_tcp; - UpnpPortBinding *sip_tls; - UpnpPortBinding *sip_udp; - LinphoneUpnpState state; - bctbx_list_t *removing_configs; - bctbx_list_t *adding_configs; - bctbx_list_t *pending_bindings; - - ms_mutex_t mutex; - ms_cond_t empty_cond; - - time_t last_ready_check; - LinphoneUpnpState last_ready_state; -}; - - -bool_t linphone_core_upnp_hook(void *data); -void linphone_upnp_update(UpnpContext *ctx); -bool_t linphone_upnp_is_blacklisted(UpnpContext *ctx); - -UpnpPortBinding *linphone_upnp_port_binding_new(void); -UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_protocol protocol, int local_port, int external_port); -UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(bctbx_list_t *list, upnp_igd_ip_protocol protocol, int local_port, int external_port); -UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port); -void linphone_upnp_port_binding_set_device_id(UpnpPortBinding *port, const char * device_id); -bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2); -UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(bctbx_list_t *list, const UpnpPortBinding *port); -UpnpPortBinding *linphone_upnp_port_binding_retain(UpnpPortBinding *port); -void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay); -void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port); -void linphone_upnp_port_binding_release(UpnpPortBinding *port); -void linphone_upnp_update_config(UpnpContext *lupnp); -void linphone_upnp_update_proxy(UpnpContext *lupnp, bool_t force); - -// Configuration -bctbx_list_t *linphone_upnp_config_list_port_bindings(struct _LpConfig *lpc, const char *device_id); -void linphone_upnp_config_add_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port); -void linphone_upnp_config_remove_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port); - -// uPnP -int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry); -int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry); - -static int linphone_upnp_strncmpi(const char *str1, const char *str2, int len) { - int i = 0; - char char1, char2; - while(i < len) { - char1 = toupper(*str1); - char2 = toupper(*str2); - if(char1 == '\0' || char1 != char2) { - return char1 - char2; - } - str1++; - str2++; - i++; - } - return 0; -} - -static int linphone_upnp_str_min(const char *str1, const char *str2) { - int len1 = strlen(str1); - int len2 = strlen(str2); - if(len1 > len2) { - return len2; - } - return len1; -} - -char * linphone_upnp_format_device_id(const char *device_id) { - char *ret = NULL; - char *tmp; - char tchar; - bool_t copy; - if(device_id == NULL) { - return ret; - } - ret = ms_new0(char, UPNP_UUID_LEN + 1); - tmp = ret; - if(linphone_upnp_strncmpi(device_id, "uuid:", linphone_upnp_str_min(device_id, "uuid:")) == 0) { - device_id += strlen("uuid:"); - } - while(*device_id != '\0' && tmp - ret < UPNP_UUID_LEN) { - copy = FALSE; - tchar = *device_id; - if(tchar >= '0' && tchar <= '9') - copy = TRUE; - if(!copy && tchar >= 'A' && tchar <= 'Z') - copy = TRUE; - if(!copy && tchar >= 'a' && tchar <= 'z') - copy = TRUE; - if(copy) { - *tmp = *device_id; - tmp++; - } - device_id++; - } - *tmp = '\0'; - return ret; -} - -/** - * uPnP Callbacks - */ - -/* Convert uPnP IGD logs to ortp logs */ -void linphone_upnp_igd_print(void *cookie, upnp_igd_print_level level, const char *fmt, va_list list) { - int ortp_level = ORTP_DEBUG; - switch(level) { - case UPNP_IGD_MESSAGE: - ortp_level = ORTP_MESSAGE; - break; - case UPNP_IGD_WARNING: - ortp_level = ORTP_DEBUG; // Too verbose otherwise - break; - case UPNP_IGD_ERROR: - ortp_level = ORTP_DEBUG; // Too verbose otherwise - break; - default: - break; - } - ortp_logv(ORTP_LOG_DOMAIN, ortp_level, fmt, list); -} - -void linphone_upnp_igd_callback(void *cookie, upnp_igd_event event, void *arg) { - UpnpContext *lupnp = (UpnpContext *)cookie; - upnp_igd_port_mapping *mapping = NULL; - UpnpPortBinding *port_mapping = NULL; - const char *ip_address = NULL; - const char *connection_status = NULL; - bool_t nat_enabled = FALSE; - bool_t blacklisted = FALSE; - LinphoneUpnpState old_state; - - if(lupnp == NULL || lupnp->upnp_igd_ctxt == NULL) { - ms_error("uPnP IGD: Invalid context in callback"); - return; - } - - ms_mutex_lock(&lupnp->mutex); - old_state = lupnp->state; - - switch(event) { - case UPNP_IGD_DEVICE_ADDED: - case UPNP_IGD_DEVICE_REMOVED: - case UPNP_IGD_EXTERNAL_IPADDRESS_CHANGED: - case UPNP_IGD_NAT_ENABLED_CHANGED: - case UPNP_IGD_CONNECTION_STATUS_CHANGED: - ip_address = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt); - connection_status = upnp_igd_get_connection_status(lupnp->upnp_igd_ctxt); - nat_enabled = upnp_igd_get_nat_enabled(lupnp->upnp_igd_ctxt); - blacklisted = linphone_upnp_is_blacklisted(lupnp); - - if(ip_address == NULL || connection_status == NULL) { - ms_message("uPnP IGD: Pending"); - lupnp->state = LinphoneUpnpStatePending; - } else if(strcasecmp(connection_status, "Connected") || !nat_enabled) { - ms_message("uPnP IGD: Not Available"); - lupnp->state = LinphoneUpnpStateNotAvailable; - } else if(blacklisted) { - ms_message("uPnP IGD: Router is blacklisted"); - lupnp->state = LinphoneUpnpStateBlacklisted; - } else { - ms_message("uPnP IGD: Connected"); - lupnp->state = LinphoneUpnpStateOk; - if(old_state != LinphoneUpnpStateOk) { - linphone_upnp_update(lupnp); - } - } - - break; - - case UPNP_IGD_PORT_MAPPING_ADD_SUCCESS: - mapping = (upnp_igd_port_mapping *) arg; - port_mapping = (UpnpPortBinding*) mapping->cookie; - port_mapping->external_port = mapping->remote_port; - port_mapping->state = LinphoneUpnpStateOk; - linphone_upnp_port_binding_log(ORTP_MESSAGE, "Added port binding", port_mapping); - linphone_upnp_config_add_port_binding(lupnp, port_mapping); - - break; - - case UPNP_IGD_PORT_MAPPING_ADD_FAILURE: - mapping = (upnp_igd_port_mapping *) arg; - port_mapping = (UpnpPortBinding*) mapping->cookie; - port_mapping->external_port = -1; //Force random external port - if(linphone_upnp_context_send_add_port_binding(lupnp, port_mapping, TRUE) != 0) { - linphone_upnp_port_binding_log(ORTP_ERROR, "Can't add port binding", port_mapping); - } - - break; - - case UPNP_IGD_PORT_MAPPING_REMOVE_SUCCESS: - mapping = (upnp_igd_port_mapping *) arg; - port_mapping = (UpnpPortBinding*) mapping->cookie; - port_mapping->state = LinphoneUpnpStateIdle; - linphone_upnp_port_binding_log(ORTP_MESSAGE, "Removed port binding", port_mapping); - linphone_upnp_config_remove_port_binding(lupnp, port_mapping); - - break; - - case UPNP_IGD_PORT_MAPPING_REMOVE_FAILURE: - mapping = (upnp_igd_port_mapping *) arg; - port_mapping = (UpnpPortBinding*) mapping->cookie; - if(linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, TRUE) != 0) { - linphone_upnp_port_binding_log(ORTP_ERROR, "Can't remove port binding", port_mapping); - linphone_upnp_config_remove_port_binding(lupnp, port_mapping); - } - - break; - - default: - break; - } - - if(port_mapping != NULL) { - /* - * Execute delayed actions - */ - if(port_mapping->to_remove) { - if(port_mapping->state == LinphoneUpnpStateOk) { - port_mapping->to_remove = FALSE; - linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, FALSE); - } else if(port_mapping->state == LinphoneUpnpStateKo) { - port_mapping->to_remove = FALSE; - } - } - if(port_mapping->to_add) { - if(port_mapping->state == LinphoneUpnpStateIdle || port_mapping->state == LinphoneUpnpStateKo) { - port_mapping->to_add = FALSE; - linphone_upnp_context_send_add_port_binding(lupnp, port_mapping, FALSE); - } - } - - lupnp->pending_bindings = bctbx_list_remove(lupnp->pending_bindings, port_mapping); - linphone_upnp_port_binding_release(port_mapping); - } - - /* - * If there is no pending binding emit a signal - */ - if(lupnp->pending_bindings == NULL) { - ms_cond_signal(&lupnp->empty_cond); - } - ms_mutex_unlock(&lupnp->mutex); -} - - -/** - * uPnP Context - */ - -UpnpContext* linphone_upnp_context_new(LinphoneCore *lc) { - UpnpContext *lupnp = (UpnpContext *)ms_new0(UpnpContext,1); - char address[LINPHONE_IPADDR_SIZE]; - const char*upnp_binding_address=address; - if (linphone_core_get_local_ip_for(lc->sip_conf.ipv6_enabled ? AF_INET6 : AF_INET,NULL,address)) { - ms_warning("Linphone core [%p] cannot guess local address for upnp, let's choice the lib",lc); - upnp_binding_address=NULL; - } - ms_mutex_init(&lupnp->mutex, NULL); - ms_cond_init(&lupnp->empty_cond, NULL); - - lupnp->last_ready_check = 0; - lupnp->last_ready_state = LinphoneUpnpStateIdle; - - lupnp->lc = lc; - lupnp->pending_bindings = NULL; - lupnp->adding_configs = NULL; - lupnp->removing_configs = NULL; - lupnp->state = LinphoneUpnpStateIdle; - ms_message("uPnP IGD: New %p for core %p bound to %s", lupnp, lc,upnp_binding_address); - - // Init ports - lupnp->sip_udp = NULL; - lupnp->sip_tcp = NULL; - lupnp->sip_tls = NULL; - - linphone_core_add_iterate_hook(lc, linphone_core_upnp_hook, lupnp); - - lupnp->upnp_igd_ctxt = NULL; - lupnp->upnp_igd_ctxt = upnp_igd_create(linphone_upnp_igd_callback, linphone_upnp_igd_print, address, lupnp); - if(lupnp->upnp_igd_ctxt == NULL) { - lupnp->state = LinphoneUpnpStateKo; - ms_error("Can't create uPnP IGD context"); - return NULL; - } - - lupnp->state = LinphoneUpnpStatePending; - upnp_igd_start(lupnp->upnp_igd_ctxt); - - return lupnp; -} - -void linphone_upnp_context_destroy(UpnpContext *lupnp) { - linphone_core_remove_iterate_hook(lupnp->lc, linphone_core_upnp_hook, lupnp); - - ms_mutex_lock(&lupnp->mutex); - - if(lupnp->lc->sip_network_reachable) { - /* Send port binding removes */ - if(lupnp->sip_udp != NULL) { - linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_udp, TRUE); - } - if(lupnp->sip_tcp != NULL) { - linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tcp, TRUE); - } - if(lupnp->sip_tls != NULL) { - linphone_upnp_context_send_remove_port_binding(lupnp, lupnp->sip_tls, TRUE); - } - } - - /* Wait all pending bindings are done */ - if(lupnp->pending_bindings != NULL) { - ms_message("uPnP IGD: Wait all pending port bindings ..."); - ms_cond_wait(&lupnp->empty_cond, &lupnp->mutex); - } - ms_mutex_unlock(&lupnp->mutex); - - if(lupnp->upnp_igd_ctxt != NULL) { - upnp_igd_destroy(lupnp->upnp_igd_ctxt); - lupnp->upnp_igd_ctxt = NULL; - } - - /* No more multi threading here */ - - /* Run one more time configuration update and proxy */ - linphone_upnp_update_config(lupnp); - linphone_upnp_update_proxy(lupnp, TRUE); - - /* Release port bindings */ - if(lupnp->sip_udp != NULL) { - linphone_upnp_port_binding_release(lupnp->sip_udp); - lupnp->sip_udp = NULL; - } - if(lupnp->sip_tcp != NULL) { - linphone_upnp_port_binding_release(lupnp->sip_tcp); - lupnp->sip_tcp = NULL; - } - if(lupnp->sip_tls != NULL) { - linphone_upnp_port_binding_release(lupnp->sip_tls); - lupnp->sip_tcp = NULL; - } - - /* Release lists */ - bctbx_list_for_each(lupnp->adding_configs,(void (*)(void*))linphone_upnp_port_binding_release); - lupnp->adding_configs = bctbx_list_free(lupnp->adding_configs); - bctbx_list_for_each(lupnp->removing_configs,(void (*)(void*))linphone_upnp_port_binding_release); - lupnp->removing_configs = bctbx_list_free(lupnp->removing_configs); - bctbx_list_for_each(lupnp->pending_bindings,(void (*)(void*))linphone_upnp_port_binding_release); - lupnp->pending_bindings = bctbx_list_free(lupnp->pending_bindings); - - ms_mutex_destroy(&lupnp->mutex); - ms_cond_destroy(&lupnp->empty_cond); - - ms_message("uPnP IGD: destroy %p", lupnp); - ms_free(lupnp); -} - -LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *lupnp) { - LinphoneUpnpState state = LinphoneUpnpStateKo; - if(lupnp != NULL) { - ms_mutex_lock(&lupnp->mutex); - state = lupnp->state; - ms_mutex_unlock(&lupnp->mutex); - } - return state; -} - -bool_t _linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { - bool_t ready = TRUE; - - // 1 Check global uPnP state - ready = (lupnp->state == LinphoneUpnpStateOk); - - // 2 Check external ip address - if(ready) { - if (upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt) == NULL) { - ready = FALSE; - } - } - - // 3 Check sip ports bindings - if(ready) { - if(lupnp->sip_udp != NULL) { - if(lupnp->sip_udp->state != LinphoneUpnpStateOk) { - ready = FALSE; - } - } else if(lupnp->sip_tcp != NULL) { - if(lupnp->sip_tcp->state != LinphoneUpnpStateOk) { - ready = FALSE; - } - } else if(lupnp->sip_tls != NULL) { - if(lupnp->sip_tls->state != LinphoneUpnpStateOk) { - ready = FALSE; - } - } else { - ready = FALSE; - } - } - - return ready; -} - -bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *lupnp) { - bool_t ready = FALSE; - if(lupnp != NULL) { - ms_mutex_lock(&lupnp->mutex); - ready = _linphone_upnp_context_is_ready_for_register(lupnp); - ms_mutex_unlock(&lupnp->mutex); - } - return ready; -} - -int linphone_upnp_context_get_external_port(UpnpContext *lupnp) { - int port = -1; - if(lupnp != NULL) { - ms_mutex_lock(&lupnp->mutex); - - if(lupnp->sip_udp != NULL) { - if(lupnp->sip_udp->state == LinphoneUpnpStateOk) { - port = lupnp->sip_udp->external_port; - } - } else if(lupnp->sip_tcp != NULL) { - if(lupnp->sip_tcp->state == LinphoneUpnpStateOk) { - port = lupnp->sip_tcp->external_port; - } - } else if(lupnp->sip_tls != NULL) { - if(lupnp->sip_tls->state == LinphoneUpnpStateOk) { - port = lupnp->sip_tls->external_port; - } - } - - ms_mutex_unlock(&lupnp->mutex); - } - return port; -} - -bool_t linphone_upnp_is_blacklisted(UpnpContext *lupnp) { - const char * device_model_name = upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt); - const char * device_model_number = upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt); - const char * blacklist = lp_config_get_string(lupnp->lc->config, "net", "upnp_blacklist", NULL); - bool_t blacklisted = FALSE; - char *str; - char *pch; - char *model_name; - char *model_number; - - // Sanity checks - if(device_model_name == NULL || device_model_number == NULL || blacklist == NULL) { - return FALSE; - } - - // Find in the list - str = strdup(blacklist); - pch = strtok(str, ";"); - while (pch != NULL && !blacklisted) { - // Extract model name & number - model_name = pch; - model_number = strstr(pch, ","); - if(model_number != NULL) { - *(model_number++) = '\0'; - } - - // Compare with current device - if(strcmp(model_name, device_model_name) == 0) { - if(model_number == NULL || strcmp(model_number, device_model_number) == 0) { - blacklisted = TRUE; - } - } - pch = strtok(NULL, ";"); - } - free(str); - - return blacklisted; -} - -void linphone_upnp_refresh(UpnpContext * lupnp) { - upnp_igd_refresh(lupnp->upnp_igd_ctxt); -} - -const char* linphone_upnp_context_get_external_ipaddress(UpnpContext *lupnp) { - const char* addr = NULL; - if(lupnp != NULL) { - ms_mutex_lock(&lupnp->mutex); - addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt); - ms_mutex_unlock(&lupnp->mutex); - } - return addr; -} - -int linphone_upnp_context_send_add_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry) { - upnp_igd_port_mapping mapping; - char description[128]; - int ret; - - if(lupnp->state != LinphoneUpnpStateOk) { - return -2; - } - - // Compute port binding state - if(port->state != LinphoneUpnpStateAdding) { - port->to_remove = FALSE; - switch(port->state) { - case LinphoneUpnpStateKo: - case LinphoneUpnpStateIdle: { - port->retry = 0; - port->state = LinphoneUpnpStateAdding; - } - break; - case LinphoneUpnpStateRemoving: { - port->to_add = TRUE; - return 0; - } - break; - default: - return 0; - } - } - - // No retry if specified - if(port->retry != 0 && !retry) { - return -1; - } - - if(port->retry >= UPNP_ADD_MAX_RETRY) { - ret = -1; - } else { - linphone_upnp_port_binding_set_device_id(port, upnp_igd_get_device_id(lupnp->upnp_igd_ctxt)); - mapping.cookie = linphone_upnp_port_binding_retain(port); - lupnp->pending_bindings = bctbx_list_append(lupnp->pending_bindings, mapping.cookie); - - mapping.local_port = port->local_port; - mapping.local_host = port->local_addr; - if(port->external_port == -1) - port->external_port = rand()%(0xffff - 1024) + 1024; - mapping.remote_port = port->external_port; - mapping.remote_host = ""; - snprintf(description, 128, "%s %s at %s:%d", - "Linphone", - (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP": "UDP", - port->local_addr, port->local_port); - mapping.description = description; - mapping.protocol = port->protocol; - - port->retry++; - linphone_upnp_port_binding_log(ORTP_MESSAGE, "Try to add port binding", port); - ret = upnp_igd_add_port_mapping(lupnp->upnp_igd_ctxt, &mapping); - } - if(ret != 0) { - port->state = LinphoneUpnpStateKo; - } - return ret; -} - -int linphone_upnp_context_send_remove_port_binding(UpnpContext *lupnp, UpnpPortBinding *port, bool_t retry) { - upnp_igd_port_mapping mapping; - int ret; - - if(lupnp->state != LinphoneUpnpStateOk) { - return -2; - } - - // Compute port binding state - if(port->state != LinphoneUpnpStateRemoving) { - port->to_add = FALSE; - switch(port->state) { - case LinphoneUpnpStateOk: { - port->retry = 0; - port->state = LinphoneUpnpStateRemoving; - } - break; - case LinphoneUpnpStateAdding: { - port->to_remove = TRUE; - return 0; - } - break; - default: - return 0; - } - } - - // No retry if specified - if(port->retry != 0 && !retry) { - return 1; - } - - if(port->retry >= UPNP_REMOVE_MAX_RETRY) { - ret = -1; - } else { - linphone_upnp_port_binding_set_device_id(port, upnp_igd_get_device_id(lupnp->upnp_igd_ctxt)); - mapping.cookie = linphone_upnp_port_binding_retain(port); - lupnp->pending_bindings = bctbx_list_append(lupnp->pending_bindings, mapping.cookie); - - mapping.remote_port = port->external_port; - mapping.remote_host = ""; - mapping.protocol = port->protocol; - port->retry++; - linphone_upnp_port_binding_log(ORTP_MESSAGE, "Try to remove port binding", port); - ret = upnp_igd_delete_port_mapping(lupnp->upnp_igd_ctxt, &mapping); - } - if(ret != 0) { - port->state = LinphoneUpnpStateKo; - } - return ret; -} - -/* - * uPnP Core interfaces - */ - -int linphone_call_update_upnp_audio_video(LinphoneCall *call, bool_t audio, bool_t video) { - LinphoneCore *lc = call->core; - UpnpContext *lupnp = lc->upnp; - int ret = -1; - - if(lupnp == NULL) { - return ret; - } - - ms_mutex_lock(&lupnp->mutex); - - // Don't handle when the call - if(lupnp->state == LinphoneUpnpStateOk && call->upnp_session != NULL) { - ret = 0; - - /* - * Audio part - */ - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtp, - UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[call->main_audio_stream_index].rtp_port:0, UPNP_CALL_RETRY_DELAY); - - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->audio->rtcp, - UPNP_IGD_IP_PROTOCOL_UDP, (audio)? call->media_ports[call->main_audio_stream_index].rtcp_port:0, UPNP_CALL_RETRY_DELAY); - - /* - * Video part - */ - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtp, - UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[call->main_video_stream_index].rtp_port:0, UPNP_CALL_RETRY_DELAY); - - linphone_upnp_update_port_binding(lupnp, &call->upnp_session->video->rtcp, - UPNP_IGD_IP_PROTOCOL_UDP, (video)? call->media_ports[call->main_video_stream_index].rtcp_port:0, UPNP_CALL_RETRY_DELAY); - } - - ms_mutex_unlock(&lupnp->mutex); - - /* - * Update uPnP call state - */ - linphone_upnp_call_process(call); - - return ret; -} - - - -int linphone_call_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md) { - bool_t audio = FALSE; - bool_t video = FALSE; - int i; - const SalStreamDescription *stream; - - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - stream = &md->streams[i]; - if (!sal_stream_description_active(stream)) continue; - if(stream->type == SalAudio) { - audio = TRUE; - } else if(stream->type == SalVideo) { - video = TRUE; - } - } - - return linphone_call_update_upnp_audio_video(call, audio, video); -} - -int linphone_call_update_upnp(LinphoneCall *call) { - return linphone_call_update_upnp_audio_video(call, call->audiostream!=NULL, call->videostream!=NULL); -} - -void linphone_call_update_upnp_state_in_call_stats(LinphoneCall *call) { - call->audio_stats->upnp_state = call->upnp_session->audio->state; - call->video_stats->upnp_state = call->upnp_session->video->state; -} - -void linphone_upnp_update_stream_state(UpnpStream *stream) { - if((stream->rtp == NULL || stream->rtp->state == LinphoneUpnpStateOk || stream->rtp->state == LinphoneUpnpStateIdle) && - (stream->rtcp == NULL || stream->rtcp->state == LinphoneUpnpStateOk || stream->rtcp->state == LinphoneUpnpStateIdle)) { - stream->state = LinphoneUpnpStateOk; - } else if((stream->rtp != NULL && - (stream->rtp->state == LinphoneUpnpStateAdding || stream->rtp->state == LinphoneUpnpStateRemoving)) || - (stream->rtcp != NULL && - (stream->rtcp->state == LinphoneUpnpStateAdding || stream->rtcp->state == LinphoneUpnpStateRemoving))) { - stream->state = LinphoneUpnpStatePending; - } else if((stream->rtp != NULL && stream->rtp->state == LinphoneUpnpStateKo) || - (stream->rtcp != NULL && stream->rtcp->state == LinphoneUpnpStateKo)) { - stream->state = LinphoneUpnpStateKo; - } else { - ms_error("Invalid stream %p state", stream); - } -} - -int linphone_upnp_call_process(LinphoneCall *call) { - LinphoneCore *lc = call->core; - UpnpContext *lupnp = lc->upnp; - int ret = -1; - LinphoneUpnpState oldState = 0, newState = 0; - - if(lupnp == NULL) { - return ret; - } - - ms_mutex_lock(&lupnp->mutex); - - // Don't handle when the call - if(lupnp->state == LinphoneUpnpStateOk && call->upnp_session != NULL) { - ret = 0; - - /* - * Update Audio state - */ - linphone_upnp_update_stream_state(call->upnp_session->audio); - - /* - * Update Video state - */ - linphone_upnp_update_stream_state(call->upnp_session->video); - - /* - * Update stat - */ - linphone_call_update_upnp_state_in_call_stats(call); - - /* - * Update session state - */ - oldState = call->upnp_session->state; - if(call->upnp_session->audio->state == LinphoneUpnpStateOk && - call->upnp_session->video->state == LinphoneUpnpStateOk) { - call->upnp_session->state = LinphoneUpnpStateOk; - } else if(call->upnp_session->audio->state == LinphoneUpnpStatePending || - call->upnp_session->video->state == LinphoneUpnpStatePending) { - call->upnp_session->state = LinphoneUpnpStatePending; - } else if(call->upnp_session->audio->state == LinphoneUpnpStateKo || - call->upnp_session->video->state == LinphoneUpnpStateKo) { - call->upnp_session->state = LinphoneUpnpStateKo; - } else { - call->upnp_session->state = LinphoneUpnpStateIdle; - } - newState = call->upnp_session->state; - } - - ms_mutex_unlock(&lupnp->mutex); - - /* When change is done proceed update */ - if(oldState != LinphoneUpnpStateOk && oldState != LinphoneUpnpStateKo && - (newState == LinphoneUpnpStateOk || newState == LinphoneUpnpStateKo)) { - if(call->upnp_session->state == LinphoneUpnpStateOk) - ms_message("uPnP IGD: uPnP for Call %p is ok", call); - else - ms_message("uPnP IGD: uPnP for Call %p is ko", call); - - switch (call->state) { - case LinphoneCallUpdating: - linphone_call_start_update(call); - break; - case LinphoneCallUpdatedByRemote: - linphone_call_start_accept_update(call, call->prevstate, linphone_call_state_to_string(call->prevstate)); - break; - case LinphoneCallOutgoingInit: - linphone_call_proceed_with_invite_if_ready(call, NULL); - break; - case LinphoneCallIdle: - linphone_call_update_local_media_description_from_ice_or_upnp(call); - sal_call_set_local_media_description(call->op,call->localdesc); - linphone_core_notify_incoming_call(lc, call); - break; - default: - break; - } - } - - return ret; -} - -static const char *linphone_core_upnp_get_charptr_null(const char *str) { - if(str != NULL) { - return str; - } - return "(Null)"; -} - -void linphone_upnp_update(UpnpContext *lupnp) { - bctbx_list_t *global_list = NULL; - bctbx_list_t *list = NULL; - bctbx_list_t *item; - LinphoneCall *call; - UpnpPortBinding *port_mapping, *port_mapping2; - - ms_message("uPnP IGD: Name:%s", linphone_core_upnp_get_charptr_null(upnp_igd_get_device_name(lupnp->upnp_igd_ctxt))); - ms_message("uPnP IGD: Device:%s %s", - linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_name(lupnp->upnp_igd_ctxt)), - linphone_core_upnp_get_charptr_null(upnp_igd_get_device_model_number(lupnp->upnp_igd_ctxt))); - ms_message("uPnP IGD: Refresh mappings"); - - if(lupnp->sip_udp != NULL) { - global_list = bctbx_list_append(global_list, lupnp->sip_udp); - } - if(lupnp->sip_tcp != NULL) { - global_list = bctbx_list_append(global_list, lupnp->sip_tcp); - } - if(lupnp->sip_tls != NULL) { - global_list = bctbx_list_append(global_list, lupnp->sip_tls); - } - - list = lupnp->lc->calls; - while(list != NULL) { - call = (LinphoneCall *)list->data; - if(call->upnp_session != NULL) { - if(call->upnp_session->audio->rtp != NULL) { - global_list = bctbx_list_append(global_list, call->upnp_session->audio->rtp); - } - if(call->upnp_session->audio->rtcp != NULL) { - global_list = bctbx_list_append(global_list, call->upnp_session->audio->rtcp); - } - if(call->upnp_session->video->rtp != NULL) { - global_list = bctbx_list_append(global_list, call->upnp_session->video->rtp); - } - if(call->upnp_session->video->rtcp != NULL) { - global_list = bctbx_list_append(global_list, call->upnp_session->video->rtcp); - } - } - list = list->next; - } - - list = linphone_upnp_config_list_port_bindings(lupnp->lc->config, upnp_igd_get_device_id(lupnp->upnp_igd_ctxt)); - for(item = list;item != NULL; item = item->next) { - port_mapping = (UpnpPortBinding *)item->data; - port_mapping2 = linphone_upnp_port_binding_equivalent_in_list(global_list, port_mapping); - if(port_mapping2 == NULL) { - linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, TRUE); - } else if(port_mapping2->state == LinphoneUpnpStateIdle){ - /* Force to remove */ - port_mapping2->state = LinphoneUpnpStateOk; - } - } - bctbx_list_for_each(list, (void (*)(void*))linphone_upnp_port_binding_release); - list = bctbx_list_free(list); - - - // (Re)Add removed port bindings - list = global_list; - while(list != NULL) { - port_mapping = (UpnpPortBinding *)list->data; - linphone_upnp_context_send_remove_port_binding(lupnp, port_mapping, TRUE); - linphone_upnp_context_send_add_port_binding(lupnp, port_mapping, TRUE); - list = list->next; - } - global_list = bctbx_list_free(global_list); -} - -void linphone_upnp_update_port_binding(UpnpContext *lupnp, UpnpPortBinding **port_mapping, upnp_igd_ip_protocol protocol, int port, int retry_delay) { - const char *local_addr, *external_addr; - time_t now = time(NULL); - if(port != 0) { - if(*port_mapping != NULL) { - if(port != (*port_mapping)->local_port) { - linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE); - *port_mapping = NULL; - } - } - if(*port_mapping == NULL) { - *port_mapping = linphone_upnp_port_binding_new_or_collect(lupnp->pending_bindings, protocol, port, port); - } - - // Get addresses - local_addr = upnp_igd_get_local_ipaddress(lupnp->upnp_igd_ctxt); - external_addr = upnp_igd_get_external_ipaddress(lupnp->upnp_igd_ctxt); - - // Force binding update on local address change - if(local_addr != NULL) { - if(strncmp((*port_mapping)->local_addr, local_addr, sizeof((*port_mapping)->local_addr))) { - linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE); - strncpy((*port_mapping)->local_addr, local_addr, sizeof((*port_mapping)->local_addr)); - } - } - if(external_addr != NULL) { - strncpy((*port_mapping)->external_addr, external_addr, sizeof((*port_mapping)->external_addr)); - } - - // Add (if not already done) the binding - if(now - (*port_mapping)->last_update >= retry_delay) { - (*port_mapping)->last_update = now; - linphone_upnp_context_send_add_port_binding(lupnp, *port_mapping, FALSE); - } - } else { - if(*port_mapping != NULL) { - linphone_upnp_context_send_remove_port_binding(lupnp, *port_mapping, FALSE); - *port_mapping = NULL; - } - } -} - -void linphone_upnp_update_config(UpnpContext* lupnp) { - char key[64]; - const bctbx_list_t *item; - UpnpPortBinding *port_mapping; - - /* Add configs */ - for(item = lupnp->adding_configs;item!=NULL;item=item->next) { - port_mapping = (UpnpPortBinding *)item->data; - snprintf(key, sizeof(key), "%s-%s-%d-%d", - port_mapping->device_id, - (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port_mapping->external_port, - port_mapping->local_port); - lp_config_set_string(lupnp->lc->config, UPNP_SECTION_NAME, key, "uPnP"); - linphone_upnp_port_binding_log(ORTP_DEBUG, "Configuration: Added port binding", port_mapping); - } - bctbx_list_for_each(lupnp->adding_configs,(void (*)(void*))linphone_upnp_port_binding_release); - lupnp->adding_configs = bctbx_list_free(lupnp->adding_configs); - - /* Remove configs */ - for(item = lupnp->removing_configs;item!=NULL;item=item->next) { - port_mapping = (UpnpPortBinding *)item->data; - snprintf(key, sizeof(key), "%s-%s-%d-%d", - port_mapping->device_id, - (port_mapping->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port_mapping->external_port, - port_mapping->local_port); - lp_config_set_string(lupnp->lc->config, UPNP_SECTION_NAME, key, NULL); - linphone_upnp_port_binding_log(ORTP_DEBUG, "Configuration: Removed port binding", port_mapping); - } - bctbx_list_for_each(lupnp->removing_configs,(void (*)(void*))linphone_upnp_port_binding_release); - lupnp->removing_configs = bctbx_list_free(lupnp->removing_configs); -} - -void linphone_upnp_update_proxy(UpnpContext* lupnp, bool_t force) { - LinphoneUpnpState ready_state; - const bctbx_list_t *item; - time_t now = (force)? (lupnp->last_ready_check + UPNP_CORE_READY_CHECK) : time(NULL); - - /* Refresh registers if we are ready */ - if(now - lupnp->last_ready_check >= UPNP_CORE_READY_CHECK) { - lupnp->last_ready_check = now; - ready_state = (_linphone_upnp_context_is_ready_for_register(lupnp))? LinphoneUpnpStateOk: LinphoneUpnpStateKo; - if(ready_state != lupnp->last_ready_state) { - for(item=linphone_core_get_proxy_config_list(lupnp->lc);item!=NULL;item=item->next) { - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)item->data; - if (linphone_proxy_config_register_enabled(cfg)) { - if (ready_state != LinphoneUpnpStateOk) { - // Only reset ithe registration if we require that upnp should be ok - if(lupnp->lc->sip_conf.register_only_when_upnp_is_ok) { - linphone_proxy_config_set_state(cfg, LinphoneRegistrationNone, "Registration impossible (uPnP not ready)"); - } else { - cfg->commit=TRUE; - } - } else { - cfg->commit=TRUE; - } - } - } - lupnp->last_ready_state = ready_state; - } - } -} - -bool_t linphone_core_upnp_hook(void *data) { - LCSipTransports transport; - UpnpContext *lupnp = (UpnpContext *)data; - - ms_mutex_lock(&lupnp->mutex); - - /* Update ports */ - if(lupnp->state == LinphoneUpnpStateOk) { - linphone_core_get_sip_transports(lupnp->lc, &transport); - linphone_upnp_update_port_binding(lupnp, &lupnp->sip_udp, UPNP_IGD_IP_PROTOCOL_UDP, transport.udp_port, UPNP_CORE_RETRY_DELAY); - linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tcp, UPNP_IGD_IP_PROTOCOL_TCP, transport.tcp_port, UPNP_CORE_RETRY_DELAY); - linphone_upnp_update_port_binding(lupnp, &lupnp->sip_tls, UPNP_IGD_IP_PROTOCOL_TCP, transport.tls_port, UPNP_CORE_RETRY_DELAY); - } - - linphone_upnp_update_proxy(lupnp, FALSE); - linphone_upnp_update_config(lupnp); - - ms_mutex_unlock(&lupnp->mutex); - return TRUE; -} - -int linphone_call_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session) { - int i; - SalStreamDescription *stream; - UpnpStream *upnpStream; - - for (i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { - stream = &desc->streams[i]; - if (!sal_stream_description_active(stream)) continue; - upnpStream = NULL; - if(stream->type == SalAudio) { - upnpStream = session->audio; - } else if(stream->type == SalVideo) { - upnpStream = session->video; - } - if(upnpStream != NULL) { - if(upnpStream->rtp != NULL && upnpStream->rtp->state == LinphoneUpnpStateOk) { - strncpy(stream->rtp_addr, upnpStream->rtp->external_addr, LINPHONE_IPADDR_SIZE); - stream->rtp_port = upnpStream->rtp->external_port; - } - if(upnpStream->rtcp != NULL && upnpStream->rtcp->state == LinphoneUpnpStateOk) { - strncpy(stream->rtcp_addr, upnpStream->rtcp->external_addr, LINPHONE_IPADDR_SIZE); - stream->rtcp_port = upnpStream->rtcp->external_port; - } - } - } - return 0; -} - - -/* - * uPnP Port Binding - */ - -UpnpPortBinding *linphone_upnp_port_binding_new(void) { - UpnpPortBinding *port = NULL; - port = ms_new0(UpnpPortBinding,1); - ms_mutex_init(&port->mutex, NULL); - port->state = LinphoneUpnpStateIdle; - port->protocol = UPNP_IGD_IP_PROTOCOL_UDP; - port->device_id = NULL; - port->local_addr[0] = '\0'; - port->local_port = -1; - port->external_addr[0] = '\0'; - port->external_port = -1; - port->to_remove = FALSE; - port->to_add = FALSE; - port->ref = 1; - port->last_update = 0; - return port; -} - -UpnpPortBinding *linphone_upnp_port_binding_new_with_parameters(upnp_igd_ip_protocol protocol, int local_port, int external_port) { - UpnpPortBinding *port_binding = linphone_upnp_port_binding_new(); - port_binding->protocol = protocol; - port_binding->local_port = local_port; - port_binding->external_port = external_port; - return port_binding; -} - -UpnpPortBinding *linphone_upnp_port_binding_new_or_collect(bctbx_list_t *list, upnp_igd_ip_protocol protocol, int local_port, int external_port) { - UpnpPortBinding *tmp_binding; - UpnpPortBinding *end_binding; - - // Seek an binding with same protocol and local port - end_binding = linphone_upnp_port_binding_new_with_parameters(protocol, local_port, -1); - tmp_binding = linphone_upnp_port_binding_equivalent_in_list(list, end_binding); - - // Must be not attached to any struct - if(tmp_binding != NULL && tmp_binding->ref == 1) { - linphone_upnp_port_binding_release(end_binding); - end_binding = linphone_upnp_port_binding_retain(tmp_binding); - } else { - end_binding->external_port = external_port; - } - return end_binding; -} - -UpnpPortBinding *linphone_upnp_port_binding_copy(const UpnpPortBinding *port) { - UpnpPortBinding *new_port = NULL; - new_port = ms_new0(UpnpPortBinding,1); - memcpy(new_port, port, sizeof(UpnpPortBinding)); - new_port->device_id = NULL; - linphone_upnp_port_binding_set_device_id(new_port, port->device_id); - ms_mutex_init(&new_port->mutex, NULL); - new_port->ref = 1; - return new_port; -} - -void linphone_upnp_port_binding_set_device_id(UpnpPortBinding *port, const char *device_id) { - char *formated_device_id = linphone_upnp_format_device_id(device_id); - if(formated_device_id != NULL && port->device_id != NULL) { - if(strcmp(formated_device_id, port->device_id) == 0) { - ms_free(formated_device_id); - return; - } - } - if(port->device_id != NULL) { - ms_free(port->device_id); - } - port->device_id = formated_device_id; -} - -void linphone_upnp_port_binding_log(int level, const char *msg, const UpnpPortBinding *port) { - if(strlen(port->local_addr)) { - ortp_log(level, "uPnP IGD: %s %s|%d->%s:%d (retry %d)", msg, - (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port->external_port, - port->local_addr, - port->local_port, - port->retry - 1); - } else { - ortp_log(level, "uPnP IGD: %s %s|%d->%d (retry %d)", msg, - (port->protocol == UPNP_IGD_IP_PROTOCOL_TCP)? "TCP":"UDP", - port->external_port, - port->local_port, - port->retry - 1); - } -} - -// Return true if the binding are equivalent. (Note external_port == -1 means "don't care") -bool_t linphone_upnp_port_binding_equal(const UpnpPortBinding *port1, const UpnpPortBinding *port2) { - return port1->protocol == port2->protocol && - port1->local_port == port2->local_port && - (port1->external_port == -1 || port2->external_port == -1 || port1->external_port == port2->external_port); -} - -UpnpPortBinding *linphone_upnp_port_binding_equivalent_in_list(bctbx_list_t *list, const UpnpPortBinding *port) { - UpnpPortBinding *port_mapping; - while(list != NULL) { - port_mapping = (UpnpPortBinding *)list->data; - if(linphone_upnp_port_binding_equal(port, port_mapping)) { - return port_mapping; - } - list = list->next; - } - - return NULL; -} - -UpnpPortBinding *linphone_upnp_port_binding_retain(UpnpPortBinding *port) { - ms_mutex_lock(&port->mutex); - port->ref++; - ms_mutex_unlock(&port->mutex); - return port; -} - -void linphone_upnp_port_binding_release(UpnpPortBinding *port) { - ms_mutex_lock(&port->mutex); - if(--port->ref == 0) { - if(port->device_id != NULL) { - ms_free(port->device_id); - } - ms_mutex_unlock(&port->mutex); - ms_mutex_destroy(&port->mutex); - ms_free(port); - return; - } - ms_mutex_unlock(&port->mutex); -} - - -/* - * uPnP Stream - */ - -UpnpStream* linphone_upnp_stream_new(void) { - UpnpStream *stream = ms_new0(UpnpStream,1); - stream->state = LinphoneUpnpStateIdle; - stream->rtp = NULL; - stream->rtcp = NULL; - return stream; -} - -void linphone_upnp_stream_destroy(UpnpStream* stream) { - if(stream->rtp != NULL) { - linphone_upnp_port_binding_release(stream->rtp); - stream->rtp = NULL; - } - if(stream->rtcp != NULL) { - linphone_upnp_port_binding_release(stream->rtcp); - stream->rtcp = NULL; - } - ms_free(stream); -} - - -/* - * uPnP Session - */ - -UpnpSession* linphone_upnp_session_new(LinphoneCall* call) { - UpnpSession *session = ms_new0(UpnpSession,1); - session->call = call; - session->state = LinphoneUpnpStateIdle; - session->audio = linphone_upnp_stream_new(); - session->video = linphone_upnp_stream_new(); - return session; -} - -void linphone_upnp_session_destroy(UpnpSession *session) { - LinphoneCore *lc = session->call->core; - - if(lc->upnp != NULL) { - /* Remove bindings */ - if(session->audio->rtp != NULL) { - linphone_upnp_context_send_remove_port_binding(lc->upnp, session->audio->rtp, TRUE); - } - if(session->audio->rtcp != NULL) { - linphone_upnp_context_send_remove_port_binding(lc->upnp, session->audio->rtcp, TRUE); - } - if(session->video->rtp != NULL) { - linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtp, TRUE); - } - if(session->video->rtcp != NULL) { - linphone_upnp_context_send_remove_port_binding(lc->upnp, session->video->rtcp, TRUE); - } - } - - session->call->audio_stats->upnp_state = LinphoneUpnpStateKo; - session->call->video_stats->upnp_state = LinphoneUpnpStateKo; - - linphone_upnp_stream_destroy(session->audio); - linphone_upnp_stream_destroy(session->video); - ms_free(session); -} - -LinphoneUpnpState linphone_upnp_session_get_state(UpnpSession *session) { - return session->state; -} - - -/* - * uPnP Config - */ - -struct linphone_upnp_config_list_port_bindings_struct { - struct _LpConfig *lpc; - bctbx_list_t *retList; - const char *device_id; -}; - -static void linphone_upnp_config_list_port_bindings_cb(const char *entry, struct linphone_upnp_config_list_port_bindings_struct *cookie) { - char device_id[UPNP_UUID_LEN + 1]; - char protocol_str[4]; // TCP or UDP - upnp_igd_ip_protocol protocol; - int external_port; - int local_port; - int ret; - bool_t valid = TRUE; - UpnpPortBinding *port; - - ret = sscanf(entry, "%"UPNP_UUID_LEN_STR"[^-]-%3s-%i-%i", device_id, protocol_str, &external_port, &local_port); - if(ret == 4) { - // Handle only wanted device bindings - if(device_id != NULL && strcmp(cookie->device_id, device_id) != 0) { - return; - } - if(linphone_upnp_strncmpi(protocol_str, "TCP", 3) == 0) { - protocol = UPNP_IGD_IP_PROTOCOL_TCP; - } else if(linphone_upnp_strncmpi(protocol_str, "UDP", 3) == 0) { - protocol = UPNP_IGD_IP_PROTOCOL_UDP; - } else { - valid = FALSE; - } - if(valid) { - port = linphone_upnp_port_binding_new(); - linphone_upnp_port_binding_set_device_id(port, device_id); - port->state = LinphoneUpnpStateOk; - port->protocol = protocol; - port->external_port = external_port; - port->local_port = local_port; - cookie->retList = bctbx_list_append(cookie->retList, port); - } - } else { - valid = FALSE; - } - if(!valid) { - ms_warning("uPnP configuration invalid line: %s", entry); - } -} - -bctbx_list_t *linphone_upnp_config_list_port_bindings(struct _LpConfig *lpc, const char *device_id) { - char *formated_device_id = linphone_upnp_format_device_id(device_id); - struct linphone_upnp_config_list_port_bindings_struct cookie = {lpc, NULL, formated_device_id}; - lp_config_for_each_entry(lpc, UPNP_SECTION_NAME, (void(*)(const char *, void*))linphone_upnp_config_list_port_bindings_cb, &cookie); - ms_free(formated_device_id); - return cookie.retList; -} - -void linphone_upnp_config_add_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port) { - bctbx_list_t *list; - UpnpPortBinding *list_port; - - if(port->device_id == NULL) { - ms_error("Can't remove port binding without device_id"); - return; - } - - list = lupnp->removing_configs; - while(list != NULL) { - list_port = (UpnpPortBinding *)list->data; - if(linphone_upnp_port_binding_equal(list_port, port) == TRUE) { - lupnp->removing_configs = bctbx_list_remove(lupnp->removing_configs, list_port); - linphone_upnp_port_binding_release(list_port); - return; - } - list = bctbx_list_next(list); - } - - list = lupnp->adding_configs; - while(list != NULL) { - list_port = (UpnpPortBinding *)list->data; - if(linphone_upnp_port_binding_equal(list_port, port) == TRUE) { - return; - } - list = bctbx_list_next(list); - } - - list_port = linphone_upnp_port_binding_copy(port); - lupnp->adding_configs = bctbx_list_append(lupnp->adding_configs, list_port); -} - -void linphone_upnp_config_remove_port_binding(UpnpContext *lupnp, const UpnpPortBinding *port) { - bctbx_list_t *list; - UpnpPortBinding *list_port; - - if(port->device_id == NULL) { - ms_error("Can't remove port binding without device_id"); - return; - } - - list = lupnp->adding_configs; - while(list != NULL) { - list_port = (UpnpPortBinding *)list->data; - if(linphone_upnp_port_binding_equal(list_port, port) == TRUE) { - lupnp->adding_configs = bctbx_list_remove(lupnp->adding_configs, list_port); - linphone_upnp_port_binding_release(list_port); - return; - } - list = bctbx_list_next(list); - } - - list = lupnp->removing_configs; - while(list != NULL) { - list_port = (UpnpPortBinding *)list->data; - if(linphone_upnp_port_binding_equal(list_port, port) == TRUE) { - return; - } - list = bctbx_list_next(list); - } - - list_port = linphone_upnp_port_binding_copy(port); - lupnp->removing_configs = bctbx_list_append(lupnp->removing_configs, list_port); -} diff --git a/coreapi/upnp.h b/coreapi/upnp.h deleted file mode 100644 index a8abeb16b..000000000 --- a/coreapi/upnp.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -linphone -Copyright (C) 2012 Belledonne Communications SARL - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef LINPHONE_UPNP_H -#define LINPHONE_UPNP_H - -#include "mediastreamer2/upnp_igd.h" -#include "linphone/core.h" -#include "sal/sal.h" - -typedef struct _UpnpSession UpnpSession; -typedef struct _UpnpContext UpnpContext; - -int linphone_call_update_local_media_description_from_upnp(SalMediaDescription *desc, UpnpSession *session); -int linphone_call_update_upnp_from_remote_media_description(LinphoneCall *call, const SalMediaDescription *md); -int linphone_call_update_upnp(LinphoneCall *call); - -int linphone_upnp_call_process(LinphoneCall *call); -UpnpSession* linphone_upnp_session_new(LinphoneCall *call); -void linphone_upnp_session_destroy(UpnpSession* session); -LinphoneUpnpState linphone_upnp_session_get_state(UpnpSession *session); - -UpnpContext *linphone_upnp_context_new(LinphoneCore *lc); -void linphone_upnp_context_destroy(UpnpContext *ctx); -void linphone_upnp_refresh(UpnpContext *ctx); -LinphoneUpnpState linphone_upnp_context_get_state(UpnpContext *ctx); -const char *linphone_upnp_context_get_external_ipaddress(UpnpContext *ctx); -int linphone_upnp_context_get_external_port(UpnpContext *ctx); -bool_t linphone_upnp_context_is_ready_for_register(UpnpContext *ctx); -void linphone_call_update_upnp_state_in_call_stats(LinphoneCall *call); - -#endif //LINPHONE_UPNP_H diff --git a/coreapi/vcard.cc b/coreapi/vcard.cc index c1925e60e..36488137f 100644 --- a/coreapi/vcard.cc +++ b/coreapi/vcard.cc @@ -17,15 +17,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "vcard_private.h" -#include "belcard/belcard.hpp" -#include "belcard/belcard_parser.hpp" -#include "sal/sal.h" #include -#include "private.h" + +#include +#include + #include "linphone/factory.h" #include "linphone/wrapper_utils.h" +#include "c-wrapper/c-wrapper.h" +#include "c-wrapper/internal/c-sal.h" +#include "vcard_private.h" + #define VCARD_MD5_HASH_SIZE 16 using namespace std; @@ -139,11 +142,8 @@ bctbx_list_t* linphone_vcard_context_get_vcard_list_from_file(LinphoneVcardConte } shared_ptr belCards = context->parser->parseFile(filename); if (belCards) { - for (auto it = belCards->getCards().begin(); it != belCards->getCards().end(); ++it) { - shared_ptr belCard = (*it); - LinphoneVcard *vCard = linphone_vcard_new_from_belcard(belCard); - result = bctbx_list_append(result, vCard); - } + for (auto &belCard : belCards->getCards()) + result = bctbx_list_append(result, linphone_vcard_new_from_belcard(belCard)); } } return result; @@ -157,11 +157,8 @@ bctbx_list_t* linphone_vcard_context_get_vcard_list_from_buffer(LinphoneVcardCon } shared_ptr belCards = context->parser->parse(buffer); if (belCards) { - for (auto it = belCards->getCards().begin(); it != belCards->getCards().end(); ++it) { - shared_ptr belCard = (*it); - LinphoneVcard *vCard = linphone_vcard_new_from_belcard(belCard); - result = bctbx_list_append(result, vCard); - } + for (auto &belCard : belCards->getCards()) + result = bctbx_list_append(result, linphone_vcard_new_from_belcard(belCard)); } } return result; @@ -274,17 +271,13 @@ void linphone_vcard_add_sip_address(LinphoneVcard *vCard, const char *sip_addres void linphone_vcard_remove_sip_address(LinphoneVcard *vCard, const char *sip_address) { if (!vCard) return; - shared_ptr impp; - for (auto it = vCard->belCard->getImpp().begin(); it != vCard->belCard->getImpp().end(); ++it) { - const char *value = (*it)->getValue().c_str(); + for (auto &impp : vCard->belCard->getImpp()) { + const char *value = impp->getValue().c_str(); if (strcmp(value, sip_address) == 0) { - impp = *it; + vCard->belCard->removeImpp(impp); break; } } - if (impp) { - vCard->belCard->removeImpp(impp); - } } void linphone_vcard_edit_main_sip_address(LinphoneVcard *vCard, const char *sip_address) { @@ -303,8 +296,8 @@ void linphone_vcard_edit_main_sip_address(LinphoneVcard *vCard, const char *sip_ const bctbx_list_t* linphone_vcard_get_sip_addresses(LinphoneVcard *vCard) { if (!vCard) return NULL; if (!vCard->sip_addresses_cache) { - for (auto it = vCard->belCard->getImpp().begin(); it != vCard->belCard->getImpp().end(); ++it) { - LinphoneAddress* addr = linphone_address_new((*it)->getValue().c_str()); + for (auto &impp : vCard->belCard->getImpp()) { + LinphoneAddress* addr = linphone_address_new(impp->getValue().c_str()); if (addr) { vCard->sip_addresses_cache = bctbx_list_append(vCard->sip_addresses_cache, addr); } @@ -325,24 +318,21 @@ void linphone_vcard_remove_phone_number(LinphoneVcard *vCard, const char *phone) if (!vCard) return; shared_ptr tel; - for (auto it = vCard->belCard->getPhoneNumbers().begin(); it != vCard->belCard->getPhoneNumbers().end(); ++it) { - const char *value = (*it)->getValue().c_str(); + for (auto &phoneNumber : vCard->belCard->getPhoneNumbers()) { + const char *value = phoneNumber->getValue().c_str(); if (strcmp(value, phone) == 0) { - tel = *it; + vCard->belCard->removePhoneNumber(phoneNumber); break; } } - if (tel) { - vCard->belCard->removePhoneNumber(tel); - } } bctbx_list_t* linphone_vcard_get_phone_numbers(const LinphoneVcard *vCard) { bctbx_list_t *result = NULL; if (!vCard) return NULL; - for (auto it = vCard->belCard->getPhoneNumbers().begin(); it != vCard->belCard->getPhoneNumbers().end(); ++it) { - const char *value = (*it)->getValue().c_str(); + for (auto &phoneNumber : vCard->belCard->getPhoneNumbers()) { + const char *value = phoneNumber->getValue().c_str(); result = bctbx_list_append(result, (char *)value); } return result; @@ -377,7 +367,7 @@ bool_t linphone_vcard_generate_unique_id(LinphoneVcard *vCard) { if (linphone_vcard_get_uid(vCard)) { return FALSE; } - if (sal_generate_uuid(uuid, sizeof(uuid)) == 0) { + if (LinphonePrivate::Sal::generateUuid(uuid, sizeof(uuid)) == 0) { char vcard_uuid[sizeof(uuid)+4]; snprintf(vcard_uuid, sizeof(vcard_uuid), "urn:%s", uuid); linphone_vcard_set_uid(vCard, vcard_uuid); @@ -445,7 +435,7 @@ bool_t linphone_vcard_compare_md5_hash(LinphoneVcard *vCard) { unsigned char previous_md5[VCARD_MD5_HASH_SIZE]; memcpy(previous_md5, vCard->md5, VCARD_MD5_HASH_SIZE); linphone_vcard_compute_md5_hash(vCard); - return memcmp(vCard->md5, previous_md5, VCARD_MD5_HASH_SIZE); + return !!memcmp(vCard->md5, previous_md5, VCARD_MD5_HASH_SIZE); } bool_t linphone_core_vcard_supported(void) { diff --git a/coreapi/video_definition.c b/coreapi/video_definition.c index 717fdfd73..98d75e0b0 100644 --- a/coreapi/video_definition.c +++ b/coreapi/video_definition.c @@ -1,6 +1,6 @@ /* linphone -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -20,8 +20,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/factory.h" #include "linphone/video_definition.h" -#include "private.h" +#include "c-wrapper/c-wrapper.h" +// TODO: From coreapi. Remove me later. +#include "private.h" static void linphone_video_definition_destroy(LinphoneVideoDefinition *vdef) { if (vdef->name) bctbx_free(vdef->name); diff --git a/coreapi/vtables.c b/coreapi/vtables.c index ca9960ef9..25d7254b0 100644 --- a/coreapi/vtables.c +++ b/coreapi/vtables.c @@ -18,7 +18,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "c-wrapper/c-wrapper.h" +#include "core/core-p.h" + #include "private.h" +#include "linphone/wrapper_utils.h" LinphoneCoreVTable *linphone_core_v_table_new() { @@ -84,6 +88,7 @@ static void cleanup_dead_vtable_refs(LinphoneCore *lc){ lc->vtable_notify_recursion--; void linphone_core_notify_global_state_changed(LinphoneCore *lc, LinphoneGlobalState gstate, const char *message) { + L_GET_PRIVATE_FROM_C_OBJECT(lc)->notifyGlobalStateChanged(gstate); NOTIFY_IF_EXIST(global_state_changed,lc,gstate,message); cleanup_dead_vtable_refs(lc); } @@ -99,44 +104,11 @@ void linphone_core_notify_call_encryption_changed(LinphoneCore *lc, LinphoneCall } void linphone_core_notify_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const char *message){ + L_GET_PRIVATE_FROM_C_OBJECT(lc)->notifyRegistrationStateChanged(cfg, cstate, message); NOTIFY_IF_EXIST(registration_state_changed, lc,cfg,cstate,message); cleanup_dead_vtable_refs(lc); } -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#ifdef _MSC_VER -#pragma warning(disable : 4996) -#else -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif -void linphone_core_notify_show_interface(LinphoneCore *lc){ - NOTIFY_IF_EXIST(show, lc); - cleanup_dead_vtable_refs(lc); -} -void linphone_core_notify_display_status(LinphoneCore *lc, const char *message) { - NOTIFY_IF_EXIST(display_status, lc,message); - cleanup_dead_vtable_refs(lc); -} - -void linphone_core_notify_display_message(LinphoneCore *lc, const char *message){ - NOTIFY_IF_EXIST(display_message, lc,message); - cleanup_dead_vtable_refs(lc); -} - -void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message){ - NOTIFY_IF_EXIST(display_warning, lc,message); - cleanup_dead_vtable_refs(lc); -} - -void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url){ - NOTIFY_IF_EXIST(display_url, lc,message,url); - cleanup_dead_vtable_refs(lc); -} -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf) { NOTIFY_IF_EXIST(notify_presence_received, lc, lf); cleanup_dead_vtable_refs(lc); @@ -272,6 +244,7 @@ void linphone_core_notify_configuring_status(LinphoneCore *lc, LinphoneConfiguri } void linphone_core_notify_network_reachable(LinphoneCore *lc, bool_t reachable) { + L_GET_PRIVATE_FROM_C_OBJECT(lc)->notifyNetworkReachable(!!lc->sip_network_reachable, !!lc->media_network_reachable); NOTIFY_IF_EXIST(network_reachable, lc,reachable); cleanup_dead_vtable_refs(lc); } @@ -281,6 +254,11 @@ void linphone_core_notify_notify_received(LinphoneCore *lc, LinphoneEvent *lev, cleanup_dead_vtable_refs(lc); } +void linphone_core_notify_subscribe_received(LinphoneCore *lc, LinphoneEvent *lev, const char *subscribe_event, const LinphoneContent *body) { + NOTIFY_IF_EXIST_INTERNAL(subscribe_received, linphone_event_is_internal(lev), lc, lev, subscribe_event, body); + cleanup_dead_vtable_refs(lc); +} + void linphone_core_notify_subscription_state_changed(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { NOTIFY_IF_EXIST_INTERNAL(subscription_state_changed,linphone_event_is_internal(lev), lc,lev,state); cleanup_dead_vtable_refs(lc); @@ -321,6 +299,31 @@ void linphone_core_notify_version_update_check_result_received(LinphoneCore *lc, cleanup_dead_vtable_refs(lc); } +void linphone_core_notify_chat_room_state_changed (LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatRoomState state) { + NOTIFY_IF_EXIST(chat_room_state_changed, lc, cr, state); + cleanup_dead_vtable_refs(lc); +} + +void linphone_core_notify_qrcode_found(LinphoneCore *lc, const char *result) { + NOTIFY_IF_EXIST(qrcode_found, lc, result); + cleanup_dead_vtable_refs(lc); +} + +void linphone_core_notify_ec_calibration_result(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms) { + NOTIFY_IF_EXIST(ec_calibration_result, lc, status, delay_ms); + cleanup_dead_vtable_refs(lc); +} + +void linphone_core_notify_ec_calibration_audio_init(LinphoneCore *lc) { + NOTIFY_IF_EXIST(ec_calibration_audio_init, lc); + cleanup_dead_vtable_refs(lc); +} + +void linphone_core_notify_ec_calibration_audio_uninit(LinphoneCore *lc) { + NOTIFY_IF_EXIST(ec_calibration_audio_uninit, lc); + cleanup_dead_vtable_refs(lc); +} + static VTableReference * v_table_reference_new(LinphoneCoreCbs *cbs, bool_t internal){ VTableReference *ref=ms_new0(VTableReference,1); ref->valid=TRUE; @@ -361,6 +364,16 @@ void linphone_core_remove_listener(LinphoneCore *lc, const LinphoneCoreVTable *v } } +bctbx_list_t *linphone_core_get_callbacks_list(const LinphoneCore *lc) { + bctbx_list_t *result = NULL; + bctbx_list_t *it; + for(it=lc->vtable_refs; it!=NULL; it=it->next){ + VTableReference *ref=(VTableReference*)it->data; + result = bctbx_list_append(result, ref->cbs); + } + return result; +} + void linphone_core_remove_callbacks(LinphoneCore *lc, const LinphoneCoreCbs *cbs) { bctbx_list_t *it; ms_message("Callbacks [%p] unregistered on core [%p]",cbs,lc); diff --git a/coreapi/xmlrpc.c b/coreapi/xmlrpc.c index 221876f15..459494a9a 100644 --- a/coreapi/xmlrpc.c +++ b/coreapi/xmlrpc.c @@ -17,14 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/core.h" -#include "private.h" - #include #include #include +#include "linphone/core.h" +#include "c-wrapper/c-wrapper.h" + +// TODO: From coreapi. Remove me later. +#include "private.h" BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneXmlRpcRequestCbs); @@ -384,6 +386,10 @@ void linphone_xml_rpc_session_set_user_data(LinphoneXmlRpcSession *session, void session->user_data = ud; } +LinphoneXmlRpcRequest * linphone_xml_rpc_session_create_request(LinphoneXmlRpcSession *session, LinphoneXmlRpcArgType return_type, const char *method) { + return linphone_xml_rpc_request_new(return_type, method); +} + void linphone_xml_rpc_session_send_request(LinphoneXmlRpcSession *session, LinphoneXmlRpcRequest *request) { belle_http_request_listener_callbacks_t cbs = { 0 }; belle_http_request_listener_t *l; @@ -423,4 +429,3 @@ void linphone_xml_rpc_session_release(LinphoneXmlRpcSession *session){ session->released = TRUE; belle_sip_object_unref(session); } - diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 038ef986f..a104ed5c9 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -117,7 +117,7 @@ bc_apply_compile_flags(DAEMON_PIPETEST_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OP add_executable(linphone-daemon ${DAEMON_SOURCE_FILES}) target_include_directories(linphone-daemon PRIVATE ${CMAKE_CURRENT_LIST_DIR}) -target_link_libraries(linphone-daemon ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) +target_link_libraries(linphone-daemon ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(linphone-daemon PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") add_executable(linphone-daemon-pipetest ${DAEMON_PIPETEST_SOURCE_FILES}) diff --git a/daemon/commands/adaptive-jitter-compensation.h b/daemon/commands/adaptive-jitter-compensation.h index c8a901c02..cc15bd07d 100644 --- a/daemon/commands/adaptive-jitter-compensation.h +++ b/daemon/commands/adaptive-jitter-compensation.h @@ -1,6 +1,6 @@ /* adaptive-jitter-compensation.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AdaptiveBufferCompensationCommand: public DaemonCommand { public: AdaptiveBufferCompensationCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; }; #endif // LINPHONE_DAEMON_COMMAND_ADAPTIVE_BUFFER_COMPENSATION_H_ diff --git a/daemon/commands/answer.h b/daemon/commands/answer.h index 7dcd94972..046fd3175 100644 --- a/daemon/commands/answer.h +++ b/daemon/commands/answer.h @@ -1,6 +1,6 @@ /* answer.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AnswerCommand: public DaemonCommand { public: AnswerCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; }; #endif // LINPHONE_DAEMON_COMMAND_ANSWER_H_ diff --git a/daemon/commands/audio-codec-get.h b/daemon/commands/audio-codec-get.h index 8a8075321..0068fd308 100644 --- a/daemon/commands/audio-codec-get.h +++ b/daemon/commands/audio-codec-get.h @@ -1,6 +1,6 @@ /* audio-codec-get.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AudioCodecGetCommand: public DaemonCommand { public: AudioCodecGetCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; }; #endif // LINPHONE_DAEMON_COMMAND_AUDIO_CODEC_GET_H_ diff --git a/daemon/commands/audio-codec-move.h b/daemon/commands/audio-codec-move.h index a19fa7b84..204edc95f 100644 --- a/daemon/commands/audio-codec-move.h +++ b/daemon/commands/audio-codec-move.h @@ -1,6 +1,6 @@ /* audio-codec-move.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AudioCodecMoveCommand: public DaemonCommand { public: AudioCodecMoveCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; }; #endif // LINPHONE_DAEMON_COMMAND_AUDIO_CODEC_MOVE_H_ diff --git a/daemon/commands/audio-codec-set.h b/daemon/commands/audio-codec-set.h index 0d90b2842..f5667f9f5 100644 --- a/daemon/commands/audio-codec-set.h +++ b/daemon/commands/audio-codec-set.h @@ -1,6 +1,6 @@ /* audio-codec-set.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AudioCodecSetCommand: public DaemonCommand { public: AudioCodecSetCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; }; #endif // LINPHONE_DAEMON_COMMAND_AUDIO_CODEC_SET_H_ diff --git a/daemon/commands/audio-codec-toggle.h b/daemon/commands/audio-codec-toggle.h index 36dce4300..f625112d6 100644 --- a/daemon/commands/audio-codec-toggle.h +++ b/daemon/commands/audio-codec-toggle.h @@ -1,6 +1,6 @@ /* audio-codec-toggle.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AudioCodecToggleCommand: public DaemonCommand { public: AudioCodecToggleCommand(const char *name, const char *proto, const char *help, bool enable); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; + protected: bool mEnable; }; diff --git a/daemon/commands/audio-stream-start.h b/daemon/commands/audio-stream-start.h index 4d8dc878e..730d58632 100644 --- a/daemon/commands/audio-stream-start.h +++ b/daemon/commands/audio-stream-start.h @@ -1,6 +1,6 @@ /* audio-stream-start.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AudioStreamStartCommand: public DaemonCommand { public: AudioStreamStartCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; }; #endif // LINPHONE_DAEMON_COMMAND_AUDIO_STREAM_START_H_ diff --git a/daemon/commands/audio-stream-stats.h b/daemon/commands/audio-stream-stats.h index f63fbb17c..72e93fedd 100644 --- a/daemon/commands/audio-stream-stats.h +++ b/daemon/commands/audio-stream-stats.h @@ -1,6 +1,6 @@ /* audio-stream-stats.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AudioStreamStatsCommand: public DaemonCommand { public: AudioStreamStatsCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string &args) override; }; #endif // LINPHONE_DAEMON_COMMAND_AUDIO_STREAM_STATS_H_ diff --git a/daemon/commands/audio-stream-stop.h b/daemon/commands/audio-stream-stop.h index 44dd7166d..ad2d0c051 100644 --- a/daemon/commands/audio-stream-stop.h +++ b/daemon/commands/audio-stream-stop.h @@ -1,6 +1,6 @@ /* audio-stream-stop.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AudioStreamStopCommand: public DaemonCommand { public: AudioStreamStopCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_AUDIO_STREAM_STOP_H_ diff --git a/daemon/commands/auth-infos-clear.h b/daemon/commands/auth-infos-clear.h index 35df2165a..59a53be78 100644 --- a/daemon/commands/auth-infos-clear.h +++ b/daemon/commands/auth-infos-clear.h @@ -1,6 +1,6 @@ /* auth-infos-clear.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class AuthInfosClearCommand: public DaemonCommand { public: AuthInfosClearCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_AUTH_INFOS_CLEAR_H_ diff --git a/daemon/commands/call-mute.h b/daemon/commands/call-mute.h index bab2fe128..993f9a989 100644 --- a/daemon/commands/call-mute.h +++ b/daemon/commands/call-mute.h @@ -1,6 +1,6 @@ /* call-mute.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -26,7 +26,8 @@ class CallMuteCommand : public DaemonCommand { public: CallMuteCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CALL_MUTE_H diff --git a/daemon/commands/call-pause.h b/daemon/commands/call-pause.h index 7fbb6177d..e0d96063f 100644 --- a/daemon/commands/call-pause.h +++ b/daemon/commands/call-pause.h @@ -1,6 +1,6 @@ /* call-pause.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -26,7 +26,8 @@ class CallPauseCommand : public DaemonCommand { public: CallPauseCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CALL_PAUSE_H diff --git a/daemon/commands/call-resume.h b/daemon/commands/call-resume.h index 03ac2ae85..6c08c2856 100644 --- a/daemon/commands/call-resume.h +++ b/daemon/commands/call-resume.h @@ -1,6 +1,6 @@ /* call-resume.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -26,7 +26,8 @@ class CallResumeCommand : public DaemonCommand { public: CallResumeCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CALL_RESUME_H diff --git a/daemon/commands/call-stats.h b/daemon/commands/call-stats.h index 465e38495..27814ec1b 100644 --- a/daemon/commands/call-stats.h +++ b/daemon/commands/call-stats.h @@ -1,6 +1,6 @@ /* call-stats.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class CallStatsCommand: public DaemonCommand { public: CallStatsCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CALL_STATS_H_ diff --git a/daemon/commands/call-status.h b/daemon/commands/call-status.h index df5989998..308ee1823 100644 --- a/daemon/commands/call-status.h +++ b/daemon/commands/call-status.h @@ -1,6 +1,6 @@ /* call-status.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class CallStatusCommand: public DaemonCommand { public: CallStatusCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CALL_STATUS_H_ diff --git a/daemon/commands/call-transfer.cc b/daemon/commands/call-transfer.cc index fbb41042a..e7d3f9e24 100644 --- a/daemon/commands/call-transfer.cc +++ b/daemon/commands/call-transfer.cc @@ -1,6 +1,6 @@ /* call-transfer.cc -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -85,7 +85,7 @@ void CallTransferCommand::exec(Daemon* app, const string& args) return; } if (linphone_call_transfer_to_another(call_to_transfer, call_to_transfer_to) == 0) { - std::ostringstream ostr; + ostringstream ostr; ostr << "Call ID: " << call_to_transfer_id << "\n"; ostr << "Transfer to: " << call_to_transfer_to_id << "\n"; app->sendResponse(Response(ostr.str(), Response::Ok)); @@ -93,7 +93,7 @@ void CallTransferCommand::exec(Daemon* app, const string& args) } } else { if (linphone_call_transfer(call_to_transfer, sip_uri_to_transfer_to.c_str()) == 0) { - std::ostringstream ostr; + ostringstream ostr; ostr << "Call ID: " << call_to_transfer_id << "\n"; ostr << "Transfer to: " << sip_uri_to_transfer_to << "\n"; app->sendResponse(Response(ostr.str(), Response::Ok)); diff --git a/daemon/commands/call-transfer.h b/daemon/commands/call-transfer.h index c0c0d977b..83e93d0c9 100644 --- a/daemon/commands/call-transfer.h +++ b/daemon/commands/call-transfer.h @@ -1,6 +1,6 @@ /* call-transfer.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -26,7 +26,8 @@ class CallTransferCommand : public DaemonCommand { public: CallTransferCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CALL_TRANSFER_H diff --git a/daemon/commands/call.h b/daemon/commands/call.h index e2cf8700e..881ad144e 100644 --- a/daemon/commands/call.h +++ b/daemon/commands/call.h @@ -1,6 +1,6 @@ /* call.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class CallCommand: public DaemonCommand { public: CallCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CALL_H_ diff --git a/daemon/commands/cn.h b/daemon/commands/cn.h index 6e625bea8..9b46c6cd6 100644 --- a/daemon/commands/cn.h +++ b/daemon/commands/cn.h @@ -1,6 +1,6 @@ /* cn.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class CNCommand: public DaemonCommand { public: CNCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CN_H_ diff --git a/daemon/commands/conference.cc b/daemon/commands/conference.cc index a4929f72c..6d1c83c93 100644 --- a/daemon/commands/conference.cc +++ b/daemon/commands/conference.cc @@ -1,6 +1,6 @@ /* conference.cc -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -79,7 +79,7 @@ void ConferenceCommand::exec(Daemon* app, const string& args) { } if (ret == 0) { - std::ostringstream ostr; + ostringstream ostr; ostr << "Call ID: " << id << "\n"; ostr << "Conference: " << subcommand << " OK" << "\n"; app->sendResponse(Response(ostr.str(), Response::Ok)); diff --git a/daemon/commands/conference.h b/daemon/commands/conference.h index c9d0719ee..cbf1cbe4b 100644 --- a/daemon/commands/conference.h +++ b/daemon/commands/conference.h @@ -1,6 +1,6 @@ /* conference.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -26,7 +26,8 @@ class ConferenceCommand : public DaemonCommand { public: ConferenceCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CONFERENCE_H diff --git a/daemon/commands/configcommand.h b/daemon/commands/configcommand.h index 6a138b900..36feb749e 100644 --- a/daemon/commands/configcommand.h +++ b/daemon/commands/configcommand.h @@ -1,6 +1,6 @@ /* configcommand.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,13 +25,15 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class ConfigGetCommand: public DaemonCommand { public: ConfigGetCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; class ConfigSetCommand: public DaemonCommand { public: ConfigSetCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CONFIG_H_ diff --git a/daemon/commands/contact.h b/daemon/commands/contact.h index 057472b94..4b2def6d6 100644 --- a/daemon/commands/contact.h +++ b/daemon/commands/contact.h @@ -1,6 +1,6 @@ /* contact.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class ContactCommand: public DaemonCommand { public: ContactCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_CONTACT_H_ diff --git a/daemon/commands/dtmf.h b/daemon/commands/dtmf.h index 96d52298d..ca9104b47 100644 --- a/daemon/commands/dtmf.h +++ b/daemon/commands/dtmf.h @@ -1,6 +1,6 @@ /* dtmf.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class DtmfCommand: public DaemonCommand { public: DtmfCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_DTMF_H_ diff --git a/daemon/commands/firewall-policy.h b/daemon/commands/firewall-policy.h index a19d1dfd1..475064692 100644 --- a/daemon/commands/firewall-policy.h +++ b/daemon/commands/firewall-policy.h @@ -1,6 +1,6 @@ /* firewall-policy.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class FirewallPolicyCommand: public DaemonCommand { public: FirewallPolicyCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_FIREWALL_POLICY_H_ diff --git a/daemon/commands/help.h b/daemon/commands/help.h index 6e18fd1b5..826e610f9 100644 --- a/daemon/commands/help.h +++ b/daemon/commands/help.h @@ -1,6 +1,6 @@ /* help.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class HelpCommand: public DaemonCommand { public: HelpCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_HELP_H_ diff --git a/daemon/commands/ipv6.h b/daemon/commands/ipv6.h index 31ef4899b..e3ea1e29f 100644 --- a/daemon/commands/ipv6.h +++ b/daemon/commands/ipv6.h @@ -1,6 +1,6 @@ /* ipv6.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class IPv6Command: public DaemonCommand { public: IPv6Command(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_IPV6_H_ diff --git a/daemon/commands/jitterbuffer.cc b/daemon/commands/jitterbuffer.cc index 335f7bdb2..99dee451b 100644 --- a/daemon/commands/jitterbuffer.cc +++ b/daemon/commands/jitterbuffer.cc @@ -124,9 +124,11 @@ void JitterBufferResetCommand::exec(Daemon *app, const string& args) { } istr >> streamtype; if (streamtype == "video") { - rtprecv = call->videostream ? call->videostream->ms.rtprecv : NULL; + VideoStream *vstream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeVideo)); + rtprecv = vstream ? vstream->ms.rtprecv : NULL; } else { - rtprecv = call->audiostream ? call->audiostream->ms.rtprecv : NULL; + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + rtprecv = astream ? astream->ms.rtprecv : NULL; } } else { AudioStream *stream = app->findAudioStream(arg2); diff --git a/daemon/commands/jitterbuffer.h b/daemon/commands/jitterbuffer.h index 76855e0aa..2ea34511a 100644 --- a/daemon/commands/jitterbuffer.h +++ b/daemon/commands/jitterbuffer.h @@ -1,6 +1,6 @@ /* jitterbuffer.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,15 +25,17 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class JitterBufferCommand : public DaemonCommand{ public: - JitterBufferCommand(); - virtual void exec(Daemon *app, const std::string& args); + JitterBufferCommand(); + + void exec(Daemon *app, const std::string& args) override; }; class JitterBufferResetCommand : public DaemonCommand{ public: - JitterBufferResetCommand(); - virtual void exec(Daemon *app, const std::string& args); + JitterBufferResetCommand(); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_JITTER_BUFFER_H diff --git a/daemon/commands/media-encryption.h b/daemon/commands/media-encryption.h index 7a35d0c27..ddd531a42 100644 --- a/daemon/commands/media-encryption.h +++ b/daemon/commands/media-encryption.h @@ -1,6 +1,6 @@ /* media-encryption.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class MediaEncryptionCommand: public DaemonCommand { public: MediaEncryptionCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_MEDIA_ENCRYPTION_H_ diff --git a/daemon/commands/msfilter-add-fmtp.cc b/daemon/commands/msfilter-add-fmtp.cc index afce5a513..d9aba9e55 100644 --- a/daemon/commands/msfilter-add-fmtp.cc +++ b/daemon/commands/msfilter-add-fmtp.cc @@ -54,11 +54,12 @@ void MSFilterAddFmtpCommand::exec(Daemon *app, const string& args) { app->sendResponse(Response("No Call with such id.")); return; } - if (call->audiostream == NULL || call->audiostream->ms.encoder == NULL) { + AudioStream *astream = reinterpret_cast(linphone_call_get_stream(call, LinphoneStreamTypeAudio)); + if (astream == NULL || astream->ms.encoder == NULL) { app->sendResponse(Response("This call doesn't have an active audio stream.")); return; } - ms_filter_call_method(call->audiostream->ms.encoder, MS_FILTER_ADD_FMTP, (void *)fmtp.c_str()); + ms_filter_call_method(astream->ms.encoder, MS_FILTER_ADD_FMTP, (void *)fmtp.c_str()); } else if (type.compare("stream") == 0) { AudioStream *stream = app->findAudioStream(id); if (stream == NULL) { diff --git a/daemon/commands/msfilter-add-fmtp.h b/daemon/commands/msfilter-add-fmtp.h index ecb2969ec..c9a3d3270 100644 --- a/daemon/commands/msfilter-add-fmtp.h +++ b/daemon/commands/msfilter-add-fmtp.h @@ -1,6 +1,6 @@ /* msfilter-add-fmtp.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class MSFilterAddFmtpCommand : public DaemonCommand { public: MSFilterAddFmtpCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_MSFILTER_ADD_FMTP diff --git a/daemon/commands/netsim.cc b/daemon/commands/netsim.cc index d2678d188..21d543c5a 100644 --- a/daemon/commands/netsim.cc +++ b/daemon/commands/netsim.cc @@ -96,7 +96,7 @@ void NetsimCommand::exec(Daemon* app, const string& args) { params.loss_rate = (float)atoi(value); } if (fmtp_get_value(parameters.c_str(), "latency", value, sizeof(value))) { - params.latency = atoi(value); + params.latency = (uint32_t)atoi(value); } if (fmtp_get_value(parameters.c_str(), "consecutive_loss_probability", value, sizeof(value))) { params.consecutive_loss_probability = (float)atof(value); diff --git a/daemon/commands/netsim.h b/daemon/commands/netsim.h index e6b147c63..dcedc43e9 100644 --- a/daemon/commands/netsim.h +++ b/daemon/commands/netsim.h @@ -1,6 +1,6 @@ /* netsim.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class NetsimCommand: public DaemonCommand { public: NetsimCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_NETSIM_H_ diff --git a/daemon/commands/play-wav.h b/daemon/commands/play-wav.h index 19a245205..dd9180560 100644 --- a/daemon/commands/play-wav.h +++ b/daemon/commands/play-wav.h @@ -1,6 +1,6 @@ /* play-wav.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class PlayWavCommand: public DaemonCommand { public: PlayWavCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_PLAY_WAV_H_ diff --git a/daemon/commands/play.cc b/daemon/commands/play.cc index 736919954..f60ae7198 100644 --- a/daemon/commands/play.cc +++ b/daemon/commands/play.cc @@ -90,7 +90,7 @@ void IncallPlayerStartCommand::exec(Daemon *app, const string& args) { pair *callPlayingData = (pair *)linphone_player_get_user_data(p); if(callPlayingData) callPlayingData = new pair({ - VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)), + VOIDPTR_TO_INT(linphone_call_get_user_data(call)), app }); linphone_player_set_user_data(p, callPlayingData); diff --git a/daemon/commands/play.h b/daemon/commands/play.h index e8787e71b..ad746dea8 100644 --- a/daemon/commands/play.h +++ b/daemon/commands/play.h @@ -25,7 +25,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class IncallPlayerStartCommand: public DaemonCommand { public: IncallPlayerStartCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec (Daemon *app, const std::string& args) override; + private: static void onEof(LinphonePlayer *player); }; @@ -33,18 +35,21 @@ private: class IncallPlayerStopCommand: public DaemonCommand { public: IncallPlayerStopCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec (Daemon *app, const std::string& args) override; }; class IncallPlayerPauseCommand: public DaemonCommand { public: IncallPlayerPauseCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec (Daemon *app, const std::string& args) override; }; class IncallPlayerResumeCommand: public DaemonCommand { public: IncallPlayerResumeCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec (Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_PLAY_H_ diff --git a/daemon/commands/pop-event.h b/daemon/commands/pop-event.h index 66a3a8489..e05f7c67e 100644 --- a/daemon/commands/pop-event.h +++ b/daemon/commands/pop-event.h @@ -1,6 +1,6 @@ /* pop-event.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class PopEventCommand: public DaemonCommand { public: PopEventCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_POP_EVENT_H_ diff --git a/daemon/commands/port.h b/daemon/commands/port.h index 465a087e3..99c698fcc 100644 --- a/daemon/commands/port.h +++ b/daemon/commands/port.h @@ -1,6 +1,6 @@ /* port.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class PortCommand: public DaemonCommand { public: PortCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_PORT_H_ diff --git a/daemon/commands/ptime.h b/daemon/commands/ptime.h index a54a17cd6..03a390e90 100644 --- a/daemon/commands/ptime.h +++ b/daemon/commands/ptime.h @@ -1,6 +1,6 @@ /* ptime.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class PtimeCommand: public DaemonCommand { public: PtimeCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_PTIME_H_ diff --git a/daemon/commands/quit.h b/daemon/commands/quit.h index 99bf5f49a..3ff30d890 100644 --- a/daemon/commands/quit.h +++ b/daemon/commands/quit.h @@ -1,6 +1,6 @@ /* quit.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class QuitCommand: public DaemonCommand { public: QuitCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_QUIT_H_ diff --git a/daemon/commands/register-info.cc b/daemon/commands/register-info.cc index 10ea5c2b2..da1cb58d7 100644 --- a/daemon/commands/register-info.cc +++ b/daemon/commands/register-info.cc @@ -21,6 +21,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include "register-info.h" +using namespace std; + class RegisterInfoResponse: public Response { public: RegisterInfoResponse(): Response() {} @@ -28,19 +30,19 @@ public: append(id, cfg); } void append(int id, const ::LinphoneProxyConfig *cfg) { - std::ostringstream ost; + ostringstream ost; ost << getBody(); - if (ost.tellp() > 0) ost << std::endl; - ost << "Id: " << id << std::endl; - ost << "Identity: " << linphone_proxy_config_get_identity(cfg) << std::endl; - ost << "Proxy: " << linphone_proxy_config_get_server_addr(cfg) << std::endl; + if (ost.tellp() > 0) ost << endl; + ost << "Id: " << id << endl; + ost << "Identity: " << linphone_proxy_config_get_identity(cfg) << endl; + ost << "Proxy: " << linphone_proxy_config_get_server_addr(cfg) << endl; const char *route = linphone_proxy_config_get_route(cfg); if (route != NULL) { - ost << "Route: " << route << std::endl; + ost << "Route: " << route << endl; } - ost << "State: " << linphone_registration_state_to_string(linphone_proxy_config_get_state(cfg)) << std::endl; + ost << "State: " << linphone_registration_state_to_string(linphone_proxy_config_get_state(cfg)) << endl; setBody(ost.str()); } }; @@ -72,9 +74,9 @@ RegisterInfoCommand::RegisterInfoCommand(): "Reason: No register with such id.")); } -void RegisterInfoCommand::exec(Daemon *app, const std::string& args) { - std::string param; - std::istringstream ist(args); +void RegisterInfoCommand::exec(Daemon *app, const string& args) { + string param; + istringstream ist(args); ist >> param; if (ist.fail()) { app->sendResponse(Response("Missing parameter.", Response::Error)); @@ -93,10 +95,10 @@ void RegisterInfoCommand::exec(Daemon *app, const std::string& args) { int id; try { id = atoi(param.c_str()); - } catch (const std::invalid_argument &) { + } catch (invalid_argument&) { app->sendResponse(Response("Invalid ID.", Response::Error)); return; - } catch (const std::out_of_range &) { + } catch (out_of_range&) { app->sendResponse(Response("Out of range ID.", Response::Error)); return; } diff --git a/daemon/commands/register-info.h b/daemon/commands/register-info.h index e6b437a57..cdbbaf663 100644 --- a/daemon/commands/register-info.h +++ b/daemon/commands/register-info.h @@ -1,6 +1,6 @@ /* register-info.h -Copyright (C) 2017 Belledonne Communications, Grenoble, France +Copyright (C) 2017 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -26,7 +26,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class RegisterInfoCommand: public DaemonCommand { public: RegisterInfoCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_REGISTER_INFO_H_ diff --git a/daemon/commands/register-status.h b/daemon/commands/register-status.h index 5e19cbe14..ce8bbbf57 100644 --- a/daemon/commands/register-status.h +++ b/daemon/commands/register-status.h @@ -1,6 +1,6 @@ /* register-status.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class RegisterStatusCommand: public DaemonCommand { public: RegisterStatusCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_REGISTER_STATUS_H_ diff --git a/daemon/commands/register.h b/daemon/commands/register.h index c29a17f2b..f7b2f4e05 100644 --- a/daemon/commands/register.h +++ b/daemon/commands/register.h @@ -1,6 +1,6 @@ /* register.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class RegisterCommand: public DaemonCommand { public: RegisterCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_REGISTER_H_ diff --git a/daemon/commands/terminate.h b/daemon/commands/terminate.h index 5733d3f21..0d58ebc59 100644 --- a/daemon/commands/terminate.h +++ b/daemon/commands/terminate.h @@ -1,6 +1,6 @@ /* terminate.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class TerminateCommand: public DaemonCommand { public: TerminateCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_TERMINATE_H_ diff --git a/daemon/commands/unregister.h b/daemon/commands/unregister.h index 09dd5521c..62f34ee87 100644 --- a/daemon/commands/unregister.h +++ b/daemon/commands/unregister.h @@ -1,6 +1,6 @@ /* unregister.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class UnregisterCommand: public DaemonCommand { public: UnregisterCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_UNREGISTER_H_ diff --git a/daemon/commands/version.h b/daemon/commands/version.h index 18c897b8c..76a6d81d0 100644 --- a/daemon/commands/version.h +++ b/daemon/commands/version.h @@ -1,6 +1,6 @@ /* version.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -25,7 +25,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA class VersionCommand: public DaemonCommand { public: VersionCommand(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_VERSION_H_ diff --git a/daemon/commands/video.cc b/daemon/commands/video.cc index 2b92a8db8..99679f7a4 100644 --- a/daemon/commands/video.cc +++ b/daemon/commands/video.cc @@ -1,6 +1,6 @@ /* video.cc -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -162,7 +162,7 @@ AutoVideo::AutoVideo(): "Auto video OFF")); } -void AutoVideo::exec(Daemon* app, const std::string& args) +void AutoVideo::exec(Daemon* app, const string& args) { bool enable = (args.compare("on") == 0); diff --git a/daemon/commands/video.h b/daemon/commands/video.h index b45688817..a971a2360 100644 --- a/daemon/commands/video.h +++ b/daemon/commands/video.h @@ -1,6 +1,6 @@ /* video.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -26,7 +26,8 @@ class Video : public DaemonCommand { public: Video(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; @@ -34,14 +35,16 @@ class VideoSource : public DaemonCommand { public: VideoSource(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; class AutoVideo : public DaemonCommand { public: AutoVideo(); - virtual void exec(Daemon *app, const std::string& args); + + void exec(Daemon *app, const std::string& args) override; }; #endif // LINPHONE_DAEMON_COMMAND_VIDEO_H diff --git a/daemon/daemon-pipetest.c b/daemon/daemon-pipetest.c index 625312c14..f3fa70c24 100644 --- a/daemon/daemon-pipetest.c +++ b/daemon/daemon-pipetest.c @@ -1,6 +1,6 @@ /* daemon-pipetest.c -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -79,7 +79,7 @@ int main(int argc, char *argv[]){ SetConsoleMode(hin, fdwOldMode); #else struct pollfd pfds[2] = { { 0 } }; - int bytes; + ssize_t bytes; pfds[0].fd=fd; pfds[0].events=POLLIN; pfds[1].fd=1; @@ -91,11 +91,11 @@ int main(int argc, char *argv[]){ /*splice to stdout*/ if (pfds[0].revents & POLLIN){ if ((bytes=read(pfds[0].fd,buf,sizeof(buf)))>0){ - if (write(0,buf,bytes)==-1){ + if (write(0,buf,(size_t)bytes)==-1){ ortp_error("Fail to write to stdout?"); break; } - fprintf(stdout,"\n"); + fprintf(stdout,"\n"); }else if (bytes==0){ break; } @@ -103,10 +103,10 @@ int main(int argc, char *argv[]){ /*splice from stdin to pipe */ if (pfds[1].revents & POLLIN){ if ((bytes=read(pfds[1].fd,buf,sizeof(buf)))>0){ - if (write(pfds[0].fd,buf,bytes)==-1){ + if (write(pfds[0].fd,buf,(size_t)bytes)==-1){ ortp_error("Fail to write to unix socket"); break; - } + } }else if (bytes==0){ break; } @@ -117,4 +117,3 @@ int main(int argc, char *argv[]){ return 0; } - diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 9cb576037..3b4d5d06c 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -1,6 +1,6 @@ /* daemon.cc -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by @@ -127,7 +127,7 @@ void *Daemon::iterateThread(void *arg) { EventResponse::EventResponse(Daemon *daemon, LinphoneCall *call, LinphoneCallState state) { LinphoneCallLog *callLog = linphone_call_get_call_log(call); - LinphoneAddress *fromAddr = linphone_call_log_get_from_address(callLog); + const LinphoneAddress *fromAddr = linphone_call_log_get_from_address(callLog); char *fromStr = linphone_address_as_string(fromAddr); ostringstream ostr; @@ -177,19 +177,19 @@ CallStatsResponse::CallStatsResponse(Daemon *daemon, LinphoneCall *call, const L ostr << "Event-type: call-stats\n"; ostr << "Id: " << daemon->updateCallId(call) << "\n"; ostr << "Type: "; - if (stats->type == LINPHONE_CALL_STATS_AUDIO) { + if (linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) { ostr << "Audio"; } else { ostr << "Video"; } ostr << "\n"; } else { - prefix = ((stats->type == LINPHONE_CALL_STATS_AUDIO) ? "Audio-" : "Video-"); + prefix = ((linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) ? "Audio-" : "Video-"); } printCallStatsHelper(ostr, stats, prefix); - if (stats->type == LINPHONE_CALL_STATS_AUDIO) { + if (linphone_call_stats_get_type(stats) == LINPHONE_CALL_STATS_AUDIO) { const PayloadType *audioCodec = linphone_call_params_get_used_audio_codec(callParams); ostr << PayloadTypeResponse(linphone_call_get_core(call), audioCodec, -1, prefix, false).getBody() << "\n"; } else { @@ -351,11 +351,11 @@ Daemon::Daemon(const char *config_path, const char *factory_config_path, const c linphone_core_set_user_data(mLc, this); linphone_core_enable_video_capture(mLc,capture_video); linphone_core_enable_video_display(mLc,display_video); - + for(const bctbx_list_t *proxy = linphone_core_get_proxy_config_list(mLc); proxy != NULL; proxy = bctbx_list_next(proxy)) { updateProxyId((LinphoneProxyConfig *)bctbx_list_get_data(proxy)); } - + initCommands(); mUseStatsEvents=true; } @@ -373,9 +373,9 @@ LinphoneSoundDaemon *Daemon::getLSD() { } int Daemon::updateCallId(LinphoneCall *call) { - int val = VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)); + int val = VOIDPTR_TO_INT(linphone_call_get_user_data(call)); if (val == 0) { - linphone_call_set_user_pointer(call, INT_TO_VOIDPTR(++mCallIds)); + linphone_call_set_user_data(call, INT_TO_VOIDPTR(++mCallIds)); return mCallIds; } return val; @@ -385,7 +385,7 @@ LinphoneCall *Daemon::findCall(int id) { const bctbx_list_t *elem = linphone_core_get_calls(mLc); for (; elem != NULL; elem = elem->next) { LinphoneCall *call = (LinphoneCall *) elem->data; - if (VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)) == id) + if (VOIDPTR_TO_INT(linphone_call_get_user_data(call)) == id) return call; } return NULL; @@ -423,7 +423,7 @@ LinphoneAuthInfo *Daemon::findAuthInfo(int id) { } int Daemon::updateAudioStreamId(AudioStream *audio_stream) { - for (std::map::iterator it = mAudioStreams.begin(); it != mAudioStreams.end(); ++it) { + for (map::iterator it = mAudioStreams.begin(); it != mAudioStreams.end(); ++it) { if (it->second->stream == audio_stream) return it->first; } @@ -434,21 +434,21 @@ int Daemon::updateAudioStreamId(AudioStream *audio_stream) { } AudioStreamAndOther *Daemon::findAudioStreamAndOther(int id) { - std::map::iterator it = mAudioStreams.find(id); + map::iterator it = mAudioStreams.find(id); if (it != mAudioStreams.end()) return it->second; return NULL; } AudioStream *Daemon::findAudioStream(int id) { - std::map::iterator it = mAudioStreams.find(id); + map::iterator it = mAudioStreams.find(id); if (it != mAudioStreams.end()) return it->second->stream; return NULL; } void Daemon::removeAudioStream(int id) { - std::map::iterator it = mAudioStreams.find(id); + map::iterator it = mAudioStreams.find(id); if (it != mAudioStreams.end()) { mAudioStreams.erase(it); delete(it->second); @@ -546,7 +546,7 @@ void Daemon::callStateChanged(LinphoneCall *call, LinphoneCallState state, const void Daemon::callStatsUpdated(LinphoneCall *call, const LinphoneCallStats *stats) { if (mUseStatsEvents) { /* don't queue periodical updates (3 per seconds for just bandwidth updates) */ - if (!(stats->updated & LINPHONE_CALL_STATS_PERIODICAL_UPDATE)){ + if (!(_linphone_call_stats_get_updated(stats) & LINPHONE_CALL_STATS_PERIODICAL_UPDATE)){ mEventQueue.push(new CallStatsResponse(this, call, stats, true)); } } @@ -574,7 +574,7 @@ void Daemon::dtmfReceived(LinphoneCore *lc, LinphoneCall *call, int dtmf) { } void Daemon::iterateStreamStats() { - for (std::map::iterator it = mAudioStreams.begin(); it != mAudioStreams.end(); ++it) { + for (map::iterator it = mAudioStreams.begin(); it != mAudioStreams.end(); ++it) { OrtpEvent *ev; while (it->second->queue && (NULL != (ev=ortp_ev_queue_get(it->second->queue)))){ OrtpEventType evt=ortp_event_get_type(ev); @@ -667,7 +667,7 @@ string Daemon::readPipe() { pfd[1].fd = mChildFd; nfds++; } - int err = poll(pfd, nfds, 50); + int err = poll(pfd, (nfds_t)nfds, 50); if (err > 0) { if (mServerFd != (ortp_pipe_t)-1 && (pfd[0].revents & POLLIN)) { struct sockaddr_storage addr; @@ -762,7 +762,7 @@ void Daemon::dumpCommandsHelpHtml(){ cout<<"

"<<"Description"<<"

"<"<getDescription())<<"

"<"<<"Examples"<<""< &examples=(*it)->getExamples(); + const list &examples=(*it)->getExamples(); cout<<"

"; for(list::const_iterator ex_it=examples.begin();ex_it!=examples.end();++ex_it){ cout<<""<")<getCommand())<<"
"<::max(), '\n'); + cin.ignore(numeric_limits::max(), '\n'); return outbuf.str(); #endif } @@ -888,7 +888,7 @@ void Daemon::enableLSD(bool enabled) { Daemon::~Daemon() { uninitCommands(); - for (std::map::iterator it = mAudioStreams.begin(); it != mAudioStreams.end(); ++it) { + for (map::iterator it = mAudioStreams.begin(); it != mAudioStreams.end(); ++it) { audio_stream_stop(it->second->stream); } diff --git a/daemon/daemon.h b/daemon/daemon.h index 4aad4de88..195ff1317 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -1,6 +1,6 @@ /* daemon.h -Copyright (C) 2016 Belledonne Communications, Grenoble, France +Copyright (C) 2016 Belledonne Communications, Grenoble, France This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by diff --git a/gen-gtkfilelist.sh b/gen-gtkfilelist.sh deleted file mode 100755 index 095c4979c..000000000 --- a/gen-gtkfilelist.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -# this script is used to generate a file list of gtk+ files necessary for -# execution. This is useful for generating linphone packages. -# It must be run within a gtk+ binary bundle tree, such as in the zip bundle -# downloadable from www.gtk.org -echo bin -find bin -name *.dll -find lib/gtk-2.0 -find etc -find share/locale/cs -find share/locale/de -find share/locale/es -find share/locale/fr -find share/locale/he -find share/locale/hu -find share/locale/it -find share/locale/ja -find share/locale/nb -find share/locale/nl -find share/locale/pl -find share/locale/pt -find share/locale/pt_BR -find share/locale/ru -find share/locale/sr -find share/locale/sv -find share/locale/zh_CN -find share/locale/zh_TW -find share/themes diff --git a/gtk+-2.16.2.filelist b/gtk+-2.16.2.filelist deleted file mode 100755 index 10e10a515..000000000 --- a/gtk+-2.16.2.filelist +++ /dev/null @@ -1,165 +0,0 @@ -bin -bin/libglade-2.0-0.dll -bin/intl.dll -bin/jpeg62.dll -bin/libasprintf-0.dll -bin/libatk-1.0-0.dll -bin/libcairo-2.dll -bin/libgailutil-18.dll -bin/libgdk-win32-2.0-0.dll -bin/libgdk_pixbuf-2.0-0.dll -bin/libgettextlib-0-17.dll -bin/libgettextpo-0.dll -bin/libgettextsrc-0-17.dll -bin/libgio-2.0-0.dll -bin/libglib-2.0-0.dll -bin/libgmodule-2.0-0.dll -bin/libgobject-2.0-0.dll -bin/libgthread-2.0-0.dll -bin/libgtk-win32-2.0-0.dll -bin/libpango-1.0-0.dll -bin/libpangocairo-1.0-0.dll -bin/libpangoft2-1.0-0.dll -bin/libpangowin32-1.0-0.dll -bin/libpng12-0.dll -bin/libtiff3.dll -bin/zlib1.dll -lib/gtk-2.0 -lib/gtk-2.0/2.10.0 -lib/gtk-2.0/2.10.0/engines -lib/gtk-2.0/2.10.0/engines/libpixmap.dll -lib/gtk-2.0/2.10.0/engines/libwimp.dll -lib/gtk-2.0/2.10.0/loaders -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ani.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-bmp.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-gif.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-icns.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ico.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-jpeg.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-pcx.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-png.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-pnm.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ras.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-tga.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-tiff.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-wbmp.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-xbm.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-xpm.dll -lib/gtk-2.0/include -lib/gtk-2.0/include/gdkconfig.h -lib/gtk-2.0/modules -lib/gtk-2.0/modules/libgail.dll -etc -etc/gtk-2.0 -etc/gtk-2.0/gdk-pixbuf.loaders -etc/gtk-2.0/gtk.immodules -etc/gtk-2.0/im-multipress.conf -etc/pango -etc/pango/pango.modules -share/locale/fr -share/locale/fr/LC_MESSAGES -share/locale/fr/LC_MESSAGES/atk10.mo -share/locale/fr/LC_MESSAGES/gettext-runtime.mo -share/locale/fr/LC_MESSAGES/gettext-tools.mo -share/locale/fr/LC_MESSAGES/glib20.mo -share/locale/fr/LC_MESSAGES/gtk20-properties.mo -share/locale/fr/LC_MESSAGES/gtk20.mo -share/locale/de -share/locale/de/LC_MESSAGES -share/locale/de/LC_MESSAGES/atk10.mo -share/locale/de/LC_MESSAGES/gettext-runtime.mo -share/locale/de/LC_MESSAGES/gettext-tools.mo -share/locale/de/LC_MESSAGES/glib20.mo -share/locale/de/LC_MESSAGES/gtk20-properties.mo -share/locale/de/LC_MESSAGES/gtk20.mo -share/locale/sv -share/locale/sv/LC_MESSAGES -share/locale/sv/LC_MESSAGES/atk10.mo -share/locale/sv/LC_MESSAGES/gettext-runtime.mo -share/locale/sv/LC_MESSAGES/gettext-tools.mo -share/locale/sv/LC_MESSAGES/glib20.mo -share/locale/sv/LC_MESSAGES/gtk20-properties.mo -share/locale/sv/LC_MESSAGES/gtk20.mo -share/locale/cs -share/locale/cs/LC_MESSAGES -share/locale/cs/LC_MESSAGES/atk10.mo -share/locale/cs/LC_MESSAGES/gettext-runtime.mo -share/locale/cs/LC_MESSAGES/gettext-tools.mo -share/locale/cs/LC_MESSAGES/glib20.mo -share/locale/cs/LC_MESSAGES/gtk20-properties.mo -share/locale/cs/LC_MESSAGES/gtk20.mo -share/locale/es -share/locale/es/LC_MESSAGES -share/locale/es/LC_MESSAGES/atk10.mo -share/locale/es/LC_MESSAGES/gettext-runtime.mo -share/locale/es/LC_MESSAGES/gettext-tools.mo -share/locale/es/LC_MESSAGES/glib20.mo -share/locale/es/LC_MESSAGES/gtk20-properties.mo -share/locale/es/LC_MESSAGES/gtk20.mo -share/locale/hu -share/locale/hu/LC_MESSAGES -share/locale/hu/LC_MESSAGES/atk10.mo -share/locale/hu/LC_MESSAGES/glib20.mo -share/locale/hu/LC_MESSAGES/gtk20-properties.mo -share/locale/hu/LC_MESSAGES/gtk20.mo -share/locale/it -share/locale/it/LC_MESSAGES -share/locale/it/LC_MESSAGES/atk10.mo -share/locale/it/LC_MESSAGES/gettext-runtime.mo -share/locale/it/LC_MESSAGES/gettext-tools.mo -share/locale/it/LC_MESSAGES/glib20.mo -share/locale/it/LC_MESSAGES/gtk20-properties.mo -share/locale/it/LC_MESSAGES/gtk20.mo -share/locale/ja -share/locale/ja/LC_MESSAGES -share/locale/ja/LC_MESSAGES/atk10.mo -share/locale/ja/LC_MESSAGES/gettext-runtime.mo -share/locale/ja/LC_MESSAGES/gettext-tools.mo -share/locale/ja/LC_MESSAGES/glib20.mo -share/locale/ja/LC_MESSAGES/gtk20-properties.mo -share/locale/ja/LC_MESSAGES/gtk20.mo -share/locale/nl -share/locale/nl/LC_MESSAGES -share/locale/nl/LC_MESSAGES/atk10.mo -share/locale/nl/LC_MESSAGES/gettext-runtime.mo -share/locale/nl/LC_MESSAGES/gettext-tools.mo -share/locale/nl/LC_MESSAGES/glib20.mo -share/locale/nl/LC_MESSAGES/gtk20-properties.mo -share/locale/nl/LC_MESSAGES/gtk20.mo -share/locale/pl -share/locale/pl/LC_MESSAGES -share/locale/pl/LC_MESSAGES/atk10.mo -share/locale/pl/LC_MESSAGES/gettext-runtime.mo -share/locale/pl/LC_MESSAGES/gettext-tools.mo -share/locale/pl/LC_MESSAGES/glib20.mo -share/locale/pl/LC_MESSAGES/gtk20-properties.mo -share/locale/pl/LC_MESSAGES/gtk20.mo -share/locale/ru -share/locale/ru/LC_MESSAGES -share/locale/ru/LC_MESSAGES/atk10.mo -share/locale/ru/LC_MESSAGES/gettext-runtime.mo -share/locale/ru/LC_MESSAGES/gettext-tools.mo -share/locale/ru/LC_MESSAGES/glib20.mo -share/locale/ru/LC_MESSAGES/gtk20-properties.mo -share/locale/ru/LC_MESSAGES/gtk20.mo -share/locale/pt_BR -share/locale/pt_BR/LC_MESSAGES -share/locale/pt_BR/LC_MESSAGES/atk10.mo -share/locale/pt_BR/LC_MESSAGES/gettext-runtime.mo -share/locale/pt_BR/LC_MESSAGES/gettext-tools.mo -share/locale/pt_BR/LC_MESSAGES/glib20.mo -share/locale/pt_BR/LC_MESSAGES/gtk20-properties.mo -share/locale/pt_BR/LC_MESSAGES/gtk20.mo -share/themes -share/themes/Default -share/themes/Default/gtk-2.0-key -share/themes/Default/gtk-2.0-key/gtkrc -share/themes/Emacs -share/themes/Emacs/gtk-2.0-key -share/themes/Emacs/gtk-2.0-key/gtkrc -share/themes/MS-Windows -share/themes/MS-Windows/gtk-2.0 -share/themes/MS-Windows/gtk-2.0/gtkrc -share/themes/Raleigh -share/themes/Raleigh/gtk-2.0 -share/themes/Raleigh/gtk-2.0/gtkrc diff --git a/gtk+-2.16.6.filelist b/gtk+-2.16.6.filelist deleted file mode 100644 index 2b9b82f19..000000000 --- a/gtk+-2.16.6.filelist +++ /dev/null @@ -1,146 +0,0 @@ -bin -bin/libglade-2.0-0.dll -bin/freetype6.dll -bin/intl.dll -bin/libatk-1.0-0.dll -bin/libcairo-2.dll -bin/libexpat-1.dll -bin/libfontconfig-1.dll -bin/libgailutil-18.dll -bin/libgdk-win32-2.0-0.dll -bin/libgdk_pixbuf-2.0-0.dll -bin/libgio-2.0-0.dll -bin/libglib-2.0-0.dll -bin/libgmodule-2.0-0.dll -bin/libgobject-2.0-0.dll -bin/libgthread-2.0-0.dll -bin/libgtk-win32-2.0-0.dll -bin/libjpeg-7.dll -bin/libpango-1.0-0.dll -bin/libpangocairo-1.0-0.dll -bin/libpangoft2-1.0-0.dll -bin/libpangowin32-1.0-0.dll -bin/libpng12-0.dll -bin/libtiff-3.dll -bin/libtiffxx-3.dll -bin/zlib1.dll -lib/gtk-2.0 -lib/gtk-2.0/2.10.0 -lib/gtk-2.0/2.10.0/engines -lib/gtk-2.0/2.10.0/engines/libpixmap.dll -lib/gtk-2.0/2.10.0/engines/libwimp.dll -lib/gtk-2.0/2.10.0/loaders -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ani.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-bmp.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-gif.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-icns.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ico.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-jpeg.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-pcx.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-png.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-pnm.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-ras.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-tga.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-tiff.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-wbmp.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-xbm.dll -lib/gtk-2.0/2.10.0/loaders/libpixbufloader-xpm.dll -lib/gtk-2.0/include -lib/gtk-2.0/include/gdkconfig.h -lib/gtk-2.0/modules -lib/gtk-2.0/modules/libgail.dll -etc -etc/fonts -etc/fonts/fonts.conf -etc/fonts/fonts.dtd -etc/gtk-2.0 -etc/gtk-2.0/gdk-pixbuf.loaders -etc/gtk-2.0/gtk.immodules -etc/gtk-2.0/im-multipress.conf -etc/pango -etc/pango/pango.modules -share/locale/fr -share/locale/fr/LC_MESSAGES -share/locale/fr/LC_MESSAGES/atk10.mo -share/locale/fr/LC_MESSAGES/glib20.mo -share/locale/fr/LC_MESSAGES/gtk20-properties.mo -share/locale/fr/LC_MESSAGES/gtk20.mo -share/locale/de -share/locale/de/LC_MESSAGES -share/locale/de/LC_MESSAGES/atk10.mo -share/locale/de/LC_MESSAGES/glib20.mo -share/locale/de/LC_MESSAGES/gtk20-properties.mo -share/locale/de/LC_MESSAGES/gtk20.mo -share/locale/sv -share/locale/sv/LC_MESSAGES -share/locale/sv/LC_MESSAGES/atk10.mo -share/locale/sv/LC_MESSAGES/glib20.mo -share/locale/sv/LC_MESSAGES/gtk20-properties.mo -share/locale/sv/LC_MESSAGES/gtk20.mo -share/locale/cs -share/locale/cs/LC_MESSAGES -share/locale/cs/LC_MESSAGES/atk10.mo -share/locale/cs/LC_MESSAGES/glib20.mo -share/locale/cs/LC_MESSAGES/gtk20-properties.mo -share/locale/cs/LC_MESSAGES/gtk20.mo -share/locale/es -share/locale/es/LC_MESSAGES -share/locale/es/LC_MESSAGES/atk10.mo -share/locale/es/LC_MESSAGES/glib20.mo -share/locale/es/LC_MESSAGES/gtk20-properties.mo -share/locale/es/LC_MESSAGES/gtk20.mo -share/locale/hu -share/locale/hu/LC_MESSAGES -share/locale/hu/LC_MESSAGES/atk10.mo -share/locale/hu/LC_MESSAGES/glib20.mo -share/locale/hu/LC_MESSAGES/gtk20-properties.mo -share/locale/hu/LC_MESSAGES/gtk20.mo -share/locale/it -share/locale/it/LC_MESSAGES -share/locale/it/LC_MESSAGES/atk10.mo -share/locale/it/LC_MESSAGES/glib20.mo -share/locale/it/LC_MESSAGES/gtk20-properties.mo -share/locale/it/LC_MESSAGES/gtk20.mo -share/locale/ja -share/locale/ja/LC_MESSAGES -share/locale/ja/LC_MESSAGES/atk10.mo -share/locale/ja/LC_MESSAGES/glib20.mo -share/locale/ja/LC_MESSAGES/gtk20-properties.mo -share/locale/ja/LC_MESSAGES/gtk20.mo -share/locale/nl -share/locale/nl/LC_MESSAGES -share/locale/nl/LC_MESSAGES/atk10.mo -share/locale/nl/LC_MESSAGES/glib20.mo -share/locale/nl/LC_MESSAGES/gtk20-properties.mo -share/locale/nl/LC_MESSAGES/gtk20.mo -share/locale/pl -share/locale/pl/LC_MESSAGES -share/locale/pl/LC_MESSAGES/atk10.mo -share/locale/pl/LC_MESSAGES/glib20.mo -share/locale/pl/LC_MESSAGES/gtk20-properties.mo -share/locale/pl/LC_MESSAGES/gtk20.mo -share/locale/ru -share/locale/ru/LC_MESSAGES -share/locale/ru/LC_MESSAGES/atk10.mo -share/locale/ru/LC_MESSAGES/glib20.mo -share/locale/ru/LC_MESSAGES/gtk20-properties.mo -share/locale/ru/LC_MESSAGES/gtk20.mo -share/locale/pt_BR -share/locale/pt_BR/LC_MESSAGES -share/locale/pt_BR/LC_MESSAGES/atk10.mo -share/locale/pt_BR/LC_MESSAGES/glib20.mo -share/locale/pt_BR/LC_MESSAGES/gtk20-properties.mo -share/locale/pt_BR/LC_MESSAGES/gtk20.mo -share/themes -share/themes/Default -share/themes/Default/gtk-2.0-key -share/themes/Default/gtk-2.0-key/gtkrc -share/themes/Emacs -share/themes/Emacs/gtk-2.0-key -share/themes/Emacs/gtk-2.0-key/gtkrc -share/themes/MS-Windows -share/themes/MS-Windows/gtk-2.0 -share/themes/MS-Windows/gtk-2.0/gtkrc -share/themes/Raleigh -share/themes/Raleigh/gtk-2.0 -share/themes/Raleigh/gtk-2.0/gtkrc diff --git a/gtk+-2.18.5.filelist b/gtk+-2.18.5.filelist deleted file mode 100644 index cb2f3bef4..000000000 --- a/gtk+-2.18.5.filelist +++ /dev/null @@ -1,130 +0,0 @@ -bin -bin/libglade-2.0-0.dll -bin/freetype6.dll -bin/intl.dll -bin/libatk-1.0-0.dll -bin/libcairo-2.dll -bin/libexpat-1.dll -bin/libfontconfig-1.dll -bin/libgailutil-18.dll -bin/libgdk-win32-2.0-0.dll -bin/libgdk_pixbuf-2.0-0.dll -bin/libgio-2.0-0.dll -bin/libglib-2.0-0.dll -bin/libgmodule-2.0-0.dll -bin/libgobject-2.0-0.dll -bin/libgthread-2.0-0.dll -bin/libgtk-win32-2.0-0.dll -bin/libjpeg-7.dll -bin/libpango-1.0-0.dll -bin/libpangocairo-1.0-0.dll -bin/libpangoft2-1.0-0.dll -bin/libpangowin32-1.0-0.dll -bin/libpng12-0.dll -bin/libtiff-3.dll -bin/libtiffxx-3.dll -bin/zlib1.dll -lib/gtk-2.0 -lib/gtk-2.0/2.10.0 -lib/gtk-2.0/2.10.0/engines -lib/gtk-2.0/2.10.0/engines/libpixmap.dll -lib/gtk-2.0/2.10.0/engines/libwimp.dll -lib/gtk-2.0/include -lib/gtk-2.0/include/gdkconfig.h -lib/gtk-2.0/modules -lib/gtk-2.0/modules/libgail.dll -etc -etc/fonts -etc/fonts/fonts.conf -etc/fonts/fonts.dtd -etc/gtk-2.0 -etc/gtk-2.0/gdk-pixbuf.loaders -etc/gtk-2.0/gtk.immodules -etc/gtk-2.0/im-multipress.conf -etc/pango -etc/pango/pango.modules -share/locale/fr -share/locale/fr/LC_MESSAGES -share/locale/fr/LC_MESSAGES/atk10.mo -share/locale/fr/LC_MESSAGES/glib20.mo -share/locale/fr/LC_MESSAGES/gtk20-properties.mo -share/locale/fr/LC_MESSAGES/gtk20.mo -share/locale/de -share/locale/de/LC_MESSAGES -share/locale/de/LC_MESSAGES/atk10.mo -share/locale/de/LC_MESSAGES/glib20.mo -share/locale/de/LC_MESSAGES/gtk20-properties.mo -share/locale/de/LC_MESSAGES/gtk20.mo -share/locale/sv -share/locale/sv/LC_MESSAGES -share/locale/sv/LC_MESSAGES/atk10.mo -share/locale/sv/LC_MESSAGES/glib20.mo -share/locale/sv/LC_MESSAGES/gtk20-properties.mo -share/locale/sv/LC_MESSAGES/gtk20.mo -share/locale/cs -share/locale/cs/LC_MESSAGES -share/locale/cs/LC_MESSAGES/atk10.mo -share/locale/cs/LC_MESSAGES/glib20.mo -share/locale/cs/LC_MESSAGES/gtk20-properties.mo -share/locale/cs/LC_MESSAGES/gtk20.mo -share/locale/es -share/locale/es/LC_MESSAGES -share/locale/es/LC_MESSAGES/atk10.mo -share/locale/es/LC_MESSAGES/glib20.mo -share/locale/es/LC_MESSAGES/gtk20-properties.mo -share/locale/es/LC_MESSAGES/gtk20.mo -share/locale/hu -share/locale/hu/LC_MESSAGES -share/locale/hu/LC_MESSAGES/atk10.mo -share/locale/hu/LC_MESSAGES/glib20.mo -share/locale/hu/LC_MESSAGES/gtk20-properties.mo -share/locale/hu/LC_MESSAGES/gtk20.mo -share/locale/it -share/locale/it/LC_MESSAGES -share/locale/it/LC_MESSAGES/atk10.mo -share/locale/it/LC_MESSAGES/glib20.mo -share/locale/it/LC_MESSAGES/gtk20-properties.mo -share/locale/it/LC_MESSAGES/gtk20.mo -share/locale/ja -share/locale/ja/LC_MESSAGES -share/locale/ja/LC_MESSAGES/atk10.mo -share/locale/ja/LC_MESSAGES/glib20.mo -share/locale/ja/LC_MESSAGES/gtk20-properties.mo -share/locale/ja/LC_MESSAGES/gtk20.mo -share/locale/nl -share/locale/nl/LC_MESSAGES -share/locale/nl/LC_MESSAGES/atk10.mo -share/locale/nl/LC_MESSAGES/glib20.mo -share/locale/nl/LC_MESSAGES/gtk20-properties.mo -share/locale/nl/LC_MESSAGES/gtk20.mo -share/locale/pl -share/locale/pl/LC_MESSAGES -share/locale/pl/LC_MESSAGES/atk10.mo -share/locale/pl/LC_MESSAGES/glib20.mo -share/locale/pl/LC_MESSAGES/gtk20-properties.mo -share/locale/pl/LC_MESSAGES/gtk20.mo -share/locale/ru -share/locale/ru/LC_MESSAGES -share/locale/ru/LC_MESSAGES/atk10.mo -share/locale/ru/LC_MESSAGES/glib20.mo -share/locale/ru/LC_MESSAGES/gtk20-properties.mo -share/locale/ru/LC_MESSAGES/gtk20.mo -share/locale/pt_BR -share/locale/pt_BR/LC_MESSAGES -share/locale/pt_BR/LC_MESSAGES/atk10.mo -share/locale/pt_BR/LC_MESSAGES/glib20.mo -share/locale/pt_BR/LC_MESSAGES/gtk20-properties.mo -share/locale/pt_BR/LC_MESSAGES/gtk20.mo -share/themes -share/themes/Default -share/themes/Default/gtk-2.0-key -share/themes/Default/gtk-2.0-key/gtkrc -share/themes/Emacs -share/themes/Emacs/gtk-2.0-key -share/themes/Emacs/gtk-2.0-key/gtkrc -share/themes/MS-Windows -share/themes/MS-Windows/gtk-2.0 -share/themes/MS-Windows/gtk-2.0/gtkrc -share/themes/Raleigh -share/themes/Raleigh/gtk-2.0 -share/themes/Raleigh/gtk-2.0/gtkrc diff --git a/gtk+-2.22.1.filelist b/gtk+-2.22.1.filelist deleted file mode 100644 index 792aeeb06..000000000 --- a/gtk+-2.22.1.filelist +++ /dev/null @@ -1,152 +0,0 @@ -bin -bin/freetype6.dll -bin/intl.dll -bin/libasprintf-0.dll -bin/libatk-1.0-0.dll -bin/libcairo-2.dll -bin/libcairo-gobject-2.dll -bin/libcairo-script-interpreter-2.dll -bin/libexpat-1.dll -bin/libfontconfig-1.dll -bin/libgailutil-18.dll -bin/libgcc_s_dw2-1.dll -bin/libgdk-win32-2.0-0.dll -bin/libgdk_pixbuf-2.0-0.dll -bin/libgio-2.0-0.dll -bin/libglib-2.0-0.dll -bin/libgmodule-2.0-0.dll -bin/libgobject-2.0-0.dll -bin/libgthread-2.0-0.dll -bin/libgtk-win32-2.0-0.dll -bin/libpango-1.0-0.dll -bin/libpangocairo-1.0-0.dll -bin/libpangoft2-1.0-0.dll -bin/libpangowin32-1.0-0.dll -bin/libpng14-14.dll -bin/zlib1.dll -lib/gtk-2.0 -lib/gtk-2.0/2.10.0 -lib/gtk-2.0/2.10.0/engines -lib/gtk-2.0/2.10.0/engines/libpixmap.dll -lib/gtk-2.0/2.10.0/engines/libwimp.dll -lib/gtk-2.0/include -lib/gtk-2.0/include/gdkconfig.h -lib/gtk-2.0/modules -lib/gtk-2.0/modules/libgail.dll -etc -etc/fonts -etc/fonts/fonts.conf -etc/fonts/fonts.dtd -etc/gtk-2.0 -etc/gtk-2.0/gtk.immodules -etc/gtk-2.0/im-multipress.conf -etc/pango -etc/pango/pango.modules -share/locale/fr -share/locale/fr/LC_MESSAGES -share/locale/fr/LC_MESSAGES/atk10.mo -share/locale/fr/LC_MESSAGES/gdk-pixbuf.mo -share/locale/fr/LC_MESSAGES/gettext-runtime.mo -share/locale/fr/LC_MESSAGES/glib20.mo -share/locale/fr/LC_MESSAGES/gtk20-properties.mo -share/locale/fr/LC_MESSAGES/gtk20.mo -share/locale/de -share/locale/de/LC_MESSAGES -share/locale/de/LC_MESSAGES/atk10.mo -share/locale/de/LC_MESSAGES/gdk-pixbuf.mo -share/locale/de/LC_MESSAGES/gettext-runtime.mo -share/locale/de/LC_MESSAGES/glib20.mo -share/locale/de/LC_MESSAGES/gtk20-properties.mo -share/locale/de/LC_MESSAGES/gtk20.mo -share/locale/sv -share/locale/sv/LC_MESSAGES -share/locale/sv/LC_MESSAGES/atk10.mo -share/locale/sv/LC_MESSAGES/gdk-pixbuf.mo -share/locale/sv/LC_MESSAGES/gettext-runtime.mo -share/locale/sv/LC_MESSAGES/glib20.mo -share/locale/sv/LC_MESSAGES/gtk20-properties.mo -share/locale/sv/LC_MESSAGES/gtk20.mo -share/locale/cs -share/locale/cs/LC_MESSAGES -share/locale/cs/LC_MESSAGES/atk10.mo -share/locale/cs/LC_MESSAGES/gdk-pixbuf.mo -share/locale/cs/LC_MESSAGES/gettext-runtime.mo -share/locale/cs/LC_MESSAGES/glib20.mo -share/locale/cs/LC_MESSAGES/gtk20-properties.mo -share/locale/cs/LC_MESSAGES/gtk20.mo -share/locale/es -share/locale/es/LC_MESSAGES -share/locale/es/LC_MESSAGES/atk10.mo -share/locale/es/LC_MESSAGES/gdk-pixbuf.mo -share/locale/es/LC_MESSAGES/gettext-runtime.mo -share/locale/es/LC_MESSAGES/glib20.mo -share/locale/es/LC_MESSAGES/gtk20-properties.mo -share/locale/es/LC_MESSAGES/gtk20.mo -share/locale/hu -share/locale/hu/LC_MESSAGES -share/locale/hu/LC_MESSAGES/atk10.mo -share/locale/hu/LC_MESSAGES/gdk-pixbuf.mo -share/locale/hu/LC_MESSAGES/glib20.mo -share/locale/hu/LC_MESSAGES/gtk20-properties.mo -share/locale/hu/LC_MESSAGES/gtk20.mo -share/locale/it -share/locale/it/LC_MESSAGES -share/locale/it/LC_MESSAGES/atk10.mo -share/locale/it/LC_MESSAGES/gdk-pixbuf.mo -share/locale/it/LC_MESSAGES/gettext-runtime.mo -share/locale/it/LC_MESSAGES/glib20.mo -share/locale/it/LC_MESSAGES/gtk20-properties.mo -share/locale/it/LC_MESSAGES/gtk20.mo -share/locale/ja -share/locale/ja/LC_MESSAGES -share/locale/ja/LC_MESSAGES/atk10.mo -share/locale/ja/LC_MESSAGES/gdk-pixbuf.mo -share/locale/ja/LC_MESSAGES/gettext-runtime.mo -share/locale/ja/LC_MESSAGES/glib20.mo -share/locale/ja/LC_MESSAGES/gtk20-properties.mo -share/locale/ja/LC_MESSAGES/gtk20.mo -share/locale/nl -share/locale/nl/LC_MESSAGES -share/locale/nl/LC_MESSAGES/atk10.mo -share/locale/nl/LC_MESSAGES/gdk-pixbuf.mo -share/locale/nl/LC_MESSAGES/gettext-runtime.mo -share/locale/nl/LC_MESSAGES/glib20.mo -share/locale/nl/LC_MESSAGES/gtk20-properties.mo -share/locale/nl/LC_MESSAGES/gtk20.mo -share/locale/pl -share/locale/pl/LC_MESSAGES -share/locale/pl/LC_MESSAGES/atk10.mo -share/locale/pl/LC_MESSAGES/gdk-pixbuf.mo -share/locale/pl/LC_MESSAGES/gettext-runtime.mo -share/locale/pl/LC_MESSAGES/glib20.mo -share/locale/pl/LC_MESSAGES/gtk20-properties.mo -share/locale/pl/LC_MESSAGES/gtk20.mo -share/locale/ru -share/locale/ru/LC_MESSAGES -share/locale/ru/LC_MESSAGES/atk10.mo -share/locale/ru/LC_MESSAGES/gdk-pixbuf.mo -share/locale/ru/LC_MESSAGES/gettext-runtime.mo -share/locale/ru/LC_MESSAGES/glib20.mo -share/locale/ru/LC_MESSAGES/gtk20-properties.mo -share/locale/ru/LC_MESSAGES/gtk20.mo -share/locale/pt_BR -share/locale/pt_BR/LC_MESSAGES -share/locale/pt_BR/LC_MESSAGES/atk10.mo -share/locale/pt_BR/LC_MESSAGES/gdk-pixbuf.mo -share/locale/pt_BR/LC_MESSAGES/gettext-runtime.mo -share/locale/pt_BR/LC_MESSAGES/glib20.mo -share/locale/pt_BR/LC_MESSAGES/gtk20-properties.mo -share/locale/pt_BR/LC_MESSAGES/gtk20.mo -share/themes -share/themes/Default -share/themes/Default/gtk-2.0-key -share/themes/Default/gtk-2.0-key/gtkrc -share/themes/Emacs -share/themes/Emacs/gtk-2.0-key -share/themes/Emacs/gtk-2.0-key/gtkrc -share/themes/MS-Windows -share/themes/MS-Windows/gtk-2.0 -share/themes/MS-Windows/gtk-2.0/gtkrc -share/themes/Raleigh -share/themes/Raleigh/gtk-2.0 -share/themes/Raleigh/gtk-2.0/gtkrc diff --git a/gtk+-2.24.8.filelist b/gtk+-2.24.8.filelist deleted file mode 100644 index f893fafa0..000000000 --- a/gtk+-2.24.8.filelist +++ /dev/null @@ -1,213 +0,0 @@ -bin -bin/freetype6.dll -bin/intl.dll -bin/libasprintf-0.dll -bin/libatk-1.0-0.dll -bin/libcairo-2.dll -bin/libcairo-gobject-2.dll -bin/libcairo-script-interpreter-2.dll -bin/libexpat-1.dll -bin/libfontconfig-1.dll -bin/libgailutil-18.dll -bin/libgcc_s_dw2-1.dll -bin/libgdk-win32-2.0-0.dll -bin/libgdk_pixbuf-2.0-0.dll -bin/libgio-2.0-0.dll -bin/libglib-2.0-0.dll -bin/libgmodule-2.0-0.dll -bin/libgobject-2.0-0.dll -bin/libgthread-2.0-0.dll -bin/libgtk-win32-2.0-0.dll -bin/libpango-1.0-0.dll -bin/libpangocairo-1.0-0.dll -bin/libpangoft2-1.0-0.dll -bin/libpangowin32-1.0-0.dll -bin/libpng14-14.dll -bin/zlib1.dll -lib/gtk-2.0 -lib/gtk-2.0/2.10.0 -lib/gtk-2.0/2.10.0/engines -lib/gtk-2.0/2.10.0/engines/libpixmap.dll -lib/gtk-2.0/2.10.0/engines/libwimp.dll -lib/gtk-2.0/include -lib/gtk-2.0/include/gdkconfig.h -lib/gtk-2.0/modules -lib/gtk-2.0/modules/libgail.dll -etc -etc/bash_completion.d -etc/bash_completion.d/gdbus-bash-completion.sh -etc/bash_completion.d/gsettings-bash-completion.sh -etc/fonts -etc/fonts/fonts.conf -etc/fonts/fonts.dtd -etc/gtk-2.0 -etc/gtk-2.0/gtk.immodules -etc/gtk-2.0/im-multipress.conf -etc/pango -etc/pango/pango.modules -share/locale/ar/LC_MESSAGES/atk10.mo -share/locale/ar/LC_MESSAGES/gdk-pixbuf.mo -share/locale/ar/LC_MESSAGES/glib20.mo -share/locale/ar/LC_MESSAGES/gtk20-properties.mo -share/locale/ar/LC_MESSAGES/gtk20.mo -share/locale/cs -share/locale/cs/LC_MESSAGES -share/locale/cs/LC_MESSAGES/atk10.mo -share/locale/cs/LC_MESSAGES/gdk-pixbuf.mo -share/locale/cs/LC_MESSAGES/gettext-runtime.mo -share/locale/cs/LC_MESSAGES/glib20.mo -share/locale/cs/LC_MESSAGES/gtk20-properties.mo -share/locale/cs/LC_MESSAGES/gtk20.mo -share/locale/de -share/locale/de/LC_MESSAGES -share/locale/de/LC_MESSAGES/atk10.mo -share/locale/de/LC_MESSAGES/gdk-pixbuf.mo -share/locale/de/LC_MESSAGES/gettext-runtime.mo -share/locale/de/LC_MESSAGES/glib20.mo -share/locale/de/LC_MESSAGES/gtk20-properties.mo -share/locale/de/LC_MESSAGES/gtk20.mo -share/locale/es -share/locale/es/LC_MESSAGES -share/locale/es/LC_MESSAGES/atk10.mo -share/locale/es/LC_MESSAGES/gdk-pixbuf.mo -share/locale/es/LC_MESSAGES/gettext-runtime.mo -share/locale/es/LC_MESSAGES/glib20.mo -share/locale/es/LC_MESSAGES/gtk20-properties.mo -share/locale/es/LC_MESSAGES/gtk20.mo -share/locale/fr -share/locale/fr/LC_MESSAGES -share/locale/fr/LC_MESSAGES/atk10.mo -share/locale/fr/LC_MESSAGES/gdk-pixbuf.mo -share/locale/fr/LC_MESSAGES/gettext-runtime.mo -share/locale/fr/LC_MESSAGES/glib20.mo -share/locale/fr/LC_MESSAGES/gtk20-properties.mo -share/locale/fr/LC_MESSAGES/gtk20.mo -share/locale/he -share/locale/he/LC_MESSAGES -share/locale/he/LC_MESSAGES/atk10.mo -share/locale/he/LC_MESSAGES/gdk-pixbuf.mo -share/locale/he/LC_MESSAGES/glib20.mo -share/locale/he/LC_MESSAGES/gtk20-properties.mo -share/locale/he/LC_MESSAGES/gtk20.mo -share/locale/hu -share/locale/hu/LC_MESSAGES -share/locale/hu/LC_MESSAGES/atk10.mo -share/locale/hu/LC_MESSAGES/gdk-pixbuf.mo -share/locale/hu/LC_MESSAGES/glib20.mo -share/locale/hu/LC_MESSAGES/gtk20-properties.mo -share/locale/hu/LC_MESSAGES/gtk20.mo -share/locale/it -share/locale/it/LC_MESSAGES -share/locale/it/LC_MESSAGES/atk10.mo -share/locale/it/LC_MESSAGES/gdk-pixbuf.mo -share/locale/it/LC_MESSAGES/gettext-runtime.mo -share/locale/it/LC_MESSAGES/glib20.mo -share/locale/it/LC_MESSAGES/gtk20-properties.mo -share/locale/it/LC_MESSAGES/gtk20.mo -share/locale/ja -share/locale/ja/LC_MESSAGES -share/locale/ja/LC_MESSAGES/atk10.mo -share/locale/ja/LC_MESSAGES/gdk-pixbuf.mo -share/locale/ja/LC_MESSAGES/gettext-runtime.mo -share/locale/ja/LC_MESSAGES/glib20.mo -share/locale/ja/LC_MESSAGES/gtk20-properties.mo -share/locale/ja/LC_MESSAGES/gtk20.mo -share/locale/nb -share/locale/nb/LC_MESSAGES -share/locale/nb/LC_MESSAGES/atk10.mo -share/locale/nb/LC_MESSAGES/gdk-pixbuf.mo -share/locale/nb/LC_MESSAGES/gettext-runtime.mo -share/locale/nb/LC_MESSAGES/glib20.mo -share/locale/nb/LC_MESSAGES/gtk20-properties.mo -share/locale/nb/LC_MESSAGES/gtk20.mo -share/locale/nl -share/locale/nl/LC_MESSAGES -share/locale/nl/LC_MESSAGES/atk10.mo -share/locale/nl/LC_MESSAGES/gdk-pixbuf.mo -share/locale/nl/LC_MESSAGES/gettext-runtime.mo -share/locale/nl/LC_MESSAGES/glib20.mo -share/locale/nl/LC_MESSAGES/gtk20-properties.mo -share/locale/nl/LC_MESSAGES/gtk20.mo -share/locale/pl -share/locale/pl/LC_MESSAGES -share/locale/pl/LC_MESSAGES/atk10.mo -share/locale/pl/LC_MESSAGES/gdk-pixbuf.mo -share/locale/pl/LC_MESSAGES/gettext-runtime.mo -share/locale/pl/LC_MESSAGES/glib20.mo -share/locale/pl/LC_MESSAGES/gtk20-properties.mo -share/locale/pl/LC_MESSAGES/gtk20.mo -share/locale/pt -share/locale/pt/LC_MESSAGES -share/locale/pt/LC_MESSAGES/atk10.mo -share/locale/pt/LC_MESSAGES/gdk-pixbuf.mo -share/locale/pt/LC_MESSAGES/gettext-runtime.mo -share/locale/pt/LC_MESSAGES/glib20.mo -share/locale/pt/LC_MESSAGES/gtk20-properties.mo -share/locale/pt/LC_MESSAGES/gtk20.mo -share/locale/pt_BR -share/locale/pt_BR/LC_MESSAGES -share/locale/pt_BR/LC_MESSAGES/atk10.mo -share/locale/pt_BR/LC_MESSAGES/gdk-pixbuf.mo -share/locale/pt_BR/LC_MESSAGES/gettext-runtime.mo -share/locale/pt_BR/LC_MESSAGES/glib20.mo -share/locale/pt_BR/LC_MESSAGES/gtk20-properties.mo -share/locale/pt_BR/LC_MESSAGES/gtk20.mo -share/locale/ru -share/locale/ru/LC_MESSAGES -share/locale/ru/LC_MESSAGES/atk10.mo -share/locale/ru/LC_MESSAGES/gdk-pixbuf.mo -share/locale/ru/LC_MESSAGES/gettext-runtime.mo -share/locale/ru/LC_MESSAGES/glib20.mo -share/locale/ru/LC_MESSAGES/gtk20-properties.mo -share/locale/ru/LC_MESSAGES/gtk20.mo -share/locale/sr -share/locale/sr/LC_MESSAGES -share/locale/sr/LC_MESSAGES/atk10.mo -share/locale/sr/LC_MESSAGES/gdk-pixbuf.mo -share/locale/sr/LC_MESSAGES/gettext-runtime.mo -share/locale/sr/LC_MESSAGES/glib20.mo -share/locale/sr/LC_MESSAGES/gtk20-properties.mo -share/locale/sr/LC_MESSAGES/gtk20.mo -share/locale/sv -share/locale/sv/LC_MESSAGES -share/locale/sv/LC_MESSAGES/atk10.mo -share/locale/sv/LC_MESSAGES/gdk-pixbuf.mo -share/locale/sv/LC_MESSAGES/gettext-runtime.mo -share/locale/sv/LC_MESSAGES/glib20.mo -share/locale/sv/LC_MESSAGES/gtk20-properties.mo -share/locale/sv/LC_MESSAGES/gtk20.mo -share/locale/tr/LC_MESSAGES/atk10.mo -share/locale/tr/LC_MESSAGES/gdk-pixbuf.mo -share/locale/tr/LC_MESSAGES/gettext-runtime.mo -share/locale/tr/LC_MESSAGES/glib20.mo -share/locale/tr/LC_MESSAGES/gtk20-properties.mo -share/locale/tr/LC_MESSAGES/gtk20.mo -share/locale/zh_CN -share/locale/zh_CN/LC_MESSAGES -share/locale/zh_CN/LC_MESSAGES/atk10.mo -share/locale/zh_CN/LC_MESSAGES/gdk-pixbuf.mo -share/locale/zh_CN/LC_MESSAGES/gettext-runtime.mo -share/locale/zh_CN/LC_MESSAGES/glib20.mo -share/locale/zh_CN/LC_MESSAGES/gtk20-properties.mo -share/locale/zh_CN/LC_MESSAGES/gtk20.mo -share/locale/zh_TW -share/locale/zh_TW/LC_MESSAGES -share/locale/zh_TW/LC_MESSAGES/atk10.mo -share/locale/zh_TW/LC_MESSAGES/gdk-pixbuf.mo -share/locale/zh_TW/LC_MESSAGES/gettext-runtime.mo -share/locale/zh_TW/LC_MESSAGES/glib20.mo -share/locale/zh_TW/LC_MESSAGES/gtk20-properties.mo -share/locale/zh_TW/LC_MESSAGES/gtk20.mo -share/themes -share/themes/Default -share/themes/Default/gtk-2.0-key -share/themes/Default/gtk-2.0-key/gtkrc -share/themes/Emacs -share/themes/Emacs/gtk-2.0-key -share/themes/Emacs/gtk-2.0-key/gtkrc -share/themes/MS-Windows -share/themes/MS-Windows/gtk-2.0 -share/themes/MS-Windows/gtk-2.0/gtkrc -share/themes/Raleigh -share/themes/Raleigh/gtk-2.0 -share/themes/Raleigh/gtk-2.0/gtkrc diff --git a/gtk/.gitignore b/gtk/.gitignore deleted file mode 100644 index b1b1529c6..000000000 --- a/gtk/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -linphone -.libs -.deps -linphone.res - diff --git a/gtk/CMakeLists.txt b/gtk/CMakeLists.txt deleted file mode 100644 index a30704778..000000000 --- a/gtk/CMakeLists.txt +++ /dev/null @@ -1,133 +0,0 @@ -############################################################################ -# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -############################################################################ - -set(UI_FILES - about.ui - audio_assistant.ui - buddylookup.ui - callee_frame.ui - call_logs.ui - call_statistics.ui - chatroom_frame.ui - conf_frame.ui - config-uri.ui - contact.ui - dscp_settings.ui - in_call_frame.ui - keypad.ui - ldap.ui - login_frame.ui - log.ui - main.ui - parameters.ui - password.ui - provisioning-fetch.ui - setup_wizard.ui - sip_account.ui - tunnel_config.ui - waiting.ui -) - -set(PIXMAPS stock_people.png) -set(LICENSE ../COPYING) - -set(SOURCE_FILES - audio_assistant.c - buddylookup.c - calllogs.c - chat.c - conference.c - config-fetching.c - friendlist.c - incall_view.c - logging.c - loginframe.c - main.c - propertybox.c - singleinstance.c - status_icon.c - status_notifier.c - support.c - update.c - utils.c - videowindow.c -) - -if(ENABLE_ASSISTANT) - list(APPEND SOURCE_FILES setupwizard.c) -endif() -if(WIN32) - list(APPEND SOURCE_FILES linphone.rc) -endif() - -set(OBJC_FILES) -if (APPLE) - list(APPEND OBJC_FILES mac.m) -endif() - -bc_apply_compile_flags(OBJC_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC) -bc_apply_compile_flags(SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) - -if(WIN32) - add_executable(linphone-gtk WIN32 ${SOURCE_FILES}) -else() - add_executable(linphone-gtk ${SOURCE_FILES} ${OBJC_FILES}) -endif() -set_target_properties(linphone-gtk PROPERTIES OUTPUT_NAME linphone LINKER_LANGUAGE CXX) -target_include_directories(linphone-gtk PUBLIC ${GTK2_INCLUDE_DIRS} ${INTL_INCLUDE_DIRS}) -target_link_libraries(linphone-gtk ${LINPHONE_LIBS_FOR_TOOLS} ${GTK2_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES}) -set_target_properties(linphone-gtk PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") -if(INTL_FOUND) - target_link_libraries(linphone-gtk ${INTL_LIBRARIES}) -endif() -if(WIN32) - target_link_libraries(linphone-gtk Wininet) -endif() -if(ENABLE_NOTIFY) - target_include_directories(linphone-gtk PUBLIC ${NOTIFY_INCLUDE_DIRS}) - target_link_libraries(linphone-gtk ${NOTIFY_LIBRARIES}) -endif() -if(HAVE_LIBUDEV_H) - target_link_libraries(linphone-gtk udev) -endif() -if(GTKMACINTEGRATION_FOUND) - target_include_directories(linphone-gtk PUBLIC ${GTKMACINTEGRATION_INCLUDE_DIRS}) - target_link_libraries(linphone-gtk ${GTKMACINTEGRATION_LIBRARIES}) -endif() -if(APPLE) - target_link_libraries(linphone-gtk "-framework Cocoa") -endif() - -set_target_properties(linphone-gtk PROPERTIES XCODE_ATTRIBUTE_WARNING_CFLAGS "") - - -install(TARGETS linphone-gtk - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE -) - -install(FILES ${UI_FILES} ${PIXMAPS} ${LICENSE} - DESTINATION ${PACKAGE_DATA_DIR}/linphone - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ -) diff --git a/gtk/Makefile.am b/gtk/Makefile.am deleted file mode 100644 index 82439e3ab..000000000 --- a/gtk/Makefile.am +++ /dev/null @@ -1,118 +0,0 @@ -UI_FILES= about.ui \ - main.ui \ - password.ui \ - contact.ui \ - parameters.ui \ - sip_account.ui \ - call_logs.ui \ - keypad.ui \ - log.ui \ - buddylookup.ui \ - tunnel_config.ui \ - waiting.ui \ - dscp_settings.ui \ - call_statistics.ui \ - ldap.ui \ - config-uri.ui \ - provisioning-fetch.ui \ - audio_assistant.ui \ - chatroom_frame.ui \ - in_call_frame.ui \ - conf_frame.ui \ - callee_frame.ui \ - login_frame.ui \ - setup_wizard.ui - -PIXMAPS= \ - stock_people.png - -LINPHONE_ICO_RC_FILE=linphone.rc -LINPHONE_ICO_FILE=linphone.ico - -EXTRA_DIST= \ - linphone.iss \ - $(LINPHONE_ICO_RC_FILE) \ - $(LINPHONE_ICO_FILE) - gtkrc \ - gtkrc.mac - -if BUILD_GTK_UI - -BUILT_SOURCES=version_date.h - -bin_PROGRAMS=linphone - -linphone_SOURCES= \ - main.c \ - propertybox.c \ - friendlist.c \ - support.c \ - chat.c \ - calllogs.c \ - logging.c \ - update.c \ - buddylookup.c \ - utils.c \ - incall_view.c \ - loginframe.c \ - singleinstance.c \ - conference.c \ - config-fetching.c \ - audio_assistant.c \ - videowindow.c \ - status_icon.c status_icon.h \ - linphone.h regex.h - -if BUILD_WIZARD -linphone_SOURCES+= \ - setupwizard.c setupwizard.h -endif - -if BUILD_STATUS_NOTIFIER -linphone_SOURCES+= \ - status_notifier.c \ - status_notifier.h -endif - - -linphone_LDADD= $(top_builddir)/coreapi/liblinphone.la \ - $(LIBGTK_LIBS) $(NOTIFY1_LIBS) $(NOTIFY4_LIBS) $(LIBGTKMAC_LIBS) $(INTLLIBS) $(SQLITE3_LIBS) $(BELLESIP_LIBS) $(BCTOOLBOX_LIBS) - - -if BUILD_WIN32 - -linphone.res: $(LINPHONE_ICO_RC_FILE) $(LINPHONE_ICO_FILE) - $(WINDRES) $(srcdir)/$(LINPHONE_ICO_RC_FILE) -O coff -o linphone.res - -linphone_LDADD+=linphone.res -lwininet -linphone_LDFLAGS=-Wl,--export-all-symbols -mwindows -else -linphone_LDFLAGS=-export-dynamic -endif - -uidir=$(datadir)/linphone -dist_ui_DATA=$(UI_FILES) $(PIXMAPS) $(top_srcdir)/COPYING - -if BUILD_MACOS -linphone_SOURCES+=mac.m -linphone_LDFLAGS+=-framework Cocoa -endif -endif - - -AM_CPPFLAGS= -I$(top_srcdir)/include/ -I$(top_builddir)/coreapi/ -I$(top_srcdir)/coreapi/ \ - $(MEDIASTREAMER_CFLAGS) \ - $(ORTP_CFLAGS) $(BELLESIP_CFLAGS) \ - $(STRICT_OPTIONS) $(STRICT_OPTIONS_CC) $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) $(IPV6_CFLAGS) \ - $(TUNNEL_CFLAGS) \ - $(SQLITE3_CFLAGS) \ - $(BCTOOLBOX_CFLAGS) - -version_date.h: $(top_srcdir)/configure.ac - echo "#define LINPHONE_VERSION_DATE \"$(VERSION)-`date +%y%m%d`\"" > $@ - -newdate: - rm -f version_date.h - -CLEANFILES=version_date.h linphone.res - diff --git a/gtk/about.ui b/gtk/about.ui deleted file mode 100644 index d647724b2..000000000 --- a/gtk/about.ui +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - About Linphone - False - center-on-parent - dialog - False - Linphone - undef - (C) Belledonne Communications, 2010 - - An internet video phone using the standard SIP (rfc3261) protocol. - http://www.linphone.org - GPL - Simon Morlat - - fr: Simon Morlat -en: Simon Morlat and Delphine Perreau -it: Alberto Zanoni <alberto.zanoni@-NO-SPAM-PLEASE!-tiscalinet.it> -de: Jean-Jacques Sarton <jj.sarton@-NO-SPAM-PLEASE-t-online.de> -sv: Daniel Nylander <po@danielnylander.se> -es: Jesus Benitez <gnelson at inMail dot sk> -ja: YAMAGUCHI YOSHIYA <yushiya@anet.ne.jp> -pt_BR: Rafael Caesar Lenzi <rc_lenzi@yahoo.com.br> -pl: Robert Nasiadek <darkone@darkone.pl> -cs: Petr Pisar <petr.pisar@atlas.cz> -hu: anonymous -he: Eli Zaretskii <eliz@gnu.org> - - Icons by kerosine.fr - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - vertical - 2 - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - end - - - False - end - 0 - - - - - - diff --git a/gtk/audio_assistant.c b/gtk/audio_assistant.c deleted file mode 100644 index b9f6d7241..000000000 --- a/gtk/audio_assistant.c +++ /dev/null @@ -1,551 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include - -#include "linphone.h" -#include "linphone/core_utils.h" -#include "mediastreamer2/mediastream.h" -#include "mediastreamer2/msvolume.h" - -static GtkWidget *audio_assistant=NULL; -static void prepare(GtkAssistant *w); - -GtkWidget *get_widget_from_assistant(const char *name){ - return (GtkWidget *)g_object_get_data(G_OBJECT(audio_assistant),name); -} - -static void set_widget_to_assistant(const char *name,GtkWidget *w){ - g_object_set_data(G_OBJECT(audio_assistant),name,w); -} - -static void update_record_button(gboolean is_visible){ - GtkWidget *rec_button = get_widget_from_assistant("rec_button"); - gtk_widget_set_sensitive(rec_button,is_visible); -} - -#if 0 -static void activate_record_button(gboolean is_active){ - GtkWidget *rec_button = get_widget_from_assistant("rec_button"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rec_button),is_active); -} -#endif - -static void update_play_button(gboolean is_visible){ - GtkWidget *play_button = get_widget_from_assistant("play_button"); - gtk_widget_set_sensitive(play_button,is_visible); -} - -static void activate_play_button(gboolean is_active){ - GtkWidget *play_button = get_widget_from_assistant("play_button"); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(play_button),is_active); -} - -static gboolean deactivate_play_button(void){ - activate_play_button(FALSE); - return FALSE; -} - -static gchar *get_record_file(void){ - char filename[256]={0}; - char date[64]={0}; - time_t curtime=time(NULL); - struct tm loctime; - - #ifdef _WIN32 - loctime=*localtime(&curtime); - #else - localtime_r(&curtime,&loctime); - #endif - snprintf(date,sizeof(date)-1,"%i%02i%02i-%02i%02i%2i",loctime.tm_year+1900,loctime.tm_mon+1,loctime.tm_mday, loctime.tm_hour, loctime.tm_min, loctime.tm_sec); - - snprintf(filename,sizeof(filename)-1,"record-%s.wav",date); - return g_build_path(G_DIR_SEPARATOR_S,g_get_tmp_dir(),filename,NULL);; -} - -static float audio_stream_get_record_volume(AudioStream *st){ - if (st && st->volsend){ - float vol=0; - ms_filter_call_method(st->volsend,MS_VOLUME_GET,&vol); - return vol; - } - return LINPHONE_VOLUME_DB_LOWEST; -} - -static float audio_stream_get_max_volume(AudioStream *st){ - if (st && st->volsend){ - float vol=0; - ms_filter_call_method(st->volsend,MS_VOLUME_GET_MAX,&vol); - return vol; - } - return LINPHONE_VOLUME_DB_LOWEST; -} - -static gboolean update_audio_label(volume_ctx_t *ctx){ - float volume_db=ctx->get_volume(ctx->data); - gchar *result; - if (volume_db < -20) result = _("No voice detected"); - else if (volume_db <= -10) result = _("Too low"); - else if (volume_db < -6) result = _("Good"); - else result = _("Too loud"); - g_message("volume_max_db=%f, text=%s",volume_db,result); - gtk_label_set_text(GTK_LABEL(ctx->widget),result); - return TRUE; -} - -static void on_audio_label_destroy(guint task_id){ - g_source_remove(task_id); -} - -void linphone_gtk_init_audio_label(GtkWidget *w, get_volume_t get_volume, void *data){ - guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id_t")); - if (task_id==0){ - volume_ctx_t *ctx=g_new(volume_ctx_t,1); - ctx->widget=w; - ctx->get_volume=get_volume; - ctx->data=data; - ctx->last_value=0; - g_object_set_data_full(G_OBJECT(w),"ctx_t",ctx,g_free); - task_id=g_timeout_add(200,(GSourceFunc)update_audio_label,ctx); - g_object_set_data_full(G_OBJECT(w),"task_id_t",GINT_TO_POINTER(task_id),(GDestroyNotify)on_audio_label_destroy); - } -} - -void linphone_gtk_uninit_audio_label(GtkWidget *w){ - guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id_t")); - if (task_id!=0){ - g_object_set_data(G_OBJECT(w),"ctx_t",NULL); - g_object_set_data(G_OBJECT(w),"task_id_t",NULL); - } -} - -static void playback_device_changed(GtkWidget *w){ - gchar *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); - linphone_core_set_playback_device(linphone_gtk_get_core(),sel); - g_free(sel); -} - -static void capture_device_changed(GtkWidget *capture_device){ - gchar *sel; - GtkWidget *mic_audiolevel; - GtkWidget *label_audiolevel; - GtkWidget *assistant=gtk_widget_get_toplevel(capture_device); - AudioStream *audio_stream; - - mic_audiolevel = get_widget_from_assistant("mic_audiolevel"); - label_audiolevel = get_widget_from_assistant("label_audiolevel"); - audio_stream = (AudioStream *) g_object_get_data(G_OBJECT(assistant),"stream"); - sel = gtk_combo_box_get_active_text(GTK_COMBO_BOX(capture_device)); - linphone_core_set_capture_device(linphone_gtk_get_core(),sel); - linphone_gtk_uninit_audio_meter(mic_audiolevel); - linphone_gtk_uninit_audio_label(label_audiolevel); - audio_stream_stop(audio_stream); - g_free(sel); - /*now restart the audio stream*/ - prepare(GTK_ASSISTANT(assistant)); -} - -static void dialog_click(GtkWidget *dialog, guint response_id, GtkWidget *page){ - switch(response_id){ - case GTK_RESPONSE_YES: - gtk_assistant_set_page_complete(GTK_ASSISTANT(audio_assistant),page,TRUE); - break; - default: - break; - } - gtk_widget_destroy(dialog); -} - -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); - - speaker_page = get_widget_from_assistant("speaker_page"); - - dialog = gtk_message_dialog_new ( - GTK_WINDOW(audio_assistant), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - "%s",_("Did you hear three beeps ?")); - - g_signal_connect(G_OBJECT (dialog), "response", - G_CALLBACK (dialog_click),speaker_page); - gtk_widget_show(dialog); -} - -void linphone_gtk_start_sound(GtkWidget *w){ - LinphoneCore *lc = linphone_gtk_get_core(); - linphone_core_start_echo_calibration(lc,calibration_finished,NULL,NULL,NULL); -} - -static gboolean linphone_gtk_stop_record(gpointer data){ - AudioStream *stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"record_stream"); - if(stream != NULL){ - audio_stream_stop(stream); - g_object_set_data(G_OBJECT(audio_assistant),"record_stream",NULL); - } - update_record_button(FALSE); - update_play_button(TRUE); - return FALSE; -} - - -void linphone_gtk_start_record_sound(GtkWidget *w, gpointer data){ - LinphoneCore *lc = linphone_gtk_get_core(); - MSFactory *factory = linphone_core_get_ms_factory(lc); - AudioStream *stream = NULL; - MSSndCardManager *manager = ms_factory_get_snd_card_manager(factory); - gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); - gint timeout_id; - - if(active){ - gchar *path = get_record_file(); - stream=audio_stream_new(factory, 8888, 8889, FALSE); - if(stream != NULL){ - audio_stream_start_full(stream,&av_profile,"127.0.0.1",8888,"127.0.0.1",8889,0,0,NULL, - 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); - } - 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"); - 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); - g_object_set_data(G_OBJECT(audio_assistant),"record_stream",NULL); - } - update_record_button(FALSE); - update_play_button(TRUE); - } -} - -static void endoffile_cb(void *ud, MSFilter *f, unsigned int ev,void * arg){ - switch (ev) { - case MS_PLAYER_EOF: { - ms_message("EndOfFile received"); - /*workaround for a mediastreamer2 bug. Don't deactivate the play button, because it will stop the graph from the end of file callback, - * which is sometimes crashing. On master branch it is fixed in mediastreamer2, the workaround is only valid in 3.8.x branch*/ - g_timeout_add(0, (GSourceFunc)deactivate_play_button, NULL); - break; - } - break; - } -} - -void linphone_gtk_start_play_record_sound(GtkWidget *w,gpointer data){ - LinphoneCore *lc = linphone_gtk_get_core(); - MSFactory *factory = linphone_core_get_ms_factory(lc); - gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); - AudioStream *stream = NULL; - MSSndCardManager *manager = ms_factory_get_snd_card_manager(factory); - - if(active){ - gchar *path = g_object_get_data(G_OBJECT(audio_assistant),"path"); - stream=audio_stream_new(factory, 8888, 8889, FALSE); - if(path != NULL){ - audio_stream_start_full(stream,&av_profile,"127.0.0.1",8888,"127.0.0.1",8889,0,0,path, - NULL,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),NULL,FALSE); - ms_filter_add_notify_callback(stream->soundread,endoffile_cb,stream,FALSE); - g_object_set_data(G_OBJECT(audio_assistant),"play_stream",stream); - } - } else { - stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"play_stream"); - if(stream != NULL){ - audio_stream_stop(stream); - g_object_set_data(G_OBJECT(audio_assistant),"play_stream",NULL); - } - } -} - -void display_popup(GtkMessageType type,const gchar *message){ - GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(audio_assistant), - GTK_DIALOG_DESTROY_WITH_PARENT, - type, - GTK_BUTTONS_CLOSE, - "%s", - (const gchar*)message); - /* Destroy the dialog when the user responds to it (e.g. clicks a button) */ - g_signal_connect_swapped (G_OBJECT (dialog), "response", - G_CALLBACK (gtk_widget_destroy), - G_OBJECT (dialog)); - gtk_widget_show(dialog); -} - -static void open_mixer(void){ - GError *error = NULL; - -#ifdef _WIN32 - if(!g_spawn_command_line_async("control mmsys.cpl",&error)){ - display_popup(GTK_MESSAGE_WARNING,_("Sound preferences not found ")); - g_error_free(error); - } -#elif __APPLE__ - if(!g_spawn_command_line_async("open /System/Library/PreferencePanes/Sound.prefPane",&error)){ - display_popup(GTK_MESSAGE_WARNING,_("Sound preferences not found ")); - g_error_free(error); - } -#else - if(!g_spawn_command_line_async("gnome-volume-control",&error)){ - if(!g_spawn_command_line_async("gnome-control-center sound",&error)){ - if(!g_spawn_command_line_async("kmix",&error)){ - if(!g_spawn_command_line_async("mate-volume-control",&error)){ - if(!g_spawn_command_line_async("xterm alsamixer",&error)){ - display_popup(GTK_MESSAGE_WARNING,_("Cannot launch system sound control ")); - g_error_free(error); - } - } - } - } - } -#endif -} - -static GtkWidget *create_intro(void){ - GtkWidget *vbox=gtk_vbox_new(FALSE,2); - GtkWidget *label=gtk_label_new(_("Welcome!\nThis assistant will help you to configure audio settings for Linphone")); - gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 2); - gtk_widget_show_all(vbox); - return vbox; -} - -static GtkWidget *create_mic_page(void){ - 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(); - GtkWidget *capture_device=gtk_combo_box_new(); - GtkWidget *box = gtk_vbox_new(FALSE,0); - GtkWidget *label_audiolevel=gtk_label_new(_("No voice")); - GtkWidget *mixer_button=gtk_button_new_with_label(_("System sound preferences")); - GtkWidget *image; - - image=gtk_image_new_from_stock(GTK_STOCK_PREFERENCES,GTK_ICON_SIZE_MENU); - gtk_button_set_image(GTK_BUTTON(mixer_button),image); - - gtk_box_pack_start(GTK_BOX(box),mic_audiolevel,TRUE,TRUE,1); - gtk_box_pack_start(GTK_BOX(box),label_audiolevel,FALSE,FALSE,1); - - gtk_table_attach_defaults(GTK_TABLE(vbox), labelMicChoice, 0, 1, 0, 1); - gtk_table_attach_defaults(GTK_TABLE(vbox), capture_device, 1, 2, 0, 1); - gtk_table_attach_defaults(GTK_TABLE(vbox), labelMicLevel, 0, 1, 1, 2); - gtk_table_attach_defaults(GTK_TABLE(vbox), box, 1, 2, 1, 2); - gtk_table_attach(GTK_TABLE(vbox), mixer_button, 0, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0,0); - - gtk_table_set_row_spacings(GTK_TABLE(vbox),10); - - set_widget_to_assistant("mic_audiolevel",mic_audiolevel); - set_widget_to_assistant("label_audiolevel",label_audiolevel); - - 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); - - g_signal_connect(G_OBJECT(capture_device),"changed",(GCallback)capture_device_changed,capture_device); - g_signal_connect(G_OBJECT(mixer_button),"clicked",(GCallback)open_mixer,vbox); - - return vbox; -} - -static GtkWidget *create_speaker_page(void){ - GtkWidget *vbox=gtk_table_new(3,2,FALSE); - LinphoneCore *lc=linphone_gtk_get_core(); - - GtkWidget *labelSpeakerChoice=gtk_label_new(_("Playback device")); - GtkWidget *labelSpeakerLevel=gtk_label_new(_("Play three beeps")); - GtkWidget *spk_button=gtk_button_new_from_stock(GTK_STOCK_MEDIA_PLAY); - 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); - - gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerChoice, 0, 1, 0, 1); - gtk_table_attach(GTK_TABLE(vbox), playback_device, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0,0); - gtk_table_attach_defaults(GTK_TABLE(vbox), labelSpeakerLevel, 0, 1, 1, 2); - gtk_table_attach(GTK_TABLE(vbox), spk_button, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0,0); - gtk_table_attach(GTK_TABLE(vbox), mixer_button, 0, 2, 2, 3, GTK_SHRINK, GTK_SHRINK, 0,0); - - gtk_table_set_row_spacings(GTK_TABLE(vbox),10); - - 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); - - set_widget_to_assistant("speaker_page",vbox); - g_signal_connect(G_OBJECT(playback_device),"changed",(GCallback)playback_device_changed,playback_device); - g_signal_connect(G_OBJECT(spk_button),"clicked",(GCallback)linphone_gtk_start_sound,vbox); - g_signal_connect(G_OBJECT(mixer_button),"clicked",(GCallback)open_mixer,vbox); - - return vbox; -} - -static GtkWidget *create_play_record_page(void){ - GtkWidget *vbox=gtk_table_new(2,2,FALSE); - GtkWidget *labelRecord=gtk_label_new(_("Press the record button and say some words")); - GtkWidget *labelPlay=gtk_label_new(_("Listen to your record voice")); - GtkWidget *rec_button=gtk_toggle_button_new_with_label(_("Record")); - GtkWidget *play_button=gtk_toggle_button_new_with_label(_("Play")); - GtkWidget *image; - - image=gtk_image_new_from_stock(GTK_STOCK_MEDIA_RECORD,GTK_ICON_SIZE_MENU); - gtk_button_set_image(GTK_BUTTON(rec_button),image); - - image=gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY,GTK_ICON_SIZE_MENU); - gtk_button_set_image(GTK_BUTTON(play_button),image); - gtk_widget_set_sensitive(play_button,FALSE); - - gtk_table_attach_defaults(GTK_TABLE(vbox), labelRecord, 0, 1, 0, 1); - 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); - g_signal_connect(G_OBJECT(play_button),"toggled",(GCallback)linphone_gtk_start_play_record_sound,vbox); - - return vbox; -} - -static GtkWidget *create_end_page(void){ - GtkWidget *vbox=gtk_vbox_new(FALSE,2); - GtkWidget *label=gtk_label_new(_("Let's start Linphone now")); - gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 2); - gtk_widget_show_all(vbox); - return vbox; -} - -static void prepare(GtkAssistant *w){ - AudioStream *audio_stream = NULL; - LinphoneCore *lc=linphone_gtk_get_core(); - MSFactory *factory = linphone_core_get_ms_factory(lc); - int page = gtk_assistant_get_current_page(w); - GtkWidget *mic_audiolevel = get_widget_from_assistant("mic_audiolevel"); - GtkWidget *label_audiolevel = get_widget_from_assistant("label_audiolevel"); - - //Speaker page - if(page == 1){ - MSSndCardManager *manager = ms_factory_get_snd_card_manager(factory); - audio_stream = audio_stream_start_with_sndcards(factory, &av_profile,9898,"127.0.0.1",19898,0,0,ms_snd_card_manager_get_card(manager,linphone_core_get_playback_device(lc)),ms_snd_card_manager_get_card(manager,linphone_core_get_capture_device(lc)),FALSE); - if (mic_audiolevel != NULL && audio_stream != NULL){ - g_object_set_data(G_OBJECT(audio_assistant),"stream",audio_stream); - linphone_gtk_init_audio_meter(mic_audiolevel,(get_volume_t)audio_stream_get_record_volume,audio_stream); - linphone_gtk_init_audio_label(label_audiolevel,(get_volume_t)audio_stream_get_max_volume,audio_stream); - } - } else if(page == 2 || page == 0){ - if(mic_audiolevel != NULL && label_audiolevel != NULL){ - audio_stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant),"stream"); - if(audio_stream != NULL){ - linphone_gtk_uninit_audio_meter(mic_audiolevel); - linphone_gtk_uninit_audio_label(label_audiolevel); - audio_stream_stop(audio_stream); - g_object_set_data(G_OBJECT(audio_assistant),"stream",NULL); - } - } - } -} - -void linphone_gtk_close_audio_assistant(GtkWidget *w){ - gchar *path; - AudioStream *stream; - - path = g_object_get_data(G_OBJECT(audio_assistant),"path"); - if(path != NULL){ - g_unlink(path); - } - stream = (AudioStream *)g_object_get_data(G_OBJECT(audio_assistant), "stream"); - if(stream) { - audio_stream_stop(stream); - } - gtk_widget_destroy(w); - if(linphone_gtk_get_audio_assistant_option()){ - gtk_main_quit(); - } - audio_assistant = NULL; -} - -void linphone_gtk_audio_assistant_apply(GtkWidget *w){ - linphone_gtk_close_audio_assistant(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", linphone_gtk_get_main_window()); - - gtk_window_set_resizable (GTK_WINDOW(w), FALSE); - gtk_window_set_title(GTK_WINDOW(w),_("Audio Assistant")); - - 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); - gtk_assistant_set_page_title(GTK_ASSISTANT(w),welcome,_("Audio assistant")); - gtk_assistant_set_page_complete(GTK_ASSISTANT(w),welcome,TRUE); - - gtk_assistant_append_page(GTK_ASSISTANT(w),mic_page); - gtk_assistant_set_page_type(GTK_ASSISTANT(w),mic_page,GTK_ASSISTANT_PAGE_CONTENT); - gtk_assistant_set_page_title(GTK_ASSISTANT(w),mic_page,_("Mic Gain calibration")); - gtk_assistant_set_page_complete(GTK_ASSISTANT(w),mic_page,TRUE); - - gtk_assistant_append_page(GTK_ASSISTANT(w),speaker_page); - gtk_assistant_set_page_type(GTK_ASSISTANT(w),speaker_page,GTK_ASSISTANT_PAGE_CONTENT); - gtk_assistant_set_page_complete(GTK_ASSISTANT(w),speaker_page,FALSE); - gtk_assistant_set_page_title(GTK_ASSISTANT(w),speaker_page,_("Speaker volume calibration")); - - gtk_assistant_append_page(GTK_ASSISTANT(w),play_record_page); - gtk_assistant_set_page_type(GTK_ASSISTANT(w),play_record_page,GTK_ASSISTANT_PAGE_CONTENT); - gtk_assistant_set_page_complete(GTK_ASSISTANT(w),play_record_page,TRUE); - gtk_assistant_set_page_title(GTK_ASSISTANT(w),play_record_page,_("Record and Play")); - - gtk_assistant_append_page(GTK_ASSISTANT(w),end_page); - gtk_assistant_set_page_type(GTK_ASSISTANT(w),end_page,GTK_ASSISTANT_PAGE_SUMMARY); - gtk_assistant_set_page_complete(GTK_ASSISTANT(w),end_page,TRUE); - gtk_assistant_set_page_title(GTK_ASSISTANT(w),end_page,_("Terminating")); - - g_signal_connect(G_OBJECT(w),"close",(GCallback)linphone_gtk_close_audio_assistant,w); - g_signal_connect(G_OBJECT(w),"cancel",(GCallback)linphone_gtk_close_audio_assistant,w); - g_signal_connect(G_OBJECT(w),"prepare",(GCallback)prepare,NULL); - - gtk_widget_show(w); -} diff --git a/gtk/audio_assistant.ui b/gtk/audio_assistant.ui deleted file mode 100644 index b8390f5d8..000000000 --- a/gtk/audio_assistant.ui +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - False - 12 - - - - - - - - - - - - - - diff --git a/gtk/buddylookup.c b/gtk/buddylookup.c deleted file mode 100644 index 73d8780db..000000000 --- a/gtk/buddylookup.c +++ /dev/null @@ -1,305 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" -#include "linphone/sipsetup.h" - -static void linphone_gtk_display_lookup_results(GtkWidget *w, const bctbx_list_t *results); - -enum { - LOOKUP_RESULT_NAME, - LOOKUP_RESULT_SIP_URI, - LOOKUP_RESULT_ADDRESS, - LOOKUP_RESULT_ICON, - LOOKUP_RESULT_NCOL -}; - -void linphone_gtk_buddy_lookup_window_destroyed(GtkWidget *w){ - guint tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"typing_timeout")); - if (tid!=0){ - g_source_remove(tid); - } - tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"buddylookup_processing")); - if (tid!=0){ - g_source_remove(tid); - } -} - -static void enable_add_buddy_button(GtkWidget *w){ - gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),TRUE); -} - -static void disable_add_buddy_button(GtkWidget *w){ - gtk_widget_set_sensitive(linphone_gtk_get_widget(w,"add_buddy"),FALSE); -} - -static void buddy_selection_changed(GtkWidget *w){ - GtkWidget *results=linphone_gtk_get_widget(w,"search_results"); - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model; - enable_add_buddy_button(w); - - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(results)); - if (gtk_tree_selection_get_selected (select, &model, &iter)) - { - GtkTreePath *path=gtk_tree_model_get_path(model,&iter); - gtk_tree_view_collapse_all(GTK_TREE_VIEW(results)); - gtk_tree_view_expand_row(GTK_TREE_VIEW(results),path,FALSE); - gtk_tree_path_free(path); - } -} - -GtkWidget * linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx){ - GtkTreeStore *store; - GtkCellRenderer *renderer,*pbuf_renderer; - GtkTreeViewColumn *column; - GtkTreeSelection *select; - GtkWidget *w=linphone_gtk_create_window("buddylookup", NULL); - GtkWidget *results=linphone_gtk_get_widget(w,"search_results"); - GtkProgressBar *pb=GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")); - - store = gtk_tree_store_new(LOOKUP_RESULT_NCOL, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF); - - /*gtk_tree_view_set_hover_expand(GTK_TREE_VIEW(results),TRUE);*/ - gtk_tree_view_set_model(GTK_TREE_VIEW(results),GTK_TREE_MODEL(store)); - g_object_unref(G_OBJECT(store)); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Firstname, Lastname"), - renderer, - "markup", LOOKUP_RESULT_NAME, - NULL); - g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); - - - pbuf_renderer=gtk_cell_renderer_pixbuf_new(); - g_object_set(G_OBJECT(renderer),"is-expander",TRUE,NULL); - gtk_tree_view_column_pack_start(column,pbuf_renderer,FALSE); - gtk_tree_view_column_add_attribute (column,pbuf_renderer, - "pixbuf", - LOOKUP_RESULT_ICON); - gtk_tree_view_append_column (GTK_TREE_VIEW (results), column); - -/* - column = gtk_tree_view_column_new_with_attributes (_("SIP address"), - renderer, - "text", LOOKUP_RESULT_SIP_URI, - NULL); - g_object_set (G_OBJECT(column), "resizable", TRUE, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (results), column); -*/ - - select = gtk_tree_view_get_selection (GTK_TREE_VIEW (results)); - gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE); - g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)buddy_selection_changed,w); -/* -#if GTK_CHECK_VERSION(2,12,0) - gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(results),LOOKUP_RESULT_ADDRESS); -#endif -*/ - g_object_set_data(G_OBJECT(w),"SipSetupContext",ctx); - g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_buddy_lookup_window_destroyed,w); - //g_signal_connect_swapped(G_OBJECT(w),"destroy",(GCallback)linphone_gtk_buddy_lookup_window_destroyed,w); - gtk_progress_bar_set_fraction(pb,0); - gtk_progress_bar_set_text(pb,NULL); - gtk_dialog_add_button(GTK_DIALOG(w),GTK_STOCK_CLOSE,GTK_RESPONSE_CLOSE); - g_object_set_data(G_OBJECT(w),"last_state",GINT_TO_POINTER(-1)); - - gtk_widget_show(w); - return w; -} - - -void linphone_gtk_buddy_lookup_set_keyword(GtkWidget *w, const char *kw){ - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"keyword")),kw); -} - -static gboolean linphone_gtk_process_buddy_lookup(GtkWidget *w){ - BuddyLookupStatus bls; - SipSetupContext *ctx; - int last_state; - gchar *tmp; - bctbx_list_t *results=NULL; - GtkProgressBar *pb=GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")); - BuddyLookupRequest *req=(BuddyLookupRequest*)g_object_get_data(G_OBJECT(w),"buddylookup_request"); - - ctx=(SipSetupContext*)g_object_get_data(G_OBJECT(w),"SipSetupContext"); - last_state=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"last_state")); - - if (req==NULL) { - g_object_set_data(G_OBJECT(w),"buddylookup_processing",GINT_TO_POINTER(0)); - return FALSE; - } - bls=req->status; - if (last_state==(int)bls) return TRUE; - - switch(bls){ - case BuddyLookupNone: - gtk_progress_bar_set_fraction(pb,0); - gtk_progress_bar_set_text(pb,NULL); - break; - case BuddyLookupFailure: - gtk_progress_bar_set_fraction(pb,0); - gtk_progress_bar_set_text(pb,_("Error communicating with server.")); - break; - case BuddyLookupConnecting: - gtk_progress_bar_set_fraction(pb,0.2); - gtk_progress_bar_set_text(pb,_("Connecting...")); - break; - case BuddyLookupConnected: - gtk_progress_bar_set_fraction(pb,0.4); - gtk_progress_bar_set_text(pb,_("Connected")); - break; - case BuddyLookupReceivingResponse: - gtk_progress_bar_set_fraction(pb,0.8); - gtk_progress_bar_set_text(pb,_("Receiving data...")); - break; - case BuddyLookupDone: - results=req->results; - linphone_gtk_display_lookup_results( - linphone_gtk_get_widget(w,"search_results"), - results); - gtk_progress_bar_set_fraction(pb,1); - tmp=g_strdup_printf(ngettext("Found %u contact", "Found %u contacts", - (unsigned int)bctbx_list_size(results)), (unsigned int)bctbx_list_size(results)); - gtk_progress_bar_set_text(pb,tmp); - g_free(tmp); - sip_setup_context_buddy_lookup_free(ctx,req); - g_object_set_data(G_OBJECT(w),"buddylookup_request",NULL); - break; - } - g_object_set_data(G_OBJECT(w),"last_state",GINT_TO_POINTER(bls)); - return TRUE; -} - -static gboolean keyword_typing_finished(GtkWidget *w){ - guint tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"typing_timeout")); - const char *keyword; - SipSetupContext *ctx; - if (tid!=0){ - g_source_remove(tid); - } - keyword=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"keyword"))); - if (strlen(keyword)>=1){ - BuddyLookupRequest *req; - guint tid2; - ctx=(SipSetupContext*)g_object_get_data(G_OBJECT(w),"SipSetupContext"); - req=(BuddyLookupRequest*)g_object_get_data(G_OBJECT(w),"buddylookup_request"); - if (req!=NULL){ - sip_setup_context_buddy_lookup_free(ctx,req); - } - req=sip_setup_context_create_buddy_lookup_request(ctx); - buddy_lookup_request_set_key(req,keyword); - sip_setup_context_buddy_lookup_submit(ctx,req); - g_object_set_data(G_OBJECT(w),"buddylookup_request",req); - if (g_object_get_data(G_OBJECT(w),"buddylookup_processing")==NULL){ - tid2=g_timeout_add(20,(GSourceFunc)linphone_gtk_process_buddy_lookup,w); - g_object_set_data(G_OBJECT(w),"buddylookup_processing",GINT_TO_POINTER(tid2)); - } - } - return FALSE; -} - -void linphone_gtk_keyword_changed(GtkEditable *e){ - GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(e)); - guint tid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"typing_timeout")); - if (tid!=0){ - g_source_remove(tid); - } - tid=g_timeout_add(2000,(GSourceFunc)keyword_typing_finished,w); - g_object_set_data(G_OBJECT(w),"typing_timeout",GINT_TO_POINTER(tid)); -} - -static void linphone_gtk_display_lookup_results(GtkWidget *w, const bctbx_list_t *results){ - GtkTreeStore *store; - GtkTreeIter iter; - gchar *tmp; - const bctbx_list_t *elem; - store=GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(w))); - gtk_tree_store_clear(store); - disable_add_buddy_button(gtk_widget_get_toplevel(w)); - for(elem=results;elem!=NULL;elem=elem->next){ - BuddyInfo *bi=(BuddyInfo*)elem->data; - GdkPixbuf *pbuf; - GtkTreeIter depth1; - gtk_tree_store_append(store,&iter,NULL); - tmp=g_strdup_printf("%s, %s (%s)",bi->firstname,bi->lastname,bi->displayname); - gtk_tree_store_set(store,&iter,LOOKUP_RESULT_NAME, tmp,-1); - g_free(tmp); - gtk_tree_store_set(store,&iter,LOOKUP_RESULT_SIP_URI, bi->sip_uri,-1); - tmp=g_strdup_printf("%s, %s %s\n%s",bi->address.street, bi->address.zip, bi->address.town, bi->address.country); - gtk_tree_store_set(store,&iter,LOOKUP_RESULT_ADDRESS, tmp,-1); - g_free(tmp); - if (bi->image_data!=NULL){ - pbuf=_gdk_pixbuf_new_from_memory_at_scale(bi->image_data,bi->image_length,-1,40,TRUE); - if (pbuf) { - gtk_tree_store_set(store,&iter,LOOKUP_RESULT_ICON,pbuf,-1); - g_object_unref(G_OBJECT(pbuf)); - } - } - gtk_tree_store_append(store,&depth1,&iter); - tmp=g_strdup_printf("%s, %s (%s)\n%s, %s %s\n%s\n%s", - bi->firstname,bi->lastname,bi->displayname,bi->address.street, - bi->address.zip, bi->address.town, bi->address.country,bi->sip_uri); - gtk_tree_store_set(store,&depth1,LOOKUP_RESULT_NAME,tmp,-1); - g_free(tmp); - if (bi->image_data!=NULL){ - pbuf=_gdk_pixbuf_new_from_memory_at_scale(bi->image_data,bi->image_length,-1,-1,TRUE); - if (pbuf) { - gtk_tree_store_set(store,&depth1,LOOKUP_RESULT_ICON,pbuf,-1); - g_object_unref(G_OBJECT(pbuf)); - } - } - } -} - -void linphone_gtk_add_buddy_from_database(GtkWidget *button){ - GtkWidget *w=gtk_widget_get_toplevel(button); - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model; - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"search_results"))); - if (gtk_tree_selection_get_selected (select, &model, &iter)) - { - char *uri; - char *name; - char *addr; - LinphoneFriend *lf; - LinphoneCore *lc = linphone_gtk_get_core(); - int presence=linphone_gtk_get_ui_config_int("use_subscribe_notify",1); - gtk_tree_model_get (model, &iter,LOOKUP_RESULT_SIP_URI , &uri,LOOKUP_RESULT_NAME, &name, -1); - addr=g_strdup_printf("%s <%s>",name,uri); - - lf=linphone_core_create_friend_with_address(lc, addr); - linphone_friend_set_inc_subscribe_policy(lf,presence ? LinphoneSPAccept : LinphoneSPDeny); - linphone_friend_send_subscribe(lf,presence); - linphone_core_add_friend(lc, lf); - linphone_gtk_show_friends(); - g_free(addr); - g_free(uri); - g_free(name); - } -} - -/*called when double clicking on a contact */ -void linphone_gtk_buddy_lookup_contact_activated(GtkWidget *treeview){ - linphone_gtk_add_buddy_from_database(treeview); - gtk_widget_destroy(gtk_widget_get_toplevel(treeview)); -} diff --git a/gtk/buddylookup.ui b/gtk/buddylookup.ui deleted file mode 100644 index c32727b05..000000000 --- a/gtk/buddylookup.ui +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - 5 - Search contacts in directory - center-on-parent - dialog - False - - - - True - 2 - - - True - 5 - 0 - - - True - 12 - - - True - - - True - True - True - - - - False - 0 - - - - - True - True - automatic - automatic - etched-in - - - 512 - 140 - True - True - - - - - - 6 - 1 - - - - - True - True - True - - - False - 2 - - - - - True - - - True - False - True - True - - - - True - - - True - gtk-add - - - False - False - 0 - - - - - True - Add to my list - - - 1 - - - - - - - False - False - 5 - 0 - - - - - False - False - 3 - - - - - - - - - True - <b>Search somebody</b> - True - - - - - 1 - - - - - True - end - - - - - - - - - False - end - 0 - - - - - - diff --git a/gtk/call_logs.ui b/gtk/call_logs.ui deleted file mode 100644 index 23184841a..000000000 --- a/gtk/call_logs.ui +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - 500 - 370 - False - 5 - Call history - center-on-parent - dialog - - - True - False - 2 - - - True - False - end - - - Clear all - True - True - True - False - image1 - - - False - False - 0 - - - - - Call back - True - True - True - False - - - False - False - 1 - - - - - gtk-close - True - True - True - False - True - - - False - False - 2 - - - - - False - True - end - 0 - - - - - True - True - never - automatic - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - - - - - True - True - 1 - - - - - - button1 - call_back_button - call_logs_close - - - - - - - - - - - - True - False - gtk-clear - - diff --git a/gtk/call_statistics.ui b/gtk/call_statistics.ui deleted file mode 100644 index d53c93a1f..000000000 --- a/gtk/call_statistics.ui +++ /dev/null @@ -1,293 +0,0 @@ - - - - - - 5 - Call statistics - dialog - - - - True - 2 - - - True - 0 - none - - - True - 12 - - - True - 10 - 2 - True - - - True - Audio codec - - - 1 - 2 - - - - - - True - Video codec - - - 2 - 3 - - - - - - True - Audio IP bandwidth usage - - - 3 - 4 - - - - - - True - - - 1 - 2 - 1 - 2 - - - - - True - - - 1 - 2 - 2 - 3 - - - - - True - - - 1 - 2 - 3 - 4 - - - - - True - Audio Media connectivity - - - 5 - 6 - - - - - - True - - - 1 - 2 - 5 - 6 - - - - - True - Video IP bandwidth usage - - - 4 - 5 - - - - - - True - - - 1 - 2 - 4 - 5 - - - - - True - Video Media connectivity - - - 6 - 7 - - - - - True - - - 1 - 2 - 6 - 7 - - - - - True - Round trip time - - - 7 - 8 - - - - - True - - - 1 - 2 - 7 - 8 - - - - - True - Video resolution received - - - 8 - 9 - - - - - True - - - 1 - 2 - 8 - 9 - - - - - True - Video resolution sent - - - 9 - 10 - - - - - True - - - 1 - 2 - 9 - 10 - - - - - True - RTP profile - - - - - - - - True - - - 1 - 2 - - - - - - - - - True - <b>Call statistics and information</b> - True - - - - - False - False - 1 - - - - - True - end - - - - - - gtk-close - True - True - True - True - - - False - False - 1 - - - - - False - end - 0 - - - - - - button1 - - - diff --git a/gtk/callee_frame.ui b/gtk/callee_frame.ui deleted file mode 100644 index 4ae4d90ef..000000000 --- a/gtk/callee_frame.ui +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 12 - - - True - False - - - True - False - - - True - True - - - False - False - 0 - - - - - False - True - 0 - - - - - True - False - <b>Callee name</b> - True - right - end - - - True - True - 1 - - - - - 90 - 30 - True - False - - - False - True - 2 - - - - - - - - - - - - - diff --git a/gtk/calllogs.c b/gtk/calllogs.c deleted file mode 100644 index 9ee24eba8..000000000 --- a/gtk/calllogs.c +++ /dev/null @@ -1,424 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" -#include - -#define CONFIG_FILE ".linphone-call-history.db" - -char *linphone_gtk_call_logs_storage_get_db_file(const char *filename){ - const int path_max=1024; - char *db_file=NULL; - - db_file=(char *)g_malloc(path_max*sizeof(char)); - if (filename==NULL) filename=CONFIG_FILE; - /*try accessing a local file first if exists*/ - if (bctbx_file_exist(CONFIG_FILE)==0){ - snprintf(db_file,path_max,"%s",filename); - }else{ -#ifdef _WIN32 - const char *appdata=getenv("APPDATA"); - if (appdata){ - snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); - CreateDirectory(db_file,NULL); - snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); - } -#else - const char *home=getenv("HOME"); - if (home==NULL) home="."; - snprintf(db_file,path_max,"%s/%s",home,filename); -#endif - } - return db_file; -} - -static void fill_renderers(GtkTreeView *v){ - GtkTreeViewColumn *c; - GtkCellRenderer *r; - - r=gtk_cell_renderer_pixbuf_new(); - c=gtk_tree_view_column_new_with_attributes("icon",r,"icon-name",0,NULL); - gtk_tree_view_append_column (v,c); - - r=gtk_cell_renderer_text_new (); - c=gtk_tree_view_column_new_with_attributes("sipaddress",r,"markup",1,NULL); - gtk_tree_view_append_column (v,c); -} - -void call_log_selection_changed(GtkTreeView *v){ - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model=NULL; - - select = gtk_tree_view_get_selection(v); - if (select!=NULL){ - if (gtk_tree_selection_get_selected (select, &model, &iter)){ - GtkTreePath *path=gtk_tree_model_get_path(model,&iter); - gtk_tree_view_collapse_all(v); - gtk_tree_view_expand_row(v,path,TRUE); - gtk_tree_path_free(path); - } - } -} - -void linphone_gtk_call_log_chat_selected(GtkWidget *w){ - GtkTreeSelection *select; - GtkTreeIter iter; - - select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); - if (select!=NULL){ - GtkTreeModel *model=NULL; - if (gtk_tree_selection_get_selected (select,&model,&iter)){ - gpointer pcl; - LinphoneAddress *la; - LinphoneCallLog *cl; - gtk_tree_model_get(model,&iter,2,&pcl,-1); - cl = (LinphoneCallLog *)pcl; - la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl); - if (la != NULL){ - linphone_gtk_friend_list_set_chat_conversation(la); - } - } - } -} - -void linphone_gtk_call_log_add_contact(GtkWidget *w){ - GtkWidget *main_window = gtk_widget_get_toplevel(w); - GtkTreeSelection *select; - GtkTreeIter iter; - - select=gtk_tree_view_get_selection(GTK_TREE_VIEW(w)); - if (select!=NULL){ - GtkTreeModel *model=NULL; - if (gtk_tree_selection_get_selected (select,&model,&iter)){ - gpointer pcl; - LinphoneAddress *la; - LinphoneCallLog *cl; - LinphoneFriend *lf; - gtk_tree_model_get(model,&iter,2,&pcl,-1); - cl = (LinphoneCallLog *)pcl; - la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl); - if (la != NULL){ - char *uri=linphone_address_as_string(la); - lf=linphone_core_create_friend_with_address(linphone_gtk_get_core(), uri); - linphone_gtk_show_contact(lf, main_window); - ms_free(uri); - } - } - } -} - -static bool_t put_selection_to_uribar(GtkWidget *treeview){ - GtkTreeSelection *sel; - sel=gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - if (sel!=NULL){ - GtkTreeModel *model=NULL; - GtkTreeIter iter; - if (gtk_tree_selection_get_selected (sel,&model,&iter)){ - char *tmp; - gpointer pcl; - LinphoneAddress *la; - LinphoneCallLog *cl; - gtk_tree_model_get(model,&iter,2,&pcl,-1); - 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) - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),tmp); - ms_free(tmp); - return TRUE; - } - } - return FALSE; -} - -static void linphone_gtk_call_selected(GtkTreeView *treeview){ - put_selection_to_uribar(GTK_WIDGET(treeview)); - linphone_gtk_start_call(linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(treeview)), - "start_call")); -} - -static GtkWidget *linphone_gtk_create_call_log_menu(GtkWidget *call_log){ - GtkWidget *menu=NULL; - GtkWidget *menu_item; - gchar *call_label=NULL; - gchar *text_label=NULL; - gchar *add_contact_label=NULL; - gchar *name=NULL; - GtkWidget *image; - GtkTreeSelection *select; - GtkTreeIter iter; - - select=gtk_tree_view_get_selection(GTK_TREE_VIEW(call_log)); - if (select!=NULL){ - GtkTreeModel *model=NULL; - if (gtk_tree_selection_get_selected (select,&model,&iter)){ - gpointer pcl; - LinphoneAddress *la; - LinphoneCallLog *cl; - gtk_tree_model_get(model,&iter,2,&pcl,-1); - cl = (LinphoneCallLog *)pcl; - la = linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl); - name=linphone_address_as_string(la); - call_label=g_strdup_printf(_("Call %s"),name); - text_label=g_strdup_printf(_("Send text to %s"),name); - if (!linphone_gtk_is_friend(linphone_gtk_get_core(), name)) { - add_contact_label=g_strdup_printf(_("Add %s to your contact list"),name); - } - ms_free(name); - menu=gtk_menu_new(); - } - } - if (menu && call_label){ - menu_item=gtk_image_menu_item_new_with_label(call_label); - image=gtk_image_new_from_icon_name("linphone-start-call",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_call_selected,call_log); - } - if (menu && text_label){ - menu_item=gtk_image_menu_item_new_with_label(text_label); - image=gtk_image_new_from_icon_name("linphone-start-chat",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_call_log_chat_selected,call_log); - } - if (menu && add_contact_label){ - menu_item=gtk_image_menu_item_new_with_label(add_contact_label); - image=gtk_image_new_from_icon_name("linphone-contact-add",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_call_log_add_contact,call_log); - } - if (menu) { - gtk_widget_show(menu); - gtk_menu_attach_to_widget(GTK_MENU(menu),call_log, NULL); - } - - if (add_contact_label) g_free(add_contact_label); - if (call_label) g_free(call_label); - if (text_label) g_free(text_label); - return menu; -} - -gboolean linphone_gtk_call_log_popup_contact(GtkWidget *list, GdkEventButton *event){ - GtkWidget *m=linphone_gtk_create_call_log_menu(list); - if (m) { - gtk_menu_popup (GTK_MENU (m), NULL, NULL, NULL, NULL, - event ? event->button : 0, event ? event->time : gtk_get_current_event_time()); - return TRUE; - } - return FALSE; -} - -gboolean linphone_gtk_call_log_button_pressed(GtkWidget *widget, GdkEventButton *event){ - if (event->button == 3 && event->type == GDK_BUTTON_PRESS){ - return linphone_gtk_call_log_popup_contact(widget, event); - } - return FALSE; -} - -void linphone_gtk_call_log_clear_missed_call(void){ - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *label = linphone_gtk_get_widget(mw, "history_tab_label"); - gtk_label_set_text(GTK_LABEL(label), _("Recent calls")); -} - -gboolean linphone_gtk_call_log_reset_missed_call(GtkWidget *w, GdkEvent *event,gpointer user_data){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(mw,"viewswitch")); - gtk_notebook_set_current_page(notebook,0); - linphone_core_reset_missed_calls_count(linphone_gtk_get_core()); - linphone_gtk_call_log_clear_missed_call(); - return TRUE; -} - -void linphone_gtk_call_log_display_missed_call(int nb){ - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *label = linphone_gtk_get_widget(mw, "history_tab_label"); - gchar *buf = g_markup_printf_escaped(_("Recent calls (%i)"), nb); - gtk_label_set_markup(GTK_LABEL(label), buf); -} - -void linphone_gtk_call_log_update(GtkWidget *w){ - GtkTreeView *v=GTK_TREE_VIEW(linphone_gtk_get_widget(w,"logs_view")); - GtkTreeStore *store; - const MSList *logs; - GtkTreeSelection *select; - GtkWidget *notebook=linphone_gtk_get_widget(w,"viewswitch"); - gint nb; - - store=(GtkTreeStore*)gtk_tree_view_get_model(v); - if (store==NULL){ - store=gtk_tree_store_new(3,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_POINTER,G_TYPE_STRING); - gtk_tree_view_set_model(v,GTK_TREE_MODEL(store)); - g_object_unref(G_OBJECT(store)); - fill_renderers(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"logs_view"))); - select=gtk_tree_view_get_selection(v); - gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE); - g_signal_connect_swapped(G_OBJECT(select),"changed",(GCallback)call_log_selection_changed,v); - g_signal_connect(G_OBJECT(notebook),"focus-tab",(GCallback)linphone_gtk_call_log_reset_missed_call,NULL); - g_signal_connect(G_OBJECT(v),"button-press-event",(GCallback)linphone_gtk_call_log_button_pressed,NULL); - } - nb=linphone_core_get_missed_calls_count(linphone_gtk_get_core()); - if(nb > 0) - linphone_gtk_call_log_display_missed_call(nb); - gtk_tree_store_clear (store); - - for (logs=linphone_core_get_call_logs(linphone_gtk_get_core());logs!=NULL;logs=logs->next){ - LinphoneCallLog *cl=(LinphoneCallLog*)logs->data; - GtkTreeIter iter, iter2; - LinphoneAddress *la=linphone_call_log_get_dir(cl)==LinphoneCallIncoming ? linphone_call_log_get_from(cl) : linphone_call_log_get_to(cl); - char *addr= linphone_address_as_string(la); - const char *display; - gchar *logtxt, *headtxt, *minutes, *seconds; - gchar quality[20]; - const char *status=NULL; - gchar *start_date=NULL; - LinphoneFriend *lf=NULL; - int duration=linphone_call_log_get_duration(cl); - time_t start_date_time=linphone_call_log_get_start_date(cl); - const gchar *call_status_icon_name; - -#if GLIB_CHECK_VERSION(2,30,0) // The g_date_time_format function exists since 2.26.0 but the '%c' format is only supported since 2.30.0 - if (start_date_time){ - GDateTime *dt=g_date_time_new_from_unix_local(start_date_time); - start_date=g_date_time_format(dt,"%c"); - g_date_time_unref(dt); - } -#else - start_date=g_strdup(ctime(&start_date_time)); - if (start_date[strlen(start_date) - 1] == '\n') { - start_date[strlen(start_date) - 1] = '\0'; - } -#endif - lf=linphone_core_find_friend(linphone_gtk_get_core(),la); - if(lf != NULL){ - /*update display name from friend*/ - display = linphone_friend_get_name(lf); - if (display != NULL) linphone_address_set_display_name(la, display); - } else { - display=linphone_address_get_display_name(la); - } - if (display==NULL){ - display=linphone_address_get_username (la); - if (display==NULL){ - display=linphone_address_get_domain (la); - } - } - - if (linphone_call_log_get_quality(cl)!=-1){ - snprintf(quality,sizeof(quality),"%.1f",linphone_call_log_get_quality(cl)); - }else snprintf(quality,sizeof(quality)-1,"%s",_("n/a")); - switch(linphone_call_log_get_status(cl)){ - case LinphoneCallAborted: - status=_("Aborted"); - break; - case LinphoneCallMissed: - status=_("Missed"); - break; - case LinphoneCallDeclined: - status=_("Declined"); - break; - case LinphoneCallAnsweredElsewhere: - status=_("Answered elsewhere"); - break; - case LinphoneCallDeclinedElsewhere: - status=_("Declined elsewhere"); - break; - default: - break; - } - minutes=g_markup_printf_escaped( - ngettext("%i minute", "%i minutes", duration/60), - duration/60); - seconds=g_markup_printf_escaped( - ngettext("%i second", "%i seconds", duration%60), - duration%60); - if (status==NULL) { - headtxt=g_markup_printf_escaped("%s\t%s",display,start_date ? start_date : ""); - logtxt=g_markup_printf_escaped( - _("%s\t" - "Quality: %s\n%s\t%s\t"), - addr, quality, minutes, seconds); - } else { - headtxt=g_markup_printf_escaped(_("%s\t%s"),display,start_date ? start_date : ""); - logtxt=g_markup_printf_escaped( - "%s\t" - "\n%s",addr, status); - } - g_free(minutes); - g_free(seconds); - if (start_date) g_free(start_date); - gtk_tree_store_append (store,&iter,NULL); - call_status_icon_name = linphone_call_log_get_dir(cl) == LinphoneCallOutgoing ? - "linphone-call-status-outgoing" : "linphone-call-status-incoming"; - gtk_tree_store_set (store,&iter, - 0, call_status_icon_name, - 1, headtxt,2,cl,-1); - gtk_tree_store_append (store,&iter2,&iter); - gtk_tree_store_set (store,&iter2,1,logtxt,-1); - ms_free(addr); - g_free(logtxt); - g_free(headtxt); - } -} - -void linphone_gtk_history_row_activated(GtkWidget *treeview){ - if (put_selection_to_uribar(treeview)){ - GtkWidget *mw=linphone_gtk_get_main_window(); - linphone_gtk_start_call(linphone_gtk_get_widget(mw,"start_call")); - } -} - -void linphone_gtk_history_row_selected(GtkWidget *treeview){ - put_selection_to_uribar(treeview); -} - -void linphone_gtk_clear_call_logs(GtkWidget *button){ - linphone_core_clear_call_logs (linphone_gtk_get_core()); - linphone_gtk_call_log_clear_missed_call(); - linphone_gtk_call_log_update(gtk_widget_get_toplevel(button)); -} - -void linphone_gtk_call_log_callback(GtkWidget *button){ - GtkWidget *mw=linphone_gtk_get_main_window(); - if (put_selection_to_uribar(linphone_gtk_get_widget(mw,"logs_view"))) - linphone_gtk_start_call(linphone_gtk_get_widget(mw,"start_call")); -} - -void linphone_gtk_call_log_response(GtkWidget *w, guint response_id){ - GtkWidget *mw=linphone_gtk_get_main_window(); - if (response_id==1){ - if (put_selection_to_uribar(linphone_gtk_get_widget(w,"logs_view"))) - linphone_gtk_start_call(linphone_gtk_get_widget(mw,"start_call")); - }else if (response_id==2){ - linphone_core_clear_call_logs (linphone_gtk_get_core()); - linphone_gtk_call_log_update(w); - return; - } - g_object_set_data(G_OBJECT(mw),"call_logs",NULL); - gtk_widget_destroy(w); -} diff --git a/gtk/chat.c b/gtk/chat.c deleted file mode 100644 index 9a15c8236..000000000 --- a/gtk/chat.c +++ /dev/null @@ -1,683 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" -#include - -#ifdef HAVE_GTK_OSX -#include -#endif - -#if defined(_WIN32) && !defined(F_OK) -#define F_OK 00 /*visual studio does not define F_OK*/ -#endif - -#define NB_MSG_HIST 250000 - -#define CONFIG_FILE ".linphone-history.db" - -#include "regex.h" - -GRegex *uri_regex = NULL; - -static void free_uri_regex(void) { - if(uri_regex) g_regex_unref(uri_regex); -} - -static const GRegex *get_uri_regex(void) { - const gchar *pattern = BC_REGEX_URI; - GError *error = NULL; - if(uri_regex == NULL) { - uri_regex = g_regex_new(pattern, G_REGEX_OPTIMIZE, 0, &error); - if(error) { - g_warning("Could not parse regex pattern for URIs: %s", error->message); - g_error_free(error); - uri_regex = NULL; - return NULL; - } - atexit(free_uri_regex); - } - return uri_regex; -} - -char *linphone_gtk_message_storage_get_db_file(const char *filename){ - const int path_max=1024; - char *db_file=NULL; - - db_file=(char *)g_malloc(path_max*sizeof(char)); - if (filename==NULL) filename=CONFIG_FILE; - /*try accessing a local file first if exists*/ - if (bctbx_file_exist(CONFIG_FILE)==0){ - snprintf(db_file,path_max,"%s",filename); - }else{ -#ifdef _WIN32 - const char *appdata=getenv("APPDATA"); - if (appdata){ - snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); - CreateDirectory(db_file,NULL); - snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); - } -#else - const char *home=getenv("HOME"); - if (home==NULL) home="."; - snprintf(db_file,path_max,"%s/%s",home,filename); -#endif - } - return db_file; -} - -void linphone_gtk_mark_chat_read(LinphoneChatRoom *cr) { - linphone_chat_room_mark_as_read(cr); -#ifdef __APPLE__ - linphone_gtk_update_badge_count(); -#endif -} - -void linphone_gtk_quit_chatroom(LinphoneChatRoom *cr) { - GtkWidget *main_window=linphone_gtk_get_main_window (); - GtkWidget *nb=linphone_gtk_get_widget(main_window,"viewswitch"); - GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); - GtkWidget *w=g_object_get_data(G_OBJECT(friendlist),"chatview"); - gchar *from; - - g_return_if_fail(w!=NULL); - gtk_notebook_remove_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb),w)); - linphone_gtk_mark_chat_read(cr); - g_object_set_data(G_OBJECT(friendlist),"chatview",NULL); - from=g_object_get_data(G_OBJECT(w),"from_message"); - if (from){ - g_object_set_data(G_OBJECT(w),"from_message",NULL); - g_free(from); - } - g_object_set_data(G_OBJECT(w),"cr",NULL); - linphone_gtk_friend_list_set_active_address(NULL); - gtk_widget_destroy(w); -} - -const char* get_display_name(const LinphoneAddress *from){ - const char *display; - display=linphone_address_get_display_name(from); - if (display==NULL || display[0]=='\0') { - display=linphone_address_get_username(from); - } - return display; -} - -GtkWidget *create_tab_chat_header(LinphoneChatRoom *cr, const LinphoneAddress *uri){ - GtkWidget *tab_header = linphone_gtk_make_tab_header(get_display_name(uri), "linphone-start-chat", TRUE, G_CALLBACK(linphone_gtk_quit_chatroom), cr); - gtk_widget_show_all(tab_header); - return tab_header; -} - -void update_chat_header(GtkNotebook *notebook, GtkWidget *chat_view, LinphoneChatRoom *cr, const LinphoneAddress *uri) { - GtkWidget *header = linphone_gtk_make_tab_header(get_display_name(uri), "linphone-start-chat", TRUE, G_CALLBACK(linphone_gtk_quit_chatroom), cr); - gtk_widget_show_all(header); - gtk_notebook_set_tab_label(notebook, chat_view, header); -} - -static gboolean scroll_to_end(GtkTextView *w){ - GtkTextBuffer *buffer=gtk_text_view_get_buffer(w); - GtkTextIter iter; - gtk_text_buffer_get_end_iter(buffer,&iter); - gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (w), &iter, 0.0, FALSE, 0, 0); - return FALSE; -} - -static void write_body(GtkTextBuffer *buffer, GtkTextIter *iter, const gchar *text, gint len, gboolean is_me, gboolean is_link) { - const char *me_tag_name = is_me ? "me" : NULL; - const char *link_tag_name = is_link ? "link" : NULL; - if(me_tag_name) { - gtk_text_buffer_insert_with_tags_by_name(buffer, iter, text, len, "body", me_tag_name, link_tag_name, NULL); - } else { - gtk_text_buffer_insert_with_tags_by_name(buffer, iter, text, len, "body", link_tag_name, NULL); - } -} - -void linphone_gtk_push_text(GtkWidget *w, const LinphoneAddress *from, - gboolean me,LinphoneChatRoom *cr,LinphoneChatMessage *msg, gboolean hist){ - GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(w,"textview")); - GtkTextBuffer *buffer=gtk_text_view_get_buffer(text); - GtkTextIter iter; - char *from_str=linphone_address_as_string_uri_only(from); - gchar *from_message=(gchar *)g_object_get_data(G_OBJECT(w),"from_message"); - GHashTable *table=(GHashTable*)g_object_get_data(G_OBJECT(w),"table"); - const GRegex *uri_regex = get_uri_regex(); - GMatchInfo *match_info = NULL; - const char *message = linphone_chat_message_get_text(msg); - const char *external_body_url = linphone_chat_message_get_external_body_url(msg); - time_t t; - char buf[80]; - time_t tnow; - struct tm *tm; - int tnow_day; - int tnow_year; - int pos = 0, start, end; - - gtk_text_buffer_get_end_iter(buffer, &iter); - if (g_strcmp0(from_message,from_str)!=0){ - gtk_text_buffer_insert_with_tags_by_name(buffer, &iter, get_display_name(from), -1, - "from", me ? "me" : NULL, NULL); - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter, " : ", -1, - "from", me ? "me" : NULL, NULL); - gtk_text_buffer_insert(buffer,&iter,"\n",-1); - g_free(from_message); - g_object_set_data(G_OBJECT(w),"from_message",g_strdup(from_str)); - } - ms_free(from_str); - - if (external_body_url) message = external_body_url; - - // Inserts message body and tags URIs as hypertext links - if(message) { - g_regex_match(uri_regex, message, 0, &match_info); - while(g_match_info_matches(match_info)) { - g_match_info_fetch_pos(match_info, 0, &start, &end); - if(pos < start) write_body(buffer, &iter, &message[pos], start-pos, me, FALSE); - write_body(buffer, &iter, &message[start], end-start, me, TRUE); - pos = end; - g_match_info_next(match_info, NULL); - } - if((size_t)pos < strlen(message)) write_body(buffer, &iter, &message[pos], -1, me, FALSE); - gtk_text_buffer_insert(buffer,&iter,"\n",-1); - g_match_info_free(match_info); - } - - g_hash_table_insert(table,GUINT_TO_POINTER(linphone_chat_message_get_storage_id(msg)),GINT_TO_POINTER(gtk_text_iter_get_line(&iter))); - switch (linphone_chat_message_get_state (msg)){ - case LinphoneChatMessageStateInProgress: - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,_("Sending..."),-1,"status", me ? "me" : NULL, NULL); - break; - case LinphoneChatMessageStateDelivered: - t=linphone_chat_message_get_time(msg); - tnow=time(NULL); - tm=localtime(&tnow); - tnow_day=tm->tm_yday; - tnow_year=tm->tm_year; - tm=localtime(&t); - if(tnow_day != tm->tm_yday || (tnow_day == tm->tm_yday && tnow_year != tm->tm_year)) { - strftime(buf,80,"%a %x, %H:%M",tm); - } else { - strftime(buf,80,"%H:%M:%S",tm); - } - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,buf,-1,"status", me ? "me" : NULL, NULL); - break; - case LinphoneChatMessageStateNotDelivered: - gtk_text_buffer_insert_with_tags_by_name(buffer,&iter,_("Message not sent"),-1,"status", me ? "me" : NULL, NULL); - break; - default: - break; - } - gtk_text_buffer_insert(buffer,&iter,"\n",-1); - g_idle_add((GSourceFunc)scroll_to_end,text); -} - -void update_chat_state_message(LinphoneChatMessageState state,LinphoneChatMessage *msg){ - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); - GtkWidget *page=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); - GHashTable *table=(GHashTable*)g_object_get_data(G_OBJECT(page),"table"); - - if (page!=NULL) { - char buf[80]; - time_t t; - struct tm *tm; - GtkTextView *text=GTK_TEXT_VIEW(linphone_gtk_get_widget(page,"textview")); - GtkTextBuffer *b=gtk_text_view_get_buffer(text); - GtkTextIter iter; - GtkTextIter end; - GtkTextIter start; - gint line; - gpointer hash_table_ptr = g_hash_table_lookup(table,GUINT_TO_POINTER(linphone_chat_message_get_storage_id(msg))); - if (hash_table_ptr != NULL) { - line = GPOINTER_TO_INT(hash_table_ptr); - gtk_text_buffer_get_iter_at_line(b,&iter,line); - if(gtk_text_iter_get_chars_in_line(&iter) >0) { - gtk_text_buffer_get_iter_at_line_offset(b,&start,line, - gtk_text_iter_get_chars_in_line(&iter)-1); - }else{ - gtk_text_buffer_get_iter_at_line_offset(b,&start,line,0); - } - gtk_text_buffer_get_iter_at_line_offset(b,&end,line,0); - gtk_text_buffer_delete(b,&start,&end); - gtk_text_buffer_get_iter_at_line(b,&iter,line); - - switch (state) { - case LinphoneChatMessageStateInProgress: - gtk_text_buffer_insert_with_tags_by_name(b,&iter,_("Sending..."),-1,"status", "me", NULL); - break; - case LinphoneChatMessageStateDelivered: - t=time(NULL); - tm=localtime(&t); - strftime(buf,80,"%H:%M:%S",tm); - gtk_text_buffer_insert_with_tags_by_name(b,&iter,(gchar*)buf,-1,"status", "me", NULL); - break; - case LinphoneChatMessageStateNotDelivered: - gtk_text_buffer_insert_with_tags_by_name(b,&iter,_("Message not sent"),-1,"status", "me", NULL); - break; - default: - break; - } - } - } -} - -static void on_chat_state_changed(LinphoneChatMessage *msg, LinphoneChatMessageState state){ - update_chat_state_message(state,msg); -} - -void linphone_gtk_compose_text(void) { - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); - GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); - LinphoneChatRoom *cr=g_object_get_data(G_OBJECT(w),"cr"); - if (cr) { - linphone_chat_room_compose(cr); - linphone_gtk_mark_chat_read(cr); - linphone_gtk_friend_list_update_button_display(GTK_TREE_VIEW(friendlist)); - } -} - -void linphone_gtk_send_text(void){ - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); - GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); - GtkWidget *entry=linphone_gtk_get_widget(w,"text_entry"); - const gchar *entered; - LinphoneChatRoom *cr=g_object_get_data(G_OBJECT(w),"cr"); - entered=gtk_entry_get_text(GTK_ENTRY(entry)); - if (strlen(entered)>0) { - LinphoneChatMessage *msg; - LinphoneChatMessageCbs *cbs; - msg=linphone_chat_message_ref(linphone_chat_room_create_message(cr,entered)); - cbs=linphone_chat_message_get_callbacks(msg); - linphone_chat_message_cbs_set_msg_state_changed(cbs,on_chat_state_changed); - linphone_chat_room_send_chat_message(cr,msg); - linphone_gtk_push_text(w,linphone_chat_message_get_from(msg), - TRUE,cr,msg,FALSE); - - // Disconnect and reconnect the "changed" signal to prevent triggering it when clearing the text entry. - g_signal_handlers_disconnect_by_func(G_OBJECT(entry),(GCallback)linphone_gtk_compose_text,NULL); - gtk_entry_set_text(GTK_ENTRY(entry),""); - g_signal_connect_swapped(G_OBJECT(entry),"changed",(GCallback)linphone_gtk_compose_text,NULL); - - linphone_chat_message_unref(msg); - } -} - -static void linphone_gtk_chat_message_destroy(LinphoneChatMessage *msg){ - linphone_chat_message_destroy(msg); -} - -void linphone_gtk_free_list(bctbx_list_t *messages){ - bctbx_list_for_each(messages,(void (*)(void*))linphone_gtk_chat_message_destroy); - bctbx_list_free(messages); -} - -void display_history_message(GtkWidget *chat_view,bctbx_list_t *messages,const LinphoneAddress *with){ - if (messages != NULL){ - bctbx_list_t *it; - char *from_str; - char *with_str; - gchar *tmp; - for(it=messages;it!=NULL;it=it->next){ - LinphoneChatMessage *msg=(LinphoneChatMessage *)it->data; - from_str=linphone_address_as_string_uri_only(linphone_chat_message_get_from(msg)); - with_str=linphone_address_as_string_uri_only(with); - linphone_gtk_push_text(chat_view,strcmp(from_str,with_str)==0? with : - linphone_chat_message_get_from(msg), - strcmp(from_str,with_str)==0? FALSE : TRUE, - linphone_chat_message_get_chat_room(msg),msg,TRUE); - ms_free(from_str); - ms_free(with_str); - } - tmp=g_object_get_data(G_OBJECT(chat_view),"from_message"); - if (tmp){ - g_object_set_data(G_OBJECT(chat_view),"from_message",NULL); - g_free(tmp); - } - - linphone_gtk_free_list(messages); - } -} - -static void linphone_gtk_chat_add_contact(const LinphoneAddress *addr){ - LinphoneFriend *lf=NULL; - LinphoneCore *lc = linphone_gtk_get_core(); - gboolean show_presence=FALSE; - char *uri=linphone_address_as_string(addr); - - lf=linphone_core_create_friend_with_address(lc, uri); - ms_free(uri); - - linphone_friend_set_inc_subscribe_policy(lf,LinphoneSPWait); - linphone_friend_send_subscribe(lf,show_presence); - - linphone_friend_set_address(lf,addr); - linphone_core_add_friend(lc, lf); - linphone_gtk_show_friends(); -} - -static GdkColor *_linphone_gtk_chatroom_get_link_color(GtkWidget *chatview) { - GValue color_value = {0}; - g_value_init(&color_value, GDK_TYPE_COLOR); - gtk_style_get_style_property( - gtk_widget_get_style(chatview), - G_OBJECT_TYPE(chatview), - "link-color", &color_value); - - return (GdkColor *)g_value_get_boxed(&color_value); -} - -static gboolean link_event_handler(GtkTextTag *tag, GObject *text_view,GdkEvent *event, GtkTextIter *iter, GtkWidget *chat_view) { - if(event->type == GDK_BUTTON_PRESS) { - GtkTextIter uri_begin = *iter; - GtkTextIter uri_end = *iter; - gchar *uri = NULL; - LinphoneChatRoom *chat_room = (LinphoneChatRoom *)g_object_get_data(G_OBJECT(chat_view), "cr"); - GtkWidget *main_window = linphone_gtk_get_main_window(); - GtkWidget *friendlist = linphone_gtk_get_widget(main_window, "contact_list"); - - gtk_text_iter_backward_to_tag_toggle(&uri_begin, tag); - gtk_text_iter_forward_to_tag_toggle(&uri_end, tag); - uri = gtk_text_iter_get_slice(&uri_begin, &uri_end); - if(((GdkEventButton *)event)->button == 1) { - linphone_gtk_open_browser(uri); - } else if(((GdkEventButton *)event)->button == 3) { - GtkMenu *menu = GTK_MENU(g_object_get_data(text_view, "link_ctx_menu")); - g_object_set_data_full(G_OBJECT(menu), "uri", g_strdup(uri), g_free); - gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 3, gdk_event_get_time(event)); - } - g_free(uri); - - linphone_gtk_mark_chat_read(chat_room); - linphone_gtk_friend_list_update_button_display(GTK_TREE_VIEW(friendlist)); - - return TRUE; - } - return FALSE; -} - -static void chatroom_enable_hand_cursor(GdkWindow *window, gboolean hand_cursor_enabled) { -#if GTK_CHECK_VERSION(2,22,0) - GdkCursor *cursor = gdk_window_get_cursor(window); - GdkCursor *new_cursor = NULL; - if(!hand_cursor_enabled && gdk_cursor_get_cursor_type(cursor) != GDK_XTERM) { - new_cursor = gdk_cursor_new(GDK_XTERM); - } else if(hand_cursor_enabled && gdk_cursor_get_cursor_type(cursor) != GDK_HAND1) { - new_cursor = gdk_cursor_new(GDK_HAND1); - } - if(new_cursor) { - gdk_window_set_cursor(window, new_cursor); - gdk_cursor_unref(new_cursor); - } -#endif -} - -static gboolean chatroom_event(GtkWidget *widget, GdkEvent *event, gpointer user_data) { - gint wx, wy, bx, by; - GtkTextView *chatroom = GTK_TEXT_VIEW(widget); - GtkTextBuffer *buffer = gtk_text_view_get_buffer(chatroom); - GtkTextTag *link_tag = gtk_text_tag_table_lookup(gtk_text_buffer_get_tag_table(buffer), "link"); - GdkWindow *window = gtk_text_view_get_window(chatroom, GTK_TEXT_WINDOW_TEXT); - GtkTextIter iter; - if(event->type == GDK_MOTION_NOTIFY) { - GdkEventMotion *motion_ev = (GdkEventMotion *)event; - wx = (gint)motion_ev->x; - wy = (gint)motion_ev->y; - gtk_text_view_window_to_buffer_coords(chatroom, GTK_TEXT_WINDOW_TEXT, wx, wy, &bx, &by); - gtk_text_view_get_iter_at_location(chatroom, &iter, bx, by); - if(gtk_text_iter_has_tag(&iter, link_tag)) { - chatroom_enable_hand_cursor(window, TRUE); - } else { - chatroom_enable_hand_cursor(window, FALSE); - } - } - return FALSE; -} - -static gboolean copy_uri_into_clipboard_handler(GtkMenuItem *menuitem, gpointer user_data) { - GtkWidget *menu = gtk_widget_get_parent(GTK_WIDGET(menuitem)); - const gchar *uri = (const gchar *)g_object_get_data(G_OBJECT(menu), "uri"); - GtkClipboard *clipboard = NULL; - GdkAtom clipboard_atom = gdk_atom_intern("CLIPBOARD", TRUE); - if(clipboard_atom == GDK_NONE) { - g_warning("Could not find CLIPBOARD atom"); - return FALSE; - } - clipboard = gtk_clipboard_get(clipboard_atom); - if(uri) gtk_clipboard_set_text(clipboard, uri, -1); - return FALSE; -} - -static void refresh_lime_icon(GtkWidget* chat_view, LinphoneChatRoom*cr) { - GtkWidget *lime_icon = linphone_gtk_get_widget(chat_view, "lime_icon"); - if (linphone_chat_room_lime_available(cr)) { - gtk_widget_show(lime_icon); - } else { - gtk_widget_hide(lime_icon); - } -} - -static gint linphone_gtk_window_focused(GtkWidget* widget, GdkEvent *event, gpointer user_data) { - // if we are in a chat, mark it as read - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(main_window,"contact_list"); - GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); - LinphoneChatRoom *cr=w?g_object_get_data(G_OBJECT(w),"cr"):NULL; - if (cr) { - linphone_gtk_mark_chat_read(cr); - } - refresh_lime_icon(w, cr); - return FALSE; -} - -GtkWidget* linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddress *with){ - GtkWidget *chat_view=linphone_gtk_create_widget("chatroom_frame"); - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch"); - GtkWidget *text=linphone_gtk_get_widget(chat_view,"textview"); - GdkColor color_grey = {0, 32512, 32512, 32512}; - GdkColor color_light_grey = {0, 56832, 60928, 61952}; - GdkColor color_black = {0}; - int idx; - GtkWidget *button; - GtkWidget *entry = linphone_gtk_get_widget(chat_view,"text_entry"); - bctbx_list_t *messages; - GHashTable *table; - GtkTextTag *tmp_tag; - GtkWidget *link_ctx_menu = gtk_menu_new(); - GtkWidget *link_ctx_menu_copy_item = gtk_menu_item_new_with_label(_("Copy")); - - gtk_notebook_append_page(notebook,chat_view,create_tab_chat_header(cr,with)); - idx = gtk_notebook_page_num(notebook, chat_view); - gtk_notebook_set_current_page(notebook, idx); - gtk_widget_show(chat_view); - table=g_hash_table_new_full(g_direct_hash,g_direct_equal,NULL,NULL); - g_object_set_data(G_OBJECT(chat_view),"cr",cr); - g_object_set_data(G_OBJECT(chat_view),"from_message",NULL); - g_object_set_data_full(G_OBJECT(chat_view),"table",table,(GDestroyNotify)g_hash_table_destroy); - - gtk_text_buffer_create_tag( - gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), - "me", - "foreground_gdk", &color_black, - "paragraph-background-gdk", &color_light_grey, - NULL); - - gtk_text_buffer_create_tag( - gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), - "from", - "weight", PANGO_WEIGHT_BOLD, - NULL); - - gtk_text_buffer_create_tag( - gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), - "body", - "indent", 10, - NULL); - - gtk_text_buffer_create_tag( - gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), - "status", - "size-points", 9.0, - "foreground_gdk", &color_grey, - "style", PANGO_STYLE_ITALIC, - "justification", GTK_JUSTIFY_RIGHT, - NULL); - - tmp_tag = gtk_text_buffer_create_tag( - gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), - "link", - "underline", PANGO_UNDERLINE_SINGLE, - "foreground_gdk", _linphone_gtk_chatroom_get_link_color(chat_view), - NULL); - g_signal_connect(G_OBJECT(tmp_tag), "event", G_CALLBACK(link_event_handler), chat_view); - g_signal_connect(G_OBJECT(text), "event", G_CALLBACK(chatroom_event), NULL); - gtk_menu_shell_append(GTK_MENU_SHELL(link_ctx_menu), link_ctx_menu_copy_item); - g_signal_connect(G_OBJECT(link_ctx_menu_copy_item), "activate", G_CALLBACK(copy_uri_into_clipboard_handler), NULL); - gtk_widget_show_all(link_ctx_menu); - g_object_set_data_full(G_OBJECT(text), "link_ctx_menu", link_ctx_menu, g_object_unref); - g_object_ref_sink(G_OBJECT(link_ctx_menu)); - - messages = linphone_chat_room_get_history(cr,NB_MSG_HIST); - display_history_message(chat_view,messages,with); - button = linphone_gtk_get_widget(chat_view,"send"); - g_signal_connect_swapped(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_send_text,NULL); - - g_signal_connect_swapped(G_OBJECT(entry),"activate",(GCallback)linphone_gtk_send_text,NULL); - g_signal_connect_swapped(G_OBJECT(entry),"changed",(GCallback)linphone_gtk_compose_text,NULL); - g_signal_connect(G_OBJECT(notebook),"switch_page",(GCallback)linphone_gtk_notebook_tab_select,NULL); - - gtk_signal_connect(GTK_OBJECT(main_window), "focus-in-event", GTK_SIGNAL_FUNC(linphone_gtk_window_focused), NULL); - - refresh_lime_icon(chat_view, cr); - - return chat_view; -} - -LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with){ - LinphoneChatRoom *cr=linphone_core_get_chat_room(linphone_gtk_get_core(), with); - return cr; -} - -void linphone_gtk_load_chatroom(LinphoneChatRoom *cr,const LinphoneAddress *uri,GtkWidget *chat_view){ - GtkWidget *main_window=linphone_gtk_get_main_window (); - GtkWidget *notebook = linphone_gtk_get_widget(main_window, "viewswitch"); - LinphoneChatRoom *cr2=(LinphoneChatRoom *)g_object_get_data(G_OBJECT(chat_view),"cr"); - const LinphoneAddress *from=linphone_chat_room_get_peer_address(cr2); - char *from_str=linphone_address_as_string_uri_only(from); - char *uri_str=linphone_address_as_string(uri); - char *uri_only=linphone_address_as_string_uri_only(uri); - bctbx_list_t *messages=NULL; - - if(g_strcmp0(from_str,uri_only)!=0){ - GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview")); - GtkTextIter start; - GtkTextIter end; - GtkTextBuffer *text_buffer; - - text_buffer=gtk_text_view_get_buffer(text_view); - gtk_text_buffer_get_bounds(text_buffer, &start, &end); - gtk_text_buffer_delete (text_buffer, &start, &end); - update_chat_header(GTK_NOTEBOOK(notebook), chat_view, cr, uri); - g_object_set_data(G_OBJECT(chat_view),"cr",cr); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(main_window,"contact_list")),"chatview",(gpointer)chat_view); - messages=linphone_chat_room_get_history(cr,NB_MSG_HIST); - g_object_set_data(G_OBJECT(chat_view),"from_message",g_strdup(uri_str)); - display_history_message(chat_view,messages,uri); - gtk_text_buffer_get_end_iter(text_buffer,&end); - gtk_text_view_scroll_to_iter(text_view,&end,0,FALSE,1.0,0); - } - refresh_lime_icon(chat_view, cr); - - ms_free(from_str); - ms_free(uri_str); - ms_free(uri_only); -} - -void linphone_gtk_chat_destroyed(GtkWidget *w){ - /* - LinphoneChatRoom *cr=(LinphoneChatRoom*)g_object_get_data(G_OBJECT(w),"cr"); - */ -} - - -void linphone_gtk_text_received ( LinphoneCore *lc, LinphoneChatRoom *room, - LinphoneChatMessage *msg ) { - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget ( main_window,"contact_list" ); - GtkWidget *w; - 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 */ - const LinphoneAddress *from_chatview=linphone_gtk_friend_list_get_active_address(); - if (linphone_address_weak_equal(from,from_chatview)) { - send=TRUE; - } else { - if ( !linphone_gtk_friend_list_is_contact ( linphone_chat_message_get_from ( msg ) ) ) { - linphone_gtk_chat_add_contact ( linphone_chat_message_get_from ( msg ) ); - } - send=FALSE; - } - } else { - /* Chat window closed */ -#ifdef SQLITE_STORAGE_ENABLED - send=FALSE; -#else - send=TRUE; -#endif - if ( !linphone_gtk_friend_list_is_contact ( linphone_chat_message_get_from ( msg ) ) ) { - linphone_gtk_chat_add_contact ( linphone_chat_message_get_from ( msg ) ); - } - w=linphone_gtk_init_chatroom ( room,linphone_chat_message_get_from ( msg ) ); - g_object_set_data ( G_OBJECT ( friendlist ),"chatview", ( gpointer ) w ); - linphone_gtk_friend_list_set_active_address(from); - } - -#ifdef HAVE_GTK_OSX - /* Notified when a new message is sent */ - linphone_gtk_status_icon_set_blinking ( TRUE ); -#else - if ( !gtk_window_is_active ( GTK_WINDOW ( main_window ) ) ) { - if ( !GPOINTER_TO_INT ( g_object_get_data ( G_OBJECT ( w ),"is_notified" ) ) ) { - linphone_gtk_notify ( NULL, msg, NULL ); - g_object_set_data ( G_OBJECT ( w ),"is_notified",GINT_TO_POINTER ( TRUE ) ); - } else { - g_object_set_data ( G_OBJECT ( w ),"is_notified",GINT_TO_POINTER ( FALSE ) ); - } - } -#endif - if ( send ) { - linphone_gtk_push_text ( w,linphone_chat_message_get_from ( msg ), - FALSE,room,msg,FALSE ); - } - 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) { - GtkWidget *main_window = linphone_gtk_get_main_window(); - GtkWidget *friendlist = linphone_gtk_get_widget(main_window, "contact_list"); - linphone_gtk_friend_list_update_button_display(GTK_TREE_VIEW(friendlist)); -} diff --git a/gtk/chatroom_frame.ui b/gtk/chatroom_frame.ui deleted file mode 100644 index d7b8137a3..000000000 --- a/gtk/chatroom_frame.ui +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - True - False - 0 - none - - - True - False - - - True - True - never - - - True - True - 4 - False - word-char - False - - - - - True - True - 0 - - - - - True - False - 10 - - - True - False - 16 - linphone-security-ok - - - False - False - 0 - - - - - True - True - - True - False - False - True - True - - - True - True - 1 - - - - - True - True - True - - - True - False - - - True - False - linphone-chat-send - - - True - True - 0 - - - - - True - False - Send - - - True - True - 7 - 1 - - - - - - - False - False - 2 - - - - - False - False - 1 - - - - - - - - - diff --git a/gtk/conf_frame.ui b/gtk/conf_frame.ui deleted file mode 100644 index c9503e7f6..000000000 --- a/gtk/conf_frame.ui +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - True - False - 0 - none - - - True - False - - - True - False - - - End conference - True - True - True - - - False - False - end - 0 - - - - - True - True - end - 0 - - - - - True - False - - - Record - True - True - True - - - - False - False - 0 - - - - - True - False - True - char - - - True - True - 1 - - - - - False - False - end - 1 - - - - - - - - - diff --git a/gtk/conference.c b/gtk/conference.c deleted file mode 100644 index 9073d629e..000000000 --- a/gtk/conference.c +++ /dev/null @@ -1,183 +0,0 @@ -/*************************************************************************** - * gtk/conference.c - * - * Mon Sep 12, 2011 - * Copyright 2011 Belledonne Communications - * Author: Simon Morlat - * Email simon dot morlat at linphone dot org - ****************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "linphone.h" - -#define PADDING_PIXELS 4 - -/* - * conferencee_box = a vbox where participants are added or removed - * conf_frame = the conference tab - */ - -static GtkWidget *create_conference_label(void){ - GtkWidget *box=gtk_hbox_new(FALSE,0); - gtk_box_pack_start(GTK_BOX(box),gtk_image_new_from_icon_name("linphone-conference-start",GTK_ICON_SIZE_MENU),FALSE,FALSE,0); - gtk_box_pack_end(GTK_BOX(box),gtk_label_new(_("Conference")),TRUE,FALSE,0); - gtk_widget_show_all(box); - return box; -} - -static void init_local_participant(GtkWidget *participant){ - GtkWidget *sound_meter; - GtkWidget *button=linphone_gtk_get_widget(participant,"conference_control"); - gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(participant,"callee_name_label")),_("Me")); - sound_meter=linphone_gtk_get_widget(participant,"sound_indicator"); - linphone_gtk_enable_mute_button(GTK_BUTTON(button),TRUE); - g_signal_connect(G_OBJECT(button),"clicked",(GCallback)linphone_gtk_mute_clicked,NULL); - gtk_widget_show(button); - linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_core_get_conference_local_input_volume, linphone_gtk_get_core()); -} - -static GtkWidget *get_conferencee_box(GtkWidget *mw){ - GtkWidget *box=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"conferencee_box"); - return box; -} - -static GtkWidget *find_conferencee_from_call(LinphoneCall *call){ - GtkWidget *mw=linphone_gtk_get_main_window(); - 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){ - GtkWidget *frame=(GtkWidget*)elem->data; - if (call==g_object_get_data(G_OBJECT(frame),"call")){ - ret=frame; - break; - } - } - g_list_free(l); - } - //g_message("find_conferencee_from_call(): found widget %p for call %p",ret,call); - return ret; -} - -static GtkWidget * create_conference_panel(void){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *conf_frame=linphone_gtk_create_widget("conf_frame"); - GtkWidget *conf_box=linphone_gtk_get_widget(conf_frame,"conf_box"); - GtkWidget *button_conf=linphone_gtk_get_widget(conf_frame,"terminate_conf"); - GtkWidget *image=gtk_image_new_from_icon_name("linphone-stop-call", GTK_ICON_SIZE_BUTTON); - GtkWidget *box; - GtkWidget *viewswitch=linphone_gtk_get_widget(mw,"viewswitch"); - GtkWidget *participant; - GtkWidget *record = linphone_gtk_get_widget(conf_frame, "conf_record_button"); - - gtk_button_set_image(GTK_BUTTON(record), gtk_image_new_from_icon_name("linphone-record", GTK_ICON_SIZE_BUTTON)); - 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); - participant=linphone_gtk_create_widget("callee_frame"); - gtk_widget_show(participant); - gtk_box_set_homogeneous(GTK_BOX(box),TRUE); - init_local_participant(participant); - gtk_box_pack_start(GTK_BOX(box),participant,FALSE,FALSE,PADDING_PIXELS); - gtk_widget_show(box); - g_object_set_data(G_OBJECT(mw),"conferencee_box",box); - gtk_box_pack_start(GTK_BOX(conf_box),box,FALSE,FALSE,PADDING_PIXELS); - - gtk_notebook_append_page(GTK_NOTEBOOK(viewswitch),conf_frame, - create_conference_label()); - return conf_frame; -} - -void linphone_gtk_set_in_conference(LinphoneCall *call){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *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(); - } - 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("callee_frame"); - gtk_widget_show(participant); - if (linphone_address_get_display_name(addr)!=NULL){ - markup=g_strdup_printf("%s",linphone_address_get_display_name(addr)); - }else{ - char *tmp=linphone_address_as_string_uri_only(addr); - markup=g_strdup_printf("%s",tmp); - ms_free(tmp); - } - gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(participant,"callee_name_label")),markup); - g_free(markup); - sound_meter=linphone_gtk_get_widget(participant,"sound_indicator"); - linphone_gtk_init_audio_meter(sound_meter, (get_volume_t) linphone_call_get_play_volume, call); - gtk_box_pack_start(GTK_BOX(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)); - } -} - -void linphone_gtk_terminate_conference_participant(LinphoneCall *call){ - GtkWidget *frame=find_conferencee_from_call(call); - if (frame){ - gtk_widget_set_sensitive(frame,FALSE); - } -} - -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)); - if (g_list_length(children)==1){ /* only local participant */ - /*the conference is terminated */ - g_message("The conference is terminated"); - g_object_set_data(G_OBJECT(mw),"conferencee_box",NULL); - gtk_widget_destroy(conf_frame); - g_object_set_data(G_OBJECT(mw),"conf_frame",NULL); - } - g_list_free(children); - } -} - -bool_t linphone_gtk_call_is_in_conference_view(LinphoneCall *call) { - return (find_conferencee_from_call(call) != NULL); -} diff --git a/gtk/config-fetching.c b/gtk/config-fetching.c deleted file mode 100644 index 59a40a0ca..000000000 --- a/gtk/config-fetching.c +++ /dev/null @@ -1,97 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" -#include "linphone/lpconfig.h" - - -void linphone_gtk_set_configuration_uri(void){ - GtkWidget *w=linphone_gtk_create_window("config-uri", linphone_gtk_get_main_window()); - GtkWidget *entry=linphone_gtk_get_widget(w,"uri_entry"); - const char *uri=linphone_core_get_provisioning_uri(linphone_gtk_get_core()); - if (uri) gtk_entry_set_text(GTK_ENTRY(entry),uri); - gtk_widget_show(w); -} - -void linphone_gtk_config_uri_changed(GtkWidget *button){ - GtkWidget *w=gtk_widget_get_toplevel(button); - GtkWidget *entry=linphone_gtk_get_widget(w,"uri_entry"); - const char *uri=gtk_entry_get_text(GTK_ENTRY(entry)); - - if (uri && (strlen(uri)==0 || strcmp(uri,"https://")==0)) uri=NULL; - - if(linphone_core_set_provisioning_uri(linphone_gtk_get_core(),uri) == 0) { - gtk_widget_destroy(w); - if (uri){ -#ifndef _WIN32 - linphone_gtk_schedule_restart(); - gtk_main_quit(); -#else - GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(linphone_gtk_get_main_window()), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_OK, - _("Remote provisioning URI successfully set. Please restart Linphone in order to load the new remote settings")); - g_signal_connect_swapped(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), dialog); - gtk_widget_show(dialog); -#endif - } - } else { - GtkWidget *dialog = gtk_message_dialog_new(GTK_WINDOW(w), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - _("Invalid remote provisioning URI")); - g_signal_connect_swapped(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), dialog); - gtk_widget_show(dialog); - } -} - -void linphone_gtk_config_uri_cancel(GtkWidget *button){ - GtkWidget *w=gtk_widget_get_toplevel(button); - gtk_widget_destroy(w); -} - -GtkWidget * linphone_gtk_show_config_fetching(void){ - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *w=linphone_gtk_create_window("provisioning-fetch", linphone_gtk_get_main_window()); - g_message("Fetching started"); - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(w),_("fetching from %s"),linphone_core_get_provisioning_uri(lc)); -#if GTK_CHECK_VERSION(2,20,0) - { - GtkWidget *spinner=gtk_spinner_new(); - gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(w),spinner); - } -#endif - gtk_widget_show(w); - return w; -} - -void linphone_gtk_close_config_fetching(GtkWidget *w, LinphoneConfiguringState state){ - LinphoneCore *lc=linphone_gtk_get_core(); - gtk_widget_destroy(w); - g_message("Fetching finished"); - if (state==LinphoneConfiguringFailed){ - GtkWidget *msg=gtk_message_dialog_new(NULL,0,GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,_("Downloading of remote configuration from %s failed."), - linphone_core_get_provisioning_uri(lc)); - g_signal_connect(G_OBJECT(msg),"response",(GCallback)gtk_widget_destroy,NULL); - gtk_widget_show(msg); - } -} - diff --git a/gtk/config-uri.ui b/gtk/config-uri.ui deleted file mode 100644 index 26c1fef0e..000000000 --- a/gtk/config-uri.ui +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - False - 5 - Specifying a remote configuration URI - dialog - - - True - False - 2 - - - True - False - end - - - gtk-cancel - True - True - True - True - - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - This dialog allows to set an http or https address when configuration is to be fetched at startup. -Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. - True - 80 - - - True - True - 1 - - - - - True - True - - https:// - False - False - True - True - - - True - True - 2 - - - - - - button2 - button1 - - - diff --git a/gtk/contact.ui b/gtk/contact.ui deleted file mode 100644 index db22d9310..000000000 --- a/gtk/contact.ui +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - center-on-parent - dialog - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - end - - - gtk-cancel - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 0 - - - - - gtk-ok - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Name - - - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - SIP Address - - - 1 - 2 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - - - 1 - 2 - GTK_FILL - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - False - 0 - - - - - Show this contact presence status - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - True - - - True - True - 1 - - - - - Allow this contact to see my presence status - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - True - - - True - True - 2 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Contact information</b> - True - - - - - True - True - 1 - - - - - - cancel_button - ok_button - - - diff --git a/gtk/dscp_settings.ui b/gtk/dscp_settings.ui deleted file mode 100644 index 7f5061f72..000000000 --- a/gtk/dscp_settings.ui +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - False - 5 - DSCP settings - True - dialog - - - - True - False - 2 - - - True - False - end - - - gtk-close - True - True - True - False - True - - - False - False - 0 - - - - - gtk-ok - True - True - True - False - True - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - 0 - none - - - True - False - 3 - 2 - True - - - True - True - - True - False - False - True - True - - - 1 - 2 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 1 - 2 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 2 - 3 - - - - - True - False - SIP - - - - - True - False - Audio RTP stream - - - 1 - 2 - - - - - True - False - Video RTP stream - - - 2 - 3 - - - - - - - True - False - <b>Set DSCP values (in hexadecimal)</b> - True - - - - - False - False - 1 - - - - - - button2 - button1 - - - diff --git a/gtk/friendlist.c b/gtk/friendlist.c deleted file mode 100644 index 239ba9477..000000000 --- a/gtk/friendlist.c +++ /dev/null @@ -1,1104 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" -#include -#include - -static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list); - -enum{ - FRIEND_PRESENCE_IMG, - FRIEND_NAME, - FRIEND_ID, - FRIEND_CHATROOM, - FRIEND_SIP_ADDRESS, - FRIEND_CHAT, - FRIEND_CALL_BUTTON_VISIBLE, - FRIEND_CHAT_BUTTON_VISIBLE, - FRIEND_LIST_NCOL -}; - -typedef struct _status_picture_tab_t{ - LinphoneOnlineStatus status; - const char *img; -} status_picture_tab_t; - -status_picture_tab_t status_picture_tab[]={ - { LinphoneStatusOnline , "linphone-status-online" }, - { LinphoneStatusBusy , "linphone-status-away" }, - { LinphoneStatusBeRightBack , "linphone-status-away" }, - { LinphoneStatusAway , "linphone-status-away" }, - { LinphoneStatusOnThePhone , "linphone-status-away" }, - { LinphoneStatusOutToLunch , "linphone-status-away" }, - { LinphoneStatusDoNotDisturb , "linphone-status-donotdisturb" }, - { LinphoneStatusMoved , "linphone-status-away" }, - { LinphoneStatusAltService , "linphone-status-away" }, - { LinphoneStatusOffline , "linphone-status-offline" }, - { LinphoneStatusPending , "linphone-status-offline" }, - { LinphoneStatusEnd , NULL } -}; - -static const char *status_to_icon_name(LinphoneOnlineStatus ss) { - status_picture_tab_t *t=status_picture_tab; - while(t->img!=NULL){ - if (ss==t->status) { - return t->img; - } - ++t; - } - g_error("No icon name defined for status %i",ss); - return NULL; -} - -static GtkWidget *create_status_picture(LinphoneOnlineStatus ss, GtkIconSize icon_size){ - const char *icon_name = status_to_icon_name(ss); - if(icon_name) return gtk_image_new_from_icon_name(icon_name, icon_size); - else return NULL; -} - -gboolean linphone_gtk_friend_list_is_contact(const LinphoneAddress *addr){ - LinphoneFriend *lf; - char *addr_str=linphone_address_as_string(addr); - lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),addr_str); - if(lf == NULL){ - return FALSE; - } return TRUE; -} - -static void linphone_gtk_set_selection_to_uri_bar(GtkTreeView *treeview){ - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model; - LinphoneFriend *lf=NULL; - gchar* friend; - select = gtk_tree_view_get_selection (treeview); - if (gtk_tree_selection_get_selected (select, &model, &iter)) { - const LinphoneAddress *addr; - gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1); - addr = linphone_friend_get_address(lf); - if (addr) { - friend=linphone_address_as_string(addr); - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")),friend); - ms_free(friend); - } - } -} - -void linphone_gtk_add_contact(void){ - GtkWidget *w=linphone_gtk_create_window("contact", linphone_gtk_get_main_window()); - int presence_enabled=linphone_gtk_get_ui_config_int("use_subscribe_notify",1); - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"show_presence")),presence_enabled); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"allow_presence")), - presence_enabled); - gtk_widget_show(w); -} - -void linphone_gtk_edit_contact(GtkWidget *button){ - GtkWidget *w=gtk_widget_get_toplevel(button); - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model; - LinphoneFriend *lf=NULL; - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"contact_list"))); - if (gtk_tree_selection_get_selected (select, &model, &iter)) - { - gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1); - linphone_gtk_show_contact(lf, w); - } -} - -void linphone_gtk_remove_contact(GtkWidget *button){ - GtkWidget *w=gtk_widget_get_toplevel(button); - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model; - LinphoneFriend *lf=NULL; - LinphoneChatRoom *cr=NULL; - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(linphone_gtk_get_widget(w,"contact_list"))); - if (gtk_tree_selection_get_selected (select, &model, &iter)) - { - gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1); - linphone_core_remove_friend(linphone_gtk_get_core(),lf); - gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1); - linphone_chat_room_delete_history(cr); - linphone_gtk_show_friends(); - } -} - -gboolean linphone_gtk_on_key_press(GtkWidget *widget, GdkEvent *event, gpointer user_data) { - - if (event->type == GDK_KEY_PRESS && ((GdkEventKey*)event)->state & GDK_CONTROL_MASK) { - int cpt; - int key = -1; - static int key_map[9] = {0}; - if (key_map[0] == 0) { - GdkKeymapKey *keys = NULL; - gint n_keys = 0; - for (cpt = 0; cpt < 9; cpt++) { - if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), - GDK_KEY_1+cpt, &keys, &n_keys)) - key_map[cpt] = keys->keycode; - } - } - - for(cpt = 0; cpt < 9 ; cpt++) { - if (key_map[cpt] == (((GdkEventKey*)event)->hardware_keycode)) { - key = cpt; - break; - } - } - - if (key != -1) { - GtkWidget *main_window = linphone_gtk_get_main_window(); - GtkWidget *friendlist = linphone_gtk_get_widget(main_window,"contact_list"); - GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist)); - GtkTreeIter iter; - - if (gtk_tree_model_get_iter_first(model, &iter)) { - int index = 0; - LinphoneFriend *lf = NULL; - LinphoneChatRoom *cr; - do{ - if (index == key) { - const LinphoneAddress *addr; - gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1); - gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1); - if (lf != NULL) { - addr = linphone_friend_get_address(lf); - if (addr != NULL) { - linphone_gtk_friend_list_set_chat_conversation(addr); - } - } - if (cr != NULL){ - linphone_gtk_mark_chat_read(cr); - linphone_gtk_friend_list_update_button_display(GTK_TREE_VIEW(friendlist)); - } - return TRUE; - } - index++; - }while(gtk_tree_model_iter_next(model,&iter) && index <= 9); - } - } - } - return FALSE; -} - -void linphone_gtk_delete_history(GtkWidget *button){ - GtkWidget *w=linphone_gtk_get_main_window(); - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model; - GtkWidget *chat_view; - LinphoneFriend *lf=NULL; - GtkWidget *friendlist; - - friendlist=linphone_gtk_get_widget(w,"contact_list"); - chat_view=(GtkWidget *)g_object_get_data(G_OBJECT(friendlist),"chatview"); - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist)); - if (gtk_tree_selection_get_selected (select, &model, &iter)) - { - LinphoneChatRoom *cr; - gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1); - gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1); - linphone_chat_room_delete_history(cr); - if(chat_view!=NULL){ - const LinphoneAddress *from=linphone_gtk_friend_list_get_active_address(); - const LinphoneAddress *addr=linphone_friend_get_address(lf); - if (addr != NULL) { - if(linphone_address_weak_equal(from,addr)){ - GtkTextView *text_view=GTK_TEXT_VIEW(linphone_gtk_get_widget(chat_view,"textview")); - GtkTextIter start; - GtkTextIter end; - GtkTextBuffer *text_buffer; - - text_buffer=gtk_text_view_get_buffer(text_view); - gtk_text_buffer_get_bounds(text_buffer, &start, &end); - gtk_text_buffer_delete (text_buffer, &start, &end); - g_object_set_data(G_OBJECT(chat_view),"from_message",NULL); - } - } - } - linphone_gtk_show_friends(); - } -} - -static void linphone_gtk_call_selected(GtkTreeView *treeview){ - linphone_gtk_set_selection_to_uri_bar(treeview); - linphone_gtk_start_call(linphone_gtk_get_widget(gtk_widget_get_toplevel(GTK_WIDGET(treeview)), - "start_call")); -} - -void linphone_gtk_friend_list_update_button_display(GtkTreeView *friendlist){ - GtkTreeIter iter, selected_iter; - GtkTreeModel *model=gtk_tree_view_get_model(friendlist); - GtkTreeSelection *select=gtk_tree_view_get_selection(friendlist); - LinphoneChatRoom *cr=NULL; - gboolean is_composing; - int nbmsg=0; - GtkTreePath *selected_path = NULL; - GtkTreePath *hovered_row = (GtkTreePath *)g_object_get_data(G_OBJECT(friendlist), "hovered_row"); - - if (gtk_tree_selection_get_selected(select, &model, &selected_iter)){ - selected_path = gtk_tree_model_get_path(model, &selected_iter); - } - - if (gtk_tree_model_get_iter_first(model,&iter)) { - do{ - const char *icon_name = NULL; - gboolean show_chat_button = FALSE; - gboolean show_call_button = FALSE; - GtkTreePath *path = gtk_tree_model_get_path(model, &iter); - - gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1); - nbmsg=linphone_chat_room_get_unread_messages_count(cr); - is_composing=linphone_chat_room_is_remote_composing(cr); - if(nbmsg != 0){ - if (is_composing) icon_name = "linphone-chat-new-message-and-writing"; - else icon_name = "linphone-chat-new-message"; - show_chat_button = TRUE; - } else { - if (is_composing) { - icon_name = "linphone-chat-writing"; - show_chat_button = TRUE; - } else { - icon_name = "linphone-chat-nothing"; - } - } - - if ((selected_path && gtk_tree_path_compare(path, selected_path) == 0) - || (hovered_row && gtk_tree_path_compare(path, hovered_row) == 0)){ - show_chat_button = TRUE; - show_call_button = TRUE; - } - - gtk_list_store_set(GTK_LIST_STORE(model),&iter,FRIEND_CHAT,icon_name, - FRIEND_CHAT_BUTTON_VISIBLE, show_chat_button, -1); - gtk_list_store_set(GTK_LIST_STORE(model), &iter, FRIEND_CALL_BUTTON_VISIBLE, show_call_button, -1); - - gtk_tree_path_free(path); - }while(gtk_tree_model_iter_next(model,&iter)); - } - if (selected_path) gtk_tree_path_free(selected_path); -} - -static gboolean grab_focus(GtkWidget *w){ - gtk_widget_grab_focus(w); - return FALSE; -} - -void linphone_gtk_friend_list_set_active_address(const LinphoneAddress *addr){ - GtkWidget *w=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list"); - g_object_set_data_full(G_OBJECT(friendlist),"from", addr ? linphone_address_clone(addr) : NULL, (GDestroyNotify)linphone_address_unref); -} - -const LinphoneAddress *linphone_gtk_friend_list_get_active_address(void){ - GtkWidget *w=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list"); - return (const LinphoneAddress*)g_object_get_data(G_OBJECT(friendlist),"from"); -} - -void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la){ - GtkTreeIter iter; - GtkListStore *store=NULL; - GtkWidget *w = linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list"); - GtkTreeModel *model=gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist)); - GtkWidget *chat_view=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); - LinphoneFriend *lf=NULL; - LinphoneChatRoom *cr=NULL; - GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch"); - GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist)); - - lf=linphone_core_find_friend(linphone_gtk_get_core(),la); - if(lf==NULL){ - cr=linphone_gtk_create_chatroom(la); - linphone_gtk_friend_list_set_active_address(la); - } else { - store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))); - if (gtk_tree_model_get_iter_first(model,&iter)) { - do{ - const LinphoneAddress *addr; - gtk_tree_model_get(model, &iter,FRIEND_ID , &lf, -1); - addr=linphone_friend_get_address(lf); - if (addr != NULL) { - if (linphone_address_weak_equal(addr,la)){ - gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1); - if(cr==NULL){ - cr=linphone_gtk_create_chatroom(addr); - gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1); - } - linphone_gtk_friend_list_set_active_address(addr); - gtk_tree_selection_select_iter(selection, &iter); - break; - } - } - }while(gtk_tree_model_iter_next(model,&iter)); - } - } - if(cr) { - if(chat_view == NULL){ - chat_view=linphone_gtk_init_chatroom(cr,la); - g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)chat_view); - } else { - linphone_gtk_load_chatroom(cr,la,chat_view); - } - gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,chat_view)); - g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(chat_view,"text_entry")); - } -} - -void linphone_gtk_notebook_tab_select(GtkNotebook *notebook,GtkWidget *page,guint page_num, gpointer data){ - GtkWidget *w=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list"); - GtkWidget *chat_view; - LinphoneChatRoom *cr=NULL; - chat_view=(GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); - if(page != NULL){ - notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch"); - if(gtk_notebook_page_num(notebook,page)==gtk_notebook_page_num(notebook,chat_view)){ - cr=g_object_get_data(G_OBJECT(chat_view),"cr"); - if(cr!=NULL){ - linphone_gtk_mark_chat_read(cr); - linphone_gtk_show_friends(); - } - } - } -} - -void linphone_gtk_chat_selected(GtkWidget *item){ - GtkWidget *w=gtk_widget_get_toplevel(item); - GtkTreeSelection *select; - GtkListStore *store=NULL; - GtkTreeIter iter; - GtkTreeModel *model; - LinphoneFriend *lf=NULL; - LinphoneChatRoom *cr=NULL; - GtkWidget *friendlist=linphone_gtk_get_widget(w,"contact_list"); - GtkWidget *page; - - select=gtk_tree_view_get_selection(GTK_TREE_VIEW(friendlist)); - store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(item))); - if (gtk_tree_selection_get_selected (select, &model, &iter)){ - GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(w,"viewswitch"); - const LinphoneAddress *addr; - gtk_tree_model_get (model, &iter,FRIEND_ID , &lf, -1); - gtk_tree_model_get (model, &iter,FRIEND_CHATROOM , &cr, -1); - addr=linphone_friend_get_address(lf); - if (addr != NULL) { - if(cr==NULL){ - cr=linphone_gtk_create_chatroom(addr); - gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1); - } - page=GTK_WIDGET(g_object_get_data(G_OBJECT(friendlist),"chatview")); - linphone_gtk_friend_list_set_active_address(addr); - if(page==NULL){ - page=linphone_gtk_init_chatroom(cr,addr); - g_object_set_data(G_OBJECT(friendlist),"chatview",(gpointer)page); - } else { - linphone_gtk_load_chatroom(cr,addr,page); - } - linphone_gtk_mark_chat_read(cr); - gtk_notebook_set_current_page(notebook,gtk_notebook_page_num(notebook,page)); - g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(page,"text_entry")); - } - } -} - -void linphone_gtk_contact_clicked(GtkTreeSelection *selection){ - GtkTreeView *friendlist = gtk_tree_selection_get_tree_view(selection); - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *edit_button = linphone_gtk_get_widget(mw, "edit_button"); - GtkWidget *remove_button = linphone_gtk_get_widget(mw, "remove_button"); - - linphone_gtk_set_selection_to_uri_bar(friendlist); - linphone_gtk_friend_list_update_button_display(friendlist); - if(gtk_tree_selection_get_selected(selection, NULL, NULL)) { - gtk_widget_set_sensitive(edit_button, TRUE); - gtk_widget_set_sensitive(remove_button, TRUE); - } else { - gtk_widget_set_sensitive(edit_button, FALSE); - gtk_widget_set_sensitive(remove_button, FALSE); - } -} - - -void linphone_gtk_add_button_clicked(void){ - linphone_gtk_add_contact(); -} - -void linphone_gtk_edit_button_clicked(GtkWidget *button){ - linphone_gtk_edit_contact(button); -} - -void linphone_gtk_remove_button_clicked(GtkWidget *button){ - linphone_gtk_remove_contact(button); -} - -static GtkWidget * create_presence_menu(void){ - GtkWidget *menu=gtk_menu_new(); - GtkWidget *menu_item; - status_picture_tab_t *t; - for(t=status_picture_tab;t->img!=NULL;++t){ - if (t->status==LinphoneStatusPending){ - continue; - } - menu_item=gtk_image_menu_item_new_with_label(linphone_online_status_to_string(t->status)); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), - gtk_image_new_from_icon_name(t->img, GTK_ICON_SIZE_LARGE_TOOLBAR)); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_set_my_presence,GINT_TO_POINTER(t->status)); - } - return menu; -} - -void linphone_gtk_set_my_presence(LinphoneOnlineStatus ss){ - GtkWidget *button=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"presence_button"); - GtkWidget *image=create_status_picture(ss, GTK_ICON_SIZE_LARGE_TOOLBAR); - GtkWidget *menu; - - gtk_widget_set_tooltip_text(button,linphone_online_status_to_string(ss)); - gtk_button_set_image(GTK_BUTTON(button),image); - /*prepare menu*/ - menu=(GtkWidget*)g_object_get_data(G_OBJECT(button),"presence_menu"); - if (menu==NULL){ - menu=create_presence_menu(); - /*the menu is destroyed when the button is destroyed*/ - g_object_weak_ref(G_OBJECT(button),(GWeakNotify)gtk_widget_destroy,menu); - g_object_set_data(G_OBJECT(button),"presence_menu",menu); - } - linphone_core_set_presence_info(linphone_gtk_get_core(),0,NULL,ss); -} - -void linphone_gtk_my_presence_clicked(GtkWidget *button){ - GtkWidget *menu=(GtkWidget*)g_object_get_data(G_OBJECT(button),"presence_menu"); - gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0, - gtk_get_current_event_time()); - gtk_widget_show(menu); -} - -static void icon_press_handler(GtkEntry *entry){ - GtkWidget *w = gtk_widget_get_toplevel(GTK_WIDGET(entry)); - const char *text=gtk_entry_get_text(entry); - if (text && strlen(text)>0){ - LinphoneAddress *addr; - LinphoneFriend *lf; - char *uri; - addr=linphone_core_interpret_url(linphone_gtk_get_core(),text); - if (addr==NULL){ - return ; - } - uri=linphone_address_as_string_uri_only(addr); - lf=linphone_core_get_friend_by_address(linphone_gtk_get_core(),uri); - ms_free(uri); - if (lf==NULL) - lf=linphone_core_create_friend(linphone_gtk_get_core()); - if (lf!=NULL){ - linphone_friend_set_address(lf,addr); - linphone_gtk_show_contact(lf, w); - } - linphone_address_unref(addr); - } -} - -static void update_star(GtkEntry *entry, gboolean is_known){ - if (is_known){ - gtk_entry_set_icon_from_icon_name(entry,GTK_ENTRY_ICON_SECONDARY,NULL); - gtk_entry_set_icon_sensitive(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,FALSE); - gtk_entry_set_icon_tooltip_text(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,NULL); - }else{ - gtk_entry_set_icon_from_icon_name(entry,GTK_ENTRY_ICON_SECONDARY,"linphone-contact-add"); - gtk_entry_set_icon_sensitive(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,TRUE); - gtk_entry_set_icon_tooltip_text(GTK_ENTRY(entry),GTK_ENTRY_ICON_SECONDARY,_("Add to addressbook")); - } -} - -static void check_contact(GtkEditable *editable, LinphoneCore *lc){ - bool_t known = TRUE; - char *tmp = gtk_editable_get_chars(editable, 0, -1); - if (tmp != NULL) { - if (strlen(tmp) > 0) { - known = linphone_gtk_is_friend(lc, tmp); - } - g_free(tmp); - } - update_star(GTK_ENTRY(editable), known); -} - -static void linphone_gtk_init_bookmark_icon(void){ - GtkWidget *entry = linphone_gtk_get_widget(linphone_gtk_get_main_window(), "uribar"); - g_signal_connect(G_OBJECT(entry),"icon-release",(GCallback)icon_press_handler,NULL); - g_signal_connect(G_OBJECT(GTK_EDITABLE(entry)),"changed",(GCallback)check_contact,linphone_gtk_get_core()); -} - -static gboolean friend_search_func(GtkTreeModel *model, gint column, - const gchar *key, - GtkTreeIter *iter, - gpointer search_data){ - char *name=NULL; - gboolean ret=TRUE; - gtk_tree_model_get(model,iter,FRIEND_NAME,&name,-1); - if (name!=NULL){ - gchar *uname=g_utf8_casefold(name,-1); /* need that to perform case-insensitive search in utf8 */ - gchar *ukey=g_utf8_casefold(key,-1); - ret=strstr(uname,ukey)==NULL; - g_free(uname); - g_free(ukey); - g_free(name); - } - return ret; -} - -static gint friend_sort(GtkTreeModel *model, GtkTreeIter *a,GtkTreeIter *b,gpointer user_data){ - char *n1=NULL,*n2=NULL; - int ret; - gtk_tree_model_get(model,a,FRIEND_NAME,&n1,-1); - gtk_tree_model_get(model,b,FRIEND_NAME,&n2,-1); - if (n1 && n2) { - ret=strcmp(n1,n2); - g_free(n1); - g_free(n2); - }else if (n1){ - g_free(n1); - ret=-1; - }else if (n2){ - g_free(n2); - ret=1; - }else ret=0; - return ret; -} - -void linphone_gtk_friend_list_on_name_column_clicked(GtkTreeModel *model){ - GtkSortType st; - gint column; - - gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model),&column,&st); - if (column==FRIEND_NAME){ - if (st==GTK_SORT_ASCENDING) st=GTK_SORT_DESCENDING; - else st=GTK_SORT_ASCENDING; - }else st=GTK_SORT_ASCENDING; - gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),FRIEND_NAME,st); -} - -static int get_friend_weight(const LinphoneFriend *lf){ - int w=0; - LinphoneCore *lc=linphone_gtk_get_core(); - const LinphoneAddress *addr = linphone_friend_get_address(lf); - LinphoneChatRoom *cr = NULL; - - if (addr != NULL) { - cr = linphone_core_get_chat_room(lc, addr); - } - if (cr && linphone_chat_room_get_unread_messages_count(cr)>0){ - w+=2000; - } - - switch(linphone_friend_get_status(lf)){ - case LinphoneStatusOnline: - w+=1000; - break; - case LinphoneStatusOffline: - if (linphone_friend_get_send_subscribe(lf)) - w+=100; - break; - default: - w+=500; - break; - } - return w; -} - -static int friend_compare_func(const LinphoneFriend *lf1, const LinphoneFriend *lf2){ - int w1,w2,ret; - w1=get_friend_weight(lf1); - w2=get_friend_weight(lf2); - if (w1==w2){ - const char *u1,*u2; - const LinphoneAddress *addr1,*addr2; - addr1=linphone_friend_get_address(lf1); - addr2=linphone_friend_get_address(lf2); - if ((addr1 == NULL) && (addr2 == NULL)) return 0; - if ((addr1 == NULL) && (addr2 != NULL)) return -1; - if ((addr1 != NULL) && (addr2 == NULL)) return 1; - u1=linphone_friend_get_name(lf1) ? linphone_friend_get_name(lf1) : linphone_address_get_display_name(addr1) ? linphone_address_get_display_name(addr1) : linphone_address_get_username(addr1); - u2=linphone_friend_get_name(lf2) ? linphone_friend_get_name(lf2) :linphone_address_get_display_name(addr2) ? linphone_address_get_display_name(addr2) : linphone_address_get_username(addr2); - if (u1 && u2) { - ret = strcasecmp(u1,u2); - } else if (u1) { - ret = 1; - } else { - ret = -1; - } - } else { - ret = w2-w1; - } - return ret; -} - -static bctbx_list_t *sort_friend_list(const bctbx_list_t *friends){ - bctbx_list_t *ret=NULL; - const bctbx_list_t *elem; - LinphoneFriend *lf; - - for(elem=friends;elem!=NULL;elem=elem->next){ - lf=(LinphoneFriend*)elem->data; - ret=bctbx_list_insert_sorted(ret,lf,(bctbx_compare_func)friend_compare_func); - } - return ret; -} - -#if 0 -void linphone_gtk_friend_list_on_presence_column_clicked(GtkTreeModel *model){ - GtkSortType st; - gint column; - - gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model),&column,&st); - if (column==FRIEND_ID){ - if (st==GTK_SORT_ASCENDING) st=GTK_SORT_DESCENDING; - else st=GTK_SORT_ASCENDING; - }else st=GTK_SORT_ASCENDING; - gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(model),FRIEND_ID,st); -} -#endif - -static void linphone_gtk_friend_list_init(GtkWidget *friendlist){ - GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist)); - GtkTreeSelection *select = gtk_tree_view_get_selection (GTK_TREE_VIEW (friendlist)); - - linphone_gtk_init_bookmark_icon(); - gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(friendlist),friend_search_func,NULL,NULL); - gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store),FRIEND_NAME,friend_sort,NULL,NULL); - gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE); - g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(linphone_gtk_contact_clicked), NULL); - - g_object_set_data(G_OBJECT(friendlist), "friendlist_initialized", (gpointer)TRUE); -} - -void linphone_gtk_show_directory_search(void){ - LinphoneProxyConfig *cfg=NULL; - SipSetupContext * ssc=NULL; - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *search_box=linphone_gtk_get_widget(mw,"directory_search_box"); - - cfg = linphone_core_get_default_proxy_config(linphone_gtk_get_core()); - if (cfg){ - ssc=linphone_proxy_config_get_sip_setup_context(cfg); - if (ssc!=NULL && sip_setup_context_get_capabilities(ssc) & SIP_SETUP_CAP_BUDDY_LOOKUP){ - GtkWidget *entry=linphone_gtk_get_widget(mw,"directory_search_entry"); - gchar *tooltip; - GdkColor grey={0,40000,40000,40000}; - gtk_widget_show(search_box); - tooltip=g_strdup_printf(_("Search in %s directory"),linphone_proxy_config_get_domain(cfg)); - gtk_widget_modify_text(entry,GTK_STATE_NORMAL,&grey); - gtk_entry_set_text(GTK_ENTRY(entry),tooltip); - g_object_set_data(G_OBJECT(entry),"active",GINT_TO_POINTER(0)); - g_free(tooltip); - return; - } - } - gtk_widget_hide(search_box); -} - -gboolean linphone_gtk_directory_search_focus_out(GtkWidget *entry){ - if (gtk_entry_get_text_length(GTK_ENTRY(entry))==0) - linphone_gtk_show_directory_search(); - return FALSE; -} - -gboolean linphone_gtk_directory_search_focus_in(GtkWidget *entry){ - if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(entry),"active"))==0){ - gtk_entry_set_text(GTK_ENTRY(entry),""); - gtk_widget_modify_text(entry,GTK_STATE_NORMAL,NULL); - g_object_set_data(G_OBJECT(entry),"active",GINT_TO_POINTER(1)); - } - return FALSE; -} - -void linphone_gtk_directory_search_activate(GtkWidget *entry){ - LinphoneProxyConfig *cfg; - GtkWidget *w; - cfg = linphone_core_get_default_proxy_config(linphone_gtk_get_core()); - 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))); -} - -void linphone_gtk_directory_search_button_clicked(GtkWidget *button){ - linphone_gtk_directory_search_activate( - linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"directory_search_entry")); -} - -void linphone_gtk_show_friends(void){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *friendlist=linphone_gtk_get_widget(mw,"contact_list"); - GtkListStore *store=NULL; - GtkTreeIter iter; - const bctbx_list_t *itf; - LinphoneCore *core=linphone_gtk_get_core(); - bctbx_list_t *sorted; - LinphoneChatRoom *cr=NULL; - - linphone_gtk_show_directory_search(); - if (!g_object_get_data(G_OBJECT(friendlist), "friendlist_initialized")) { - linphone_gtk_friend_list_init(friendlist); - } - - store=GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(friendlist))); - gtk_list_store_clear(store); - - sorted=sort_friend_list(linphone_core_get_friend_list(core)); - - for(itf=sorted;itf!=NULL;itf=bctbx_list_next(itf)){ - LinphoneFriend *lf=(LinphoneFriend*)itf->data; - const LinphoneAddress *f_addr=linphone_friend_get_address(lf); - const char *name=linphone_friend_get_name(lf); - char *uri = NULL; - const char *display=name; - char *escaped=NULL; - int nbmsg=0; - - //BuddyInfo *bi; - gboolean send_subscribe=linphone_friend_get_send_subscribe(lf); - if (f_addr != NULL) uri = linphone_address_as_string(f_addr); - if ((display==NULL || display[0]=='\0') && (f_addr != NULL)) { - display=linphone_address_get_username(f_addr); - } - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,FRIEND_NAME, display,FRIEND_ID,lf, - FRIEND_PRESENCE_IMG, send_subscribe ? status_to_icon_name(linphone_friend_get_status(lf)) : NULL, - FRIEND_CHAT,"linphone-chat-nothing", -1); - - if (f_addr != NULL) { - cr=linphone_gtk_create_chatroom(f_addr); - gtk_list_store_set(store,&iter,FRIEND_CHATROOM,cr,-1); - nbmsg=linphone_chat_room_get_unread_messages_count(cr); - if(nbmsg != 0){ - gtk_list_store_set(store,&iter,FRIEND_CHAT,"linphone-chat-new-message", - FRIEND_CHAT_BUTTON_VISIBLE, TRUE, -1); - } - escaped=g_markup_escape_text(uri,-1); - gtk_list_store_set(store,&iter,FRIEND_SIP_ADDRESS,escaped,-1); - g_free(escaped); - ms_free(uri); - } - } - bctbx_list_free(sorted); -} - -void linphone_gtk_show_contact(LinphoneFriend *lf, GtkWidget *parent){ - GtkWidget *w = linphone_gtk_create_window("contact", parent); - char *uri; - const char *name = linphone_friend_get_name(lf); - const LinphoneAddress *f_addr = linphone_friend_get_address(lf); - - if (f_addr != NULL) { - uri=linphone_address_as_string_uri_only(f_addr); - if (uri) { - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"sip_address")),uri); - ms_free(uri); - } - } - - if (name){ - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"name")),name); - } - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"show_presence")), - linphone_friend_get_send_subscribe(lf)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"allow_presence")), - linphone_friend_get_inc_subscribe_policy(lf)==LinphoneSPAccept); - g_object_set_data(G_OBJECT(w),"friend_ref",(gpointer)lf); - - gtk_widget_show(w); -} - -void linphone_gtk_contact_cancel(GtkWidget *button){ - gtk_widget_destroy(gtk_widget_get_toplevel(button)); -} - -void linphone_gtk_contact_ok(GtkWidget *button){ - GtkWidget *w=gtk_widget_get_toplevel(button); - LinphoneFriend *lf=(LinphoneFriend*)g_object_get_data(G_OBJECT(w),"friend_ref"); - LinphoneFriend *lf2; - gboolean show_presence=FALSE,allow_presence=FALSE; - const gchar *name,*uri; - LinphoneAddress* friend_address; - if (lf==NULL){ - lf=linphone_core_create_friend(linphone_gtk_get_core()); - if (linphone_gtk_get_ui_config_int("use_subscribe_notify",1)==1){ - show_presence=FALSE; - allow_presence=FALSE; - } - linphone_friend_set_inc_subscribe_policy(lf,allow_presence ? LinphoneSPAccept : LinphoneSPDeny); - linphone_friend_send_subscribe(lf,show_presence); - } - - name = NULL; - if(gtk_entry_get_text_length(GTK_ENTRY(linphone_gtk_get_widget(w,"name"))) != 0){ - name=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"name"))); - } - uri=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"sip_address"))); - show_presence=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"show_presence"))); - allow_presence=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"allow_presence"))); - friend_address=linphone_core_interpret_url(linphone_gtk_get_core(),uri); - if (friend_address==NULL){ - linphone_gtk_display_something(GTK_MESSAGE_WARNING,_("Invalid sip contact !")); - return ; - } - - linphone_friend_set_address(lf,friend_address); - linphone_friend_set_name(lf,name); - linphone_friend_send_subscribe(lf,show_presence); - linphone_friend_set_inc_subscribe_policy(lf,allow_presence==TRUE ? LinphoneSPAccept : LinphoneSPDeny); - if (linphone_friend_in_list(lf)) { - linphone_friend_done(lf); - } else { - char *uri=linphone_address_as_string_uri_only(friend_address); - lf2=linphone_core_get_friend_by_address(linphone_gtk_get_core(),uri); - ms_free(uri); - if(lf2==NULL){ - linphone_core_add_friend(linphone_gtk_get_core(),lf); - } - } - linphone_address_unref(friend_address); - linphone_gtk_show_friends(); - gtk_widget_destroy(w); -} - -static GtkWidget *linphone_gtk_create_contact_menu(GtkWidget *contact_list){ - GtkWidget *menu=gtk_menu_new(); - GtkWidget *menu_item; - gchar *edit_label=NULL; - gchar *delete_label=NULL; - gchar *delete_hist_label=NULL; - gchar *add_contact_label=NULL; - gchar *name=NULL; - GtkTreeSelection *select; - GtkTreeIter iter; - GtkTreeModel *model; - GtkWidget *image; - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneProxyConfig *cfg=NULL; - SipSetupContext * ssc=NULL; - bool_t show_menu_separator=FALSE; - - cfg = linphone_core_get_default_proxy_config(lc); - if (cfg){ - ssc=linphone_proxy_config_get_sip_setup_context(cfg); - } - - g_signal_connect(G_OBJECT(menu), "selection-done", G_CALLBACK (gtk_widget_destroy), NULL); - select = gtk_tree_view_get_selection(GTK_TREE_VIEW(contact_list)); - add_contact_label=g_strdup_printf(_("Add a new contact")); - if (gtk_tree_selection_get_selected (select, &model, &iter)){ - gtk_tree_model_get(model, &iter,FRIEND_NAME , &name, -1); - edit_label=g_strdup_printf(_("Edit contact '%s'"),name); - delete_label=g_strdup_printf(_("Delete contact '%s'"),name); - delete_hist_label=g_strdup_printf(_("Delete chat history of '%s'"),name); - g_free(name); - show_menu_separator=TRUE; - } - if (edit_label){ - menu_item=gtk_image_menu_item_new_with_label(edit_label); - image=gtk_image_new_from_icon_name("linphone-edit",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_edit_contact,contact_list); - } - if (delete_label){ - menu_item=gtk_image_menu_item_new_with_label(delete_label); - image=gtk_image_new_from_icon_name("linphone-delete",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_remove_contact,contact_list); - } - - if (delete_hist_label){ - GtkWidget *menu_item_separator=gtk_separator_menu_item_new(); - gtk_widget_show(menu_item_separator); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item_separator); - menu_item=gtk_image_menu_item_new_with_label(delete_hist_label); - image=gtk_image_new_from_icon_name("linphone-delete",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_delete_history,contact_list); - } - - if (ssc && (sip_setup_context_get_capabilities(ssc) & SIP_SETUP_CAP_BUDDY_LOOKUP)) { - gchar *tmp=g_strdup_printf(_("Add new contact from %s directory"),linphone_proxy_config_get_domain(cfg)); - menu_item=gtk_image_menu_item_new_with_label(tmp); - g_free(tmp); - image=gtk_image_new_from_icon_name("linphone-contact-add",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_show_buddy_lookup_window,ssc); - } - - if (show_menu_separator) { - GtkWidget *menu_item_separator=gtk_separator_menu_item_new(); - gtk_widget_show(menu_item_separator); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item_separator); - } - - menu_item=gtk_image_menu_item_new_with_label(add_contact_label); - image=gtk_image_new_from_icon_name("linphone-contact-add",GTK_ICON_SIZE_MENU); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - gtk_widget_show(image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_add_contact,contact_list); - gtk_widget_show(menu); - gtk_menu_attach_to_widget (GTK_MENU (menu), contact_list, NULL); - - g_free(add_contact_label); - if (edit_label) g_free(edit_label); - if (delete_label) g_free(delete_label); - return menu; -} - -gboolean linphone_gtk_popup_contact_menu(GtkWidget *list, GdkEventButton *event){ - GtkWidget *m=linphone_gtk_create_contact_menu(list); - gtk_menu_popup (GTK_MENU (m), NULL, NULL, NULL, NULL, - event ? event->button : 0, event ? event->time : gtk_get_current_event_time()); - return TRUE; -} - -static int get_column_index(GtkTreeView *friendlist, const GtkTreeViewColumn *column) { - GList *columns = gtk_tree_view_get_columns(friendlist); - int i = g_list_index(columns, column); - g_list_free(columns); - return i; -} - -static void select_row(GtkTreeView *treeview, GtkTreePath *path) { - GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); - gtk_tree_selection_select_path(selection, path); -} - -gboolean linphone_gtk_contact_list_button_pressed(GtkTreeView *friendlist, GdkEventButton *event){ - /* Ignore double-clicks and triple-clicks */ - gboolean ret = FALSE; - int x_bin, y_bin; - GtkTreePath *path; - GtkTreeViewColumn *column; - GtkTreeSelection *selection = gtk_tree_view_get_selection(friendlist); - - gtk_tree_view_convert_widget_to_bin_window_coords(friendlist, (gint)event->x, (gint)event->y, &x_bin, &y_bin); - gtk_tree_view_get_path_at_pos(friendlist, x_bin, y_bin, &path, &column, NULL, NULL); - - if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { - if(path) gtk_tree_selection_select_path(selection, path); - ret = linphone_gtk_popup_contact_menu(GTK_WIDGET(friendlist), event); - } else if(event->button == 1 && event->type == GDK_BUTTON_PRESS){ - if(path && column) { - int numcol = get_column_index(friendlist, column); - if(numcol == 2) { - select_row(friendlist, path); - linphone_gtk_call_selected(friendlist); - ret = TRUE; - } else if(numcol == 3) { - select_row(friendlist, path); - linphone_gtk_chat_selected(GTK_WIDGET(friendlist)); - ret = TRUE; - } - } - } - if(path) gtk_tree_path_free(path); - return ret; -} - -void linphone_gtk_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf){ - /*refresh the entire list*/ - linphone_gtk_show_friends(); -} - -static gboolean update_hovered_row_path(GtkTreeView *friendlist, int x_window, int y_window) { - int x_bin, y_bin; - GtkTreePath *new_path; - GtkTreePath *old_path = (GtkTreePath *)g_object_get_data(G_OBJECT(friendlist), "hovered_row"); - gtk_tree_view_convert_widget_to_bin_window_coords(friendlist, x_window, y_window, &x_bin, &y_bin); - gtk_tree_view_get_path_at_pos(friendlist, x_bin, y_bin, &new_path, NULL, NULL, NULL); - if((new_path == NULL && old_path == NULL) || (new_path && old_path && gtk_tree_path_compare(new_path, old_path) == 0)) { - if(new_path) gtk_tree_path_free(new_path); - return FALSE; - } else { - g_object_set_data_full(G_OBJECT(friendlist), "hovered_row", new_path, (GDestroyNotify)gtk_tree_path_free); - return TRUE; - } -} - -gboolean linphone_gtk_friend_list_enter_event_handler(GtkTreeView *friendlist, GdkEventCrossing *event) { - gboolean path_has_changed = update_hovered_row_path(friendlist, (int)event->x, (int)event->y); - if(path_has_changed) linphone_gtk_friend_list_update_button_display(friendlist); - return FALSE; -} - -gboolean linphone_gtk_friend_list_leave_event_handler(GtkTreeView *friendlist, GdkEventCrossing *event) { - GtkTreePath *hovered_row = (GtkTreePath *)g_object_get_data(G_OBJECT(friendlist), "hovered_row"); - if(hovered_row) { - g_object_set_data(G_OBJECT(friendlist), "hovered_row", NULL); - linphone_gtk_friend_list_update_button_display(friendlist); - } - return FALSE; -} - -gboolean linphone_gtk_friend_list_motion_event_handler(GtkTreeView *friendlist, GdkEventMotion *event) { - gboolean path_has_changed = update_hovered_row_path(friendlist, (int)event->x, (int)event->y); - if(path_has_changed) linphone_gtk_friend_list_update_button_display(friendlist); - return FALSE; -} - -#define CONFIG_FILE ".linphone-friends.db" - -char *linphone_gtk_friends_storage_get_db_file(const char *filename){ - const int path_max=1024; - char *db_file=NULL; - - db_file=(char *)g_malloc(path_max*sizeof(char)); - if (filename==NULL) filename=CONFIG_FILE; - /*try accessing a local file first if exists*/ - if (bctbx_file_exist(CONFIG_FILE)==0){ - snprintf(db_file,path_max,"%s",filename); - }else{ -#ifdef _WIN32 - const char *appdata=getenv("APPDATA"); - if (appdata){ - snprintf(db_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); - CreateDirectory(db_file,NULL); - snprintf(db_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); - } -#else - const char *home=getenv("HOME"); - if (home==NULL) home="."; - snprintf(db_file,path_max,"%s/%s",home,filename); -#endif - } - return db_file; -} diff --git a/gtk/gtkrc b/gtk/gtkrc deleted file mode 100644 index 73d21744f..000000000 --- a/gtk/gtkrc +++ /dev/null @@ -1,4 +0,0 @@ -#include "share/themes/XLiquid_GTK-1.0.3/gtk-2.0/gtkrc" -#include "share/themes/Aero-ion3.1/gtk-2.0/gtkrc" -include "share/themes/Outcrop/gtk-2.0/gtkrc" - diff --git a/gtk/gtkrc.mac b/gtk/gtkrc.mac deleted file mode 100644 index da38efafc..000000000 --- a/gtk/gtkrc.mac +++ /dev/null @@ -1 +0,0 @@ -include "../../share/themes/Quartz/gtk-2.0/gtkrc" diff --git a/gtk/in_call_frame.ui b/gtk/in_call_frame.ui deleted file mode 100644 index 1e713d19c..000000000 --- a/gtk/in_call_frame.ui +++ /dev/null @@ -1,433 +0,0 @@ - - - - - - True - False - 16 - linphone-security-pending - - - False - cursor - 0.5 - none - - - True - False - 12 - 12 - - - True - False - - - True - False - center - - - True - True - 0 - - - - - True - False - - - - - - False - False - 1 - - - - - False - - - True - True - True - zrtp_button_icon - none - - - - True - False - 0 - - - - - False - False - 2 - - - - - False - 4 - - - True - False - 1 - 16 - linphone-security-ok - - - True - True - 0 - - - - - True - False - 0 - Encryption status - - - True - True - 1 - - - - - True - True - 3 - - - - - True - False - - - True - False - - - True - True - True - True - none - False - vertical - linphone-micro-enabled - - - False - False - 5 - 0 - - - - - True - False - - - False - False - 5 - 1 - - - - - True - False - 10 - 0 - - - - - True - False - - - True - True - True - True - Click here to set the speakers volume - none - False - vertical - linphone-speaker-enabled - - - False - False - 5 - 0 - - - - - True - False - - - False - False - 5 - 1 - - - - - True - False - 10 - 1 - - - - - False - False - 5 - 4 - - - - - False - spread - - - Answer - True - True - True - - - - False - False - 0 - - - - - Decline - True - True - True - - - - False - False - 1 - - - - - False - False - 5 - - - - - False - - - Record - True - True - True - Record this call to an audio file - - - - False - False - 0 - - - - - True - False - True - char - - - True - True - 1 - - - - - False - False - 6 - - - - - True - False - 2 - 3 - True - - - Video - True - True - True - - - - - Pause - True - True - True - - - - 1 - 2 - - - - - Mute - True - True - True - - - - 2 - 3 - - - - - Transfer - True - True - True - - - 1 - 2 - - - - - Hang up - True - True - True - - - - 1 - 2 - 1 - 2 - - - - - Conference - True - True - True - - - 2 - 3 - 1 - 2 - - - - - False - False - 7 - 7 - - - - - - - - - True - False - True - - - True - False - In call - True - center - - - True - True - 0 - - - - - True - False - Duration - center - - - True - True - 1 - - - - - 90 - 10 - True - False - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - Call quality rating - - - False - False - 2 - - - - - - diff --git a/gtk/incall_view.c b/gtk/incall_view.c deleted file mode 100644 index 3b4429602..000000000 --- a/gtk/incall_view.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2009 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -/* -* C Implementation: incall_frame -* -* Description: -* -* -* Author: Simon Morlat , (C) 2009 -* -* -*/ - -#include "linphone.h" - -gboolean linphone_gtk_use_in_call_view(void){ - static int val=-1; - if (val==-1) val=linphone_gtk_get_ui_config_int("use_incall_view",1); - return val; -} - -LinphoneCall *linphone_gtk_get_currently_displayed_call(gboolean *is_conf){ - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *main_window=linphone_gtk_get_main_window (); - GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch"); - const bctbx_list_t *calls=linphone_core_get_calls(lc); - if (is_conf) *is_conf=FALSE; - if (!linphone_gtk_use_in_call_view() || bctbx_list_size(calls)==1){ - if (calls) return (LinphoneCall*)calls->data; - }else{ - int idx=gtk_notebook_get_current_page (notebook); - GtkWidget *page=gtk_notebook_get_nth_page(notebook,idx); - if (page!=NULL){ - LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(page),"call"); - if (call==NULL){ - GtkWidget *conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(main_window),"conf_frame"); - if (conf_frame==page){ - if (is_conf) - *is_conf=TRUE; - return NULL; - } - } - return call; - } - } - return NULL; -} - -static GtkWidget *make_tab_header(int number){ - gchar text[20]; - g_snprintf(text, sizeof(text), _("Call #%i"), number); - return linphone_gtk_make_tab_header(text, "linphone-start-call", FALSE, NULL, NULL); -} - -void linphone_gtk_call_update_tab_header(LinphoneCall *call,gboolean pause){ - GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *main_window=linphone_gtk_get_main_window(); - GtkNotebook *notebook=GTK_NOTEBOOK(linphone_gtk_get_widget(main_window,"viewswitch")); - gint call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"call_index")); - GtkWidget *new_label=gtk_hbox_new (FALSE,0); - GtkWidget *i=NULL; - GtkWidget *l; - gchar *text; - - if(pause){ - i=gtk_image_new_from_icon_name("linphone-hold-off",GTK_ICON_SIZE_BUTTON); - } else { - i=gtk_image_new_from_icon_name("linphone-start-call", GTK_ICON_SIZE_BUTTON); - } - - text=g_strdup_printf(_("Call #%i"),call_index); - l=gtk_label_new (text); - gtk_box_pack_start (GTK_BOX(new_label),i,FALSE,FALSE,0); - gtk_box_pack_end(GTK_BOX(new_label),l,TRUE,TRUE,0); - - gtk_notebook_set_tab_label(notebook,w,new_label); - gtk_widget_show_all(new_label); - g_free(text); -} - -static void linphone_gtk_in_call_set_animation_image(GtkWidget *callview, const char *image_name){ - GtkWidget *container=linphone_gtk_get_widget(callview,"in_call_animation"); - GList *elem=gtk_container_get_children(GTK_CONTAINER(container)); - GtkWidget *image; - - if (image_name==NULL){ - gtk_widget_hide(container); - } - image=gtk_image_new_from_icon_name(image_name,GTK_ICON_SIZE_DIALOG); - if (elem) - gtk_widget_destroy((GtkWidget*)elem->data); - gtk_widget_show(image); - gtk_container_add(GTK_CONTAINER(container),image); - gtk_widget_show_all(container); -} - -static void linphone_gtk_in_call_set_animation_spinner(GtkWidget *callview){ -#if GTK_CHECK_VERSION(2,20,0) - GtkWidget *container=linphone_gtk_get_widget(callview,"in_call_animation"); - GList *elem=gtk_container_get_children(GTK_CONTAINER(container)); - GtkWidget *spinner=gtk_spinner_new(); - if (elem) - gtk_widget_destroy((GtkWidget*)elem->data); - gtk_widget_show(spinner); - gtk_container_add(GTK_CONTAINER(container),spinner); - gtk_widget_set_size_request(spinner, 20,20); - gtk_spinner_start(GTK_SPINNER(spinner)); -#endif -} - -static void linphone_gtk_transfer_call(LinphoneCall *dest_call){ - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); - if (call) linphone_call_transfer_to_another(call,dest_call); -} - -void transfer_button_clicked(GtkWidget *button, gpointer call_ref){ - GtkWidget *menu_item; - GtkWidget *menu=gtk_menu_new(); - LinphoneCall *call=(LinphoneCall*)call_ref; - LinphoneCore *lc=linphone_gtk_get_core(); - const bctbx_list_t *elem=linphone_core_get_calls(lc); - - for(;elem!=NULL;elem=elem->next){ - LinphoneCall *other_call=(LinphoneCall*)elem->data; - GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(other_call); - if (other_call!=call){ - int call_index=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(call_view),"call_index")); - char *remote_uri=linphone_call_get_remote_address_as_string (other_call); - char *text=g_strdup_printf(_("Transfer to call #%i with %s"),call_index,remote_uri); - GtkWidget *image = gtk_image_new_from_icon_name("linphone-start-call", GTK_ICON_SIZE_MENU); - menu_item=gtk_image_menu_item_new_with_label(text); - ms_free(remote_uri); - g_free(text); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item), image); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_transfer_call,other_call); - } - } - gtk_menu_popup(GTK_MENU(menu),NULL,NULL,NULL,NULL,0,gtk_get_current_event_time()); - gtk_widget_show(menu); -} - -void linphone_gtk_enable_transfer_button(LinphoneCore *lc, gboolean value){ - const bctbx_list_t *elem=linphone_core_get_calls(lc); - for(;elem!=NULL;elem=elem->next){ - LinphoneCall *call=(LinphoneCall*)elem->data; - GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *button=linphone_gtk_get_widget (call_view,"transfer_button"); - if(button != NULL){ - gtk_widget_set_sensitive(button,value); - } - } -} - -static void conference_button_clicked(GtkWidget *button, gpointer call_ref){ - gtk_widget_set_sensitive(button,FALSE); - linphone_core_add_all_to_conference(linphone_gtk_get_core()); - -} - -void linphone_gtk_enable_conference_button(LinphoneCore *lc, gboolean value){ - const bctbx_list_t *elem=linphone_core_get_calls(lc); - for(;elem!=NULL;elem=elem->next){ - LinphoneCall *call=(LinphoneCall*)elem->data; - GtkWidget *call_view=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *button=linphone_gtk_get_widget (call_view,"conference_button"); - if (button != NULL){ - gtk_widget_set_sensitive(button,value); - } - } -} - -static void show_used_codecs(GtkWidget *callstats, LinphoneCall *call){ - const LinphoneCallParams *params=linphone_call_get_current_params(call); - if (params){ - const PayloadType *acodec=linphone_call_params_get_used_audio_codec(params); - const PayloadType *vcodec=linphone_call_params_get_used_video_codec(params); - GtkWidget *acodec_ui=linphone_gtk_get_widget(callstats,"audio_codec"); - GtkWidget *vcodec_ui=linphone_gtk_get_widget(callstats,"video_codec"); - if (acodec){ - char tmp[64]={0}; - snprintf(tmp,sizeof(tmp)-1,"%s/%i/%i",acodec->mime_type,acodec->clock_rate,acodec->channels); - gtk_label_set_label(GTK_LABEL(acodec_ui),tmp); - }else gtk_label_set_label(GTK_LABEL(acodec_ui),_("Not used")); - if (vcodec){ - gtk_label_set_label(GTK_LABEL(vcodec_ui),vcodec->mime_type); - }else gtk_label_set_label(GTK_LABEL(vcodec_ui),_("Not used")); - } -} - -static const char *ice_state_to_string(LinphoneIceState ice_state){ - switch(ice_state){ - case LinphoneIceStateNotActivated: - return _("ICE not activated"); - case LinphoneIceStateFailed: - return _("ICE failed"); - case LinphoneIceStateInProgress: - return _("ICE in progress"); - case LinphoneIceStateReflexiveConnection: - return _("Going through one or more NATs"); - case LinphoneIceStateHostConnection: - return _("Direct"); - case LinphoneIceStateRelayConnection: - return _("Through a relay server"); - } - return "invalid"; -} - -static const char *upnp_state_to_string(LinphoneUpnpState ice_state){ - switch(ice_state){ - case LinphoneUpnpStateIdle: - return _("uPnP not activated"); - case LinphoneUpnpStatePending: - return _("uPnP in progress"); - case LinphoneUpnpStateNotAvailable: - return _("uPnp not available"); - case LinphoneUpnpStateOk: - return _("uPnP is running"); - case LinphoneUpnpStateKo: - return _("uPnP failed"); - default: - break; - } - return "invalid"; -} - -static void _refresh_call_stats(GtkWidget *callstats, LinphoneCall *call){ - LinphoneUpnpState upnp_state; - LinphoneIceState ice_state; - LinphoneCallStats *as=linphone_call_get_audio_stats(call); - LinphoneCallStats *vs=linphone_call_get_video_stats(call); - const char *audio_media_connectivity = _("Direct or through server"); - const char *video_media_connectivity = _("Direct or through server"); - const LinphoneCallParams *curparams=linphone_call_get_current_params(call); - gboolean has_video=linphone_call_params_video_enabled(curparams); - MSVideoSize size_received = linphone_call_params_get_received_video_size(curparams); - MSVideoSize size_sent = linphone_call_params_get_sent_video_size(curparams); - const char *rtp_profile = linphone_call_params_get_rtp_profile(curparams); - gchar *tmp = g_strdup_printf("%s", rtp_profile); - gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"rtp_profile")),tmp); - g_free(tmp); - tmp=g_strdup_printf(_("download: %f\nupload: %f (kbit/s)"), - linphone_call_stats_get_download_bandwidth(as),linphone_call_stats_get_upload_bandwidth(as)); - 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, - 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)); - gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_recv")),size_r); - gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_size_sent")),size_s); - - tmp=g_strdup_printf(_("download: %f (kbit/s)\nupload: %f (kbit/s)\nestimated download: %f (kbits/s)"), - linphone_call_stats_get_download_bandwidth(vs), - linphone_call_stats_get_upload_bandwidth(vs), - linphone_call_stats_get_estimated_download_bandwidth(vs)); - g_free(size_r); - g_free(size_s); - } else { - tmp=NULL; - } - gtk_label_set_markup(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_bandwidth_usage")),tmp); - if (tmp) g_free(tmp); - upnp_state = linphone_call_stats_get_upnp_state(as); - ice_state = linphone_call_stats_get_ice_state(as); - if(upnp_state != LinphoneUpnpStateNotAvailable && upnp_state != LinphoneUpnpStateIdle) { - audio_media_connectivity = upnp_state_to_string(upnp_state); - } else if(ice_state != LinphoneIceStateNotActivated) { - audio_media_connectivity = ice_state_to_string(ice_state); - } - gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"audio_media_connectivity")),audio_media_connectivity); - - if (has_video){ - upnp_state = linphone_call_stats_get_upnp_state(vs); - ice_state = linphone_call_stats_get_ice_state(vs); - if(upnp_state != LinphoneUpnpStateNotAvailable && upnp_state != LinphoneUpnpStateIdle) { - video_media_connectivity = upnp_state_to_string(upnp_state); - } else if(ice_state != LinphoneIceStateNotActivated) { - video_media_connectivity = ice_state_to_string(ice_state); - } - }else video_media_connectivity=NULL; - gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"video_media_connectivity")),video_media_connectivity); - - if (linphone_call_stats_get_round_trip_delay(as)>0){ - tmp=g_strdup_printf(_("%.3f seconds"),linphone_call_stats_get_round_trip_delay(as)); - gtk_label_set_text(GTK_LABEL(linphone_gtk_get_widget(callstats,"round_trip_time")),tmp); - g_free(tmp); - } - linphone_call_stats_unref(as); - linphone_call_stats_unref(vs); -} - -static gboolean refresh_call_stats(GtkWidget *callstats){ - LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(callstats),"call"); - switch (linphone_call_get_state(call)){ - case LinphoneCallError: - case LinphoneCallEnd: - case LinphoneCallReleased: - gtk_widget_destroy(callstats); - return FALSE; - break; - case LinphoneCallStreamsRunning: - _refresh_call_stats(callstats,call); - break; - default: - break; - } - return TRUE; -} - -static void on_call_stats_destroyed(GtkWidget *call_view){ - GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(call_view),"call_stats"); - LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(call_stats),"call"); - g_source_remove(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(call_stats),"tid"))); - g_object_set_data(G_OBJECT(call_view),"call_stats",NULL); - linphone_call_unref(call); -} - -static void linphone_gtk_show_call_stats(LinphoneCall *call){ - GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(w),"call_stats"); - if (call_stats==NULL){ - guint tid; - call_stats=linphone_gtk_create_window("call_statistics", NULL); - g_object_set_data(G_OBJECT(w),"call_stats",call_stats); - g_object_set_data(G_OBJECT(call_stats),"call",linphone_call_ref(call)); - tid=g_timeout_add(1000,(GSourceFunc)refresh_call_stats,call_stats); - g_object_set_data(G_OBJECT(call_stats),"tid",GINT_TO_POINTER(tid)); - g_signal_connect_swapped(G_OBJECT(call_stats),"destroy",(GCallback)on_call_stats_destroyed,(gpointer)w); - show_used_codecs(call_stats,call); - refresh_call_stats(call_stats); - gtk_widget_show(call_stats); - } - -} - -void linphone_gtk_enable_video_button(LinphoneCall *call, gboolean sensitive, gboolean holdon){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer (call); - GtkWidget *button; - g_return_if_fail(callview!=NULL); - button=linphone_gtk_get_widget(callview,"video_button"); - gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive); - gtk_widget_set_visible(GTK_WIDGET(button),sensitive); -} - - -typedef enum { VOLUME_CTRL_PLAYBACK, VOLUME_CTRL_RECORD } VolumeControlType; - -static void volume_control_value_changed(GtkScaleButton *button, gdouble value, gpointer user_data) { - LinphoneCall *call = (LinphoneCall *)g_object_get_data(G_OBJECT(button), "call"); - VolumeControlType type = (VolumeControlType)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "type")); - - if(type == VOLUME_CTRL_PLAYBACK) { - linphone_call_set_speaker_volume_gain(call, (float)value); - } else if(type == VOLUME_CTRL_RECORD) { - linphone_call_set_microphone_volume_gain(call, (float)value); - } -} - -static gboolean volume_control_button_update_value(GtkWidget *widget) { - LinphoneCall *call = (LinphoneCall *)g_object_get_data(G_OBJECT(widget), "call"); - VolumeControlType type = (VolumeControlType)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "type")); - float gain = -1; - - if(type == VOLUME_CTRL_PLAYBACK) { - gain = linphone_call_get_speaker_volume_gain(call); - } else if(type == VOLUME_CTRL_RECORD) { - gain = linphone_call_get_microphone_volume_gain(call); - } - if(gain >= 0.0f) { - gtk_scale_button_set_value(GTK_SCALE_BUTTON(widget), gain); - return TRUE; - } else { - return FALSE; - } -} - -static gboolean volume_control_button_enter_event_handler(GtkWidget *widget) { - volume_control_button_update_value(widget); - return FALSE; -} - -static void volume_control_init(GtkWidget *vol_ctrl, VolumeControlType type, LinphoneCall *call) { - g_object_set_data(G_OBJECT(vol_ctrl), "call", call); - g_object_set_data(G_OBJECT(vol_ctrl), "type", GINT_TO_POINTER(type)); - if(!volume_control_button_update_value(vol_ctrl)) { - gtk_widget_set_sensitive(vol_ctrl, FALSE); - } else { - gtk_widget_set_sensitive(vol_ctrl, TRUE); - g_signal_connect(G_OBJECT(vol_ctrl), "enter-notify-event", G_CALLBACK(volume_control_button_enter_event_handler), NULL); - g_signal_connect(G_OBJECT(vol_ctrl), "value-changed", G_CALLBACK(volume_control_value_changed), NULL); - } -} - -void linphone_gtk_create_in_call_view(LinphoneCall *call){ - GtkWidget *call_view=linphone_gtk_create_widget("in_call_frame"); - GtkWidget *main_window=linphone_gtk_get_main_window (); - GtkNotebook *notebook=(GtkNotebook *)linphone_gtk_get_widget(main_window,"viewswitch"); - GtkWidget *audio_bar = linphone_gtk_get_widget(call_view, "incall_audioview"); - static int call_index=1; - int idx; - GtkWidget *record; - GtkWidget *transfer; - GtkWidget *conf; - GtkWidget *button; - GtkWidget *image; - - if (bctbx_list_size(linphone_core_get_calls(linphone_gtk_get_core()))==1){ - /*this is the only call at this time */ - call_index=1; - } - g_object_set_data(G_OBJECT(call_view),"call",call); - g_object_set_data(G_OBJECT(call_view),"call_index",GINT_TO_POINTER(call_index)); - - linphone_call_set_user_pointer (call,call_view); - linphone_call_ref(call); - gtk_notebook_append_page (notebook,call_view,make_tab_header(call_index)); - gtk_widget_show(call_view); - idx = gtk_notebook_page_num(notebook, call_view); - gtk_notebook_set_current_page(notebook, idx); - call_index++; - linphone_gtk_enable_hold_button (call,FALSE,TRUE); - linphone_gtk_enable_video_button (call,FALSE,TRUE); - linphone_gtk_enable_mute_button( - GTK_BUTTON(linphone_gtk_get_widget(call_view,"incall_mute")),FALSE); - - record = linphone_gtk_get_widget(call_view, "record_button"); - gtk_button_set_image(GTK_BUTTON(record), gtk_image_new_from_icon_name("linphone-record", GTK_ICON_SIZE_BUTTON)); - gtk_widget_hide(record); - transfer = linphone_gtk_get_widget(call_view,"transfer_button"); - gtk_button_set_image(GTK_BUTTON(transfer),gtk_image_new_from_icon_name("linphone-call-transfer",GTK_ICON_SIZE_BUTTON)); - g_signal_connect(G_OBJECT(transfer),"clicked",(GCallback)transfer_button_clicked,call); - gtk_widget_hide(transfer); - - conf = linphone_gtk_get_widget(call_view,"conference_button"); - gtk_button_set_image(GTK_BUTTON(conf),gtk_image_new_from_icon_name("linphone-conference-start",GTK_ICON_SIZE_BUTTON)); - g_signal_connect(G_OBJECT(conf),"clicked",(GCallback)conference_button_clicked,call); - gtk_widget_hide(conf); - - button=linphone_gtk_get_widget(call_view,"terminate_call"); - image=gtk_image_new_from_icon_name( - linphone_gtk_get_ui_config("stop_call_icon_name","linphone-stop-call"), - GTK_ICON_SIZE_BUTTON - ); - gtk_button_set_label(GTK_BUTTON(button),_("Hang up")); - gtk_button_set_image(GTK_BUTTON(button),image); - gtk_widget_show(image); - g_signal_connect_swapped(G_OBJECT(linphone_gtk_get_widget(call_view,"quality_indicator")),"button-press-event",(GCallback)linphone_gtk_show_call_stats,call); - - gtk_widget_hide(audio_bar); -} - -static void video_button_clicked(GtkWidget *button, LinphoneCall *call){ - gboolean adding=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"adding_video")); - LinphoneCore *lc=linphone_call_get_core(call); - LinphoneCallParams *params = linphone_core_create_call_params(lc, call); - gtk_widget_set_sensitive(button,FALSE); - linphone_call_params_enable_video(params, adding); - linphone_call_update(call,params); - linphone_call_params_unref(params); -} - -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); - gboolean button_sensitive=FALSE; - if (call_view==NULL) return; - - button=linphone_gtk_get_widget(call_view,"video_button"); - - gtk_button_set_image(GTK_BUTTON(button), - gtk_image_new_from_icon_name(has_video ? "linphone-camera-disabled" : "linphone-camera-enabled",GTK_ICON_SIZE_BUTTON)); - g_object_set_data(G_OBJECT(button),"adding_video",GINT_TO_POINTER(!has_video)); - if (!linphone_core_video_supported(linphone_call_get_core(call))){ - gtk_widget_set_sensitive(button,FALSE); - return; - } - switch(linphone_call_get_state(call)){ - case LinphoneCallStreamsRunning: - button_sensitive=!linphone_call_media_in_progress(call); - break; - default: - button_sensitive=FALSE; - break; - } - gtk_widget_set_sensitive(button,button_sensitive); - if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"signal_connected"))==0){ - 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)); - } - conf_frame=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); - if(conf_frame!=NULL){ - gtk_widget_set_sensitive(button,FALSE); - } -} - -void linphone_gtk_remove_in_call_view(LinphoneCall *call){ - GtkWidget *w=(GtkWidget*)linphone_call_get_user_pointer (call); - GtkWidget *main_window=linphone_gtk_get_main_window (); - GtkWidget *nb=linphone_gtk_get_widget(main_window,"viewswitch"); - int idx,id_current_page; - g_return_if_fail(w!=NULL); - idx=gtk_notebook_page_num(GTK_NOTEBOOK(nb),w); - if (linphone_gtk_call_is_in_conference_view(call)){ - linphone_gtk_unset_from_conference(call); - } - linphone_call_set_user_pointer (call,NULL); - linphone_call_unref(call); - call=linphone_core_get_current_call(linphone_gtk_get_core()); - id_current_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(nb)); - if (id_current_page == idx) { - if (call==NULL){ - if (linphone_core_is_in_conference(linphone_gtk_get_core())){ - /*show the conference*/ - gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb), - g_object_get_data(G_OBJECT(main_window),"conf_frame"))); - } else { - gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),0); - } - }else{ - /*show the active call*/ - gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),gtk_notebook_page_num(GTK_NOTEBOOK(nb), - linphone_call_get_user_pointer(call))); - } - } - gtk_notebook_remove_page (GTK_NOTEBOOK(nb),idx); - gtk_widget_destroy(w); -} - -static void display_peer_name_in_label(GtkWidget *label, const LinphoneAddress *from){ - const char *displayname=NULL; - char *id; - char *uri_label; - displayname=linphone_address_get_display_name(from); - id=linphone_address_as_string_uri_only(from); - - if (displayname!=NULL){ - uri_label=g_markup_printf_escaped("%s\n%s", - displayname,id); - }else - uri_label=g_markup_printf_escaped("%s\n",id); - gtk_label_set_markup(GTK_LABEL(label),uri_label); - g_free(uri_label); - ms_free(id); -} - -void linphone_gtk_in_call_view_set_calling(LinphoneCall *call){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); - GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri"); - GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration"); - - gtk_label_set_markup(GTK_LABEL(status),_("Calling...")); - display_peer_name_in_label(callee,linphone_call_get_remote_address (call)); - - gtk_label_set_text(GTK_LABEL(duration),_("00:00:00")); - linphone_gtk_in_call_set_animation_spinner(callview); -} - -void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); - GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri"); - GtkWidget *answer_button; - GtkWidget *image; - - gtk_label_set_markup(GTK_LABEL(status),_("Incoming call")); - gtk_widget_show_all(linphone_gtk_get_widget(callview,"answer_decline_panel")); - gtk_widget_hide(linphone_gtk_get_widget(callview,"buttons_panel")); - display_peer_name_in_label(callee,linphone_call_get_remote_address (call)); - - answer_button=linphone_gtk_get_widget(callview,"accept_call"); - image=gtk_image_new_from_icon_name("linphone-start-call", GTK_ICON_SIZE_BUTTON); - gtk_button_set_label(GTK_BUTTON(answer_button),_("Answer")); - gtk_button_set_image(GTK_BUTTON(answer_button),image); - gtk_widget_show(image); - - image=gtk_image_new_from_icon_name("linphone-stop-call", GTK_ICON_SIZE_BUTTON); - gtk_button_set_image(GTK_BUTTON(linphone_gtk_get_widget(callview,"decline_call")),image); - gtk_widget_show(image); - - linphone_gtk_in_call_set_animation_image(callview,"linphone-call-status-incoming"); -} - -static void rating_to_color(float rating, GdkColor *color){ - const char *colorname="grey"; - if (rating>=4.0) - colorname="green"; - else if (rating>=3.0) - colorname="white"; - else if (rating>=2.0) - colorname="yellow"; - else if (rating>=1.0) - colorname="orange"; - else if (rating>=0) - colorname="red"; - if (!gdk_color_parse(colorname,color)){ - g_warning("Fail to parse color %s",colorname); - } -} - -static const char *rating_to_text(float rating){ - if (rating>=4.0) - return _("good"); - if (rating>=3.0) - return _("average"); - if (rating>=2.0) - return _("poor"); - if (rating>=1.0) - return _("very poor"); - if (rating>=0) - return _("too bad"); - return _("unavailable"); -} - -static gboolean linphone_gtk_in_call_view_refresh(LinphoneCall *call){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *qi=linphone_gtk_get_widget(callview,"quality_indicator"); - float rating=linphone_call_get_current_quality(call); - GdkColor color; - gchar tmp[50]; - linphone_gtk_in_call_view_update_duration(call); - if (rating>=0){ - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(qi),rating/5.0); - snprintf(tmp,sizeof(tmp),"%.1f (%s)",rating,rating_to_text(rating)); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(qi),tmp); - }else{ - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(qi),0); - gtk_progress_bar_set_text(GTK_PROGRESS_BAR(qi),_("unavailable")); - } - rating_to_color(rating,&color); - gtk_widget_modify_bg(qi,GTK_STATE_NORMAL,&color); - - linphone_gtk_update_video_button(call); /*in case of no ice re-invite, video button status shall be checked by polling*/ - return TRUE; -} - -#define UNSIGNIFICANT_VOLUME (-23) -#define SMOOTH 0.15f - -static gboolean update_audio_meter(volume_ctx_t *ctx){ - float volume_db=ctx->get_volume(ctx->data); - float frac=(volume_db-UNSIGNIFICANT_VOLUME)/(float)(-UNSIGNIFICANT_VOLUME-3.0); - if (frac<0) frac=0; - if (frac>1.0) frac=1.0; - if (fraclast_value){ - frac=(frac*SMOOTH)+(ctx->last_value*(1-SMOOTH)); - } - ctx->last_value=frac; - //g_message("volume_db=%f, frac=%f",volume_db,frac); - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(ctx->widget),frac); - return TRUE; -} - -static void on_audio_meter_destroy(GtkWidget *w, gpointer data){ - guint task_id = GPOINTER_TO_INT(data); - g_source_remove(task_id); -} - - -void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void *data){ - guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id")); - if (task_id==0){ - volume_ctx_t *ctx=g_new(volume_ctx_t,1); - ctx->widget=w; - ctx->get_volume=get_volume; - ctx->data=data; - ctx->last_value=0; - g_object_set_data_full(G_OBJECT(w),"ctx",ctx,g_free); - task_id=g_timeout_add(50,(GSourceFunc)update_audio_meter,ctx); - g_object_set_data(G_OBJECT(w), "task_id", GINT_TO_POINTER(task_id)); - g_signal_connect(G_OBJECT(w), "destroy", (GCallback)on_audio_meter_destroy, GINT_TO_POINTER(task_id)); - } -} - -void linphone_gtk_uninit_audio_meter(GtkWidget *w){ - guint task_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"task_id")); - if (task_id!=0){ - g_object_set_data(G_OBJECT(w),"ctx",NULL); - g_object_set_data(G_OBJECT(w),"task_id",NULL); - g_source_remove(task_id); - } -} - -void linphone_gtk_in_call_view_enable_audio_view(LinphoneCall *call, gboolean val){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *audio_view=linphone_gtk_get_widget(callview,"incall_audioview"); - GtkWidget *mic_level=linphone_gtk_get_widget(callview,"mic_audiolevel"); - GtkWidget *spk_level=linphone_gtk_get_widget(callview,"spk_audiolevel"); - GtkWidget *mic_ctrl = linphone_gtk_get_widget(callview, "incall_mic_vol_ctrl_button"); - GtkWidget *spk_ctrl = linphone_gtk_get_widget(callview, "incall_spk_vol_ctrl_button"); - - if (val){ - linphone_gtk_init_audio_meter(mic_level,(get_volume_t)linphone_call_get_record_volume,call); - linphone_gtk_init_audio_meter(spk_level,(get_volume_t)linphone_call_get_play_volume,call); - volume_control_init(mic_ctrl, VOLUME_CTRL_RECORD, call); - volume_control_init(spk_ctrl, VOLUME_CTRL_PLAYBACK, call); - gtk_widget_show_all(audio_view); - }else{ - linphone_gtk_uninit_audio_meter(mic_level); - linphone_gtk_uninit_audio_meter(spk_level); - gtk_widget_hide(audio_view); - } -} - -void linphone_gtk_auth_token_verified_clicked(GtkButton *button){ - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); - if (call){ - linphone_call_set_authentication_token_verified(call,!linphone_call_get_authentication_token_verified(call)); - } -} - -void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call){ - GtkWidget *callview = (GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *encryption_status_box = linphone_gtk_get_widget(callview, "encryption_status_box"); - GtkWidget *encryption_status_label = linphone_gtk_get_widget(callview, "encryption_status_label"); - GtkWidget *encryption_status_icon = linphone_gtk_get_widget(callview, "encryption_status_icon"); - GtkWidget *zrtp_box = linphone_gtk_get_widget(callview, "zrtp_box"); - GtkWidget *zrtp_button = linphone_gtk_get_widget(callview, "zrtp_button"); - GtkWidget *zrtp_status_icon = gtk_button_get_image(GTK_BUTTON(zrtp_button)); - LinphoneMediaEncryption me = linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)); - - switch (me) { - case LinphoneMediaEncryptionSRTP: - gtk_widget_hide_all(zrtp_box); - gtk_widget_show_all(encryption_status_box); - gtk_label_set_markup(GTK_LABEL(encryption_status_label), _("Secured by SRTP")); - gtk_image_set_from_icon_name(GTK_IMAGE(encryption_status_icon), "linphone-security-ok", GTK_ICON_SIZE_MENU); - break; - case LinphoneMediaEncryptionDTLS: - gtk_widget_hide_all(zrtp_box); - gtk_widget_show_all(encryption_status_box); - gtk_label_set_markup(GTK_LABEL(encryption_status_label), _("Secured by DTLS")); - gtk_image_set_from_icon_name(GTK_IMAGE(encryption_status_icon), "linphone-security-ok", GTK_ICON_SIZE_MENU); - break; - case LinphoneMediaEncryptionZRTP: - { - bool_t verified = linphone_call_get_authentication_token_verified(call); - gchar *text = g_strdup_printf(_("Secured by ZRTP - [auth token: %s]"), linphone_call_get_authentication_token(call)); - gtk_button_set_label(GTK_BUTTON(zrtp_button), text); - g_free(text); - gtk_image_set_from_icon_name(GTK_IMAGE(zrtp_status_icon), verified ? "linphone-security-ok" : "linphone-security-pending", GTK_ICON_SIZE_MENU); - gtk_widget_set_tooltip_text(zrtp_button, verified ? _("Set unverified") : _("Set verified")); - gtk_widget_hide_all(encryption_status_box); - gtk_widget_show_all(zrtp_box); - } - break; - default: - gtk_widget_hide_all(encryption_status_box); - gtk_widget_hide_all(zrtp_box); - break; - } -} - -void linphone_gtk_in_call_view_hide_encryption(LinphoneCall *call) { - GtkWidget *callview = (GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *encryption_status_box = linphone_gtk_get_widget(callview, "encryption_status_box"); - GtkWidget *zrtp_box = linphone_gtk_get_widget(callview, "zrtp_box"); - gtk_widget_hide_all(encryption_status_box); - gtk_widget_hide_all(zrtp_box); -} - -char *linphone_gtk_address(const LinphoneAddress *addr){ - const char *displayname=linphone_address_get_display_name(addr); - if (!displayname) return linphone_address_as_string_uri_only(addr); - return ms_strdup(displayname); -} - -void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); - GtkWidget *callee=linphone_gtk_get_widget(callview,"in_call_uri"); - GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration"); - guint taskid=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(callview),"taskid")); - gboolean in_conf=(linphone_call_get_conference(call) != NULL); - GtkWidget *call_stats=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"call_stats"); - - linphone_gtk_in_call_show_video(call); - - display_peer_name_in_label(callee,linphone_call_get_remote_address (call)); - - gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel")); - gtk_label_set_markup(GTK_LABEL(status),in_conf ? _("In conference") : _("In call")); - - gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"conference_button"),!in_conf); - gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"transfer_button"),!in_conf); - - gtk_label_set_text(GTK_LABEL(duration),_("00:00:00")); - linphone_gtk_in_call_set_animation_image(callview,"linphone-media-play"); - linphone_gtk_call_update_tab_header(call,FALSE); - linphone_gtk_enable_mute_button( - GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),TRUE); - - if (taskid==0){ - taskid=g_timeout_add(250,(GSourceFunc)linphone_gtk_in_call_view_refresh,call); - g_object_set_data(G_OBJECT(callview),"taskid",GINT_TO_POINTER(taskid)); - } - linphone_gtk_in_call_view_enable_audio_view(call, !in_conf); - linphone_gtk_in_call_view_show_encryption(call); - if (in_conf){ - linphone_gtk_set_in_conference(call); - gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),FALSE); - gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"hold_call"),FALSE); - }else{ - linphone_gtk_unset_from_conference(call); /*in case it was previously*/ - gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"incall_mute"),TRUE); - gtk_widget_set_sensitive(linphone_gtk_get_widget(callview,"hold_call"),TRUE); - } - gtk_widget_show_all(linphone_gtk_get_widget(callview,"buttons_panel")); - if (!in_conf) gtk_widget_show_all(linphone_gtk_get_widget(callview,"record_hbox")); - else gtk_widget_hide(linphone_gtk_get_widget(callview,"record_hbox")); - if (call_stats) show_used_codecs(call_stats,call); -} - -void linphone_gtk_in_call_view_set_paused(LinphoneCall *call){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *status=linphone_gtk_get_widget(callview,"in_call_status"); - GtkWidget *record_bar = linphone_gtk_get_widget(callview, "record_hbox"); - gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel")); - gtk_label_set_markup(GTK_LABEL(status),_("Paused call")); - linphone_gtk_in_call_show_video(call); - linphone_gtk_in_call_set_animation_image(callview,"linphone-media-pause"); - gtk_widget_show_all(record_bar); -} - -void linphone_gtk_in_call_view_update_duration(LinphoneCall *call){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *duration_label=linphone_gtk_get_widget(callview,"in_call_duration"); - int duration=linphone_call_get_duration(call); - char tmp[256]={0}; - int seconds=duration%60; - int minutes=(duration/60)%60; - int hours=duration/3600; - snprintf(tmp,sizeof(tmp)-1,"%02i:%02i:%02i",hours,minutes,seconds); - gtk_label_set_text(GTK_LABEL(duration_label),tmp); -} - -static gboolean in_call_view_terminated(LinphoneCall *call){ - linphone_gtk_remove_in_call_view(call); - return FALSE; -} - -void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *status; - GtkWidget *video_window; - gboolean in_conf; - guint taskid; - if(callview==NULL) return; - video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window"); - 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_get_conference(call) != NULL); - if (video_window) gtk_widget_destroy(video_window); - if (status==NULL) return; - if (error_msg==NULL) - gtk_label_set_markup(GTK_LABEL(status),_("Call ended.")); - else{ - char *msg=g_markup_printf_escaped("%s",error_msg); - gtk_label_set_markup(GTK_LABEL(status),msg); - g_free(msg); - } - - linphone_gtk_in_call_set_animation_image(callview, linphone_gtk_get_ui_config("stop_call_icon_name","linphone-stop-call")); - linphone_gtk_in_call_view_hide_encryption(call); - - gtk_widget_hide(linphone_gtk_get_widget(callview,"answer_decline_panel")); - gtk_widget_hide(linphone_gtk_get_widget(callview,"record_hbox")); - gtk_widget_hide(linphone_gtk_get_widget(callview,"buttons_panel")); - gtk_widget_hide(linphone_gtk_get_widget(callview,"incall_audioview")); - gtk_widget_hide(linphone_gtk_get_widget(callview,"quality_indicator")); - linphone_gtk_enable_mute_button( - GTK_BUTTON(linphone_gtk_get_widget(callview,"incall_mute")),FALSE); - linphone_gtk_enable_hold_button(call,FALSE,TRUE); - - if (taskid!=0) g_source_remove(taskid); - g_timeout_add_seconds(2,(GSourceFunc)in_call_view_terminated,call); - if (in_conf) - linphone_gtk_terminate_conference_participant(call); -} - -void linphone_gtk_in_call_view_set_transfer_status(LinphoneCall *call,LinphoneCallState cstate){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - if (callview){ - GtkWidget *duration=linphone_gtk_get_widget(callview,"in_call_duration"); - const char *transfer_status="unknown"; - switch(cstate){ - case LinphoneCallOutgoingProgress: - transfer_status=_("Transfer in progress"); - break; - case LinphoneCallConnected: - transfer_status=_("Transfer done."); - break; - case LinphoneCallError: - transfer_status=_("Transfer failed."); - break; - default: - break; - } - gtk_label_set_text(GTK_LABEL(duration),transfer_status); - } -} - -void linphone_gtk_draw_mute_button(GtkButton *button, gboolean active){ - const char *icon_name = active ? "linphone-micro-muted" : "linphone-micro-enabled"; - GtkWidget *image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_BUTTON); - gtk_button_set_image(button, image); - gtk_widget_show(image); - g_object_set_data(G_OBJECT(button),"active",GINT_TO_POINTER(active)); -} - -void linphone_gtk_mute_clicked(GtkButton *button){ - int active=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"active")); - linphone_core_enable_mic(linphone_gtk_get_core(),active); - linphone_gtk_draw_mute_button(button,!active); -} - -void linphone_gtk_enable_mute_button(GtkButton *button, gboolean sensitive){ - /*gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive);*/ - gtk_widget_set_visible(GTK_WIDGET(button),sensitive); - linphone_gtk_draw_mute_button(button,FALSE); -} - -void linphone_gtk_draw_hold_button(GtkButton *button, gboolean active){ - const gchar *icon_name = active ? "linphone-hold-on" : "linphone-hold-off"; - const gchar *label = active ? _("Resume") : _("Pause"); - GtkWidget *image = gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_BUTTON); - g_object_set_data(G_OBJECT(button),"active",GINT_TO_POINTER(active)); - gtk_button_set_label(GTK_BUTTON(button),label); - gtk_button_set_image(GTK_BUTTON(button),image); - gtk_widget_show(image); -} - -void linphone_gtk_hold_clicked(GtkButton *button){ - int active=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button),"active")); - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); - linphone_gtk_call_update_tab_header(call,active); - if (!call) return; - if(!active) - { - linphone_call_pause(call); - } - else - { - linphone_call_resume(call); - } -} - -void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gboolean holdon){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer (call); - GtkWidget *button; - g_return_if_fail(callview!=NULL); - linphone_gtk_call_update_tab_header(call,!holdon); - button=linphone_gtk_get_widget(callview,"hold_call"); - gtk_widget_set_sensitive(GTK_WIDGET(button),sensitive); - gtk_widget_set_visible(GTK_WIDGET(button),sensitive); - linphone_gtk_draw_hold_button(GTK_BUTTON(button),!holdon); -} - -void linphone_gtk_call_statistics_closed(GtkWidget *call_stats){ - gtk_widget_destroy(call_stats); -} - -void linphone_gtk_record_call_toggled(GtkWidget *button){ - gboolean active=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)); - gboolean is_conf=FALSE; - const char *filepath; - gchar *message; - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(&is_conf); - GtkWidget *callview; - GtkWidget *label; - if (call){ - const LinphoneCallParams *params; - callview=(GtkWidget*)linphone_call_get_user_pointer (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){ - GtkWidget *mw=linphone_gtk_get_main_window(); - callview=(GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"conf_frame"); - label=linphone_gtk_get_widget(callview,"conf_record_status"); - filepath=(const char*)g_object_get_data(G_OBJECT(mw),"conf_record_path"); - if (filepath==NULL){ - filepath=linphone_gtk_get_record_path(NULL,TRUE); - g_object_set_data_full(G_OBJECT(mw),"conf_record_path",(char*)filepath,g_free); - } - }else{ - g_warning("linphone_gtk_record_call_toggled(): bug."); - return; - } - message=g_strdup_printf(_("Recording into\n%s %s"),filepath,active ? "" : _("(Paused)")); - - if (active){ - if (call) - linphone_call_start_recording(call); - else - linphone_core_start_conference_recording(lc,filepath); - }else { - if (call) - linphone_call_stop_recording(call); - else - linphone_core_stop_conference_recording(lc); - - } - gtk_label_set_markup(GTK_LABEL(label),g_locale_to_utf8(message, -1, NULL, NULL, NULL)); - g_free(message); -} - diff --git a/gtk/keypad.ui b/gtk/keypad.ui deleted file mode 100644 index 020204f2b..000000000 --- a/gtk/keypad.ui +++ /dev/null @@ -1,265 +0,0 @@ - - - - - - False - - - - True - False - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK - 0.5 - none - - - - - True - False - 0 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 4 - 4 - 4 - True - - - D - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - 3 - 4 - - - - - # - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 2 - 3 - 3 - 4 - - - - - 0 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 3 - 4 - - - - - * - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - - - - - C - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - 2 - 3 - - - - - 9 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 2 - 3 - 2 - 3 - - - - - 8 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 2 - 3 - - - - - 7 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 2 - 3 - - - - - B - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - 1 - 2 - - - - - 6 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 2 - 3 - 1 - 2 - - - - - 5 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - 1 - 2 - - - - - 4 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - - - - - A - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 3 - 4 - - - - - 3 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 2 - 3 - - - - - 2 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - 1 - 2 - - - - - 1 - 40 - 40 - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - - - - - - - - - diff --git a/gtk/ldap.ui b/gtk/ldap.ui deleted file mode 100644 index a5df241d1..000000000 --- a/gtk/ldap.ui +++ /dev/null @@ -1,669 +0,0 @@ - - - - - - False - LDAP Settings - - - True - False - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 5 - 2 - - - True - False - 1 - Server address: - - - - - True - False - Authentication method: - - - 1 - 2 - - - - - True - False - Username: - - - 2 - 3 - - - - - True - False - Password: - - - 3 - 4 - - - - - Use TLS Connection - True - False - True - False - Not yet available - False - True - - - 1 - 2 - 4 - 5 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 2 - 3 - - - - - True - True - False - False - False - True - True - - - 1 - 2 - 3 - 4 - - - - - True - False - liststore2 - 0 - - - - 0 - - - - - 1 - 2 - 1 - 2 - - - - - - - - - - - - True - False - <b>Connection</b> - True - - - - - True - True - 0 - - - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 3 - 2 - - - True - False - Bind DN - - - - - True - False - Authname - - - 1 - 2 - - - - - True - False - Realm - - - 2 - 3 - - - - - True - True - - False - False - True - True - - - 1 - 2 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 1 - 2 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 2 - 3 - - - - - - - - - True - False - <b>SASL</b> - True - - - - - True - True - 1 - - - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 5 - 2 - - - True - False - Base object: - - - - - True - False - Filter (%s for name): - - - 1 - 2 - - - - - True - False - Name Attribute: - - - 2 - 3 - - - - - True - False - SIP address attribute: - - - 3 - 4 - - - - - True - False - Attributes to query: - - - 4 - 5 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 1 - 2 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 2 - 3 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 3 - 4 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - 4 - 5 - - - - - - - - - True - False - <b>Search</b> - True - - - - - True - True - 2 - - - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 3 - 2 - - - True - False - Timeout for search: - - - - - True - False - Max results: - - - 1 - 2 - - - - - True - True - - True - False - False - True - True - timeout_adjustment - - - 1 - 2 - - - - - True - True - 3 - - True - False - False - True - True - result_adjustment - True - - - 1 - 2 - 1 - 2 - - - - - Follow Aliases - True - True - False - False - True - - - 1 - 2 - 2 - 3 - - - - - - - - - - - - True - False - <b>Miscellaneous</b> - True - - - - - True - True - 3 - - - - - True - False - 2 - - - - - - gtk-apply - True - True - True - False - True - - - - False - False - end - 1 - - - - - gtk-cancel - True - True - True - False - True - - - - False - False - end - 2 - - - - - False - True - 4 - - - - - - - - - - - - - ANONYMOUS - - - SIMPLE - - - DIGEST-MD5 - - - NTLM - - - - - 1 - 100 - 50 - 1 - 10 - - - 1 - 100 - 10 - 1 - 10 - - diff --git a/gtk/linphone.h b/gtk/linphone.h deleted file mode 100644 index 796ee8fb2..000000000 --- a/gtk/linphone.h +++ /dev/null @@ -1,379 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#ifndef _MSC_VER -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#endif - -#include - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif - -#ifdef _WIN32 -// alloca is already defined by gtk -#undef alloca -#endif -#include "linphone/core.h" - -#include "linphone/ldapprovider.h" - -#ifdef ENABLE_NLS - -#ifdef _MSC_VER -// prevent libintl.h from re-defining fprintf and vfprintf -#ifndef fprintf -#define fprintf fprintf -#endif -#ifndef vfprintf -#define vfprintf vfprintf -#endif -#define _GL_STDIO_H -#endif - -# include -# undef _ -# define _(String) dgettext (GETTEXT_PACKAGE,String) -#else -# define _(String) (String) -# define ngettext(singular,plural,number) ((number>1) ? (plural) : (singular) ) -#endif // ENABLE_NLS - -#undef N_ -#define N_(str) (str) - -#ifdef USE_BUILDDATE_VERSION -#include "version_date.h" -#undef LINPHONE_VERSION -#define LINPHONE_VERSION LINPHONE_VERSION_DATE -#endif - -#include "setupwizard.h" - -#define LINPHONE_ICON "linphone.png" -#define LINPHONE_ICON_NAME "linphone" - -enum { - COMPLETION_HISTORY, - COMPLETION_LDAP -}; - -typedef float (*get_volume_t)(void *data); - -typedef struct _volume_ctx{ - GtkWidget *widget; - get_volume_t get_volume; - void *data; - float last_value; -}volume_ctx_t; - -typedef enum { - CAP_IGNORE, - CAP_PLAYBACK, - CAP_CAPTURE -}DeviceCap; - -enum { - START_LINPHONE, - START_AUDIO_ASSISTANT, - START_LINPHONE_WITH_CALL -}; - -GdkPixbuf * create_pixbuf(const gchar *filename); -GdkPixbufAnimation *create_pixbuf_animation(const gchar *filename); -void add_pixmap_directory(const gchar *directory); -GtkWidget*create_pixmap(const gchar *filename); -GtkWidget *_gtk_image_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio); -GdkPixbuf *_gdk_pixbuf_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio); - -LINPHONE_PUBLIC void linphone_gtk_destroy_window(GtkWidget *window); -LINPHONE_PUBLIC GtkWidget *linphone_gtk_create_window(const char *window_name, GtkWidget *parent); -LINPHONE_PUBLIC GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name); -LINPHONE_PUBLIC GtkWidget *linphone_gtk_create_widget(const char* widget_name); -LINPHONE_PUBLIC GtkWidget *linphone_gtk_make_tab_header(const gchar *label, const gchar *icon_name, gboolean show_quit_button, GCallback cb, gpointer user_data); - -char *linphone_gtk_message_storage_get_db_file(const char *filename); -char *linphone_gtk_call_logs_storage_get_db_file(const char *filename); -char *linphone_gtk_friends_storage_get_db_file(const char* filename); -LINPHONE_PUBLIC void linphone_gtk_close_assistant(void); - -LINPHONE_PUBLIC LinphoneCore *linphone_gtk_get_core(void); -LINPHONE_PUBLIC GtkWidget *linphone_gtk_get_main_window(void); -LINPHONE_PUBLIC void linphone_gtk_display_something(GtkMessageType type, const gchar *message); -LINPHONE_PUBLIC void linphone_gtk_call_terminated(LinphoneCall *call, const char *error); -LINPHONE_PUBLIC void linphone_gtk_set_my_presence(LinphoneOnlineStatus ss); -LINPHONE_PUBLIC void linphone_gtk_show_parameters(void); -LINPHONE_PUBLIC void linphone_gtk_fill_soundcards(GtkWidget *pb); -LINPHONE_PUBLIC void linphone_gtk_fill_webcams(GtkWidget *pb); -LINPHONE_PUBLIC void linphone_gtk_load_identities(void); -LINPHONE_PUBLIC void linphone_gtk_call_log_update(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_create_log_window(void); -LINPHONE_PUBLIC void linphone_gtk_log_show(void); -LINPHONE_PUBLIC void linphone_gtk_show_main_window(void); -LINPHONE_PUBLIC void linphone_gtk_log_push(OrtpLogLevel lev, const char *fmt, va_list args); -LINPHONE_PUBLIC void linphone_gtk_destroy_log_window(void); -LINPHONE_PUBLIC void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to); -LINPHONE_PUBLIC gboolean linphone_gtk_check_logs(void); -LINPHONE_PUBLIC const gchar *linphone_gtk_get_ui_config(const char *key, const char *def); -LINPHONE_PUBLIC int linphone_gtk_get_ui_config_int(const char *key, int def); -LINPHONE_PUBLIC void linphone_gtk_set_ui_config_int(const char *key, int val); -LINPHONE_PUBLIC void linphone_gtk_visibility_set(const char *hiddens, const char *window_name, GtkWidget *w, gboolean show); - -LINPHONE_PUBLIC LinphoneLDAPContactProvider* linphone_gtk_get_ldap(void); -LINPHONE_PUBLIC void linphone_gtk_set_ldap(LinphoneLDAPContactProvider* ldap); -LINPHONE_PUBLIC int linphone_gtk_is_ldap_supported(void); - -LINPHONE_PUBLIC void linphone_gtk_open_browser(const char *url); -LINPHONE_PUBLIC void linphone_gtk_check_for_new_version(void); -LINPHONE_PUBLIC const char *linphone_gtk_get_lang(const char *config_file); -LINPHONE_PUBLIC void linphone_gtk_set_lang(const char *code); -LINPHONE_PUBLIC SipSetupContext* linphone_gtk_get_default_sip_setup_context(void); -LINPHONE_PUBLIC GtkWidget * linphone_gtk_show_buddy_lookup_window(SipSetupContext *ctx); -LINPHONE_PUBLIC void linphone_gtk_buddy_lookup_set_keyword(GtkWidget *w, const char *kw); -LINPHONE_PUBLIC void * linphone_gtk_wait(LinphoneCore *lc, void *ctx, LinphoneWaitingState ws, const char *purpose, float progress); -LINPHONE_PUBLIC void linphone_gtk_terminate_call(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_call_update_tab_header(LinphoneCall *call, gboolean pause); -LINPHONE_PUBLIC void linphone_gtk_show_directory_search(void); -LINPHONE_PUBLIC void linphone_gtk_status_icon_set_blinking(gboolean val); -LINPHONE_PUBLIC void linphone_gtk_notify(LinphoneCall *call, LinphoneChatMessage *chat_message, const char *msg); - -LINPHONE_PUBLIC void linphone_gtk_load_chatroom(LinphoneChatRoom *cr, const LinphoneAddress *uri, GtkWidget *chat_view); -LINPHONE_PUBLIC void linphone_gtk_send_text(void); -LINPHONE_PUBLIC GtkWidget * linphone_gtk_init_chatroom(LinphoneChatRoom *cr, const LinphoneAddress *with); -LINPHONE_PUBLIC LinphoneChatRoom * linphone_gtk_create_chatroom(const LinphoneAddress *with); -LINPHONE_PUBLIC void linphone_gtk_text_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *msg); -LINPHONE_PUBLIC void linphone_gtk_is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room); - -LINPHONE_PUBLIC void linphone_gtk_friend_list_update_button_display(GtkTreeView *friendlist); -LINPHONE_PUBLIC void linphone_gtk_friend_list_set_chat_conversation(const LinphoneAddress *la); -LINPHONE_PUBLIC gboolean linphone_gtk_friend_list_is_contact(const LinphoneAddress *addr); -LINPHONE_PUBLIC void linphone_gtk_friend_list_set_active_address(const LinphoneAddress *addr); -LINPHONE_PUBLIC const LinphoneAddress *linphone_gtk_friend_list_get_active_address(void); -LINPHONE_PUBLIC gboolean linphone_gtk_friend_list_enter_event_handler(GtkTreeView *friendlist, GdkEventCrossing *event); -LINPHONE_PUBLIC gboolean linphone_gtk_friend_list_leave_event_handler(GtkTreeView *friendlist, GdkEventCrossing *event); -LINPHONE_PUBLIC gboolean linphone_gtk_friend_list_motion_event_handler(GtkTreeView *friendlist, GdkEventMotion *event); -LINPHONE_PUBLIC void linphone_gtk_friend_list_on_name_column_clicked(GtkTreeModel *model); -LINPHONE_PUBLIC void linphone_gtk_notebook_tab_select(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer data); -LINPHONE_PUBLIC void linphone_gtk_show_friends(void); -LINPHONE_PUBLIC void linphone_gtk_show_contact(LinphoneFriend *lf, GtkWidget *parent); -LINPHONE_PUBLIC void linphone_gtk_buddy_info_updated(LinphoneCore *lc, LinphoneFriend *lf); - -/*functions controlling the different views*/ -LINPHONE_PUBLIC gboolean linphone_gtk_use_in_call_view(void); -LINPHONE_PUBLIC LinphoneCall *linphone_gtk_get_currently_displayed_call(gboolean *is_conf); -LINPHONE_PUBLIC void linphone_gtk_create_in_call_view(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_set_calling(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_set_in_call(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_update_duration(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_terminate(LinphoneCall *call, const char *error_msg); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_set_incoming(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_set_paused(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_set_transfer_status(LinphoneCall *call, LinphoneCallState cstate); -LINPHONE_PUBLIC void linphone_gtk_mute_clicked(GtkButton *button); -LINPHONE_PUBLIC void transfer_button_clicked(GtkWidget *button, gpointer call_ref); -LINPHONE_PUBLIC void linphone_gtk_enable_mute_button(GtkButton *button, gboolean sensitive); -LINPHONE_PUBLIC void linphone_gtk_enable_hold_button(LinphoneCall *call, gboolean sensitive, gboolean holdon); -LINPHONE_PUBLIC void linphone_gtk_enable_transfer_button(LinphoneCore *lc, gboolean value); -LINPHONE_PUBLIC void linphone_gtk_enable_conference_button(LinphoneCore *lc, gboolean value); -LINPHONE_PUBLIC void linphone_gtk_set_in_conference(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_unset_from_conference(LinphoneCall *call); -LINPHONE_PUBLIC bool_t linphone_gtk_call_is_in_conference_view(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_terminate_conference_participant(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_show_encryption(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_in_call_view_hide_encryption(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_update_video_button(LinphoneCall *call); -LINPHONE_PUBLIC void linphone_gtk_init_audio_meter(GtkWidget *w, get_volume_t get_volume, void *data); -LINPHONE_PUBLIC void linphone_gtk_uninit_audio_meter(GtkWidget *w); - -LINPHONE_PUBLIC void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg, gboolean disable_auto_login); -LINPHONE_PUBLIC void linphone_gtk_exit_login_frame(void); -LINPHONE_PUBLIC void linphone_gtk_set_ui_config(const char *key, const char *value); - -LINPHONE_PUBLIC void linphone_gtk_log_uninit(void); - -LINPHONE_PUBLIC bool_t linphone_gtk_init_instance(const char *app_name, int option, const char *addr_to_call); -LINPHONE_PUBLIC void linphone_gtk_uninit_instance(void); -LINPHONE_PUBLIC void linphone_gtk_monitor_usb(void); -LINPHONE_PUBLIC void linphone_gtk_unmonitor_usb(void); - -LINPHONE_PUBLIC void linphone_gtk_fill_combo_box(GtkWidget *combo, const char **devices, const char *selected, DeviceCap cap); -LINPHONE_PUBLIC gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference); -LINPHONE_PUBLIC gchar *linphone_gtk_get_snapshot_path(void); -LINPHONE_PUBLIC void linphone_gtk_schedule_restart(void); - -LINPHONE_PUBLIC void linphone_gtk_show_audio_assistant(void); -LINPHONE_PUBLIC gboolean linphone_gtk_get_audio_assistant_option(void); - -LINPHONE_PUBLIC void linphone_gtk_set_configuration_uri(void); -LINPHONE_PUBLIC GtkWidget * linphone_gtk_show_config_fetching(void); -LINPHONE_PUBLIC void linphone_gtk_close_config_fetching(GtkWidget *w, LinphoneConfiguringState state); -LINPHONE_PUBLIC const char *linphone_gtk_get_sound_path(const char *file); -LINPHONE_PUBLIC void linphone_gtk_in_call_show_video(LinphoneCall *call); -LINPHONE_PUBLIC char *linphone_gtk_address(const LinphoneAddress *addr);/*return human readable identifier for a LinphoneAddress */ -LINPHONE_PUBLIC GtkWidget *linphone_gtk_get_camera_preview_window(void); - -LINPHONE_PUBLIC void linphone_gtk_login_frame_connect_clicked(GtkWidget *button, GtkWidget *login_frame); - -LINPHONE_PUBLIC gboolean linphone_gtk_call_log_reset_missed_call(GtkWidget *w, GdkEvent *event, gpointer user_data); -LINPHONE_PUBLIC void linphone_gtk_history_row_activated(GtkWidget *treeview); -LINPHONE_PUBLIC void linphone_gtk_history_row_selected(GtkWidget *treeview); -LINPHONE_PUBLIC void linphone_gtk_clear_call_logs(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_add_contact(void); -LINPHONE_PUBLIC void linphone_gtk_contact_clicked(GtkTreeSelection *selection); -LINPHONE_PUBLIC void linphone_gtk_add_button_clicked(void); -LINPHONE_PUBLIC void linphone_gtk_edit_button_clicked(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_remove_button_clicked(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_my_presence_clicked(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_directory_search_button_clicked(GtkWidget *button); -LINPHONE_PUBLIC gboolean linphone_gtk_popup_contact_menu(GtkWidget *list, GdkEventButton *event); -LINPHONE_PUBLIC gboolean linphone_gtk_contact_list_button_pressed(GtkTreeView* firendlist, GdkEventButton* event); -LINPHONE_PUBLIC void linphone_gtk_auth_token_verified_clicked(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_hold_clicked(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_record_call_toggled(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_log_hide(void); -LINPHONE_PUBLIC void linphone_gtk_log_scroll_to_end(GtkToggleButton *button); -LINPHONE_PUBLIC void linphone_gtk_log_clear(void); -LINPHONE_PUBLIC void linphone_gtk_logout_clicked(void); - -LINPHONE_PUBLIC void linphone_gtk_about_response(GtkDialog *dialog, gint id); -LINPHONE_PUBLIC void linphone_gtk_show_about(void); -LINPHONE_PUBLIC void linphone_gtk_start_call(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_start_chat(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_uri_bar_activate(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_terminate_call(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_decline_clicked(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_answer_clicked(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_enable_video(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_enable_self_view(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_used_identity_changed(GtkWidget *w); -LINPHONE_PUBLIC void on_proxy_refresh_button_clicked(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_link_to_website(GtkWidget *item); -LINPHONE_PUBLIC void linphone_gtk_options_activate(GtkWidget *item); -LINPHONE_PUBLIC void linphone_gtk_show_keypad_checked(GtkCheckMenuItem *check_menu_item); -LINPHONE_PUBLIC gboolean linphone_gtk_keypad_destroyed_handler(void); - -LINPHONE_PUBLIC void linphone_gtk_keyword_changed(GtkEditable *e); -LINPHONE_PUBLIC void linphone_gtk_buddy_lookup_contact_activated(GtkWidget *treeview); -LINPHONE_PUBLIC void linphone_gtk_add_buddy_from_database(GtkWidget *button); -LINPHONE_PUBLIC gboolean linphone_gtk_call_log_button_pressed(GtkWidget *widget, GdkEventButton *event); -LINPHONE_PUBLIC void linphone_gtk_call_statistics_closed(GtkWidget *call_stats); -LINPHONE_PUBLIC void linphone_gtk_config_uri_cancel(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_config_uri_changed(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_contact_cancel(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_contact_ok(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_dscp_edit(void); -LINPHONE_PUBLIC void linphone_gtk_dscp_edit_response(GtkWidget *dialog, guint response_id); -LINPHONE_PUBLIC void linphone_gtk_keypad_key_released(GtkWidget *w, GdkEvent *event, gpointer userdata); -LINPHONE_PUBLIC void linphone_gtk_keypad_key_pressed(GtkWidget *w, GdkEvent *event, gpointer userdata); -LINPHONE_PUBLIC void linphone_gtk_ldap_save(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_ldap_reset(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_parameters_destroyed(GtkWidget *pb); -LINPHONE_PUBLIC void linphone_gtk_mtu_set(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_mtu_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_use_sip_info_dtmf_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_ipv6_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_lime_changed(GtkComboBoxText *comboext); -LINPHONE_PUBLIC void linphone_gtk_disabled_udp_port_toggle(GtkCheckButton *button); -LINPHONE_PUBLIC void linphone_gtk_random_udp_port_toggle(GtkCheckButton *button); -LINPHONE_PUBLIC void linphone_gtk_udp_port_value_changed(GtkSpinButton *button); -LINPHONE_PUBLIC void linphone_gtk_disabled_tcp_port_toggle(GtkCheckButton *button); -LINPHONE_PUBLIC void linphone_gtk_random_tcp_port_toggle(GtkCheckButton *button); -LINPHONE_PUBLIC void linphone_gtk_tcp_port_value_changed(GtkSpinButton *button); -LINPHONE_PUBLIC void linphone_gtk_min_audio_port_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_max_audio_port_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_fixed_audio_port_toggle(void); -LINPHONE_PUBLIC void linphone_gtk_min_video_port_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_max_video_port_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_fixed_video_port_toggle(void); -LINPHONE_PUBLIC void linphone_gtk_set_media_encryption_mandatory(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_edit_tunnel(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_no_firewall_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_use_nat_address_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_use_stun_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_use_ice_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_use_upnp_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_nat_address_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_stun_server_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_ring_file_set(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_play_ring_file(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_alsa_special_device_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_capture_device_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_ring_device_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_playback_device_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_echo_cancelation_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_cam_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_video_size_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_video_renderer_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_video_preset_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_show_camera_preview_clicked(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_update_my_contact(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_add_proxy(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_show_sip_accounts(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_edit_proxy(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_remove_proxy(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_clear_passwords(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_audio_codec_up(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_audio_codec_down(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_audio_codec_enable(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_audio_codec_disable(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_video_codec_up(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_video_codec_down(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_video_codec_enable(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_video_codec_disable(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_video_framerate_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_upload_bw_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_download_bw_changed(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_adaptive_rate_control_toggled(GtkToggleButton *button); -LINPHONE_PUBLIC void linphone_gtk_lang_changed(GtkComboBox *combo); -LINPHONE_PUBLIC void linphone_gtk_ui_level_toggled(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_show_ldap_config(GtkWidget* button); -LINPHONE_PUBLIC void linphone_gtk_parameters_closed(GtkWidget *button); -LINPHONE_PUBLIC void linphone_gtk_password_ok(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_password_cancel(GtkWidget *w); -LINPHONE_PUBLIC void linphone_gtk_proxy_ok(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_proxy_cancel(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_proxy_address_changed(GtkEditable *editable); -LINPHONE_PUBLIC void linphone_gtk_proxy_transport_changed(GtkWidget *combo); -LINPHONE_PUBLIC void linphone_gtk_tunnel_ok(GtkButton *button); -LINPHONE_PUBLIC void linphone_gtk_notebook_current_page_changed(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data); -LINPHONE_PUBLIC void linphone_gtk_reload_sound_devices(void); -LINPHONE_PUBLIC void linphone_gtk_reload_video_devices(void); -LINPHONE_PUBLIC bool_t linphone_gtk_is_friend(LinphoneCore *lc, const char *contact); -LINPHONE_PUBLIC gboolean linphone_gtk_auto_answer_enabled(void); -LINPHONE_PUBLIC void linphone_gtk_auto_answer_delay_changed(GtkSpinButton *spinbutton, gpointer user_data); -LINPHONE_PUBLIC void linphone_gtk_update_status_bar_icons(void); -LINPHONE_PUBLIC void linphone_gtk_enable_auto_answer(GtkToggleButton *checkbox, gpointer user_data); - -LINPHONE_PUBLIC void linphone_gtk_import_contacts(void); -LINPHONE_PUBLIC void linphone_gtk_export_contacts(void); - -LINPHONE_PUBLIC void linphone_gtk_mark_chat_read(LinphoneChatRoom *cr); -#ifdef __APPLE__ -LINPHONE_PUBLIC void linphone_gtk_update_badge_count(); -#endif - -LINPHONE_PUBLIC gboolean linphone_gtk_on_key_press(GtkWidget *widget, GdkEvent *event, gpointer user_data); diff --git a/gtk/linphone.ico b/gtk/linphone.ico deleted file mode 100755 index 2633d58f3..000000000 Binary files a/gtk/linphone.ico and /dev/null differ diff --git a/gtk/linphone.iss b/gtk/linphone.iss deleted file mode 100755 index f69104659..000000000 --- a/gtk/linphone.iss +++ /dev/null @@ -1,90 +0,0 @@ -; Script generated by the Inno Setup Script Wizard. -; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! - -[Setup] -AppName=Linphone -AppVerName=Linphone version 3.1.2 -AppPublisher=linphone.org -AppPublisherURL=http://www.linphone.org -AppSupportURL=http://www.linphone.org -AppUpdatesURL=http://www.linphone.org -DefaultDirName={pf}\Linphone -DefaultGroupName=Linphone -LicenseFile=..\COPYING -;InfoBeforeFile=..\README -OutputBaseFilename=setup -Compression=lzma -SolidCompression=yes - -[Languages] -Name: "english"; MessagesFile: "compiler:Default.isl" - -[Tasks] -Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked - -[Files] -Source: "linphone.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\mediastreamer2\build\win32native\mediastream.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\console\linphonec.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\console\linphonecsh.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "*.glade"; DestDir: "{app}/linphone"; Flags: ignoreversion -Source: "..\pixmaps\*.png"; DestDir: "{app}/linphone"; Flags: ignoreversion -Source: "*.png"; DestDir: "{app}/linphone"; Flags: ignoreversion -Source: "..\mediastreamer2\src\nowebcamCIF.jpg"; DestDir: "{app}\images"; Flags: ignoreversion -;;internal linphone dlls: -Source: "..\..\linphone-deps\bin\osipparser2.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\osip2.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\exosip2.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\libogg.dll"; DestDir: "{app}"; Flags: ignoreversion -;;Source: "..\..\linphone-deps\bin\speex.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\avcodec.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\avutil-49.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\swscale.dll"; DestDir: "{app}"; Flags: ignoreversion -;;Source: "..\..\linphone-deps\bin\libspeex-1.dll"; DestDir: "{app}"; Flags: ignoreversion -;;Source: "..\..\linphone-deps\bin\libspeexdsp-1.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\coreapi\linphone.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\mediastreamer2\build\win32native\mediastreamer2.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\oRTP\build\win32native\ortp.dll"; DestDir: "{app}"; Flags: ignoreversion -;;Sound files: -Source: "..\COPYING"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\share\ringback.wav"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\share\rings\orig.wav"; DestDir: "{app}\rings"; Flags: ignoreversion -Source: "..\share\rings\bigben.wav"; DestDir: "{app}\rings"; Flags: ignoreversion -Source: "..\share\rings\toy.wav"; DestDir: "{app}\rings"; Flags: ignoreversion -Source: "..\share\rings\tapping.wav"; DestDir: "{app}\rings"; Flags: ignoreversion -Source: "..\share\rings\oldphone.wav"; DestDir: "{app}\rings"; Flags: ignoreversion -;;Default my preferred gtk theme on windows: -Source: "..\gtk-glade\gtkrc"; DestDir: "{app}"; Flags: ignoreversion -;;Locales for linphone: -Source: "..\po\fr.gmo"; DestDir: "{app}\share\locale\fr\LC_MESSAGES"; DestName: "linphone.mo"; Flags: ignoreversion -Source: "..\po\sv.gmo"; DestDir: "{app}\share\locale\sv\LC_MESSAGES"; DestName: "linphone.mo"; Flags: ignoreversion - -;;GTK stuff: -Source: "..\..\gtk+-2.14.7\bin\*.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\libglade-2.6.3\bin\*.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\gtk+-2.14.7\etc\gtk-2.0\*"; DestDir: "{app}\etc\gtk-2.0\"; Flags: ignoreversion -Source: "..\..\linphone-deps\bin\libxml2.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\iconv-1.9.2.win32\bin\*.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\gtk+-2.14.7\lib\gtk-2.0\2.10.0\engines\*"; DestDir: "{app}\lib\gtk-2.0\2.10.0\engines"; Flags: ignoreversion -Source: "..\..\gtk+-2.14.7\lib\gtk-2.0\2.10.0\loaders\*"; DestDir: "{app}\lib\gtk-2.0\2.10.0\loaders"; Flags: ignoreversion -;;Source: "..\..\gtk+-2.14.7\lib\gtk-2.0\2.10.0\immodules\*"; DestDir: "{app}\lib\gtk-2.0\2.10.0\immodules"; Flags: ignoreversion -Source: "..\..\gtk+-2.14.7\share\locale\fr\LC_MESSAGES\*"; DestDir: "{app}\share\locale\fr\LC_MESSAGES"; Flags: ignoreversion -Source: "..\..\gtk+-2.14.7\share\locale\sv\LC_MESSAGES\*"; DestDir: "{app}\share\locale\sv\LC_MESSAGES"; Flags: ignoreversion -Source: "..\..\XLiquid_GTK-1.0.3\gtk-2.0\*"; DestDir: "{app}\share\themes\XLiquid_GTK-1.0.3\gtk-2.0"; Flags: ignoreversion -; NOTE: Don't use "Flags: ignoreversion" on any shared system files - -;; BuddyLookup plugin -Source: "..\coreapi\plugins\buddylookup\libbuddylookup.dll"; DestDir: "{app}\liblinphone\plugins"; Flags: ignoreversion -Source: "..\..\libsoup\bin\libsoup-2.4-1.dll"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\..\gnutls-2.6.4\bin\*.dll"; DestDir: "{app}"; Flags: ignoreversion - -;;Directshow capture plugin -Source: "..\mediastreamer2\plugins\msdscap\libmsdscap.dll"; DestDir: "{app}\plugins" ; Flags: ignoreversion - -[Icons] -Name: "{group}\Linphone"; Filename: "{app}\linphone.exe" ; WorkingDir: "{app}" -Name: "{userdesktop}\Linphone"; Filename: "{app}\linphone.exe"; WorkingDir: "{app}" ; Tasks: desktopicon - -[Run] -Filename: "{app}\linphone.exe"; Description: "{cm:LaunchProgram,Linphone}"; WorkingDir: "{app}" ; Flags: nowait postinstall skipifsilent - diff --git a/gtk/linphone.rc b/gtk/linphone.rc deleted file mode 100755 index 9455ab6b3..000000000 --- a/gtk/linphone.rc +++ /dev/null @@ -1,5 +0,0 @@ -// This file is automatically generated by wxDev-C++. -// All changes to this file will be lost when the project is recompiled. - -A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "linphone.ico" - diff --git a/gtk/log.ui b/gtk/log.ui deleted file mode 100644 index 40658b7db..000000000 --- a/gtk/log.ui +++ /dev/null @@ -1,113 +0,0 @@ - - - - - 540 - 290 - False - 5 - Linphone debug window - center-on-parent - normal - False - - - True - False - vertical - 2 - - - True - False - True - spread - - - Scroll to end - True - True - False - False - 0 - False - True - - - - False - True - 0 - - - - - gtk-clear - True - True - True - False - True - - - - False - True - 1 - - - - - gtk-close - True - True - True - False - True - - - - False - True - 2 - - - - - False - True - 0 - - - - - True - True - never - bottom-left - True - in - - - True - True - False - word - - - - - True - True - 1 - - - - - - scroll_to_end - button2 - button1 - - - diff --git a/gtk/logging.c b/gtk/logging.c deleted file mode 100644 index 068428564..000000000 --- a/gtk/logging.c +++ /dev/null @@ -1,373 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" - -#ifdef _WIN32 -#include -#define mkdir _mkdir -#else -#include -#include -#endif - -#ifdef _MSC_VER -#pragma warning(disable : 4996) -#else -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - -extern gchar *linphone_logfile; - -static GtkWidget *log_window=NULL; -static GStaticMutex log_mutex=G_STATIC_MUTEX_INIT; -static GList *log_queue=NULL; -static const char *dateformat="%Y%m%d-%H:%M:%S"; - -#define LOG_MAX_CHARS 1000000 /*1 mega bytes of traces*/ - -typedef struct _LinphoneGtkLog{ - OrtpLogLevel lev; - gchar *msg; -}LinphoneGtkLog; - - -/****** - * Module to log to a file - ******/ - -/* Marker to insert as a line at the start of every log file */ -#define LOGFILE_MARKER_START "--------" -/* Marker to insert as a line at the end of every log file */ -#define LOGFILE_MARKER_STOP "--------" -/* Number of files to keep in history, log file rotation will be - performed. */ -#define LOGFILE_ROTATION 4 -/* Pointer to opened log file */ -static FILE *_logfile = NULL; - - -/* Called on exit, print out the marker, close the file and avoid to - continue logging. */ -void linphone_gtk_log_uninit(void) -{ - if (_logfile != NULL) { - fprintf(_logfile, "%s\n", LOGFILE_MARKER_STOP); - fclose(_logfile); - _logfile = NULL; - } -} - -/* Called when we start logging, find a good place for the log files, - perform rotation, insert the start marker and return the pointer to - the file that should be used for logging, or NULL on errors or if - disabled. */ -static FILE *linphone_gtk_log_init(void) -{ - static char _logdir[1024]; - static char _logfname[1024]; - static gboolean _log_init = FALSE; - const char *dst_fname=NULL; - - if (!_log_init) { - if (linphone_gtk_get_core()!=NULL){ - dst_fname = linphone_gtk_get_ui_config("logfile",NULL); - dateformat=linphone_gtk_get_ui_config("logfile_date_format",dateformat); - } - /* For anything to happen, we need a logfile configuration variable, - this is our trigger */ - if (dst_fname) { - /* arrange for _logdir to contain a - directory that has been created and _logfname to contain the - path to a file to which we will log */ -#ifdef _WIN32 - const char *appdata=getenv("LOCALAPPDATA"); - if (appdata) { - snprintf(_logdir, sizeof(_logdir),"%s\\Linphone", appdata); - mkdir(_logdir); - } else { - _logdir[0] = '\0'; - } -#define PATH_SEPARATOR '\\' -#else - const char *home=getenv("HOME"); - if (home) { - snprintf(_logdir, sizeof(_logdir),"%s/.linphone", home); - mkdir(_logdir,S_IRUSR | S_IWUSR | S_IRGRP); - } else { - _logdir[0] = '\0'; - } -#define PATH_SEPARATOR '/' -#endif - if (_logdir[0] != '\0') { - /* We have a directory, fix the path to the log file in it and - open the file so that we will be appending to it. */ - snprintf(_logfname, sizeof(_logfname), "%s%c%s",_logdir, PATH_SEPARATOR, dst_fname); - } - }else if (linphone_logfile!=NULL){ - snprintf(_logfname,sizeof(_logfname),"%s",linphone_logfile); - } - - if (_logfname[0]!='\0'){ - /* If the constant LOGFILE_ROTATION is greater than zero, then - we kick away a simple rotation that will ensure that there - are never more than LOGFILE_ROTATION+1 old copies of the - log file on the disk. The oldest file is always rotated - "away" as expected. Rotated files have the same name as - the main log file, though with a number 0..LOGFILE_ROTATION - at the end, where the greater the number is, the older the - file is. */ - if (ortp_file_exist(_logfname)==0 && LOGFILE_ROTATION > 0) { - int i; - char old_fname[1024]; - char new_fname[1024]; - - /* Rotate away existing files. We make sure to remove the - old files otherwise rename() would not work properly. We - have to loop in reverse here. */ - for (i=LOGFILE_ROTATION-1;i>=0;i--) { - snprintf(old_fname, sizeof(old_fname), "%s%c%s.%d", - _logdir, PATH_SEPARATOR, dst_fname, i); - snprintf(new_fname, sizeof(new_fname), "%s%c%s.%d", - _logdir, PATH_SEPARATOR, dst_fname, i+1); - if (ortp_file_exist(old_fname)==0) { - if (ortp_file_exist(new_fname)==0) - unlink(new_fname); - rename(old_fname, new_fname); - } - } - /* Move current log file as the first of the rotation. Make - sure to remove the old .0 also, since otherwise rename() - would not work as expected. */ - snprintf(new_fname, sizeof(new_fname), "%s%c%s.%d", - _logdir, PATH_SEPARATOR, dst_fname, 0); - if (ortp_file_exist(new_fname)==0) - unlink(new_fname); - rename(_logfname, new_fname); - } - /* Start a new log file and mark that we have now initialised */ - _logfile = fopen(_logfname, "w"); - fprintf(_logfile, "%s\n", LOGFILE_MARKER_START); - } - _log_init = TRUE; - } - return _logfile; -} - -static void linphone_gtk_log_file(OrtpLogLevel lev, const char *msg) -{ - FILE *outlog; - - outlog = linphone_gtk_log_init(); - if (outlog != NULL) { - /* We have an opened file and we have initialised properly, it's - time to write all these log messages. We convert the log level - from oRTP into something readable and timestamp each log - message. The format of the time stamp can be controlled by - logfile_date_format in the GtkUi section of the config file, - but it defaults to something compact, but yet readable. */ - const char *lname="undef"; - - /* Convert level constant to text */ - switch(lev){ - case ORTP_DEBUG: - lname="debug "; - break; - case ORTP_MESSAGE: - lname="message"; - break; - case ORTP_WARNING: - lname="warning"; - break; - case ORTP_ERROR: - lname="error "; - break; - case ORTP_FATAL: - lname="fatal "; - break; - default: - lname="undef "; - break; - } - fprintf(outlog, "[%s] %s\n", lname, msg); - fflush(outlog); - } -} - -void linphone_gtk_log_hide(void){ - if (log_window) - gtk_widget_hide(log_window); -} - -void linphone_gtk_create_log_window(void){ - GtkTextBuffer *b; - log_window=linphone_gtk_create_window("log", NULL); - b=gtk_text_view_get_buffer(GTK_TEXT_VIEW(linphone_gtk_get_widget(log_window,"textview"))); - gtk_text_buffer_create_tag(b,"red","foreground","red",NULL); - gtk_text_buffer_create_tag(b,"orange","foreground","orange",NULL); - /*prevent the log window from being destroyed*/ - g_signal_connect (G_OBJECT (log_window), "delete-event", - G_CALLBACK (gtk_widget_hide_on_delete), log_window); -} - -void linphone_gtk_destroy_log_window(void){ - GtkWidget *w=log_window; - g_static_mutex_lock(&log_mutex); - log_window=NULL; - gtk_widget_destroy(w); - g_static_mutex_unlock(&log_mutex); -} - -void linphone_gtk_log_show(void){ - gtk_widget_show(log_window); - gtk_window_present(GTK_WINDOW(log_window)); -} - -static void linphone_gtk_display_log(GtkTextView *v, OrtpLogLevel lev, const char *msg){ - GtkTextIter iter,begin; - int off; - GtkTextBuffer *b; - const char *lname="undef"; - - b=gtk_text_view_get_buffer(v); - switch(lev){ - case ORTP_DEBUG: - lname="debug"; - break; - case ORTP_MESSAGE: - lname="message"; - break; - case ORTP_WARNING: - lname="warning"; - break; - case ORTP_ERROR: - lname="error"; - break; - case ORTP_FATAL: - lname="fatal"; - break; - default: - g_error("Bad level !"); - } - - gtk_text_buffer_get_end_iter(b,&iter); - off=gtk_text_iter_get_offset(&iter); - gtk_text_buffer_insert(b,&iter,lname,-1); - gtk_text_buffer_get_end_iter(b,&iter); - gtk_text_buffer_insert(b,&iter,": ",-1); - gtk_text_buffer_get_end_iter(b,&iter); - gtk_text_buffer_insert(b,&iter,msg,-1); - gtk_text_buffer_get_end_iter(b,&iter); - gtk_text_buffer_insert(b,&iter,"\n",-1); - gtk_text_buffer_get_end_iter(b,&iter); - gtk_text_buffer_get_iter_at_offset(b,&begin,off); - if (lev==ORTP_ERROR || lev==ORTP_FATAL) gtk_text_buffer_apply_tag_by_name(b,"red",&begin,&iter); - else if (lev==ORTP_WARNING) gtk_text_buffer_apply_tag_by_name(b,"orange",&begin,&iter); - - while(gtk_text_buffer_get_char_count(b)>LOG_MAX_CHARS){ - GtkTextIter iter_line_after; - gtk_text_buffer_get_start_iter(b,&iter); - iter_line_after=iter; - if (gtk_text_iter_forward_line(&iter_line_after)){ - gtk_text_buffer_delete(b,&iter,&iter_line_after); - } - } - -} - -static void stick_to_end(GtkTextView *v){ - GtkTextBuffer *b; - GtkTextIter iter; - b=gtk_text_view_get_buffer(v); - gtk_text_buffer_get_end_iter(b,&iter); - gtk_text_view_scroll_to_iter(v,&iter,0,FALSE,1.0,0); -} - -void linphone_gtk_log_scroll_to_end(GtkToggleButton *button) { - if (gtk_toggle_button_get_active(button)){ - GtkTextView *v=GTK_TEXT_VIEW(linphone_gtk_get_widget(log_window,"textview")); - stick_to_end(v); - } - lp_config_set_int(linphone_core_get_config(linphone_gtk_get_core()), "GtkUi", "logs_scroll_to_end", gtk_toggle_button_get_active(button) ? 1 : 0); -} - -/* - * called from Gtk main loop. -**/ -gboolean linphone_gtk_check_logs(void){ - GList *elem; - GtkTextView *v=NULL; - if (log_window) v=GTK_TEXT_VIEW(linphone_gtk_get_widget(log_window,"textview")); - g_static_mutex_lock(&log_mutex); - for(elem=log_queue;elem!=NULL;elem=elem->next){ - LinphoneGtkLog *lgl=(LinphoneGtkLog*)elem->data; - if (v) linphone_gtk_display_log(v,lgl->lev,lgl->msg); - g_free(lgl->msg); - g_free(lgl); - } - if (log_queue) g_list_free(log_queue); - log_queue=NULL; - g_static_mutex_unlock(&log_mutex); - if (v) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(log_window,"scroll_to_end")), lp_config_get_int(linphone_core_get_config(linphone_gtk_get_core()), "GtkUi", "logs_scroll_to_end", 0) == 1); - linphone_gtk_log_scroll_to_end(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(log_window,"scroll_to_end"))); - } - return TRUE; -} - - -/* - * Called from any linphone thread. - */ -void linphone_gtk_log_push(OrtpLogLevel lev, const char *fmt, va_list args){ - LinphoneGtkLog *lgl=g_new(LinphoneGtkLog,1); - gchar *msg=g_strdup_vprintf(fmt,args); - gchar *dated_msg; - struct timeval tp; - struct tm *lt; - time_t tt; - - ortp_gettimeofday(&tp, NULL); - tt = (time_t)tp.tv_sec; - lt = localtime((const time_t*)&tt); - dated_msg=g_strdup_printf("%i-%.2i-%.2i %.2i:%.2i:%.2i:%.3i %s", - 1900 + lt->tm_year, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec, (int)(tp.tv_usec / 1000), msg); - g_free(msg); - lgl->lev=lev; - lgl->msg=dated_msg; - linphone_gtk_log_file(lev, dated_msg); - g_static_mutex_lock(&log_mutex); - log_queue=g_list_append(log_queue,lgl); - g_static_mutex_unlock(&log_mutex); -} - -void linphone_gtk_log_clear(void){ - if (log_window){ - GtkTextIter end,begin; - GtkTextView *v; - GtkTextBuffer *b; - v=GTK_TEXT_VIEW(linphone_gtk_get_widget(log_window,"textview")); - b=gtk_text_view_get_buffer(v); - gtk_text_buffer_get_start_iter(b,&begin); - gtk_text_buffer_get_end_iter(b,&end); - gtk_text_buffer_delete(b,&begin,&end); - } -} - - diff --git a/gtk/login_frame.ui b/gtk/login_frame.ui deleted file mode 100644 index f65229f14..000000000 --- a/gtk/login_frame.ui +++ /dev/null @@ -1,250 +0,0 @@ - - - - - - False - 0 - etched-out - - - True - False - 12 - - - True - False - - - True - False - gtk-missing-image - - - True - True - 0 - - - - - True - False - 0 - none - - - True - False - 12 - 12 - - - True - False - 5 - 2 - - - - - - True - False - Username - - - - - True - False - Password - - - 1 - 2 - - - - - False - Internet connection: - - - 3 - 4 - - - - - True - True - - True - False - False - True - True - - - 1 - 2 - - - - - True - True - False - - True - False - False - True - True - - - 1 - 2 - 1 - 2 - - - - - False - 0 - - - - 0 - - - - - 1 - 2 - 3 - 4 - - - - - Automatically log me in - True - True - False - True - - - 1 - 2 - 4 - 5 - - - - - False - UserID - - - 2 - 3 - - - - - True - - True - False - False - True - True - - - 1 - 2 - 2 - 3 - - - - - - - - - True - False - Login information - True - - - - - True - True - 10 - 1 - - - - - True - False - - - gtk-connect - True - True - True - True - - - - False - False - 0 - - - - - - - - True - True - 2 - - - - - - - - - True - False - <b>Welcome!</b> - True - - - - - - - - - - - ADSL - - - Fiber Channel - - - - diff --git a/gtk/loginframe.c b/gtk/loginframe.c deleted file mode 100644 index 85174a18b..000000000 --- a/gtk/loginframe.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2009 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" - -void test_button_clicked_cb(GtkWidget *button); -void linphone_gtk_exit_login_frame(void); - - -static void do_login(SipSetupContext *ssctx, const char *identity, const char * passwd, const char *userid){ - if (sip_setup_context_login_account(ssctx,identity,passwd,userid)==0){ - } -} - -static gboolean do_login_noprompt(LinphoneProxyConfig *cfg){ - SipSetupContext *ssctx=linphone_proxy_config_get_sip_setup_context(cfg); - LinphoneAddress *addr; - const char *username; - char *tmp; - if (ssctx==NULL) return TRUE;/*not ready ?*/ - username=linphone_gtk_get_ui_config ("login_username",NULL); - if (username==NULL) { - linphone_gtk_show_login_frame(cfg,TRUE); - return FALSE; - } - addr=linphone_address_clone(linphone_proxy_config_get_identity_address(cfg)); - linphone_address_set_username(addr,username); - tmp=linphone_address_as_string (addr); - do_login(ssctx,tmp,NULL,NULL); - linphone_address_unref(addr); - linphone_gtk_load_identities(); - return FALSE; -} - -static void linphone_gtk_init_login_frame(GtkWidget *login_frame, LinphoneProxyConfig *cfg) { - gboolean auto_login=linphone_gtk_get_ui_config_int("automatic_login",0); - const char *login_image=linphone_gtk_get_ui_config("login_image","linphone-banner.png"); - GtkWidget *label=linphone_gtk_get_widget(login_frame,"login_label"); - LinphoneCore *lc=linphone_gtk_get_core(); - gchar *str; - LinphoneAddress *from; - const LinphoneAuthInfo *ai; - const char *passwd=NULL; - const char *userid=NULL; - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(login_frame, "automatic_login")),auto_login); - - if (login_image){ - GdkPixbuf *pbuf=create_pixbuf (login_image); - gtk_image_set_from_pixbuf (GTK_IMAGE(linphone_gtk_get_widget(login_frame, "login_image")), pbuf); - g_object_unref(G_OBJECT(pbuf)); - } - - if (linphone_gtk_get_ui_config_int("login_needs_userid",FALSE)){ - gtk_widget_show(linphone_gtk_get_widget(login_frame,"userid")); - gtk_widget_show(linphone_gtk_get_widget(login_frame,"login_userid")); - } - - str=g_strdup_printf(_("Please enter login information for %s"),linphone_proxy_config_get_domain(cfg)); - gtk_label_set_text(GTK_LABEL(label),str); - g_object_set_data(G_OBJECT(login_frame),"login_proxy_config",cfg); - g_free(str); - - from=linphone_address_new(linphone_proxy_config_get_identity(cfg)); - if (linphone_address_get_username(from)[0]=='?'){ - const char *username=linphone_gtk_get_ui_config ("login_username",NULL); - if (username) - linphone_address_set_username(from,username); - } - - ai=linphone_core_find_auth_info(lc,linphone_proxy_config_get_domain(cfg),linphone_address_get_username(from),NULL); - /*display the last entered username, if not '?????'*/ - if (linphone_address_get_username(from)[0]!='?') - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(login_frame,"login_username")), - linphone_address_get_username(from)); - if (ai) { - passwd=linphone_auth_info_get_passwd(ai); - userid=linphone_auth_info_get_userid(ai); - } - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(login_frame,"login_password")), - passwd!=NULL ? passwd : ""); - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(login_frame,"login_userid")), - userid ? userid : ""); - - linphone_address_unref(from); -} - -void linphone_gtk_show_login_frame(LinphoneProxyConfig *cfg, gboolean disable_auto_login){ - GtkWidget *mw=linphone_gtk_get_main_window(); - gboolean auto_login=linphone_gtk_get_ui_config_int("automatic_login",0); - GtkWidget *main_frame = linphone_gtk_get_widget(mw, "main_frame"); - GtkWidget *main_layout = linphone_gtk_get_widget(mw, "main_layout"); - GtkWidget *login_frame; - - if (auto_login && !disable_auto_login){ - g_timeout_add(250,(GSourceFunc)do_login_noprompt,cfg); - return; - } - - login_frame = linphone_gtk_create_widget("login_frame"); - linphone_gtk_init_login_frame(login_frame, cfg); - g_object_set_data_full(G_OBJECT(mw), "main_frame", g_object_ref(main_frame), g_object_unref); - g_object_set_data(G_OBJECT(mw), "login_frame", login_frame); - gtk_container_remove(GTK_CONTAINER(main_layout), main_frame); - gtk_box_pack_start(GTK_BOX(main_layout), login_frame, TRUE, TRUE, 0); - gtk_widget_show(login_frame); - - gtk_widget_hide(linphone_gtk_get_widget(mw,"disconnect_item")); - gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"options_menu"),FALSE); -} - -void linphone_gtk_exit_login_frame(void){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *main_layout = linphone_gtk_get_widget(mw, "main_layout"); - GtkWidget *main_frame = GTK_WIDGET(g_object_get_data(G_OBJECT(mw), "main_frame")); - GtkWidget *login_frame = GTK_WIDGET(g_object_get_data(G_OBJECT(mw), "login_frame")); - - gtk_container_remove(GTK_CONTAINER(main_layout), login_frame); - gtk_box_pack_start(GTK_BOX(main_layout), main_frame, TRUE, TRUE, 0); - g_object_set_data(G_OBJECT(mw), "login_frame", NULL); - g_object_set_data(G_OBJECT(mw), "main_frame", NULL); - - gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"options_menu"),TRUE); - gtk_widget_show(linphone_gtk_get_widget(mw,"disconnect_item")); -} - -void linphone_gtk_logout_clicked(void){ - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneProxyConfig *cfg=NULL; - cfg = linphone_core_get_default_proxy_config(lc); - if (cfg){ - SipSetupContext *ss=linphone_proxy_config_get_sip_setup_context(cfg); - if (ss){ - sip_setup_context_logout(ss); - linphone_gtk_show_login_frame(cfg,TRUE); - } - } -} - - - -void linphone_gtk_login_frame_connect_clicked(GtkWidget *button, GtkWidget *login_frame){ - const char *username; - const char *password; - const char *userid; - char *identity; - gboolean autologin; - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)g_object_get_data(G_OBJECT(login_frame),"login_proxy_config"); - LinphoneAddress *from; - SipSetupContext *ssctx=linphone_proxy_config_get_sip_setup_context(cfg); - - username=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(login_frame,"login_username"))); - password=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(login_frame,"login_password"))); - userid=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(login_frame,"login_userid"))); - - if (username==NULL || username[0]=='\0') - return; - - autologin=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(login_frame,"automatic_login"))); - linphone_gtk_set_ui_config_int("automatic_login",autologin); - linphone_gtk_set_ui_config("login_username",username); - - from=linphone_address_new(linphone_proxy_config_get_identity(cfg)); - linphone_address_set_username(from,username); - identity=linphone_address_as_string(from); - do_login(ssctx,identity,password,userid); - /*we need to refresh the identities since the proxy config may have changed.*/ - linphone_gtk_load_identities(); -} diff --git a/gtk/mac.m b/gtk/mac.m deleted file mode 100644 index 7a45d0d48..000000000 --- a/gtk/mac.m +++ /dev/null @@ -1,47 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifdef __APPLE__ - -#import -#import "linphone.h" - - -static int unread_messages_count() { - LinphoneCore* lc = linphone_gtk_get_core(); - int count = 0; - const MSList *rooms = linphone_core_get_chat_rooms(lc); - const MSList *item = rooms; - while (item) { - LinphoneChatRoom *room = (LinphoneChatRoom *)item->data; - if (room) { - count += linphone_chat_room_get_unread_messages_count(room); - } - item = item->next; - } - return count; -} - -void linphone_gtk_update_badge_count() { - int count = unread_messages_count(); - NSString* badgeStr = (count > 0) ? [NSString stringWithFormat:@"%d", count] : @""; - [[NSApp dockTile] setBadgeLabel:badgeStr]; -} - -#endif diff --git a/gtk/main.c b/gtk/main.c deleted file mode 100644 index 579fc8296..000000000 --- a/gtk/main.c +++ /dev/null @@ -1,2383 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - - -#define VIDEOSELFVIEW_DEFAULT 0 - -#include "linphone.h" -#include "linphone/lpconfig.h" -#include "liblinphone_gitversion.h" -#include -#include - -#include -#include -#ifndef _WIN32 -#include -#endif - -#ifdef HAVE_GTK_OSX -#include -#endif - -#ifdef _WIN32 -#include "direct.h" -#define chdir _chdir -#ifndef F_OK -#define F_OK 00 /*visual studio does not define F_OK*/ -#endif -#endif - -#if defined(HAVE_NOTIFY1) || defined(HAVE_NOTIFY4) -#define HAVE_NOTIFY -#endif - -#ifdef HAVE_NOTIFY -#include -#endif - -#ifdef ENABLE_NLS -#include -#endif - -#include "status_icon.h" - - -const char *this_program_ident_string="linphone_ident_string=" LINPHONE_VERSION; - -static LinphoneCore *the_core=NULL; -static GtkWidget *the_ui=NULL; -static LinphoneLDAPContactProvider* ldap_provider = NULL; - -static void linphone_gtk_global_state_changed(LinphoneCore *lc, LinphoneGlobalState state, const char*str); -static void linphone_gtk_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState rs, const char *msg); -static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid); -static void linphone_gtk_new_unknown_subscriber(LinphoneCore *lc, LinphoneFriend *lf, const char *url); -static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain); -static void linphone_gtk_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message); -static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl); -static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg); -static void linphone_gtk_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t enabled, const char *token); -static void linphone_gtk_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate); -static void linphone_gtk_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf); -void linphone_gtk_save_main_window_position(GtkWindow* mw, GdkEvent *event, gpointer data); -static gboolean linphone_gtk_auto_answer(LinphoneCall *call); -void linphone_gtk_status_icon_set_blinking(gboolean val); -void _linphone_gtk_enable_video(gboolean val); -void linphone_gtk_on_uribar_changed(GtkEditable *uribar, gpointer user_data); -static void linphone_gtk_init_ui(void); -static void linphone_gtk_quit(void); - -#ifndef HAVE_GTK_OSX -static gint main_window_x=0; -static gint main_window_y=0; -#endif -static gboolean verbose=0; -static gboolean quit_done=FALSE; -static gchar * addr_to_call = NULL; -static int start_option = START_LINPHONE; -static gboolean no_video=FALSE; -static gboolean iconified=FALSE; -static gboolean run_audio_assistant=FALSE; -static gboolean version=FALSE; -static gboolean selftest=FALSE; -static gchar *workingdir=NULL; -static char *progpath=NULL; -gchar *linphone_logfile=NULL; -static gboolean workaround_gtk_entry_chinese_bug=FALSE; -static gchar *custom_config_file=NULL; -static gboolean restart=FALSE; -static GtkWidget *config_fetching_dialog=NULL; - -#if _MSC_VER - -#define LINPHONE_OPTION(optlname, optsname, optarg, optargdata, optdesc) \ -{ \ - optlname, \ - optsname, \ - 0, \ - optarg, \ - optargdata, \ - optdesc, \ - NULL \ -} - -#else - -#define LINPHONE_OPTION(optlname, optsname, optarg, optargdata, optdesc) \ -{ \ - .long_name = optlname, \ - .short_name = optsname, \ - .arg = optarg, \ - .arg_data = optargdata, \ - .description = optdesc, \ -} - -#endif - -static GOptionEntry linphone_options[]={ - LINPHONE_OPTION("verbose", '\0', G_OPTION_ARG_NONE, (gpointer)&verbose, N_("log to stdout some debug information while running.")), - LINPHONE_OPTION("version", '\0', G_OPTION_ARG_NONE, (gpointer)&version, N_("display version and exit.")), - LINPHONE_OPTION("logfile", 'l', G_OPTION_ARG_STRING, &linphone_logfile, N_("path to a file to write logs into.")), - LINPHONE_OPTION("no-video", '\0', G_OPTION_ARG_NONE, (gpointer)&no_video, N_("Start linphone with video disabled.")), - LINPHONE_OPTION("iconified", '\0', G_OPTION_ARG_NONE, (gpointer)&iconified, N_("Start only in the system tray, do not show the main interface.")), - LINPHONE_OPTION("call", 'c', G_OPTION_ARG_STRING, &addr_to_call, N_("address to call right now")), - LINPHONE_OPTION("workdir", '\0', G_OPTION_ARG_STRING, (gpointer) & workingdir, N_("Specifiy a working directory (should be the base of the installation, eg: c:\\Program Files\\Linphone)")), - LINPHONE_OPTION("config", '\0', G_OPTION_ARG_FILENAME, (gpointer) &custom_config_file, N_("Configuration file")), - LINPHONE_OPTION("run-audio-assistant", '\0', G_OPTION_ARG_NONE, (gpointer) &run_audio_assistant, N_("Run the audio assistant")), - LINPHONE_OPTION("selftest", '\0', G_OPTION_ARG_NONE, (gpointer) &selftest, N_("Run self test and exit 0 if succeed")), - {0} -}; - -#define RELATIVE_XML_DIR -#define BUILD_TREE_XML_DIR "gtk" - -#ifndef _WIN32 -#define CONFIG_FILE ".linphonerc" -#define SECRETS_FILE ".linphone-zidcache" -#define CERTIFICATES_PATH ".linphone-usr-crt" -#else -#define CONFIG_FILE "linphonerc" -#define SECRETS_FILE "linphone-zidcache" -#define CERTIFICATES_PATH "linphone-usr-crt" -#endif - -char *linphone_gtk_get_config_file(const char *filename){ - const int path_max=1024; - char *config_file=g_malloc0(path_max); - if (filename==NULL) filename=CONFIG_FILE; - if (g_path_is_absolute(filename)) { - snprintf(config_file,path_max,"%s",filename); - } else{ -#ifdef _WIN32 - const char *appdata=getenv("APPDATA"); - if (appdata){ - snprintf(config_file,path_max,"%s\\%s",appdata,LINPHONE_CONFIG_DIR); - CreateDirectory(config_file,NULL); - snprintf(config_file,path_max,"%s\\%s\\%s",appdata,LINPHONE_CONFIG_DIR,filename); - } -#else - const char *home=getenv("HOME"); - if (home==NULL) home="."; - snprintf(config_file,path_max,"%s/%s",home,filename); -#endif - } - return config_file; -} - -#define FACTORY_CONFIG_FILE "linphonerc.factory" -static char _factory_config_file[1024]; -static const char *linphone_gtk_get_factory_config_file(void){ - char* path = NULL; - /*try accessing a local file first if exists*/ - if (bctbx_file_exist(FACTORY_CONFIG_FILE)==0){ - path = ms_strdup(FACTORY_CONFIG_FILE); - } else { - char *progdir; - - if (progpath != NULL) { - char *basename; - progdir = strdup(progpath); -#ifdef _WIN32 - basename = strrchr(progdir, '\\'); - if (basename != NULL) { - basename ++; - *basename = '\0'; - path = ms_strdup_printf("%s\\..\\%s", progdir, FACTORY_CONFIG_FILE); - } else if (workingdir!=NULL) { - path = ms_strdup_printf("%s\\%s", workingdir, FACTORY_CONFIG_FILE); - } -#else - basename = strrchr(progdir, '/'); - if (basename != NULL) { - basename ++; - *basename = '\0'; - path = ms_strdup_printf("%s/../share/linphone/%s", progdir, FACTORY_CONFIG_FILE); - } -#endif - free(progdir); - } - } - if (path) { - ms_message("Factory config file expected at %s", path); - //use factory file only if it exists - if (bctbx_file_exist(path)==0){ - snprintf(_factory_config_file, sizeof(_factory_config_file), "%s", path); - ms_free(path); - return _factory_config_file; - } - ms_free(path); - } - return NULL; -} - -LinphoneLDAPContactProvider* linphone_gtk_get_ldap(void){ - return ldap_provider; -} - -int linphone_gtk_is_ldap_supported(void){ - return linphone_ldap_contact_provider_available(); -} - -void linphone_gtk_set_ldap(LinphoneLDAPContactProvider* ldap) -{ - if( ldap_provider ) - linphone_contact_provider_unref(ldap_provider); - - ldap_provider = ldap ? linphone_ldap_contact_provider_ref( ldap ) - : NULL; -} - -void linphone_gtk_schedule_restart(void){ - restart=TRUE; -} - -gboolean linphone_gtk_get_audio_assistant_option(void){ - return run_audio_assistant; -} - -static void linphone_gtk_init_liblinphone(const char *config_file, - const char *factory_config_file, const char *chat_messages_db_file, - const char *call_logs_db_file, const char *friends_db_file) { - LinphoneCoreVTable vtable={0}; - gchar *secrets_file=linphone_gtk_get_config_file(SECRETS_FILE); - gchar *user_certificates_dir=linphone_gtk_get_config_file(CERTIFICATES_PATH); - MSFactory *msfactory = NULL; - MSFilterDesc *ogl_filter_desc; - - vtable.global_state_changed=linphone_gtk_global_state_changed; - vtable.call_state_changed=linphone_gtk_call_state_changed; - vtable.registration_state_changed=linphone_gtk_registration_state_changed; - vtable.notify_presence_received=linphone_gtk_notify_recv; - vtable.new_subscription_requested=linphone_gtk_new_unknown_subscriber; - vtable.auth_info_requested=linphone_gtk_auth_info_requested; - vtable.call_log_updated=linphone_gtk_call_log_updated; - vtable.message_received=linphone_gtk_text_received; - vtable.is_composing_received=linphone_gtk_is_composing_received; - vtable.refer_received=linphone_gtk_refer_received; - vtable.buddy_info_updated=linphone_gtk_buddy_info_updated; - vtable.call_encryption_changed=linphone_gtk_call_encryption_changed; - vtable.transfer_state_changed=linphone_gtk_transfer_state_changed; - vtable.dtmf_received=linphone_gtk_dtmf_received; - vtable.configuring_status=linphone_gtk_configuring_status; - - the_core=linphone_core_new(&vtable,config_file,factory_config_file,NULL); - linphone_core_migrate_to_multi_transport(the_core); - //lp_config_set_int(linphone_core_get_config(the_core), "sip", "store_auth_info", 0); - - - if( lp_config_has_section(linphone_core_get_config(the_core),"ldap") ){ - LpConfig* cfg = linphone_core_get_config(the_core); - LinphoneDictionary* ldap_cfg = lp_config_section_to_dict(cfg, "ldap"); - linphone_gtk_set_ldap( linphone_ldap_contact_provider_create(the_core, ldap_cfg) ); - } - - linphone_core_set_user_agent(the_core,"Linphone", LINPHONE_VERSION); - linphone_core_set_waiting_callback(the_core,linphone_gtk_wait,NULL); - linphone_core_set_zrtp_secrets_file(the_core,secrets_file); /* XML cache is superseeded by the sqlite one, keep it for migration purpose but it shall be removed in future version */ - g_free(secrets_file); - linphone_core_set_user_certificates_path(the_core,user_certificates_dir); - g_free(user_certificates_dir); - linphone_core_enable_video_capture(the_core, TRUE); - linphone_core_enable_video_display(the_core, TRUE); - linphone_core_set_native_video_window_id(the_core,LINPHONE_VIDEO_DISPLAY_NONE);/*don't create the window*/ - if (no_video) { - _linphone_gtk_enable_video(FALSE); - linphone_gtk_set_ui_config_int("videoselfview",0); - } - if (chat_messages_db_file) linphone_core_set_chat_database_path(the_core,chat_messages_db_file); - if (call_logs_db_file) linphone_core_set_call_logs_database_path(the_core, call_logs_db_file); - if (friends_db_file) linphone_core_set_friends_database_path(the_core, friends_db_file); - - // Disable the generic OpenGL displaying filter - msfactory = linphone_core_get_ms_factory(the_core); - ogl_filter_desc = ms_factory_lookup_filter_by_id(msfactory, MS_OGL_ID); - if (ogl_filter_desc != NULL) ogl_filter_desc->flags &= ~MS_FILTER_IS_ENABLED; -} - -LinphoneCore *linphone_gtk_get_core(void){ - return the_core; -} - -GtkWidget *linphone_gtk_get_main_window(void){ - return the_ui; -} - -void linphone_gtk_destroy_main_window(void) { - linphone_gtk_destroy_window(the_ui); - the_ui = NULL; -} - -static void linphone_gtk_configure_window(GtkWidget *w, const char *window_name){ - static const char *hiddens=NULL; - static const char *shown=NULL; - static bool_t config_loaded=FALSE; - if (linphone_gtk_get_core()==NULL) return; - if (config_loaded==FALSE){ - hiddens=linphone_gtk_get_ui_config("hidden_widgets",NULL); - shown=linphone_gtk_get_ui_config("shown_widgets",NULL); - config_loaded=TRUE; - } - if (hiddens) linphone_gtk_visibility_set(hiddens,window_name,w,FALSE); - if (shown) linphone_gtk_visibility_set(shown,window_name,w,TRUE); -} - -static int get_ui_file(const char *name, char *path, int pathsize){ - snprintf(path,pathsize,"%s/%s.ui",BUILD_TREE_XML_DIR,name); - if (bctbx_file_exist(path)!=0){ - LinphoneFactory *factory = linphone_factory_get(); - const char *data_dir = linphone_factory_get_data_resources_dir(factory); - snprintf(path,pathsize,"%s/%s.ui",data_dir,name); - if (bctbx_file_exist(path)!=0){ - g_error("Could not locate neither %s/%s.ui nor %s/%s.ui",BUILD_TREE_XML_DIR,name,data_dir,name); - return -1; - } - } - return 0; -} - -void linphone_gtk_destroy_window(GtkWidget *widget) { - GtkBuilder* builder = g_object_get_data(G_OBJECT(widget), "builder"); - gtk_widget_destroy(widget); - g_object_unref (G_OBJECT (builder)); -} - -GtkWidget *linphone_gtk_create_widget(const char *widget_name) { - char path[2048]; - GtkBuilder *builder = gtk_builder_new(); - GError *error = NULL; - GObject *obj; - - if(get_ui_file(widget_name, path, sizeof(path)) == -1) goto fail; - - gtk_builder_set_translation_domain(builder, GETTEXT_PACKAGE); - - if(gtk_builder_add_from_file(builder, path, &error) == 0) { - g_error("Couldn't load builder file: %s", error->message); - g_error_free(error); - goto fail; - } - - obj = gtk_builder_get_object(builder, widget_name); - if(obj == NULL) { - g_error("'%s' widget not found", widget_name); - goto fail; - } - g_object_set_data(G_OBJECT(obj), "builder", builder); - g_signal_connect_data(G_OBJECT(obj),"destroy",(GCallback)g_object_unref,builder, NULL, G_CONNECT_AFTER|G_CONNECT_SWAPPED); - gtk_builder_connect_signals(builder, obj); - - return GTK_WIDGET(obj); - -fail: - g_object_unref(builder); - return NULL; -} - -GtkWidget *linphone_gtk_create_window(const char *window_name, GtkWidget *parent){ - GtkWidget *w = linphone_gtk_create_widget(window_name); - if(w) { - linphone_gtk_configure_window(w,window_name); - if(parent) { - gtk_window_set_transient_for(GTK_WINDOW(w), GTK_WINDOW(parent)); - gtk_window_set_position(GTK_WINDOW(w), GTK_WIN_POS_CENTER_ON_PARENT); - } - } - return w; -} - -static void entry_unmapped(GtkWidget *widget){ - ms_message("%s is unmapped, calling unrealize to workaround chinese bug.",G_OBJECT_TYPE_NAME(widget)); - gtk_widget_unrealize(widget); -} - -GtkWidget *linphone_gtk_get_widget(GtkWidget *window, const char *name){ - GtkBuilder *builder; - GObject *w; - if (window==NULL) return NULL; - builder=(GtkBuilder*)g_object_get_data(G_OBJECT(window),"builder"); - if (builder==NULL){ - g_error("Fail to retrieve builder from window !"); - return NULL; - } - w=gtk_builder_get_object(builder,name); - if (w==NULL){ - g_error("No widget named %s found in xml interface.",name); - } - if (workaround_gtk_entry_chinese_bug){ - if (strcmp(G_OBJECT_TYPE_NAME(w),"GtkEntry")==0 || strcmp(G_OBJECT_TYPE_NAME(w),"GtkTextView")==0){ - if (g_object_get_data(G_OBJECT(w),"entry_bug_workaround")==NULL){ - g_object_set_data(G_OBJECT(w),"entry_bug_workaround",GINT_TO_POINTER(1)); - ms_message("%s is a %s",name,G_OBJECT_TYPE_NAME(w)); - g_signal_connect(G_OBJECT(w),"unmap",(GCallback)entry_unmapped,NULL); - } - } - } - return GTK_WIDGET(w); -} - - -void linphone_gtk_display_something(GtkMessageType type,const gchar *message){ - GtkWidget *dialog; - GtkWidget *main_window=linphone_gtk_get_main_window(); - - gtk_widget_show(main_window); - if (type==GTK_MESSAGE_QUESTION) - { - /* draw a question box. link to dialog_click callback */ - dialog = gtk_message_dialog_new ( - GTK_WINDOW(main_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - "%s", - (const gchar*)message); - /* connect to some callback : REVISIT */ - /* - g_signal_connect_swapped (G_OBJECT (dialog), "response", - G_CALLBACK (dialog_click), - G_OBJECT (dialog)); - */ - /* actually show the box */ - gtk_widget_show(dialog); - } - else - { - dialog = gtk_message_dialog_new (GTK_WINDOW(main_window), - GTK_DIALOG_DESTROY_WITH_PARENT, - type, - GTK_BUTTONS_CLOSE, - "%s", - (const gchar*)message); - /* Destroy the dialog when the user responds to it (e.g. clicks a button) */ - g_signal_connect_swapped (G_OBJECT (dialog), "response", - G_CALLBACK (gtk_widget_destroy), - G_OBJECT (dialog)); - gtk_widget_show(dialog); - } -} - -void linphone_gtk_about_response(GtkDialog *dialog, gint id){ - if (id==GTK_RESPONSE_CANCEL){ - gtk_widget_destroy(GTK_WIDGET(dialog)); - } -} - -static void about_url_clicked(GtkAboutDialog *dialog, const char *url, gpointer data){ - g_message("About url clicked"); - linphone_gtk_open_browser(url); -} - -void linphone_gtk_show_about(void){ - struct stat filestat; - const char *data_dir; - char *license_file; - GtkWidget *about; - const char *tmp; - GdkPixbuf *logo=create_pixbuf( - linphone_gtk_get_ui_config("logo","linphone-banner.png")); - static const char *defcfg="defcfg"; - LinphoneFactory *factory = linphone_factory_get(); - - about=linphone_gtk_create_window("about", the_ui); - - gtk_about_dialog_set_url_hook(about_url_clicked,NULL,NULL); - - data_dir = linphone_factory_get_data_resources_dir(factory); - license_file = bctbx_strdup_printf("%s/COPYING", data_dir); - memset(&filestat,0,sizeof(filestat)); - if (stat(license_file,&filestat)!=0){ - license_file="COPYING"; - stat(license_file,&filestat); - } - if (filestat.st_size>0){ - char *license=g_malloc(filestat.st_size+1); - FILE *f=fopen(license_file,"r"); - if (f && fread(license,1,filestat.st_size,f)>0){ - license[filestat.st_size]='\0'; - gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about),license); - } - g_free(license); - } - bctbx_free(license_file); - gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),linphone_core_get_version()); - gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("title","Linphone")); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),linphone_gtk_get_ui_config("home","http://www.linphone.org")); - if (logo) { - gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), logo); - g_object_unref(logo); - } - tmp=linphone_gtk_get_ui_config("artists",defcfg); - if (tmp!=defcfg){ - const char *tmp2[2]; - tmp2[0]=tmp; - tmp2[1]=NULL; - gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(about),tmp2); - } - tmp=linphone_gtk_get_ui_config("translators",defcfg); - if (tmp!=defcfg) - gtk_about_dialog_set_translator_credits (GTK_ABOUT_DIALOG(about),tmp); - tmp=linphone_gtk_get_ui_config("comments",defcfg); - if (tmp!=defcfg) - gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about),tmp); - gtk_widget_show(about); -} - - -static gboolean linphone_gtk_iterate(LinphoneCore *lc){ - static gboolean first_time=TRUE; - static gboolean in_iterate=FALSE; - - /*avoid reentrancy*/ - if (in_iterate) return TRUE; - in_iterate=TRUE; - linphone_core_iterate(lc); - if (first_time){ - /*after the first call to iterate, SipSetupContexts should be ready, so take actions:*/ - linphone_gtk_show_directory_search(); - first_time=FALSE; - } - - if (addr_to_call!=NULL){ - /*make sure we are not showing the login screen*/ - GtkWidget *mw=linphone_gtk_get_main_window(); - if (g_object_get_data(G_OBJECT(mw), "login_frame") == NULL){ - GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar"); - gtk_entry_set_text(GTK_ENTRY(uri_bar),addr_to_call); - addr_to_call=NULL; - linphone_gtk_start_call(uri_bar); - } - } - in_iterate=FALSE; - return TRUE; -} - -static gboolean uribar_completion_matchfunc(GtkEntryCompletion *completion, const gchar *key, GtkTreeIter *iter, gpointer user_data){ - char* address = NULL; - gboolean ret = FALSE; - gtk_tree_model_get(gtk_entry_completion_get_model(completion),iter,0,&address,-1); - - if(address) { - gchar *tmp = g_utf8_casefold(address,-1); - if (strstr(tmp,key)) ret=TRUE; - g_free(tmp); - g_free(address); - } - - return ret; -} - -static void load_uri_history(void){ - GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")); - char key[20]; - int i; - GtkEntryCompletion *gep=gtk_entry_completion_new(); - GtkListStore *model=gtk_list_store_new(2,G_TYPE_STRING,G_TYPE_INT); - for (i=0;;i++){ - const char *uri; - snprintf(key,sizeof(key),"uri%i",i); - uri=linphone_gtk_get_ui_config(key,NULL); - if (uri!=NULL) { - GtkTreeIter iter; - gtk_list_store_append(model,&iter); - gtk_list_store_set(model,&iter,0,uri,1,COMPLETION_HISTORY,-1); - if (i==0) gtk_entry_set_text(uribar,uri); - } - else break; - } - gtk_entry_completion_set_model(gep,GTK_TREE_MODEL(model)); - gtk_entry_completion_set_text_column(gep,0); - gtk_entry_completion_set_popup_completion(gep, TRUE); - gtk_entry_completion_set_match_func(gep,uribar_completion_matchfunc, NULL, NULL); - gtk_entry_completion_set_minimum_key_length(gep,3); - gtk_entry_set_completion(uribar,gep); - g_signal_connect (G_OBJECT (uribar), "changed", G_CALLBACK(linphone_gtk_on_uribar_changed), NULL); -} - -static void save_uri_history(void){ - LinphoneCore *lc=linphone_gtk_get_core(); - LpConfig *cfg=linphone_core_get_config(lc); - GtkEntry *uribar=GTK_ENTRY(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar")); - char key[20]; - int i=0; - char *uri=NULL; - GtkTreeIter iter; - GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(uribar)); - - if (!gtk_tree_model_get_iter_first(model,&iter)) return; - do { - gtk_tree_model_get(model,&iter,0,&uri,-1); - if (uri) { - snprintf(key,sizeof(key),"uri%i",i); - lp_config_set_string(cfg,"GtkUi",key,uri); - g_free(uri); - }else break; - i++; - if (i>5) break; - }while(gtk_tree_model_iter_next(model,&iter)); - lp_config_sync(cfg); -} - -static void completion_add_text(GtkEntry *entry, const char *text){ - GtkTreeIter iter; - GtkTreeModel *model=gtk_entry_completion_get_model(gtk_entry_get_completion(entry)); - - if (gtk_tree_model_get_iter_first(model,&iter)){ - do { - gchar *uri=NULL; - gtk_tree_model_get(model,&iter,0,&uri,-1); - if (uri!=NULL){ - if (strcmp(uri,text)==0) { - /*remove text */ - gtk_list_store_remove(GTK_LIST_STORE(model),&iter); - g_free(uri); - break; - } - g_free(uri); - } - }while (gtk_tree_model_iter_next(model,&iter)); - } - /* and prepend it on top of the list */ - gtk_list_store_prepend(GTK_LIST_STORE(model),&iter); - gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,text,1,COMPLETION_HISTORY,-1); - save_uri_history(); -} - -void on_contact_provider_search_results( LinphoneContactSearch* req, bctbx_list_t* friends, void* data ) -{ - GtkTreeIter iter; - GtkEntry* uribar = GTK_ENTRY(data); - GtkEntryCompletion* compl = gtk_entry_get_completion(uribar); - GtkTreeModel* model = gtk_entry_completion_get_model(compl); - GtkListStore* list = GTK_LIST_STORE(model); - LinphoneLDAPContactSearch* search = linphone_ldap_contact_search_cast(req); - gboolean valid; - - // clear completion list from previous non-history entries - valid = gtk_tree_model_get_iter_first(model,&iter); - while(valid) - { - char* url; - int type; - gtk_tree_model_get(model,&iter, 0,&url, 1,&type, -1); - - if (type != COMPLETION_HISTORY) { - valid = gtk_list_store_remove(list, &iter); - } else { - valid = gtk_tree_model_iter_next(model,&iter); - } - - if( url ) g_free(url); - if( !valid ) break; - } - - // add new non-history related matches - while( friends ){ - LinphoneFriend* lf = friends->data; - if( lf ) { - const LinphoneAddress* la = linphone_friend_get_address(lf); - if( la ){ - char *addr = linphone_address_as_string(la); - - if( addr ){ - ms_message("[LDAP]Insert match: %s", addr); - gtk_list_store_insert_with_values(list, &iter, -1, - 0, addr, - 1, COMPLETION_LDAP, -1); - ms_free(addr); - } - } - } - friends = friends->next; - } - gtk_entry_completion_complete(compl); - // save the number of LDAP results to better decide if new results should be fetched when search predicate gets bigger - gtk_object_set_data(GTK_OBJECT(uribar), "ldap_res_cout", - GINT_TO_POINTER( - linphone_ldap_contact_search_result_count(search) - ) - ); - - // Gtk bug? we need to emit a "changed" signal so that the completion appears if - // the list of results was previously empty - g_signal_handlers_block_by_func(uribar, linphone_gtk_on_uribar_changed, NULL); - g_signal_emit_by_name(uribar, "changed"); - g_signal_handlers_unblock_by_func(uribar, linphone_gtk_on_uribar_changed, NULL); -} - -struct CompletionTimeout { - guint timeout_id; -}; - -static gboolean launch_contact_provider_search(void *userdata) -{ - LinphoneLDAPContactProvider* ldap = linphone_gtk_get_ldap(); - GtkWidget* uribar = GTK_WIDGET(userdata); - const gchar* predicate = gtk_entry_get_text(GTK_ENTRY(uribar)); - gchar* previous_search = gtk_object_get_data(GTK_OBJECT(uribar), "previous_search"); - unsigned int prev_res_count = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(uribar), "ldap_res_cout")); - - 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 - - ms_message("Don't launch search on already searched data (current: %s, old search: %s), (%d/%d results)", - predicate, previous_search, prev_res_count, max_res_count); - return FALSE; - } - - // save current search - if( previous_search ) ms_free(previous_search); - gtk_object_set_data(GTK_OBJECT(uribar), "previous_search", ms_strdup(predicate)); - - ms_message("launch_contact_provider_search"); - search =linphone_contact_provider_begin_search( - linphone_contact_provider_cast(ldap_provider), - predicate, on_contact_provider_search_results, uribar - ); - - if(search) - linphone_contact_search_ref(search); - } - return FALSE; -} - -void linphone_gtk_on_uribar_changed(GtkEditable *uribar, gpointer user_data) -{ - if( linphone_gtk_get_ldap() ) { - gchar* text = gtk_editable_get_chars(uribar, 0,-1); - gint timeout = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(uribar), "complete_timeout")); - if( text ) g_free(text); - - if( timeout != 0 ) { - g_source_remove(timeout); - } - - timeout = g_timeout_add_seconds(1,(GSourceFunc)launch_contact_provider_search, uribar); - - gtk_object_set_data(GTK_OBJECT(uribar),"complete_timeout", GINT_TO_POINTER(timeout) ); - } -} - -bool_t linphone_gtk_video_enabled(void){ - const LinphoneVideoPolicy *vpol=linphone_core_get_video_policy(linphone_gtk_get_core()); - return vpol->automatically_accept && vpol->automatically_initiate; -} - -void linphone_gtk_show_main_window(){ - GtkWidget *w=linphone_gtk_get_main_window(); -#ifdef HAVE_GTK_OSX - GtkWidget *icon = linphone_gtk_get_widget(w, "history_tab_icon"); - GtkWidget *label = linphone_gtk_get_widget(w, "history_tab_label"); - gtk_misc_set_alignment(GTK_MISC(icon), 0.5f, 0.25f); - gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.f); -#endif - gtk_widget_show(w); - gtk_window_present(GTK_WINDOW(w)); -} - -void linphone_gtk_call_terminated(LinphoneCall *call, const char *error){ - GtkWidget *mw=linphone_gtk_get_main_window(); - if (linphone_core_get_calls(linphone_gtk_get_core())==NULL){ - gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),TRUE); - } - if (linphone_gtk_use_in_call_view() && call) - linphone_gtk_in_call_view_terminate(call,error); -} - -static void linphone_gtk_update_call_buttons(LinphoneCall *call){ - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *mw=linphone_gtk_get_main_window(); - const bctbx_list_t *calls=linphone_core_get_calls(lc); - GtkWidget *button; - bool_t add_call=(calls!=NULL); - int call_list_size=bctbx_list_size(calls); - GtkWidget *conf_frame; - - button=linphone_gtk_get_widget(mw,"start_call"); - gtk_widget_set_sensitive(button,TRUE); - gtk_widget_set_visible(button,!add_call); - - button=linphone_gtk_get_widget(mw,"add_call"); - - if (linphone_core_sound_resources_locked(lc) || (call && linphone_call_get_state(call)==LinphoneCallIncomingReceived)) { - gtk_widget_set_sensitive(button,FALSE); - } else { - gtk_widget_set_sensitive(button,TRUE); - } - gtk_widget_set_visible(button,add_call); - - //gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"terminate_call"),stop_active); - 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); - } else { - linphone_gtk_enable_transfer_button(lc,FALSE); - } - if (call) { - bool_t enable_conference = call_list_size>1 && linphone_call_params_get_local_conference_mode(linphone_call_get_current_params(call)) == FALSE; - linphone_gtk_enable_conference_button(lc,enable_conference); - linphone_gtk_update_video_button(call); - } -} - -gchar *linphone_gtk_get_record_path(const LinphoneAddress *address, gboolean is_conference){ - const char *dir=g_get_user_special_dir(G_USER_DIRECTORY_MUSIC); - const char *id="unknown"; - char filename[256]={0}; - char date[64]={0}; - time_t curtime=time(NULL); - struct tm loctime; - const char **fmts=linphone_core_get_supported_file_formats(linphone_gtk_get_core()); - int i; - const char *ext="wav"; - char *record_path_utf8, *record_path; - -#ifdef _WIN32 - loctime=*localtime(&curtime); -#else - localtime_r(&curtime,&loctime); -#endif - snprintf(date,sizeof(date)-1,"%i%02i%02i-%02i%02i",loctime.tm_year+1900,loctime.tm_mon+1,loctime.tm_mday, loctime.tm_hour, loctime.tm_min); - - for (i=0;fmts[i]!=NULL;++i){ - if (strcmp(fmts[i],"mkv")==0){ - ext="mkv"; - break; - } - } - - if (address){ - id=linphone_address_get_username(address); - if (id==NULL) id=linphone_address_get_domain(address); - } - if (is_conference){ - snprintf(filename,sizeof(filename)-1,"%s-conference-%s.%s", - linphone_gtk_get_ui_config("title","Linphone"), - date,ext); - }else{ - snprintf(filename,sizeof(filename)-1,"%s-call-%s-%s.%s", - linphone_gtk_get_ui_config("title","Linphone"), - date, - id,ext); - } - if (!dir) { - ms_message ("No directory for music, using [%s] instead",dir=getenv("HOME")); - } - record_path_utf8 = g_build_filename(dir,filename,NULL); - record_path = g_locale_from_utf8(record_path_utf8, -1, NULL, NULL, NULL); - g_free(record_path_utf8); - return record_path; -} - -gchar *linphone_gtk_get_snapshot_path(void) { - const char *dir=g_get_user_special_dir(G_USER_DIRECTORY_PICTURES); - char filename[256]={0}; - char date[64]={0}; - time_t curtime=time(NULL); - struct tm loctime; - const char *ext="jpg"; - char *snapshot_path_utf8, *snapshot_path; - -#ifdef _WIN32 - loctime=*localtime(&curtime); -#else - localtime_r(&curtime,&loctime); -#endif - snprintf(date,sizeof(date)-1,"%i%02i%02i-%02i%02i%02i",loctime.tm_year+1900,loctime.tm_mon+1,loctime.tm_mday, loctime.tm_hour, loctime.tm_min, loctime.tm_sec); - snprintf(filename,sizeof(filename)-1,"%s-snapshot-%s.%s", - linphone_gtk_get_ui_config("title","Linphone"), - date, ext); - if (!dir) { - ms_message ("No directory for pictures, using [%s] instead",dir=getenv("HOME")); - } - snapshot_path_utf8 = g_build_filename(dir,filename,NULL); - snapshot_path = g_locale_from_utf8(snapshot_path_utf8, -1, NULL, NULL, NULL); - g_free(snapshot_path_utf8); - return snapshot_path; -} - -static gboolean linphone_gtk_start_call_do(GtkWidget *uri_bar){ - const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar)); - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneAddress *addr=linphone_core_interpret_url(lc,entered); - - if (addr!=NULL){ - LinphoneCallParams *params=linphone_core_create_call_params(lc, NULL); - gchar *record_file=linphone_gtk_get_record_path(addr,FALSE); - linphone_call_params_set_record_file(params,record_file); - linphone_core_invite_address_with_params(lc,addr,params); - completion_add_text(GTK_ENTRY(uri_bar),entered); - linphone_address_unref(addr); - linphone_call_params_unref(params); - g_free(record_file); - }else{ - linphone_gtk_call_terminated(NULL,NULL); - } - return FALSE; -} - -static void accept_incoming_call(LinphoneCall *call){ - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneCallParams *params = linphone_core_create_call_params(lc, call); - gchar *record_file=linphone_gtk_get_record_path(linphone_call_get_remote_address(call),FALSE); - linphone_call_params_set_record_file(params,record_file); - linphone_call_accept_with_params(call,params); - linphone_call_params_unref(params); -} - -static gboolean linphone_gtk_auto_answer(LinphoneCall *call){ - LinphoneCallState state=linphone_call_get_state(call); - if (state==LinphoneCallIncomingReceived || state==LinphoneCallIncomingEarlyMedia){ - accept_incoming_call(call); - } - return FALSE; -} - -void linphone_gtk_start_call(GtkWidget *w){ - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); - /*change into in-call mode, then do the work later as it might block a bit */ - GtkWidget *mw=gtk_widget_get_toplevel(w); - GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar"); - LinphoneCallState state= call ? linphone_call_get_state(call) : LinphoneCallIdle; - - if (state == LinphoneCallIncomingReceived || state == LinphoneCallIncomingEarlyMedia){ - accept_incoming_call(call); - }else{ - /*immediately disable the button and delay a bit the execution the linphone_core_invite() - so that we don't freeze the button. linphone_core_invite() might block for some hundreds of milliseconds*/ - gtk_widget_set_sensitive(linphone_gtk_get_widget(mw,"start_call"),FALSE); - g_timeout_add(100,(GSourceFunc)linphone_gtk_start_call_do,uri_bar); - } - -} - -void linphone_gtk_start_chat(GtkWidget *w){ - GtkWidget *mw=gtk_widget_get_toplevel(w); - GtkWidget *uri_bar=linphone_gtk_get_widget(mw,"uribar"); - const char *entered=gtk_entry_get_text(GTK_ENTRY(uri_bar)); - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneAddress *addr=linphone_core_interpret_url(lc,entered); - if (addr) { - linphone_gtk_friend_list_set_chat_conversation(addr); - linphone_address_unref(addr); - } -} - -void linphone_gtk_uri_bar_activate(GtkWidget *w){ - linphone_gtk_start_call(w); -} - -void linphone_gtk_terminate_call(GtkWidget *button){ - gboolean is_conf; - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(&is_conf); - if (call){ - linphone_call_terminate(call); - }else if (is_conf){ - linphone_core_terminate_conference(linphone_gtk_get_core()); - } -} - -void linphone_gtk_decline_clicked(GtkWidget *button){ - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); - if (call) - linphone_call_terminate(call); -} - -void linphone_gtk_answer_clicked(GtkWidget *button){ - LinphoneCall *call=linphone_gtk_get_currently_displayed_call(NULL); - if (call){ - accept_incoming_call(call); - linphone_gtk_show_main_window(); /* useful when the button is clicked on a notification */ - } -} - -void _linphone_gtk_enable_video(gboolean val){ - LinphoneVideoPolicy policy={0}; - policy.automatically_initiate=policy.automatically_accept=val; - linphone_core_enable_video_capture(linphone_gtk_get_core(), TRUE); - linphone_core_enable_video_display(linphone_gtk_get_core(), TRUE); - linphone_core_set_video_policy(linphone_gtk_get_core(),&policy); -} - -void linphone_gtk_enable_video(GtkWidget *w){ - gboolean val=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)); - //GtkWidget *selfview_item=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"selfview_item"); - _linphone_gtk_enable_video(val); -} - -void linphone_gtk_enable_self_view(GtkWidget *w){ - gboolean val=gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)); - LinphoneCore *lc=linphone_gtk_get_core(); - linphone_core_enable_self_view(lc,val); - linphone_gtk_set_ui_config_int("videoselfview",val); -} - -void linphone_gtk_used_identity_changed(GtkWidget *w){ - int active=gtk_combo_box_get_active(GTK_COMBO_BOX(w)); - char *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); - if (sel && strlen(sel)>0){ //avoid a dummy "changed" at gui startup - linphone_core_set_default_proxy_index(linphone_gtk_get_core(),(active==0) ? -1 : (active-1)); - linphone_gtk_show_directory_search(); - } - if (sel) g_free(sel); -} - -void on_proxy_refresh_button_clicked(GtkWidget *w){ - LinphoneCore *lc=linphone_gtk_get_core(); - linphone_core_refresh_registers(lc); -} - -static gboolean grab_focus(GtkWidget *w){ - gtk_widget_grab_focus(w); - return FALSE; -} - -void linphone_gtk_viewswitch_changed(GtkNotebook *notebook, GtkWidget *page, gint page_num, gpointer user_data){ - GtkWidget *main_window = linphone_gtk_get_main_window(); - GtkWidget *friendlist = linphone_gtk_get_widget(main_window,"contact_list"); - GtkWidget *w = (GtkWidget*)g_object_get_data(G_OBJECT(friendlist),"chatview"); - - if (page_num == gtk_notebook_page_num(GTK_NOTEBOOK(notebook),w)) { - g_idle_add((GSourceFunc)grab_focus,linphone_gtk_get_widget(page,"text_entry")); - } -} - -static void linphone_gtk_notify_recv(LinphoneCore *lc, LinphoneFriend * fid){ - linphone_gtk_show_friends(); -} - -static void linphone_gtk_new_subscriber_response(GtkWidget *dialog, guint response_id, LinphoneFriend *lf){ - switch(response_id){ - case GTK_RESPONSE_YES: - linphone_gtk_show_contact(lf, the_ui); - break; - default: - linphone_core_reject_subscriber(linphone_gtk_get_core(),lf); - } - gtk_widget_destroy(dialog); -} - -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; - } - - message=g_strdup_printf(_("%s would like to add you to his/her contact list.\nWould you add him/her to your contact list and allow him/her to see your presence status?\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, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - "%s", - message); - g_free(message); - g_signal_connect(G_OBJECT (dialog), "response", - G_CALLBACK (linphone_gtk_new_subscriber_response),lf); - /* actually show the box */ - gtk_widget_show(dialog); -} - -typedef struct _AuthTimeout{ - GtkWidget *w; -} AuthTimeout; - -static void auth_timeout_clean(AuthTimeout *tout){ - tout->w=NULL; -} - -static gboolean auth_timeout_destroy(AuthTimeout *tout){ - if (tout->w) { - g_object_weak_unref(G_OBJECT(tout->w),(GWeakNotify)auth_timeout_clean,tout); - gtk_widget_destroy(tout->w); - } - g_free(tout); - return FALSE; -} - -static AuthTimeout * auth_timeout_new(GtkWidget *w){ - AuthTimeout *tout=g_new(AuthTimeout,1); - tout->w=w; - /*so that the timeout no more references the widget when it is destroyed:*/ - g_object_weak_ref(G_OBJECT(w),(GWeakNotify)auth_timeout_clean,tout); - /*so that the widget is automatically destroyed after some time */ - g_timeout_add(30000,(GtkFunction)auth_timeout_destroy,tout); - return tout; -} - -void linphone_gtk_password_cancel(GtkWidget *w){ - LinphoneAuthInfo *info; - GtkWidget *window=gtk_widget_get_toplevel(w); - info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info"); - linphone_core_abort_authentication(linphone_gtk_get_core(),info); - gtk_widget_destroy(window); -} - -void linphone_gtk_password_ok(GtkWidget *w){ - GtkWidget *entry; - GtkWidget *window=gtk_widget_get_toplevel(w); - LinphoneAuthInfo *info; - info=(LinphoneAuthInfo*)g_object_get_data(G_OBJECT(window),"auth_info"); - g_object_weak_unref(G_OBJECT(window),(GWeakNotify)linphone_auth_info_destroy,info); - entry=linphone_gtk_get_widget(window,"password_entry"); - linphone_auth_info_set_passwd(info,gtk_entry_get_text(GTK_ENTRY(entry))); - linphone_auth_info_set_userid(info, - gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(window,"userid_entry")))); - linphone_core_add_auth_info(linphone_gtk_get_core(),info); - gtk_widget_destroy(window); -} - -static void linphone_gtk_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain){ - GtkWidget *w=linphone_gtk_create_window("password", the_ui); - GtkWidget *label=linphone_gtk_get_widget(w,"message"); - LinphoneAuthInfo *info; - gchar *msg; - GtkWidget *mw=linphone_gtk_get_main_window(); - - if (mw && g_object_get_data(G_OBJECT(mw), "login_frame") != NULL){ - /*don't prompt for authentication when login frame is visible*/ - linphone_core_abort_authentication(lc,NULL); - return; - } - - msg=g_strdup_printf(_("Please enter your password for username %s\n at realm %s:"), - username,realm); - gtk_label_set_markup(GTK_LABEL(label),msg); - g_free(msg); - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"userid_entry")),username); - info=linphone_auth_info_new(username, NULL, NULL, NULL,realm,domain); - g_object_set_data(G_OBJECT(w),"auth_info",info); - g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_auth_info_destroy,info); - gtk_widget_show(w); - auth_timeout_new(w); -} - -static void linphone_gtk_dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf){ - ms_message("Dtmf %c received.",dtmf); -} - - -static void linphone_gtk_configuring_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) { - if (config_fetching_dialog) linphone_gtk_close_config_fetching(config_fetching_dialog, status); - config_fetching_dialog=NULL; -} - -static void linphone_gtk_call_log_updated(LinphoneCore *lc, LinphoneCallLog *cl){ - GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"call_logs"); - if (w) linphone_gtk_call_log_update(w); - linphone_gtk_call_log_update(linphone_gtk_get_main_window()); -} - -#ifdef HAVE_NOTIFY -static bool_t notify_actions_supported(void) { - bool_t accepts_actions = FALSE; - GList *capabilities = notify_get_server_caps(); - GList *c; - if(capabilities != NULL) { - for(c = capabilities; c != NULL; c = c->next) { - if(strcmp((char*)c->data, "actions") == 0 ) { - accepts_actions = TRUE; - break; - } - } - g_list_foreach(capabilities, (GFunc)g_free, NULL); - g_list_free(capabilities); - } - return accepts_actions; -} - -static NotifyNotification* build_notification(const char *title, const char *body) { - NotifyNotification *n = notify_notification_new(title, body, NULL -#ifdef HAVE_NOTIFY1 - ,NULL -#endif - ); -#ifndef HAVE_NOTIFY1 - { - GError *error = NULL; - const char *icon_name = linphone_gtk_get_ui_config("icon_name", LINPHONE_ICON_NAME); - GdkPixbuf *pbuf = gtk_icon_theme_load_icon(gtk_icon_theme_get_default(), icon_name, 48, 0, &error); - if(error) { - g_warning("Could not load '%s' icon: %s", icon_name, error->message); - g_error_free(error); - } - notify_notification_set_image_from_pixbuf(n, pbuf); - } -#endif - return n; -} - -static void show_notification(NotifyNotification* n){ - if (n && !notify_notification_show(n,NULL)) - ms_error("Failed to send notification."); -} - -static void make_notification(const char *title, const char *body){ - show_notification(build_notification(title,body)); -} - -#endif - -void linphone_gtk_notify(LinphoneCall *call, LinphoneChatMessage *chat_message, const char *msg){ -#ifdef HAVE_NOTIFY - if (!notify_is_initted()) - if (!notify_init ("Linphone")) ms_error("Libnotify failed to init."); -#endif - if (!call) { -#ifdef HAVE_NOTIFY - if (chat_message) { - const LinphoneAddress *address = linphone_chat_message_get_peer_address(chat_message); - char *remote = linphone_address_as_string(address); - make_notification(remote, linphone_chat_message_get_text(chat_message)); - } else { - if (!notify_notification_show(notify_notification_new("Linphone",msg,NULL -#ifdef HAVE_NOTIFY1 - ,NULL -#endif - ),NULL)) { - ms_error("Failed to send notification."); - } - } -#else - linphone_gtk_show_main_window(); -#endif - } else if (!gtk_window_is_active((GtkWindow*)linphone_gtk_get_main_window())) { - gboolean show_main_window = FALSE; -#ifdef HAVE_NOTIFY - char *body=NULL; - char *remote=call!=NULL ? linphone_call_get_remote_address_as_string(call) : NULL; - NotifyNotification *n; - switch(linphone_call_get_state(call)){ - case LinphoneCallError: - make_notification(_("Call error"),body=g_markup_printf_escaped("%s\n%s",msg,remote)); - break; - case LinphoneCallEnd: - make_notification(_("Call ended"),body=g_markup_printf_escaped("%s",remote)); - break; - case LinphoneCallIncomingReceived: - n=build_notification(_("Incoming call"),body=g_markup_printf_escaped("%s",remote)); - if (n){ - if (notify_actions_supported()) { - notify_notification_add_action (n,"answer", _("Answer"), - NOTIFY_ACTION_CALLBACK(linphone_gtk_answer_clicked),NULL,NULL); - notify_notification_add_action (n,"decline",_("Decline"), - NOTIFY_ACTION_CALLBACK(linphone_gtk_decline_clicked),NULL,NULL); - } - show_notification(n); - }else show_main_window = TRUE; - break; - case LinphoneCallPausedByRemote: - make_notification(_("Call paused"),body=g_markup_printf_escaped(_("by %s"),remote)); - break; - default: - break; - } - if (body) g_free(body); - if (remote) g_free(remote); -#else - if (linphone_call_get_state(call) == LinphoneCallIncomingReceived) - show_main_window = TRUE; -#endif - if (show_main_window) linphone_gtk_show_main_window(); - } -} - -static void linphone_gtk_global_state_changed(LinphoneCore *lc, LinphoneGlobalState state, const char*str){ - switch(state){ - case LinphoneGlobalStartup: - the_core=lc; - break; - case LinphoneGlobalConfiguring: - if (linphone_core_get_provisioning_uri(lc)){ - config_fetching_dialog=linphone_gtk_show_config_fetching(); - } - break; - case LinphoneGlobalOn: - linphone_gtk_init_ui(); - if (selftest) { - gtk_timeout_add(300,(GtkFunction)gtk_main_quit,NULL); - } - break; - default: - break; - } -} - -static void on_call_updated_response(GtkWidget *dialog, gint responseid, gpointer user_data){ - LinphoneCall *call = (LinphoneCall *)g_object_get_data(G_OBJECT(dialog), "call"); - if (linphone_call_get_state(call)==LinphoneCallUpdatedByRemote){ - LinphoneCore *lc=linphone_call_get_core(call); - LinphoneCallParams *params = linphone_core_create_call_params(lc, call); - linphone_call_params_enable_video(params,responseid==GTK_RESPONSE_YES); - linphone_call_accept_update(call,params); - linphone_call_params_unref(params); - } - g_source_remove_by_user_data(dialog); - gtk_widget_destroy(dialog); -} - -static void on_call_updated_timeout(GtkWidget *dialog){ - on_call_updated_response(dialog, GTK_RESPONSE_NO, NULL); -} - -static void linphone_gtk_call_updated_by_remote(LinphoneCall *call){ - LinphoneCore *lc=linphone_call_get_core(call); - const LinphoneVideoPolicy *pol=linphone_core_get_video_policy(lc); - const LinphoneCallParams *rparams=linphone_call_get_remote_params(call); - const LinphoneCallParams *current_params=linphone_call_get_current_params(call); - gboolean video_requested=linphone_call_params_video_enabled(rparams); - gboolean video_used=linphone_call_params_video_enabled(current_params); - g_message("Video used=%i, video requested=%i, automatically_accept=%i", - video_used,video_requested,pol->automatically_accept); - if (!video_used && video_requested && !pol->automatically_accept){ - linphone_call_defer_update(call); - { - const LinphoneAddress *addr=linphone_call_get_remote_address(call); - GtkWidget *dialog; - const char *dname=linphone_address_get_display_name(addr); - if (dname==NULL) dname=linphone_address_get_username(addr); - if (dname==NULL) dname=linphone_address_get_domain(addr); - dialog=gtk_message_dialog_new(GTK_WINDOW(linphone_gtk_get_main_window()), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_YES_NO, - _("%s proposed to start video. Do you accept ?"),dname); - g_object_set_data_full(G_OBJECT(dialog), "call", linphone_call_ref(call), (GDestroyNotify)linphone_call_unref); - g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(on_call_updated_response), NULL); - g_timeout_add(20000,(GSourceFunc)on_call_updated_timeout,dialog); - gtk_widget_show(dialog); - } - } -} - -static void linphone_gtk_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cs, const char *msg){ - const LinphoneErrorInfo *ei; - - switch(cs){ - case LinphoneCallOutgoingInit: - linphone_gtk_create_in_call_view (call); - break; - case LinphoneCallOutgoingProgress: - linphone_gtk_in_call_view_set_calling (call); - break; - case LinphoneCallStreamsRunning: - linphone_gtk_in_call_view_set_in_call(call); - break; - case LinphoneCallUpdatedByRemote: - linphone_gtk_call_updated_by_remote(call); - break; - case LinphoneCallError: - linphone_gtk_in_call_view_terminate (call,msg); - break; - case LinphoneCallEnd: - ei = linphone_call_get_error_info(call); - if (ei && linphone_error_info_get_reason(ei) != LinphoneReasonNone) { - linphone_gtk_in_call_view_terminate(call, linphone_error_info_get_phrase(ei)); - } else { - linphone_gtk_in_call_view_terminate(call, NULL); - } - linphone_gtk_status_icon_set_blinking(FALSE); - break; - case LinphoneCallIncomingReceived: - linphone_gtk_create_in_call_view(call); - linphone_gtk_in_call_view_set_incoming(call); - linphone_gtk_status_icon_set_blinking(TRUE); - if (linphone_gtk_auto_answer_enabled()) { - int delay = linphone_gtk_get_ui_config_int("auto_answer_delay", 2000); - linphone_call_ref(call); - g_timeout_add(delay, (GSourceFunc)linphone_gtk_auto_answer, call); - } - break; - case LinphoneCallResuming: - linphone_gtk_enable_hold_button(call,TRUE,TRUE); - linphone_gtk_in_call_view_set_in_call (call); - break; - case LinphoneCallPausing: - linphone_gtk_enable_hold_button(call,TRUE,FALSE); - linphone_gtk_call_update_tab_header(call,FALSE); - BCTBX_NO_BREAK; - case LinphoneCallPausedByRemote: - linphone_gtk_in_call_view_set_paused(call); - linphone_gtk_call_update_tab_header(call,TRUE); - break; - case LinphoneCallConnected: - linphone_gtk_enable_hold_button (call,TRUE,TRUE); - linphone_gtk_status_icon_set_blinking(FALSE); - break; - default: - break; - } - linphone_gtk_notify(call, NULL, msg); - linphone_gtk_update_call_buttons (call); -} - -static void linphone_gtk_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t enabled, const char *token){ - linphone_gtk_in_call_view_show_encryption(call); -} - -static void linphone_gtk_transfer_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate){ - linphone_gtk_in_call_view_set_transfer_status(call,cstate); -} - -static void update_registration_status(LinphoneProxyConfig *cfg, LinphoneRegistrationState rs){ - GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities")); - GtkTreeModel *model=gtk_combo_box_get_model(box); - GtkTreeIter iter; - gboolean found=FALSE; - const char *icon_name=NULL; - - if (gtk_tree_model_get_iter_first(model,&iter)){ - gpointer p; - do{ - gtk_tree_model_get(model,&iter,2,&p,-1); - if (p==cfg) { - found=TRUE; - break; - } - }while(gtk_tree_model_iter_next(model,&iter)); - } - if (!found) { - /*ignored, this is a notification for a removed proxy config.*/ - return; - } - switch (rs){ - case LinphoneRegistrationOk: - icon_name="linphone-ok"; - break; - case LinphoneRegistrationProgress: - icon_name="linphone-inprogress"; - break; - case LinphoneRegistrationCleared: - icon_name=NULL; - break; - case LinphoneRegistrationFailed: - icon_name="linphone-failed"; - break; - default: - break; - } - gtk_list_store_set(GTK_LIST_STORE(model),&iter,1,icon_name,-1); -} - -static void linphone_gtk_registration_state_changed(LinphoneCore *lc, LinphoneProxyConfig *cfg, - LinphoneRegistrationState rs, const char *msg){ - switch (rs){ - case LinphoneRegistrationOk: - if (cfg){ - SipSetup *ss=linphone_proxy_config_get_sip_setup(cfg); - if (ss && (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_LOGIN)){ - linphone_gtk_exit_login_frame(); - } - } - break; - default: - break; - } - update_registration_status(cfg,rs); -} - -void linphone_gtk_open_browser(const char *uri) { -#ifdef __APPLE__ - GError *error = NULL; - char cmd_line[256]; - - g_snprintf(cmd_line, sizeof(cmd_line), "%s %s", "/usr/bin/open", uri); - g_spawn_command_line_async(cmd_line, &error); - if (error) { - g_warning("Could not open %s: %s", uri, error->message); - g_error_free(error); - } -#elif defined(_WIN32) - HINSTANCE instance = ShellExecute(NULL, "open", uri, NULL, NULL, SW_SHOWNORMAL); - if ((int)instance <= 32) { - g_warning("Could not open %s (error #%i)", uri, (int)instance); - } -#else - GError *error = NULL; - gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, &error); - if (error) { - g_warning("Could not open %s: %s", uri, error->message); - g_error_free(error); - } -#endif -} - -void linphone_gtk_link_to_website(GtkWidget *item){ - const gchar *home=(const gchar*)g_object_get_data(G_OBJECT(item),"home"); - linphone_gtk_open_browser(home); -} - -static GtkWidget *create_icon_menu(void){ - GtkWidget *menu=gtk_menu_new(); - GtkWidget *menu_item; - GtkWidget *image; - gchar *tmp; - const gchar *homesite; - - homesite=linphone_gtk_get_ui_config("home","http://www.linphone.org"); - menu_item=gtk_image_menu_item_new_with_label(_("Website link")); - tmp=g_strdup(homesite); - g_object_set_data(G_OBJECT(menu_item),"home",tmp); - g_object_weak_ref(G_OBJECT(menu_item),(GWeakNotify)g_free,tmp); - - image=gtk_image_new_from_stock(GTK_STOCK_HELP,GTK_ICON_SIZE_MENU); - gtk_widget_show(image); - gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),image); - //g_object_unref(G_OBJECT(image)); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_link_to_website,NULL); - - menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT,NULL); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)linphone_gtk_show_about,NULL); - menu_item=gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT,NULL); - gtk_widget_show(menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),menu_item); - g_signal_connect_swapped(G_OBJECT(menu_item),"activate",(GCallback)gtk_main_quit,NULL); - gtk_widget_show(menu); - return menu; -} - -#ifndef HAVE_GTK_OSX -void linphone_gtk_save_main_window_position(GtkWindow* mw, GdkEvent *event, gpointer data){ - gtk_window_get_position(GTK_WINDOW(mw), &main_window_x, &main_window_y); -} -#endif - -static void handle_icon_click(LinphoneStatusIcon *si, void *user_data) { -#ifndef HAVE_GTK_OSX - GtkWidget *mw=linphone_gtk_get_main_window(); - if (!gtk_window_is_active((GtkWindow*)mw)) { - if(!gtk_widget_is_drawable(mw)){ - //we only move if window was hidden. If it was simply behind the window stack, ie, drawable, we keep it as it was - gtk_window_move (GTK_WINDOW(mw), main_window_x, main_window_y); - } - linphone_gtk_show_main_window(); - } else { - linphone_gtk_save_main_window_position((GtkWindow*)mw, NULL, NULL); - gtk_widget_hide(mw); - } -#endif -} - -static void linphone_gtk_status_icon_initialised_cb(LinphoneStatusIconParams *params) { - LinphoneStatusIcon *icon = linphone_status_icon_get(); - if(icon) { - linphone_status_icon_start(icon, params); - } - linphone_status_icon_params_unref(params); -} - -static void linphone_gtk_init_status_icon(void) { - GtkWidget *menu = create_icon_menu(); - LinphoneStatusIconParams *params = linphone_status_icon_params_new(); - linphone_status_icon_params_set_menu(params, menu); - linphone_status_icon_params_set_title(params, _("Linphone")); - linphone_status_icon_params_set_description(params, _("A video internet phone")); - linphone_status_icon_params_set_on_click_cb(params, handle_icon_click, NULL); - - if(linphone_status_icon_init( - (LinphoneStatusIconReadyCb)linphone_gtk_status_icon_initialised_cb, - params)) { - - LinphoneStatusIcon *icon = linphone_status_icon_get(); - if(icon) { - linphone_status_icon_start(icon, params); - } - linphone_status_icon_params_unref(params); - } -} - -void linphone_gtk_status_icon_set_blinking(gboolean val) { - LinphoneStatusIcon *icon = linphone_status_icon_get(); - if(icon) { - linphone_status_icon_enable_blinking(icon, val); - } -#ifdef __APPLE__ - linphone_gtk_update_badge_count(); -#endif -} - -void linphone_gtk_options_activate(GtkWidget *item){ -#ifndef HAVE_GTK_OSX - gtk_widget_set_visible(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"quit_item"), - TRUE); -#endif -} - -static void init_identity_combo(GtkComboBox *box){ - GtkListStore *store; - GtkCellRenderer *r1,*r2; - store=gtk_list_store_new(3,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_POINTER); - gtk_cell_layout_clear(GTK_CELL_LAYOUT(box)); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(box),(r1=gtk_cell_renderer_text_new()),TRUE); - gtk_cell_layout_pack_end(GTK_CELL_LAYOUT(box),(r2=gtk_cell_renderer_pixbuf_new()),FALSE); - gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(box),r1,"text",0); - gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(box),r2,"icon-name",1); - g_object_set(G_OBJECT(r1),"ellipsize",PANGO_ELLIPSIZE_END,NULL); - gtk_combo_box_set_model(box,GTK_TREE_MODEL(store)); -} - -void linphone_gtk_load_identities(void){ - const bctbx_list_t *elem; - GtkComboBox *box=GTK_COMBO_BOX(linphone_gtk_get_widget(linphone_gtk_get_main_window(),"identities")); - char *def_identity; - LinphoneProxyConfig *def=NULL; - int def_index=0,i; - GtkListStore *store; - GtkTreeIter iter; - - store=GTK_LIST_STORE(gtk_combo_box_get_model(box)); - if (gtk_tree_model_get_n_columns(GTK_TREE_MODEL(store))==1){ - /* model is empty, this is the first time we go here */ - init_identity_combo(box); - store=GTK_LIST_STORE(gtk_combo_box_get_model(box)); - } - gtk_list_store_clear(store); - def = linphone_core_get_default_proxy_config(linphone_gtk_get_core()); - def_identity=g_strdup_printf(_("%s (Default)"),linphone_core_get_primary_contact(linphone_gtk_get_core())); - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,0,def_identity,1,NULL,2,NULL,-1); - g_free(def_identity); - for(i=1,elem=linphone_core_get_proxy_config_list(linphone_gtk_get_core()); - elem!=NULL; - elem=bctbx_list_next(elem),i++){ - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,0,linphone_proxy_config_get_identity(cfg),1, - linphone_proxy_config_is_registered(cfg) ? "linphone-ok" : NULL, - 2,cfg,-1); - if (cfg==def) { - def_index=i; - } - } - gtk_combo_box_set_active(box,def_index); -} - -static void linphone_gtk_dtmf_pressed(GtkButton *button){ - const char *label=(char *)g_object_get_data(G_OBJECT(button),"label"); - GtkWidget *uri_bar=linphone_gtk_get_widget(linphone_gtk_get_main_window(),"uribar"); - int pos=-1; - gtk_editable_insert_text(GTK_EDITABLE(uri_bar),label,1,&pos); - linphone_core_play_dtmf (linphone_gtk_get_core(),label[0],-1); - if (linphone_core_in_call(linphone_gtk_get_core())){ - linphone_call_send_dtmf(linphone_core_get_current_call(linphone_gtk_get_core()),label[0]); - } -} - -static void linphone_gtk_dtmf_released(GtkButton *button){ - linphone_core_stop_dtmf (linphone_gtk_get_core()); -} - - -static void linphone_gtk_connect_digits(GtkWidget *w){ - GtkContainer *cont=GTK_CONTAINER(linphone_gtk_get_widget(w,"dtmf_table")); - GList *children=gtk_container_get_children(cont); - GList *elem; - for(elem=children;elem!=NULL;elem=elem->next){ - GtkButton *button=GTK_BUTTON(elem->data); - g_signal_connect(G_OBJECT(button),"pressed",(GCallback)linphone_gtk_dtmf_pressed,NULL); - g_signal_connect(G_OBJECT(button),"released",(GCallback)linphone_gtk_dtmf_released,NULL); - } -} - -static void linphone_gtk_check_menu_items(void){ - bool_t video_enabled=linphone_gtk_video_enabled(); - bool_t selfview=linphone_gtk_get_ui_config_int("videoselfview",VIDEOSELFVIEW_DEFAULT); - GtkWidget *selfview_item=linphone_gtk_get_widget( - linphone_gtk_get_main_window(),"selfview_item"); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(linphone_gtk_get_widget( - linphone_gtk_get_main_window(),"enable_video_item")), video_enabled); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(selfview_item),selfview); -} - -static gboolean linphone_gtk_can_manage_accounts(void){ - LinphoneCore *lc=linphone_gtk_get_core(); - const bctbx_list_t *elem; - for(elem=linphone_core_get_sip_setups(lc);elem!=NULL;elem=elem->next){ - SipSetup *ss=(SipSetup*)elem->data; - if (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_ACCOUNT_MANAGER){ - return TRUE; - } - } - return FALSE; -} - -static void linphone_gtk_configure_main_window(void){ - static gboolean config_loaded=FALSE; - static const char *title; - static const char *home; - static const char *search_icon; - static gboolean update_check_menu; - static gboolean show_abcd; - GtkWidget *w=linphone_gtk_get_main_window(); - - if (!config_loaded){ - title=linphone_gtk_get_ui_config("title","Linphone"); - home=linphone_gtk_get_ui_config("home","http://www.linphone.org"); - search_icon=linphone_gtk_get_ui_config("directory_search_icon",NULL); - update_check_menu=linphone_gtk_get_ui_config_int("update_check_menu",0); - show_abcd=linphone_gtk_get_ui_config_int("show_abcd",1); - config_loaded=TRUE; - } - linphone_gtk_configure_window(w,"main_window"); - if (title) { - gtk_window_set_title(GTK_WINDOW(w),title); - } - if (search_icon){ - GdkPixbuf *pbuf=create_pixbuf(search_icon); - if(pbuf) { - gtk_image_set_from_pixbuf(GTK_IMAGE(linphone_gtk_get_widget(w,"directory_search_button_icon")),pbuf); - g_object_unref(G_OBJECT(pbuf)); - } - } - if (home){ - gchar *tmp; - GtkWidget *menu_item=linphone_gtk_get_widget(w,"home_item"); - tmp=g_strdup(home); - g_object_set_data_full(G_OBJECT(menu_item),"home",tmp, (GDestroyNotify)g_free); - } - if (linphone_gtk_can_manage_accounts()) { - gtk_widget_show(linphone_gtk_get_widget(w,"assistant_item")); - } - if (update_check_menu){ - gtk_widget_show(linphone_gtk_get_widget(w,"versioncheck_item")); - } - g_object_set_data(G_OBJECT(w),"show_abcd",GINT_TO_POINTER(show_abcd)); -} - -void linphone_gtk_manage_login(void){ - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneProxyConfig *cfg=linphone_core_get_default_proxy_config(lc); - if (cfg){ - SipSetup *ss=linphone_proxy_config_get_sip_setup(cfg); - if (ss && (sip_setup_get_capabilities(ss) & SIP_SETUP_CAP_LOGIN)){ - linphone_gtk_show_login_frame(cfg,FALSE); - } - } -} - -gboolean linphone_gtk_close(GtkWidget *mw){ - /*shutdown calls if any*/ - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *camera_preview=linphone_gtk_get_camera_preview_window(); - if (linphone_core_in_call(lc)){ - linphone_core_terminate_all_calls(lc); - } - if (camera_preview) gtk_widget_destroy(camera_preview); -#ifdef __APPLE__ /*until with have a better option*/ - gtk_window_iconify(GTK_WINDOW(mw)); -#else - gtk_widget_hide(mw); -#endif - return TRUE; -} - -#ifdef HAVE_GTK_OSX -static gboolean on_window_state_event(GtkWidget *w, GdkEventWindowState *event){ - return FALSE; -} -#endif - -void linphone_gtk_init_dtmf_table(GtkWidget *mw){ - GtkWidget *dtmf_table=linphone_gtk_get_widget(mw,"dtmf_table"); - gtk_widget_set_direction(dtmf_table, GTK_TEXT_DIR_LTR); - - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_A")),"label","A"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_B")),"label","B"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_C")),"label","C"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_D")),"label","D"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_1")),"label","1"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_2")),"label","2"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_3")),"label","3"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_4")),"label","4"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_5")),"label","5"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_6")),"label","6"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_7")),"label","7"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_8")),"label","8"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_9")),"label","9"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_0")),"label","0"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_#")),"label","#"); - g_object_set_data(G_OBJECT(linphone_gtk_get_widget(mw,"dtmf_*")),"label","*"); -} - -static gboolean key_allowed(guint32 code){ - static const char *allowed="1234567890#*ABCD"; - return code!=0 && strchr(allowed,(char)code)!=NULL; -} - -static GtkButton *get_button_from_key(GtkWidget *w, GdkEvent *event){ - guint keyval=event->key.keyval; - guint32 code=gdk_keyval_to_unicode(keyval); - code=g_unichar_toupper(code); - if (key_allowed(code)){ - char widgetname[16]; - w=gtk_widget_get_toplevel(w); - snprintf(widgetname,sizeof(widgetname),"dtmf_%c",code); - return GTK_BUTTON(linphone_gtk_get_widget(w,widgetname)); - } - return NULL; -} - -void linphone_gtk_keypad_key_pressed(GtkWidget *w, GdkEvent *event, gpointer userdata){ - GtkButton *button=get_button_from_key(w,event); - if (button) { - linphone_gtk_dtmf_pressed(button); - /*g_signal_emit_by_name(button, "button-press-event");*/ - } -} - -void linphone_gtk_keypad_key_released(GtkWidget *w, GdkEvent *event, gpointer userdata){ - GtkButton *button=get_button_from_key(w,event); - if (button) { - linphone_gtk_dtmf_released(button); - /*g_signal_emit_by_name(button, "button-release-event");*/ - } -} - -static void linphone_gtk_show_keypad(void){ - 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); - } - keypad=linphone_gtk_create_window("keypad", NULL); - linphone_gtk_connect_digits(keypad); - linphone_gtk_init_dtmf_table(keypad); - g_object_set_data(G_OBJECT(mw),"keypad", keypad); - if(!GPOINTER_TO_INT(g_object_get_data(G_OBJECT(mw),"show_abcd"))){ - gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_A")); - gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_B")); - gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_C")); - gtk_widget_hide(linphone_gtk_get_widget(keypad,"dtmf_D")); - gtk_table_resize(GTK_TABLE(linphone_gtk_get_widget(keypad,"dtmf_table")),4,3); - } - gtk_widget_show(keypad); -} - -static void linphone_gtk_destroy_keypad(void) { - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *keypad = GTK_WIDGET(g_object_get_data(G_OBJECT(mw), "keypad")); - if(keypad) { - gtk_widget_destroy(keypad); - g_object_set_data(G_OBJECT(mw), "keypad", NULL); - } -} - -void linphone_gtk_show_keypad_checked(GtkCheckMenuItem *check_menu_item) { - if(gtk_check_menu_item_get_active(check_menu_item)) { - linphone_gtk_show_keypad(); - } else { - linphone_gtk_destroy_keypad(); - } -} - -void linphone_gtk_import_contacts(void) { - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *dialog = gtk_file_chooser_dialog_new("Open vCard file", (GtkWindow *)mw, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); - - if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - LinphoneCore *lc = linphone_gtk_get_core(); - char *filename_utf8 = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - char *filename = g_locale_from_utf8(filename_utf8, -1, NULL, NULL, NULL); - LinphoneFriendList *list = linphone_core_get_default_friend_list(lc); - linphone_friend_list_import_friends_from_vcard4_file(list, filename); - linphone_gtk_show_friends(); - g_free(filename_utf8); - g_free(filename); - } - gtk_widget_destroy(dialog); -} - -void linphone_gtk_export_contacts(void) { - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *dialog = gtk_file_chooser_dialog_new("Save vCards as", (GtkWindow *)mw, GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL); - gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE); - - if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - LinphoneCore *lc = linphone_gtk_get_core(); - char *filename_utf8 = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - char *filename = g_locale_from_utf8(filename_utf8, -1, NULL, NULL, NULL); - LinphoneFriendList *list = linphone_core_get_default_friend_list(lc); - linphone_friend_list_export_friends_as_vcard4_file(list, filename); - g_free(filename_utf8); - g_free(filename); - } - gtk_widget_destroy(dialog); -} - -gboolean linphone_gtk_keypad_destroyed_handler(void) { - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *show_keypad_item = linphone_gtk_get_widget(mw, "show_keypad_menu_item"); - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(show_keypad_item), FALSE); - return FALSE; -} - -void linphone_gtk_update_status_bar_icons(void) { - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *icon = linphone_gtk_get_widget(mw, "autoanswer_icon"); - gtk_widget_set_visible(icon, linphone_gtk_auto_answer_enabled()); -} - -static void linphone_gtk_init_main_window(void){ - GtkWidget *main_window; - linphone_gtk_configure_main_window(); - linphone_gtk_manage_login(); - linphone_gtk_load_identities(); - linphone_gtk_set_my_presence(linphone_core_get_presence_info(linphone_gtk_get_core())); - linphone_gtk_show_friends(); - linphone_gtk_update_status_bar_icons(); - load_uri_history(); - linphone_core_reset_missed_calls_count(linphone_gtk_get_core()); - main_window=linphone_gtk_get_main_window(); - linphone_gtk_call_log_update(main_window); - - linphone_gtk_update_call_buttons (NULL); - g_object_set_data(G_OBJECT(main_window),"keypad",NULL); - g_object_set_data(G_OBJECT(main_window),"is_conf",GINT_TO_POINTER(FALSE)); - /*prevent the main window from being destroyed by a user click on WM controls, instead we hide it*/ - g_signal_connect (G_OBJECT (main_window), "delete-event", - G_CALLBACK (linphone_gtk_close), main_window); -#ifdef HAVE_GTK_OSX - { - gtk_widget_show(main_window); - GtkWidget *menubar=linphone_gtk_get_widget(main_window,"menubar1"); - GtkosxApplication *theMacApp = gtkosx_application_get(); - gtkosx_application_set_menu_bar(theMacApp,GTK_MENU_SHELL(menubar)); - gtk_widget_hide(menubar); - gtkosx_application_ready(theMacApp); - } - g_signal_connect(G_OBJECT(main_window), "window-state-event",G_CALLBACK(on_window_state_event), NULL); -#endif - linphone_gtk_check_menu_items(); - linphone_core_enable_video_preview(linphone_gtk_get_core(),FALSE); -#ifdef BUILD_WIZARD - gtk_widget_set_visible(linphone_gtk_get_widget(main_window, "assistant_item"), TRUE); -#else - gtk_widget_set_visible(linphone_gtk_get_widget(main_window, "assistant_item"), FALSE); -#endif -} - -void linphone_gtk_log_handler(const char*domain, OrtpLogLevel lev, const char *fmt, va_list args){ - if (verbose){ - const char *lname="undef"; - char *msg; -#if defined(__linux) || defined(__APPLE__) - va_list cap;/*copy of our argument list: a va_list cannot be re-used (SIGSEGV on linux 64 bits)*/ -#endif - switch(lev){ - case ORTP_DEBUG: - lname="debug"; - break; - case ORTP_MESSAGE: - lname="message"; - break; - case ORTP_WARNING: - lname="warning"; - break; - case ORTP_ERROR: - lname="error"; - break; - case ORTP_FATAL: - lname="fatal"; - break; - default: - g_error("Bad level !"); - } -#if defined(__linux) || defined(__APPLE__) - va_copy(cap,args); - msg=g_strdup_vprintf(fmt,cap); - va_end(cap); -#else - msg=g_strdup_vprintf(fmt,args); -#endif - fprintf(stdout,"linphone-%s : %s\n",lname,msg); - ortp_free(msg); - } - linphone_gtk_log_push(lev,fmt,args); -} - - -void linphone_gtk_refer_received(LinphoneCore *lc, const char *refer_to){ - char method[20] = ""; - LinphoneAddress *addr = linphone_address_new(refer_to); - if(addr) { - const char *tmp = linphone_address_get_method_param(addr); - strncpy(method, tmp, sizeof(20)); - linphone_address_unref(addr); - } - if(strlen(method) == 0 || strcmp(method, "INVITE") == 0) { - GtkEntry * uri_bar =GTK_ENTRY(linphone_gtk_get_widget( - linphone_gtk_get_main_window(), "uribar")); - char *text; - linphone_gtk_notify(NULL,NULL,(text=ms_strdup_printf(_("We are transferred to %s"),refer_to))); - g_free(text); - gtk_entry_set_text(uri_bar, refer_to); - linphone_gtk_start_call(linphone_gtk_get_main_window()); - } -} - -static void linphone_gtk_check_soundcards(void){ - const char **devices=linphone_core_get_sound_devices(linphone_gtk_get_core()); - if (devices==NULL || devices[0]==NULL){ - linphone_gtk_display_something(GTK_MESSAGE_WARNING, - _("No sound cards have been detected on this computer.\n" - "You won't be able to send or receive audio calls.")); - } -} - -static void linphone_gtk_quit_core(void){ -#ifdef HAVE_GTK_OSX - { - GtkosxApplication *theMacApp = gtkosx_application_get(); - gtkosx_application_set_menu_bar(theMacApp,NULL); - } -#endif - linphone_gtk_unmonitor_usb(); - g_source_remove_by_user_data(linphone_gtk_get_core()); -#ifdef BUILD_WIZARD - linphone_gtk_close_assistant(); -#endif - linphone_gtk_set_ldap(NULL); - linphone_gtk_destroy_log_window(); - linphone_core_destroy(the_core); - linphone_gtk_log_uninit(); -} - -static void linphone_gtk_quit(void){ - if (!quit_done){ - quit_done=TRUE; - linphone_gtk_quit_core(); - linphone_gtk_uninit_instance(); -#ifdef HAVE_NOTIFY - notify_uninit(); -#endif - linphone_status_icon_uninit(); - gtk_widget_destroy(the_ui); - the_ui=NULL; - gdk_threads_leave(); - } -} - -#ifdef HAVE_GTK_OSX -/* -This is not the correct way to implement block termination. -The good way would be to call gtk_main_quit(), and return TRUE. -Unfortunately this does not work, because if we return TRUE the NSApplication sometimes calls the CFRunLoop recursively, which prevents gtk_main() to exit. -As a result the program cannot exit at all. -As a workaround we do all the cleanup (unregistration and config save) within the handler. -*/ -static gboolean on_block_termination(void){ - gtk_main_quit(); - linphone_gtk_quit(); - return FALSE; -} -#endif - -static void linphone_gtk_init_ui(void){ - linphone_gtk_init_main_window(); - -#ifdef BUILD_WIZARD - // Veryfing if at least one sip account is configured. If not, show wizard - if (linphone_core_get_proxy_config_list(linphone_gtk_get_core()) == NULL) { - linphone_gtk_show_assistant(); - } -#endif - - if(run_audio_assistant){ - linphone_gtk_show_audio_assistant(); - start_option=START_AUDIO_ASSISTANT; - iconified = TRUE; - } - - linphone_gtk_init_status_icon(); - - if (!iconified){ - linphone_gtk_show_main_window(); - linphone_gtk_check_soundcards(); - } - if (linphone_gtk_get_ui_config_int("update_check_menu",0)==0) - linphone_gtk_check_for_new_version(); - linphone_gtk_monitor_usb(); -} - -static void sigint_handler(int signum){ - gtk_main_quit(); -} - -static void populate_xdg_data_dirs_envvar(void) { -#ifndef _WIN32 - int i; - gchar *value; - gchar **paths; - const char *data_dir; - LinphoneFactory *factory = linphone_factory_get(); - - if(g_getenv("XDG_DATA_DIRS") == NULL) { - value = g_strdup("/usr/share:/usr/local/share:/opt/local/share"); - } else { - value = g_strdup(g_getenv("XDG_DATA_DIRS")); - } - paths = g_strsplit(value, ":", -1); - data_dir = linphone_factory_get_top_resources_dir(factory); - for(i=0; paths[i] && strcmp(paths[i], data_dir) != 0; i++); - if(paths[i] == NULL) { - gchar *new_value = g_strdup_printf("%s:%s", data_dir, value); - g_setenv("XDG_DATA_DIRS", new_value, TRUE); - g_free(new_value); - } - g_strfreev(paths); -#endif -} -#define ZRTP_CACHE_CONFIG_FILE ".linphone-zidcache.db" - - -int main(int argc, char *argv[]){ - char *config_file; - const char *factory_config_file; - const char *lang; - GtkSettings *settings; - const char *icon_name=LINPHONE_ICON_NAME; - const char *app_name="Linphone"; - LpConfig *factory_config; - char *chat_messages_db_file, *call_logs_db_file, *friends_db_file; - GError *error=NULL; - const char *tmp; - const char *resources_dir; - char *pixmaps_dir; - LinphoneFactory *factory; - -#if !GLIB_CHECK_VERSION(2, 31, 0) - g_thread_init(NULL); -#endif - gdk_threads_init(); - - progpath = strdup(argv[0]); - - config_file=linphone_gtk_get_config_file(NULL); - - workingdir= (tmp=g_getenv("LINPHONE_WORKDIR")) ? g_strdup(tmp) : NULL; - -#ifdef __linux - /*for pulseaudio:*/ - g_setenv("PULSE_PROP_media.role", "phone", TRUE); -#endif - - populate_xdg_data_dirs_envvar(); - - lang=linphone_gtk_get_lang(config_file); - if (lang == NULL || lang[0]=='\0'){ - lang = g_getenv("LANGUAGE"); - if (!lang) lang = g_getenv("LANG"); - } - if (lang && lang[0]!='\0'){ -#ifdef _WIN32 - if (strncmp(lang,"zh",2)==0){ - workaround_gtk_entry_chinese_bug=TRUE; - } -#endif - g_setenv("LANGUAGE",lang,1); - } - -#ifdef ENABLE_NLS - setlocale(LC_ALL, ""); - bindtextdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - - /*do not use textdomain(): this sets a global default domain. On Mac OS bundle, it breaks gtk translations (obscure bug somewhere)*/ - /*textdomain (GETTEXT_PACKAGE);*/ -#else - g_message("NLS disabled.\n"); -#endif -#ifdef _WIN32 - gtk_rc_add_default_file("./gtkrc"); -#endif - gdk_threads_enter(); - - if (!gtk_init_with_args(&argc,&argv,_("A free SIP video-phone"), - linphone_options,NULL,&error)){ - gdk_threads_leave(); - g_critical("%s", error->message); - return -1; - } - if(version) { - g_message("Linphone version %s.", linphone_core_get_version()); - return 0; - } - - if (config_file) g_free(config_file); - if (custom_config_file && !g_path_is_absolute(custom_config_file)) { - gchar *res = g_get_current_dir(); - res = g_strjoin(G_DIR_SEPARATOR_S, res, custom_config_file, NULL); - free(custom_config_file); - custom_config_file = res; - } - config_file=linphone_gtk_get_config_file(custom_config_file); - - if(run_audio_assistant) start_option=START_AUDIO_ASSISTANT; - if(addr_to_call != NULL) start_option=START_LINPHONE_WITH_CALL; - - settings=gtk_settings_get_default(); - g_type_class_unref (g_type_class_ref (GTK_TYPE_IMAGE_MENU_ITEM)); - g_type_class_unref (g_type_class_ref (GTK_TYPE_BUTTON)); - g_object_set(settings, "gtk-menu-images", TRUE, NULL); - g_object_set(settings, "gtk-button-images", TRUE, NULL); - - if (workingdir!=NULL){ - if (chdir(workingdir)==-1){ - g_error("Could not change directory to %s : %s",workingdir,strerror(errno)); - } - } - -#if defined(__APPLE__) && defined(ENABLE_NLS) - /*workaround for bundles. GTK is unable to find translations in the bundle (obscure bug again). - So we help it:*/ - { - if (g_file_test(PACKAGE_LOCALE_DIR, G_FILE_TEST_IS_DIR)){ - bindtextdomain("gtk20",PACKAGE_LOCALE_DIR); - bindtextdomain("gdk-pixbuf",PACKAGE_LOCALE_DIR); - bindtextdomain("glib20",PACKAGE_LOCALE_DIR); - } - } -#endif - add_pixmap_directory("pixmaps"); - factory = linphone_factory_get(); - resources_dir = linphone_factory_get_top_resources_dir(factory); - pixmaps_dir = bctbx_strdup_printf("%s/pixmaps/linphone", resources_dir); - add_pixmap_directory(pixmaps_dir); - bctbx_free(pixmaps_dir); - - /* Now, look for the factory configuration file, we do it this late - since we want to have had time to change directory and to parse - the options, in case we needed to access the working directory */ - factory_config_file = linphone_gtk_get_factory_config_file(); - if (factory_config_file){ - factory_config=lp_config_new(NULL); - lp_config_read_file(factory_config,factory_config_file); - app_name=lp_config_get_string(factory_config,"GtkUi","title","Linphone"); - icon_name=lp_config_get_string(factory_config,"GtkUi","icon_name",LINPHONE_ICON_NAME); - } - g_set_application_name(app_name); - gtk_window_set_default_icon_name(icon_name); - -#ifdef HAVE_GTK_OSX - GtkosxApplication *theMacApp = gtkosx_application_get(); - g_signal_connect(G_OBJECT(theMacApp),"NSApplicationDidBecomeActive",(GCallback)linphone_gtk_show_main_window,NULL); - g_signal_connect(G_OBJECT(theMacApp),"NSApplicationWillTerminate",(GCallback)gtk_main_quit,NULL); - /*never block termination:*/ - g_signal_connect(G_OBJECT(theMacApp),"NSApplicationBlockTermination",(GCallback)on_block_termination,NULL); -#endif - -core_start: - if (linphone_gtk_init_instance(app_name, start_option, addr_to_call) == FALSE){ - g_warning("Another running instance of Linphone has been detected. It has been woken-up."); - g_warning("This instance is going to exit now."); - gdk_threads_leave(); - return 0; - } - the_ui=linphone_gtk_create_window("main", NULL); - - g_object_set_data(G_OBJECT(the_ui),"is_created",GINT_TO_POINTER(FALSE)); - g_signal_connect(G_OBJECT (the_ui), "key_press_event", G_CALLBACK (linphone_gtk_on_key_press), NULL); - - linphone_gtk_create_log_window(); - linphone_core_enable_logs_with_cb(linphone_gtk_log_handler); - /*it is possible to filter in or out some logs by configuring per log domain:*/ - /*ortp_set_log_level_mask("belle-sip", ORTP_ERROR);*/ - - chat_messages_db_file=linphone_gtk_message_storage_get_db_file(NULL); - call_logs_db_file = linphone_gtk_call_logs_storage_get_db_file(NULL); - friends_db_file = linphone_gtk_friends_storage_get_db_file(NULL); - linphone_gtk_init_liblinphone(config_file, factory_config_file, chat_messages_db_file, call_logs_db_file, friends_db_file); - g_free(chat_messages_db_file); - g_free(call_logs_db_file); - g_free(friends_db_file); - - linphone_gtk_call_log_update(the_ui); - linphone_gtk_show_friends(); - - /* do not lower timeouts under 30 ms because it exhibits a bug on gtk+/win32, with cpu running 20% all the time...*/ - gtk_timeout_add(30,(GtkFunction)linphone_gtk_iterate,(gpointer)linphone_gtk_get_core()); - gtk_timeout_add(30,(GtkFunction)linphone_gtk_check_logs,(gpointer)linphone_gtk_get_core()); - - signal(SIGINT, sigint_handler); - - gtk_main(); - linphone_gtk_quit(); - - if (restart){ - quit_done=FALSE; - restart=FALSE; - goto core_start; - } - if (config_file) g_free(config_file); - free(progpath); - /*output a translated "hello" string to the terminal, which allows the builder to check that translations are working.*/ - if (selftest){ - printf(_("Hello\n")); - } - return 0; -} - -#ifdef _MSC_VER -int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { - return main(__argc, __argv); -} -#endif - -GtkWidget *linphone_gtk_make_tab_header(const gchar *label, const gchar *icon_name, gboolean show_quit_button, GCallback cb, gpointer user_data) { - GtkWidget *tab_header=gtk_hbox_new (FALSE,0); - GtkWidget *label_widget = gtk_label_new (label); - - if(icon_name) { - GtkWidget *icon=gtk_image_new_from_icon_name(icon_name, GTK_ICON_SIZE_MENU); -#ifdef HAVE_GTK_OSX - gtk_misc_set_alignment(GTK_MISC(icon), 0.5f, 0.25f); -#endif - gtk_box_pack_start (GTK_BOX(tab_header),icon,FALSE,FALSE,4); - } -#ifdef HAVE_GTK_OSX - gtk_misc_set_alignment(GTK_MISC(label_widget), 0.5f, 0.f); -#endif - gtk_box_pack_start (GTK_BOX(tab_header),label_widget,FALSE,FALSE,0); - if(show_quit_button) { - GtkWidget *button = gtk_button_new(); - GtkWidget *button_image=gtk_image_new_from_stock(GTK_STOCK_CLOSE,GTK_ICON_SIZE_MENU); - gtk_button_set_image(GTK_BUTTON(button),button_image); - gtk_button_set_relief(GTK_BUTTON(button),GTK_RELIEF_NONE); -#ifdef HAVE_GTK_OSX - gtk_misc_set_alignment(GTK_MISC(button_image), 0.5f, 0.f); -#endif - g_signal_connect_swapped(G_OBJECT(button),"clicked",cb,user_data); - gtk_box_pack_end(GTK_BOX(tab_header),button,FALSE,FALSE,4); - g_object_set_data(G_OBJECT(tab_header), "button", button); - } - g_object_set_data(G_OBJECT(tab_header), "label", label_widget); - return tab_header; -} diff --git a/gtk/main.ui b/gtk/main.ui deleted file mode 100644 index e7360e215..000000000 --- a/gtk/main.ui +++ /dev/null @@ -1,1056 +0,0 @@ - - - - - - - True - False - 2 - 30 - linphone-add-call - - - True - False - linphone-contact-add - - - True - False - 4 - linphone-delete - - - True - False - gtk-connect - 1 - - - - - - - - - - - - - - - - - - - - - - - linphone-status-online - Toto - toto@sip.linphone.org - linphone-chat-nothing - False - False - - - linphone-status-offline - Toto2 - toto2@sip.linphone.org - linphone-chat-nothing - False - False - - - linphone-status-offline - Toto3 - toto3@sip.linphone.org - linphone-chat-nothing - False - False - - - - - True - False - linphone-edit - - - True - False - gtk-execute - 1 - - - True - False - gtk-home - 1 - - - True - False - gtk-info - 1 - - - - - - - - - Default - - - - - True - False - gtk-properties - 1 - - - True - False - Delete - linphone-delete - - - True - False - 2 - 30 - linphone-start-call - - - True - False - 2 - 30 - linphone-start-chat - - - 640 - 480 - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 660 - 450 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - - - True - False - _Options - True - - - - True - False - - - gtk-preferences - True - False - True - True - - - - - - - True - False - Set configuration URI - True - - - - - - gtk-disconnect - False - True - True - - - - - - True - False - - - - - True - False - Always start video - True - - - - - - True - False - Enable self-view - True - True - - - - - - True - False - Show keypad - True - - - - - - True - False - - - - - True - False - Import contacts from vCards - True - - - - - - True - False - Export contacts as vCards - True - - - - - - True - False - - - - - gtk-quit - False - True - True - - - - - - - - - - - True - False - _Help - True - - - True - False - - - gtk-about - True - False - True - True - - - - - - Show debug window - True - False - info_image - False - - - - - - - _Homepage - True - False - True - home_image - False - - - - - - Check _Updates - False - True - execute_image - False - - - - - - Account assistant - False - connect_image - False - - - - - - Audio assistant - True - False - properties_image - False - - - - - - - - - - False - True - 0 - - - - - True - False - 8 - - - True - False - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 5 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - - True - linphone-contact-add - False - True - True - False - - - - True - True - 0 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - SIP address or phone number: - True - - - - - True - True - 2 - 0 - - - - - True - True - Initiate a new call - add_call_image - - - - False - False - 1 - - - - - True - True - True - start_call_image - - - - False - True - 2 - - - - - True - True - True - start_chat_image - - - - False - True - end - 3 - - - - - False - True - 8 - 0 - - - - - True - True - 200 - True - - - True - False - 4 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_STRUCTURE_MASK - 0 - Contacts - True - - - False - False - 3 - 0 - - - - - True - True - automatic - automatic - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - contact_list_model - False - True - 1 - 4 - - - - - - - - - - 3 - - - 0 - - - - - - - 60 - True - - - - 1 - - - - - - - - - linphone-start-call2 - 3 - - - 6 - - - - - - - - - 3 - - - 7 - 5 - - - - - - - - - True - True - 1 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - 32 - 32 - True - True - True - immediate - add_image1 - - - - False - False - 0 - - - - - 32 - 32 - True - False - True - True - edit_image1 - - - - False - False - 1 - - - - - 32 - 32 - True - False - True - True - remove_image1 - - - - False - False - 2 - - - - - False - False - 4 - 2 - - - - - True - True - - - - - True - True - - - - - - - - - - True - False - - - True - False - 2 - - - True - True - never - - - 350 - True - True - False - False - - - - - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - False - 0 - none - - - False - - - True - True - - True - False - False - True - True - - - True - True - 0 - - - - - True - True - True - none - - - - True - False - - - True - False - gtk-find - - - True - True - 0 - - - - - True - False - Search - - - True - True - 1 - - - - - - - False - True - 1 - - - - - - - True - False - <b>Add contacts from directory</b> - True - - - - - False - False - 5 - 0 - - - - - True - False - - - Add contact - True - True - - - - False - False - 0 - - - - - False - False - 1 - - - - - False - False - 1 - - - - - True - False - end - - - Clear call history - True - True - True - clear_call_history_image - - - - False - False - 0 - - - - - False - True - 2 - - - - - True - True - 0 - - - - - 1 - - - - - True - False - GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK - False - - - - True - False - - - True - False - linphone-history - 1 - - - True - True - 4 - 0 - - - - - True - False - Recent calls - - - True - True - 1 - - - - - - - 1 - False - - - - - - - - - - - True - True - - - - - True - True - 1 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - model3 - 0 - - - - - 0 - - - - - True - True - 0 - - - - - True - True - True - none - - - - False - True - 5 - 1 - - - - - - - True - False - 5 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - My current identity: - True - - - True - True - 0 - - - - - True - True - True - none - - - - True - True - 1 - - - - - - - False - False - 2 - - - - - True - True - 1 - - - - - True - False - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - True - True - 0 - - - - - False - Autoanswer is enabled - 16 - linphone-warning - - - False - True - 1 - - - - - False - True - 2 - - - - - - diff --git a/gtk/p2pwizard.ui b/gtk/p2pwizard.ui deleted file mode 100644 index 111f46ff5..000000000 --- a/gtk/p2pwizard.ui +++ /dev/null @@ -1,129 +0,0 @@ - - - - - Creating a FONICS account - - - - - True - Welcome! -This wizard will help you to setup a SIP account. - - True - GTK_JUSTIFY_CENTER - True - True - - - GTK_ASSISTANT_PAGE_INTRO - Introduction - - - - - True - - - True - Please choose a username: - - - - - True - 0 - - - True - 12 - - - True - - - True - - - True - True - - - - - True - True - True - - - - True - - - True - gtk-apply - - - - - True - Check availability - - - 1 - - - - - - - False - 1 - - - - - False - - - - - True - - - 1 - - - - - - - - - True - True - - - - - 1 - - - - - Create your account ! - - - - - True - Done ! Your account is now created and ready to use. - - - GTK_ASSISTANT_PAGE_CONFIRM - Finished ! - - - - diff --git a/gtk/parameters.ui b/gtk/parameters.ui deleted file mode 100644 index ee93560bb..000000000 --- a/gtk/parameters.ui +++ /dev/null @@ -1,3183 +0,0 @@ - - - - - - -1 - 100000 - 1 - 10 - - - 65535 - 2 - 10 - - - 65535 - 2 - 10 - - - 65535 - 2 - 10 - - - 65535 - 2 - 10 - - - 500 - 3001 - 500 - 1 - 10 - - - 65535 - 5060 - 1 - 10 - - - -1 - 100000 - 1 - 10 - - - 30 - 1 - 10 - - - 30000 - 2000 - 100 - 500 - - - - - - - - - - anonymous - - - GSSAPI - - - SASL - - - - - - - - - - - default soundcard - - - - - - - - - - - default soundcard - - - - - - - - - - - a sound card - - - - - - - - - - - default camera - - - - - - - - - - - CIF - - - - - - - - - - - Audio codecs - - - Video codecs - - - - - - - - - - - C - - - - - - - - - - - SIP (UDP) - - - SIP (TCP) - - - SIP (TLS) - - - - - 65535 - 5060 - 1 - 9.9999999995529656 - - - - - - - - - default - - - high-fps - - - custom - - - - - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Settings - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - This section defines your SIP address when not using a SIP account - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 2 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Your display name (eg: John Doe): - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - - - - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Your username: - - - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Your resulting SIP address: - - - 2 - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - - - - 1 - 2 - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - False - True - True - - - 1 - 2 - 2 - 3 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Default identity</b> - True - - - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - True - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-add - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Wizard - - - True - True - 1 - - - - - - - False - False - 0 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-add - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Add - - - True - True - 1 - - - - - - - False - False - 1 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-edit - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Edit - - - True - True - 1 - - - - - - - False - False - 2 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-delete - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Remove - - - True - True - 1 - - - - - - - False - False - 3 - - - - - False - False - 1 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Proxy accounts</b> - True - - - - - True - True - 1 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-delete - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Erase all passwords - - - True - True - 1 - - - - - - - False - False - 0 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Privacy</b> - True - - - - - True - True - 2 - - - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 2 - 2 - - - Automatically answer when a call is received - True - True - False - True - - - - 2 - - - - - True - False - Delay before answering (ms) - - - 1 - 2 - - - - - True - True - - False - False - True - True - ajustment_auto_answer_delay - True - - - - 1 - 2 - 1 - 2 - - - - - - - - - True - False - <b>Auto-answer</b> - True - - - - - True - True - 3 - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - stock_people.png - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Manage SIP Accounts - - - True - True - 1 - - - - - 2 - False - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - 2 - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - True - 0 - - - - - gtk-media-play - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - True - True - 1 - - - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Ring sound: - right - - - 4 - 5 - GTK_FILL - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - model1 - - - - end - 80 - - - 0 - - - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - model2 - - - - end - 80 - - - 0 - - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - ALSA special device (optional): - right - - - 3 - 4 - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Capture device: - right - - - 2 - 3 - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Ring device: - right - - - 1 - 2 - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Playback device: - right - - - GTK_FILL - GTK_FILL - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - model3 - - - - end - 80 - - - 0 - - - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - Enable echo cancellation - True - True - False - True - - - - 1 - 2 - 5 - 6 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Audio</b> - True - - - - - True - True - 0 - - - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 5 - 3 - - - True - False - Video input device: - right - - - GTK_EXPAND - - - - - True - False - model4 - - - - - 0 - - - - - 1 - 2 - GTK_EXPAND - - - - - True - False - Preferred video resolution: - - - 3 - 4 - - - - - True - False - model5 - 0 - - - - - 0 - - - - - 1 - 2 - 3 - 4 - - - - - True - False - Video output method: - right - - - 1 - 2 - GTK_EXPAND - - - - - True - False - - - - - 0 - - - - - 1 - 2 - 1 - 2 - GTK_EXPAND - - - - - Show camera preview - True - True - True - - - - 2 - 3 - 5 - - GTK_EXPAND - 10 - - - - - True - False - Video preset: - - - 2 - 3 - - - - - True - False - video_preset_model - 0 - - - - - 0 - - - - - 1 - 2 - 2 - 3 - - - - - True - False - Preferred video framerate: - - - 4 - 5 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 stands for "unlimited" - - False - False - True - True - adjustment_video_framerate - - - - 1 - 2 - 4 - 5 - GTK_FILL - GTK_EXPAND - - - - - - - - - True - False - <b>Video</b> - True - - - - - True - False - 1 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 2 - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 stands for "unlimited" - - False - False - True - True - adjustment_upload_bw - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 stands for "unlimited" - - False - False - True - True - adjustment_download_bw - - - - 1 - 2 - GTK_FILL - GTK_EXPAND - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Upload speed limit in Kbit/sec: - right - - - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Download speed limit in Kbit/sec: - right - - - - - Enable adaptive rate control - True - True - False - 0 - True - - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - - True - False - <i>Adaptive rate control is a technique to dynamically guess the available bandwidth during a call.</i> - True - True - - - 2 - 3 - GTK_FILL - - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Bandwidth control</b> - True - - - - - True - True - 2 - - - - - 1 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-media-play - 1 - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Multimedia settings - - - True - True - 1 - - - - - 1 - False - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - - - True - False - - - Set Maximum Transmission Unit: - True - True - False - True - - - - True - True - 0 - - - - - True - True - False - False - True - True - adjustment_mtu - - - - True - True - 1 - - - - - True - True - 0 - - - - - Send DTMFs as SIP info - True - True - False - True - - - - True - True - 1 - - - - - Allow IPv6 - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - True - True - 2 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Transport</b> - True - - - - - False - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - 2 - - - True - False - SIP/UDP port - - - - - True - False - - - Disabled - True - True - False - True - - - - True - True - 0 - - - - - Random - True - True - False - True - - - - True - True - 1 - - - - - True - True - - True - False - False - True - True - udp_port_adjustment - - - - True - True - 2 - - - - - 1 - 2 - - - - - True - False - SIP/TCP port - - - 1 - 2 - - - - - True - False - - - Disabled - True - True - False - True - - - - True - True - 0 - - - - - Random - True - True - False - True - - - - True - True - 1 - - - - - True - True - - True - False - False - True - True - adjustment_tcp_port - - - - True - True - 2 - - - - - 1 - 2 - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Audio RTP/UDP: - right - - - 2 - 3 - - - - - True - False - - - True - True - - False - False - True - True - adjustment_min_audio_port - True - - - - True - True - 0 - - - - - True - True - - True - False - False - True - True - adjustment_max_audio_port - True - - - - True - True - 1 - - - - - Fixed - True - True - False - True - - - - True - True - 2 - - - - - 1 - 2 - 2 - 3 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Video RTP/UDP: - right - - - 3 - 4 - - - - - True - False - - - True - True - - False - False - True - True - adjustment_min_video_port - True - - - - True - True - 0 - - - - - True - True - - True - False - False - True - True - adjustment_max_video_port - True - - - - True - True - 1 - - - - - Fixed - True - True - False - True - - - - True - True - 2 - - - - - 1 - 2 - 3 - 4 - - - - - False - Tunnel - - - 5 - 6 - - - - - gtk-edit - True - True - True - - - - 1 - 2 - 5 - 6 - - - - - True - False - DSCP fields - - - 4 - 5 - - - - - gtk-edit - True - True - True - True - - - - 1 - 2 - 4 - 5 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Network protocol and ports</b> - True - - - - - False - True - 1 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - - - True - False - - - Direct connection to the Internet - True - True - False - True - True - - - - False - False - 0 - - - - - Behind NAT / Firewall (specify gateway IP ) - True - True - False - True - no_nat - - - - True - True - 1 - - - - - Behind NAT / Firewall (use STUN to resolve) - True - True - False - True - no_nat - - - - True - True - 2 - - - - - Behind NAT / Firewall (use ICE) - True - True - False - True - no_nat - - - - True - True - 3 - - - - - Behind NAT / Firewall (use uPnP) - True - True - False - True - no_nat - - - - True - True - 4 - - - - - True - True - 0 - - - - - True - False - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Public IP address: - right - - - True - True - 0 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - True - False - False - True - True - - - - True - True - 1 - - - - - True - False - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Stun server: - right - - - True - True - 0 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - True - False - False - True - True - - - - True - True - 1 - - - - - True - False - 1 - - - - - False - False - 1 - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>NAT and Firewall</b> - True - - - - - False - True - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - 2 - - - True - False - Media encryption type - - - 1 - 2 - - - - - True - False - 0 - - - 1 - 2 - 1 - 2 - - - - - True - False - 0.51999998092651367 - Use Lime for outgoing chat messages - - - - - True - False - Media encryption is mandatory - - - 2 - 3 - - - - - True - True - False - 0.40000000596046448 - True - - - - 1 - 2 - 2 - 3 - - - - - True - False - - Disabled - Mandatory - Preferred - - - - - 1 - 2 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Encryption</b> - True - - - - - False - True - 3 - - - - - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-network - 1 - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Network settings - - - True - True - 1 - - - - - 2 - False - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - out - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - center - - - gtk-go-up - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 0 - - - - - gtk-go-down - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 1 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-yes - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Enable - - - True - True - 1 - - - - - - - False - False - 2 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-no - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Disable - - - True - True - 1 - - - - - - - False - False - 3 - - - - - False - True - 1 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Audio codecs</b> - True - - - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - out - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 10 - center - - - gtk-go-up - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 0 - - - - - gtk-go-down - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 1 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-yes - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Enable - - - True - True - 1 - - - - - - - False - False - 2 - - - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-no - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Disable - - - True - True - 1 - - - - - - - False - False - 3 - - - - - False - True - 1 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>Video codecs</b> - True - - - - - False - True - 1 - - - - - 3 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-execute - 1 - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Codecs - - - True - True - 1 - - - - - 3 - False - - - - - True - False - 10 - - - True - False - 0 - none - - - True - False - 12 - - - True - False - model7 - - - - - 0 - - - - - - - - - True - False - <b>Language</b> - True - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - 12 - - - Show advanced settings - True - True - False - True - - - - - - - - True - False - <b>Level</b> - True - - - - - False - True - 1 - - - - - 4 - - - - - True - False - - - True - False - gtk-properties - 1 - - - True - True - 0 - - - - - True - False - User interface - - - True - True - 1 - - - - - 4 - False - - - - - True - False - 10 - - - True - False - 0 - none - - - True - False - 0 - 0 - - - True - False - 4 - 2 - True - - - - - - True - False - 1 - Server address: - - - GTK_SHRINK - GTK_SHRINK - - - - - True - False - Authentication method: - - - 1 - 2 - GTK_EXPAND | GTK_SHRINK - - - - - True - False - Username: - - - 2 - 3 - GTK_SHRINK - - - - - gtk-edit - True - True - True - True - - - - 1 - 2 - 3 - 4 - GTK_SHRINK - GTK_SHRINK - - - - - True - False - - - 1 - 2 - GTK_SHRINK - - - - - True - False - - - 1 - 2 - 1 - 2 - GTK_SHRINK - - - - - True - False - - - 1 - 2 - 2 - 3 - GTK_SHRINK - - - - - - - - - True - False - <b>LDAP Account setup</b> - True - - - - - False - True - 0 - - - - - - - - 5 - - - - - True - False - - - True - False - gtk-disconnect - - - True - True - 0 - - - - - True - False - LDAP - - - True - True - 1 - - - - - 5 - False - - - - - - - - - - - True - True - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - end - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - - True - False - - - True - False - gtk-apply - - - True - True - 0 - - - - - True - False - Done - - - True - True - 1 - - - - - - - False - False - 10 - 0 - - - - - True - True - 5 - 1 - - - - - - diff --git a/gtk/password.ui b/gtk/password.ui deleted file mode 100644 index d9ce720aa..000000000 --- a/gtk/password.ui +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Linphone - Authentication required - True - center-on-parent - dialog - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Please enter the domain password - center - True - - - 0 - - - - - True - 2 - 2 - - - True - UserID - - - - - True - True - - - - 1 - 2 - - - - - True - Password: - right - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - - - - - 1 - 2 - 1 - 2 - - - - - 1 - - - - - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - end - - - gtk-ok - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 0 - - - - - gtk-cancel - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - - False - False - 1 - - - - - False - end - 0 - - - - - - diff --git a/gtk/propertybox.c b/gtk/propertybox.c deleted file mode 100644 index 9e417f88f..000000000 --- a/gtk/propertybox.c +++ /dev/null @@ -1,1966 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008-2009 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" -#include "linphone/tunnel.h" -#include "linphone/lpconfig.h" -#include "config.h" - -void linphone_gtk_fill_combo_box(GtkWidget *combo, const char **devices, const char *selected, DeviceCap cap){ - const char **p=devices; - int i=0,active=-1; - GtkTreeModel *model; - - - if ((model=gtk_combo_box_get_model(GTK_COMBO_BOX(combo)))==NULL){ - /*case where combo box is created with no model*/ - GtkCellRenderer *renderer=gtk_cell_renderer_text_new(); - model=GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_STRING)); - gtk_combo_box_set_model(GTK_COMBO_BOX(combo),model); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo),renderer,TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),renderer,"text",0,NULL); - }else{ - gtk_list_store_clear(GTK_LIST_STORE(model)); - /* 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*/ - } - - for(;*p!=NULL;++p){ - if ( cap==CAP_IGNORE - || (cap==CAP_CAPTURE && linphone_core_sound_device_can_capture(linphone_gtk_get_core(),*p)) - || (cap==CAP_PLAYBACK && linphone_core_sound_device_can_playback(linphone_gtk_get_core(),*p)) ){ - gtk_combo_box_append_text(GTK_COMBO_BOX(combo),*p); - if (selected && strcmp(selected,*p)==0) active=i; - i++; - } - } - if (active!=-1) - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),active); -} - -static void linphone_gtk_ldap_display( GtkWidget* param ) -{ - LpConfig* config = linphone_core_get_config(linphone_gtk_get_core()); - LinphoneDictionary* ldap_conf = lp_config_section_to_dict(config,"ldap"); - GtkLabel* label; - - ms_message("linphone_gtk_ldap_display"); - label= GTK_LABEL(linphone_gtk_get_widget(param,"ldap_server")); - gtk_label_set_text(label, linphone_dictionary_get_string(ldap_conf,"server", "ldap://localhost") ); - - label = GTK_LABEL(linphone_gtk_get_widget(param,"ldap_auth_method")); - gtk_label_set_text(label, linphone_dictionary_get_string(ldap_conf,"auth_method", "ANONYMOUS") ); - - label = GTK_LABEL(linphone_gtk_get_widget(param,"ldap_username")); - gtk_label_set_text(label, linphone_dictionary_get_string(ldap_conf,"username", "") ); -} - -static void linphone_gtk_ldap_set_authcombo( GtkComboBox* box, const char* authmethod ) -{ - GtkTreeModel* model = GTK_TREE_MODEL(gtk_combo_box_get_model(box)); - GtkTreeIter iter; - g_return_if_fail(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter) ); - - do{ - const char* value; - - gtk_tree_model_get(model,&iter,0,&value,-1); - if( value && strcmp(value, authmethod) == 0){ - gtk_combo_box_set_active_iter(box, &iter); - break; - } - - }while(gtk_tree_model_iter_next(model,&iter)); -} - -static void linphone_gtk_ldap_load_settings(GtkWidget* param) -{ - LpConfig* config = linphone_core_get_config(linphone_gtk_get_core()); - LinphoneDictionary* ldap_conf = lp_config_section_to_dict(config,"ldap"); - GtkEntry* entry; - GtkToggleButton* toggle; - GtkSpinButton* spin; - GtkComboBox* cbox; - - - toggle = GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(param,"ldap_use_tls")); - gtk_toggle_button_set_active(toggle, linphone_dictionary_get_int(ldap_conf,"use_tls", 0) ); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_server")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"server", "ldap://localhost") ); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_username")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"username", "") ); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_password")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"password", "") ); - - // SASL - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_bind_dn")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"bind_dn", "") ); - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_sasl_authname")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"sasl_authname", "") ); - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_sasl_realm")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"sasl_realm", "") ); - - cbox = GTK_COMBO_BOX(linphone_gtk_get_widget(param,"ldap_auth_method")); - linphone_gtk_ldap_set_authcombo(cbox, linphone_dictionary_get_string(ldap_conf,"auth_method", "ANONYMOUS")); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_base_object")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"base_object", "dc=example,dc=com") ); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_filter")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"filter", "uid=*%s*") ); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_name_attribute")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"name_attribute", "cn") ); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_sip_attribute")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"sip_attribute", "mobile") ); - - entry = GTK_ENTRY(linphone_gtk_get_widget(param,"ldap_attributes")); - gtk_entry_set_text(entry, linphone_dictionary_get_string(ldap_conf,"attributes", "cn,givenName,sn,mobile,homePhone") ); - - - toggle = GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(param,"ldap_deref_aliases")); - gtk_toggle_button_set_active(toggle, linphone_dictionary_get_int(ldap_conf,"deref_aliases", 0) ); - - spin = GTK_SPIN_BUTTON(linphone_gtk_get_widget(param,"ldap_max_results")); - gtk_spin_button_set_value(spin, linphone_dictionary_get_int(ldap_conf,"max_results", 50) ); - - spin = GTK_SPIN_BUTTON(linphone_gtk_get_widget(param,"ldap_timeout")); - gtk_spin_button_set_value(spin, linphone_dictionary_get_int(ldap_conf,"timeout", 10) ); - -} - - -void linphone_gtk_show_ldap_config(GtkWidget* button) -{ - GtkWidget* param = gtk_widget_get_toplevel(button); - GtkWidget* ldap_config = linphone_gtk_create_window("ldap", param); - linphone_gtk_ldap_load_settings(ldap_config); - - // to refresh parameters when the ldap config is destroyed - g_object_weak_ref(G_OBJECT(ldap_config), (GWeakNotify)linphone_gtk_ldap_display, (gpointer)param); - - gtk_widget_show(ldap_config); -} - -void linphone_gtk_ldap_reset(GtkWidget *button) -{ - GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button)); - ms_message("RESET LDAP"); - gtk_widget_destroy(w); -} - -void linphone_gtk_ldap_save(GtkWidget *button) -{ - LinphoneCore *lc = linphone_gtk_get_core(); - LpConfig* conf = linphone_core_get_config(lc); - LinphoneDictionary* dict = linphone_dictionary_new(); - - GtkWidget *ldap_widget = gtk_widget_get_toplevel(button); - GtkEntry* entry; - GtkToggleButton* toggle; - GtkSpinButton* spin; - GtkComboBox* cbox; - - ms_message("SAVE LDAP"); - - toggle = GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(ldap_widget,"ldap_use_tls")); - linphone_dictionary_set_int(dict, "use_tls", gtk_toggle_button_get_active(toggle)); - - - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_server")); - linphone_dictionary_set_string(dict, "server", gtk_entry_get_text(entry)); - - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_username")); - linphone_dictionary_set_string(dict, "username", gtk_entry_get_text(entry)); - - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_password")); - linphone_dictionary_set_string(dict, "password", gtk_entry_get_text(entry)); - - // SASL - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_bind_dn")); - linphone_dictionary_set_string(dict, "bind_dn", gtk_entry_get_text(entry)); - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_sasl_authname")); - linphone_dictionary_set_string(dict, "sasl_authname", gtk_entry_get_text(entry)); - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_sasl_realm")); - linphone_dictionary_set_string(dict, "sasl_realm", gtk_entry_get_text(entry)); - - - 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")); - linphone_dictionary_set_string(dict, "base_object", gtk_entry_get_text(entry)); - - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_filter")); - linphone_dictionary_set_string(dict, "filter", gtk_entry_get_text(entry)); - - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_name_attribute")); - linphone_dictionary_set_string(dict, "name_attribute", gtk_entry_get_text(entry)); - - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_sip_attribute")); - linphone_dictionary_set_string(dict, "sip_attribute", gtk_entry_get_text(entry)); - - entry = GTK_ENTRY(linphone_gtk_get_widget(ldap_widget,"ldap_attributes")); - linphone_dictionary_set_string(dict, "attributes", gtk_entry_get_text(entry)); - - toggle = GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(ldap_widget,"ldap_deref_aliases")); - linphone_dictionary_set_int(dict, "deref_aliases", gtk_toggle_button_get_active(toggle)); - - spin = GTK_SPIN_BUTTON(linphone_gtk_get_widget(ldap_widget,"ldap_max_results")); - linphone_dictionary_set_int(dict, "max_results", (int)gtk_spin_button_get_value(spin) ); - - spin = GTK_SPIN_BUTTON(linphone_gtk_get_widget(ldap_widget,"ldap_timeout")); - linphone_dictionary_set_int(dict, "timeout", (int)gtk_spin_button_get_value(spin) ); - - ms_message("Create LDAP from config"); - // create new LDAP according to the validated config - linphone_gtk_set_ldap( linphone_ldap_contact_provider_create(lc, dict) ); - // save the config to linphonerc: - lp_config_load_dict_to_section(conf, "ldap", dict); - - linphone_dictionary_unref(dict); - - // close widget - gtk_widget_destroy(ldap_widget); - -} - -void linphone_gtk_fill_video_sizes(GtkWidget *combo){ - 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*/ - gtk_combo_box_remove_text(GTK_COMBO_BOX(combo),0); - for(i=0;def->name!=NULL;++def,++i){ - snprintf(vsize_def,sizeof(vsize_def),"%s (%ix%i)",def->name,def->vsize.width,def->vsize.height); - gtk_combo_box_append_text(GTK_COMBO_BOX(combo),vsize_def); - if (cur.width==def->vsize.width && cur.height==def->vsize.height) active=i; - } - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),active); -} - -void linphone_gtk_parameters_closed(GtkWidget *button){ - GtkWidget *pb=gtk_widget_get_toplevel(button); - gtk_widget_destroy(pb); - linphone_gtk_update_status_bar_icons(); -} - -void linphone_gtk_update_my_contact(GtkWidget *w){ - GtkWidget *pb=gtk_widget_get_toplevel(w); - const char *username=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"username"))); - const char *displayname=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"displayname"))); - int port=linphone_core_get_sip_port(linphone_gtk_get_core()); - LinphoneAddress *parsed=linphone_core_get_primary_contact_parsed(linphone_gtk_get_core()); - char *contact; - g_return_if_fail(parsed!=NULL); - if (username[0]=='\0') return; - - linphone_address_set_display_name(parsed,displayname); - linphone_address_set_username(parsed,username); - linphone_address_set_port(parsed,port); - contact=linphone_address_as_string(parsed); - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"sip_address")),contact); - linphone_core_set_primary_contact(linphone_gtk_get_core(),contact); - ms_free(contact); - linphone_address_unref(parsed); - linphone_gtk_load_identities(); -} - -void linphone_gtk_set_propety_entry(GtkWidget *w, gboolean stunServer, gboolean ip){ - GtkWidget *stun_entry=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"stun_server"); - GtkWidget *ip_entry=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"nat_address"); - gtk_widget_set_sensitive(stun_entry,stunServer); - gtk_widget_set_sensitive(ip_entry,ip); -} - -void linphone_gtk_stun_server_changed(GtkWidget *w){ - const gchar *addr=gtk_entry_get_text(GTK_ENTRY(w)); - linphone_core_set_stun_server(linphone_gtk_get_core(),addr); -} - -void linphone_gtk_nat_address_changed(GtkWidget *w){ - const gchar *addr=gtk_entry_get_text(GTK_ENTRY(w)); - linphone_core_set_nat_address(linphone_gtk_get_core(),addr); -} - -void linphone_gtk_ipv6_toggled(GtkWidget *w){ - linphone_core_enable_ipv6(linphone_gtk_get_core(), - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))); -} - -void linphone_gtk_min_audio_port_changed(GtkWidget *w){ - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters"); - GtkSpinButton *min_button = GTK_SPIN_BUTTON(w); - GtkSpinButton *max_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_max_rtp_port")); - gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_audio_port"))); - - if (fixed) { - linphone_core_set_audio_port(linphone_gtk_get_core(), (gint) gtk_spin_button_get_value(min_button)); - gtk_spin_button_set_value(max_button, gtk_spin_button_get_value(min_button)); - } else { - gint min_port = (gint)gtk_spin_button_get_value(min_button); - gint max_port = (gint)gtk_spin_button_get_value(max_button); - if (min_port > max_port) { - gtk_spin_button_set_value(max_button, min_port); - max_port = min_port; - } - linphone_core_set_audio_port_range(linphone_gtk_get_core(), min_port, max_port); - } -} - -void linphone_gtk_max_audio_port_changed(GtkWidget *w){ - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters"); - GtkSpinButton *min_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")); - GtkSpinButton *max_button = GTK_SPIN_BUTTON(w); - gint min_port = (gint)gtk_spin_button_get_value(min_button); - gint max_port = (gint)gtk_spin_button_get_value(max_button); - if (max_port < min_port) { - gtk_spin_button_set_value(min_button, max_port); - min_port = max_port; - } - linphone_core_set_audio_port_range(linphone_gtk_get_core(), min_port, max_port); -} - -void linphone_gtk_min_video_port_changed(GtkWidget *w){ - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters"); - GtkSpinButton *min_button = GTK_SPIN_BUTTON(w); - GtkSpinButton *max_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_max_rtp_port")); - gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_video_port"))); - - if (fixed) { - linphone_core_set_video_port(linphone_gtk_get_core(), (gint) gtk_spin_button_get_value(min_button)); - gtk_spin_button_set_value(max_button, gtk_spin_button_get_value(min_button)); - } else { - gint min_port = (gint)gtk_spin_button_get_value(min_button); - gint max_port = (gint)gtk_spin_button_get_value(max_button); - if (min_port > max_port) { - gtk_spin_button_set_value(max_button, min_port); - max_port = min_port; - } - linphone_core_set_video_port_range(linphone_gtk_get_core(), min_port, max_port); - } -} - -void linphone_gtk_max_video_port_changed(GtkWidget *w){ - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters"); - GtkSpinButton *min_button = GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_min_rtp_port")); - GtkSpinButton *max_button = GTK_SPIN_BUTTON(w); - gint min_port = (gint)gtk_spin_button_get_value(min_button); - gint max_port = (gint)gtk_spin_button_get_value(max_button); - if (max_port < min_port) { - gtk_spin_button_set_value(min_button, max_port); - min_port = max_port; - } - linphone_core_set_video_port_range(linphone_gtk_get_core(), min_port, max_port); -} - -void linphone_gtk_no_firewall_toggled(GtkWidget *w){ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){ - linphone_gtk_set_propety_entry(w,FALSE,FALSE); - linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyNoFirewall); - } -} - -void linphone_gtk_use_nat_address_toggled(GtkWidget *w){ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){ - linphone_gtk_set_propety_entry(w,FALSE,TRUE); - linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseNatAddress); - } -} - -void linphone_gtk_use_stun_toggled(GtkWidget *w){ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){ - linphone_gtk_set_propety_entry(w,TRUE,FALSE); - linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseStun); - } -} - -void linphone_gtk_use_ice_toggled(GtkWidget *w){ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){ - linphone_gtk_set_propety_entry(w,TRUE,FALSE); - linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseIce); - } -} - -void linphone_gtk_use_upnp_toggled(GtkWidget *w){ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){ - linphone_gtk_set_propety_entry(w,FALSE,FALSE); - linphone_core_set_firewall_policy(linphone_gtk_get_core(),LinphonePolicyUseUpnp); - } -} - -void linphone_gtk_mtu_changed(GtkWidget *w){ - if (GTK_WIDGET_SENSITIVE(w)) - linphone_core_set_mtu(linphone_gtk_get_core(),(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w))); -} - -void linphone_gtk_use_sip_info_dtmf_toggled(GtkWidget *w){ - linphone_core_set_use_info_for_dtmf(linphone_gtk_get_core(), - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))); -} - -void linphone_gtk_mtu_set(GtkWidget *w){ - GtkWidget *mtu=linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"mtu"); - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){ - gtk_widget_set_sensitive(mtu,TRUE); - linphone_gtk_mtu_changed(mtu); - }else{ - gtk_widget_set_sensitive(mtu,FALSE); - linphone_core_set_mtu(linphone_gtk_get_core(),0); - } -} - -void linphone_gtk_playback_device_changed(GtkWidget *w){ - gchar *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); - linphone_core_set_playback_device(linphone_gtk_get_core(),sel); - g_free(sel); -} - -void linphone_gtk_capture_device_changed(GtkWidget *w){ - gchar *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); - linphone_core_set_capture_device(linphone_gtk_get_core(),sel); - g_free(sel); -} - -void linphone_gtk_ring_device_changed(GtkWidget *w){ - gchar *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); - linphone_core_set_ringer_device(linphone_gtk_get_core(),sel); - g_free(sel); -} - -void linphone_gtk_alsa_special_device_changed(GtkWidget *w){ - /* - const gchar *dev=gtk_entry_get_text(GTK_ENTRY(w)); - ...*/ -} - -void linphone_gtk_cam_changed(GtkWidget *w){ - LinphoneCall *call; - LinphoneCore *lc = linphone_gtk_get_core(); - gchar *sel=gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); - if (sel){ - if (strcmp(sel, linphone_core_get_video_device(lc)) != 0){ - linphone_core_set_video_device(lc,sel); - if ((call = linphone_core_get_current_call(lc)) != NULL) { - linphone_call_update(call, NULL); - } - } - } - g_free(sel); -} - -void linphone_gtk_video_size_changed(GtkWidget *w){ - int sel=gtk_combo_box_get_active(GTK_COMBO_BOX(w)); - const MSVideoSizeDef *defs=linphone_core_get_supported_video_sizes(linphone_gtk_get_core()); - if (sel<0) return; - linphone_core_set_preferred_video_size(linphone_gtk_get_core(), - defs[sel].vsize); -} - -void linphone_gtk_video_renderer_changed(GtkWidget *w){ - GtkTreeIter iter; - if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w),&iter)){ - GtkTreeModel *model=gtk_combo_box_get_model(GTK_COMBO_BOX(w)); - gchar *name; - gtk_tree_model_get(model,&iter,0,&name,-1); - linphone_core_set_video_display_filter(linphone_gtk_get_core(),name); - } -} - -void linphone_gtk_video_preset_changed(GtkWidget *w) { - gchar *sel = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w)); - GtkSpinButton *framerate = GTK_SPIN_BUTTON(linphone_gtk_get_widget(gtk_widget_get_toplevel(w), "video_framerate")); - LinphoneCore *lc = linphone_gtk_get_core(); - if (g_strcmp0(sel, "default") == 0) { - linphone_core_set_video_preset(lc, NULL); - gtk_spin_button_set_value(framerate, 0); - gtk_widget_set_sensitive(GTK_WIDGET(framerate), FALSE); - } else if (g_strcmp0(sel, "high-fps") == 0) { - linphone_core_set_video_preset(lc, "high-fps"); - gtk_spin_button_set_value(framerate, 30); - gtk_widget_set_sensitive(GTK_WIDGET(framerate), FALSE); - } else if (g_strcmp0(sel, "custom") == 0) { - linphone_core_set_video_preset(lc, "custom"); - gtk_spin_button_set_value(framerate, 30); - gtk_widget_set_sensitive(GTK_WIDGET(framerate), TRUE); - } - g_free(sel); -} - -void linphone_gtk_ring_file_set(GtkWidget *w){ - gchar *file=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(w)); - linphone_core_set_ring(linphone_gtk_get_core(),file); - g_free(file); -} - -static void linphone_gtk_end_of_ring(LinphoneCore *lc, void *user_data){ - gtk_widget_set_sensitive((GtkWidget*)user_data,TRUE); -} - -void linphone_gtk_play_ring_file(GtkWidget *w){ - if (linphone_core_preview_ring(linphone_gtk_get_core(), - linphone_core_get_ring(linphone_gtk_get_core()), - linphone_gtk_end_of_ring, - w)==0){ - gtk_widget_set_sensitive(w,FALSE); - } -} - -void linphone_gtk_echo_cancelation_toggled(GtkWidget *w){ - linphone_core_enable_echo_cancellation(linphone_gtk_get_core(), - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))); -} - -enum { - CODEC_NAME, - CODEC_RATE, - CODEC_BITRATE, - CODEC_STATUS, - CODEC_PARAMS, - CODEC_PRIVDATA, - CODEC_COLOR, - CODEC_INFO, - CODEC_NCOLUMNS -}; - -static void fmtp_edited(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer userdata){ - GtkListStore *store=(GtkListStore*)userdata; - GtkTreeIter iter; - if (gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store),&iter,path)){ - PayloadType *pt; - gtk_list_store_set(store,&iter,CODEC_PARAMS,new_text,-1); - gtk_tree_model_get(GTK_TREE_MODEL(store),&iter,CODEC_PRIVDATA,&pt,-1); - payload_type_set_recv_fmtp(pt,new_text); - } -} - -static void bitrate_edited(GtkCellRendererText *renderer, gchar *path, gchar *new_text, gpointer userdata){ - GtkListStore *store=(GtkListStore*)userdata; - GtkTreeIter iter; - float newbitrate=0; - - if (!new_text) return; - - if (sscanf(new_text, "%f", &newbitrate)!=1) return; - - if (gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store),&iter,path)){ - PayloadType *pt; - gtk_list_store_set(store,&iter,CODEC_BITRATE,newbitrate,-1); - gtk_tree_model_get(GTK_TREE_MODEL(store),&iter,CODEC_PRIVDATA,&pt,-1); - linphone_core_set_payload_type_bitrate(linphone_gtk_get_core(), pt, (int)newbitrate); - } -} - -static void linphone_gtk_init_codec_list(GtkTreeView *listview){ - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - GtkTreeSelection *select; - GValue editable = {0}; - - GtkListStore *store = gtk_list_store_new (CODEC_NCOLUMNS, G_TYPE_STRING,G_TYPE_INT, - G_TYPE_FLOAT, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_POINTER, - G_TYPE_STRING, - G_TYPE_STRING); - - gtk_tree_view_set_model(listview,GTK_TREE_MODEL(store)); - g_object_unref(G_OBJECT(store)); - - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Name"), - renderer, - "text", CODEC_NAME, - "foreground",CODEC_COLOR, - NULL); - gtk_tree_view_append_column (listview, column); - column = gtk_tree_view_column_new_with_attributes (_("Rate (Hz)"), - renderer, - "text", CODEC_RATE, - "foreground",CODEC_COLOR, - NULL); - gtk_tree_view_append_column (listview, column); - column = gtk_tree_view_column_new_with_attributes (_("Status"), - renderer, - "text", CODEC_STATUS, - "foreground",CODEC_COLOR, - NULL); - gtk_tree_view_append_column (listview, column); - - g_value_init(&editable, G_TYPE_BOOLEAN); - g_value_set_boolean(&editable, TRUE); - - renderer = gtk_cell_renderer_text_new (); - g_object_set_property(G_OBJECT(renderer), "editable", &editable); - column = gtk_tree_view_column_new_with_attributes ( - _("IP Bitrate (kbit/s)"), - renderer, - "text", CODEC_BITRATE, - "foreground",CODEC_COLOR, - NULL); - g_signal_connect(G_OBJECT(renderer),"edited",G_CALLBACK(bitrate_edited),store); - gtk_tree_view_append_column (listview, column); - - renderer = gtk_cell_renderer_text_new (); - g_object_set_property(G_OBJECT(renderer), "editable", &editable); - column = gtk_tree_view_column_new_with_attributes ( - _("Parameters"), - renderer, - "text", CODEC_PARAMS, - "foreground",CODEC_COLOR, - NULL); - g_signal_connect(G_OBJECT(renderer),"edited",G_CALLBACK(fmtp_edited),store); - gtk_tree_view_append_column (listview, column); - /* Setup the selection handler */ - select = gtk_tree_view_get_selection (listview); - gtk_tree_selection_set_mode (select, GTK_SELECTION_MULTIPLE); -} - - -const char *get_codec_color(LinphoneCore *lc, OrtpPayloadType *pt){ - const gchar *color; - if (linphone_core_check_payload_type_usability(lc,pt)) color="blue"; - else color="red"; - if (!linphone_core_payload_type_enabled(lc,pt)) { - color="grey"; - } - return color; -} - -static void linphone_gtk_show_codecs(GtkTreeView *listview, const bctbx_list_t *codeclist) -{ - const bctbx_list_t *elem; - GtkTreeIter iter; - GtkListStore *store=GTK_LIST_STORE(gtk_tree_view_get_model(listview)); -// GtkTreeSelection *selection; - - gtk_list_store_clear(store); - - for(elem=codeclist; elem!=NULL; elem=elem->next){ - gchar *status; - gint rate; - gfloat bitrate; - const gchar *color; - const char *params=""; - - OrtpPayloadType *pt=(OrtpPayloadType *)elem->data; - - color=get_codec_color(linphone_gtk_get_core(),pt); - if (linphone_core_payload_type_enabled(linphone_gtk_get_core(),pt)) status=_("Enabled"); - else { - status=_("Disabled"); - } - /* get an iterator */ - gtk_list_store_append(store,&iter); - bitrate=(gfloat)linphone_core_get_payload_type_bitrate(linphone_gtk_get_core(),pt); - rate=payload_type_get_rate(pt); - if (pt->recv_fmtp!=NULL) params=pt->recv_fmtp; - gtk_list_store_set(store,&iter, CODEC_NAME,payload_type_get_mime(pt), - CODEC_RATE,rate, - CODEC_BITRATE,bitrate, - CODEC_STATUS,status, - CODEC_PARAMS,params, - CODEC_PRIVDATA,(gpointer)pt, - CODEC_COLOR,(gpointer)color, - CODEC_INFO,(gpointer)linphone_core_get_payload_type_description(linphone_gtk_get_core(),pt), - -1); - } - - - - /* Setup the selection handler */ -// selection = gtk_tree_view_get_selection (listview); -// gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - //gtk_tree_view_columns_autosize(GTK_TREE_VIEW (sec->interfaces)); -#if GTK_CHECK_VERSION(2,12,0) - gtk_tree_view_set_tooltip_column(listview,CODEC_INFO); -#endif -} - -static void linphone_gtk_check_codec_bandwidth(GtkTreeView *v){ - GtkTreeIter iter; - GtkTreeModel *model; - model=gtk_tree_view_get_model(v); - g_return_if_fail(gtk_tree_model_get_iter_first(model,&iter)); - do{ - PayloadType *pt=NULL; - - gfloat bitrate; - gtk_tree_model_get(model,&iter,CODEC_PRIVDATA,&pt,-1); - - bitrate=(gfloat)linphone_core_get_payload_type_bitrate(linphone_gtk_get_core(),pt); - gtk_list_store_set(GTK_LIST_STORE(model),&iter,CODEC_COLOR, (gpointer)get_codec_color(linphone_gtk_get_core(),pt), - CODEC_BITRATE, bitrate,-1); - }while(gtk_tree_model_iter_next(model,&iter)); -} - -static void linphone_gtk_select_codec(GtkTreeView *v, PayloadType *ref){ - GtkTreeIter iter; - GtkTreeModel *model; - GtkTreeSelection *selection; - selection=gtk_tree_view_get_selection(v); - model=gtk_tree_view_get_model(v); - g_return_if_fail(gtk_tree_model_get_iter_first(model,&iter)); - do{ - PayloadType *pt=NULL; - gtk_tree_model_get(model,&iter,CODEC_PRIVDATA,&pt,-1); - if (pt==ref){ - gtk_tree_selection_select_iter(selection,&iter); - } - - }while(gtk_tree_model_iter_next(model,&iter)); -} - -static void linphone_gtk_draw_codec_list(GtkTreeView *v, int type){ /* 0=audio, 1=video*/ - const bctbx_list_t *list; - if (type==0) list=linphone_core_get_audio_codecs(linphone_gtk_get_core()); - else list=linphone_core_get_video_codecs(linphone_gtk_get_core()); - linphone_gtk_show_codecs(v,list); -} - -void linphone_gtk_download_bw_changed(GtkWidget *w){ - GtkTreeView *audiov=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"audio_codec_list")); - GtkTreeView *videov=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"video_codec_list")); - linphone_core_set_download_bandwidth(linphone_gtk_get_core(), - (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w))); - linphone_gtk_check_codec_bandwidth(audiov); - linphone_gtk_check_codec_bandwidth(videov); -} - -void linphone_gtk_upload_bw_changed(GtkWidget *w){ - GtkTreeView *audiov=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"audio_codec_list")); - GtkTreeView *videov=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(w),"video_codec_list")); - linphone_core_set_upload_bandwidth(linphone_gtk_get_core(), - (int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w))); - linphone_gtk_check_codec_bandwidth(audiov); - linphone_gtk_check_codec_bandwidth(videov); -} - -void linphone_gtk_video_framerate_changed(GtkWidget *w) { - linphone_core_set_preferred_framerate(linphone_gtk_get_core(), - (float)(int)gtk_spin_button_get_value(GTK_SPIN_BUTTON(w))); -} - -void linphone_gtk_adaptive_rate_control_toggled(GtkToggleButton *button){ - gboolean active=gtk_toggle_button_get_active(button); - linphone_core_enable_adaptive_rate_control(linphone_gtk_get_core(),active); -} - -static void _g_list_func_destroy_tree_path(gpointer data, gpointer user_data) { - GtkTreePath *tree_path = (GtkTreePath *)data; - gtk_tree_path_free(tree_path); -} - -static void linphone_gtk_codec_move(GtkWidget *button, int dir, int type){ /* 0=audio, 1=video*/ - GtkTreeView *v; - GtkTreeSelection *sel; - GtkTreeModel *mod; - GtkTreeIter iter; - PayloadType *pt=NULL; - LinphoneCore *lc=linphone_gtk_get_core(); - - if (type == 0) v=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"audio_codec_list")); - else v=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"video_codec_list")); - sel=gtk_tree_view_get_selection(v); - if (gtk_tree_selection_count_selected_rows(sel) == 1){ - bctbx_list_t *sel_elem,*before; - bctbx_list_t *codec_list; - - GList *selected_rows = gtk_tree_selection_get_selected_rows(sel, &mod); - gtk_tree_model_get_iter(mod, &iter, (GtkTreePath *)g_list_nth_data(selected_rows, 0)); - gtk_tree_model_get(mod,&iter,CODEC_PRIVDATA,&pt,-1); - g_list_foreach(selected_rows, _g_list_func_destroy_tree_path, NULL); - g_list_free(selected_rows); - - if (pt->type==PAYLOAD_VIDEO) - codec_list=bctbx_list_copy(linphone_core_get_video_codecs(lc)); - else codec_list=bctbx_list_copy(linphone_core_get_audio_codecs(lc)); - sel_elem=bctbx_list_find(codec_list,pt); - if (dir>0) { - if (sel_elem->prev) before=sel_elem->prev; - else before=sel_elem; - codec_list=bctbx_list_insert(codec_list,before,pt); - } - else{ - if (sel_elem->next) before=sel_elem->next->next; - else before=sel_elem; - codec_list=bctbx_list_insert(codec_list,before,pt); - } - codec_list=bctbx_list_erase_link(codec_list,sel_elem); - if (pt->type==PAYLOAD_VIDEO) - linphone_core_set_video_codecs(lc,codec_list); - else linphone_core_set_audio_codecs(lc,codec_list); - linphone_gtk_show_codecs(v,codec_list); - linphone_gtk_select_codec(v,pt); - } -} - -static void linphone_gtk_codec_set_enable(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data) { - PayloadType *pt=NULL; - gboolean *enabled = (gboolean *)data; - gtk_tree_model_get(model, iter, CODEC_PRIVDATA, &pt, -1); - linphone_core_enable_payload_type(linphone_gtk_get_core(), pt, *enabled); - gtk_list_store_set(GTK_LIST_STORE(model), iter, CODEC_STATUS, *enabled ? _("Enabled") : _("Disabled"), - CODEC_COLOR,(gpointer)get_codec_color(linphone_gtk_get_core(),pt), -1); -} - -static void linphone_gtk_codec_set_enable_all_selected(GtkWidget *button, gboolean enabled, int type){ /* 0=audio, 1=video*/ - GtkTreeView *v; - GtkTreeSelection *sel; - if (type == 0) v=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"audio_codec_list")); - else v=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"video_codec_list")); - sel=gtk_tree_view_get_selection(v); - gtk_tree_selection_selected_foreach(sel, linphone_gtk_codec_set_enable, &enabled); - if (type == 0){ - /*activating audio and video codecs has consequences on video bandwidth*/ - GtkTreeView *videov=GTK_TREE_VIEW(linphone_gtk_get_widget(gtk_widget_get_toplevel(button),"video_codec_list")); - linphone_gtk_check_codec_bandwidth(videov); - } -} - -void linphone_gtk_audio_codec_up(GtkWidget *button){ - linphone_gtk_codec_move(button,+1,0); -} - -void linphone_gtk_audio_codec_down(GtkWidget *button){ - linphone_gtk_codec_move(button,-1,0); -} - -void linphone_gtk_audio_codec_enable(GtkWidget *button){ - linphone_gtk_codec_set_enable_all_selected(button,TRUE,0); -} - -void linphone_gtk_audio_codec_disable(GtkWidget *button){ - linphone_gtk_codec_set_enable_all_selected(button,FALSE,0); -} - -void linphone_gtk_video_codec_up(GtkWidget *button){ - linphone_gtk_codec_move(button,+1,1); -} - -void linphone_gtk_video_codec_down(GtkWidget *button){ - linphone_gtk_codec_move(button,-1,1); -} - -void linphone_gtk_video_codec_enable(GtkWidget *button){ - linphone_gtk_codec_set_enable_all_selected(button,TRUE,1); -} - -void linphone_gtk_video_codec_disable(GtkWidget *button){ - linphone_gtk_codec_set_enable_all_selected(button,FALSE,1); -} - -void linphone_gtk_clear_passwords(GtkWidget *button){ - linphone_core_clear_all_auth_info(linphone_gtk_get_core()); -} - -enum{ - PROXY_CONFIG_IDENTITY, - PROXY_CONFIG_REF, - PROXY_CONFIG_NCOL -}; - -void linphone_gtk_show_sip_accounts(GtkWidget *w){ - GtkTreeView *v=GTK_TREE_VIEW(linphone_gtk_get_widget(w,"proxy_list")); - GtkTreeModel *model=gtk_tree_view_get_model(v); - GtkListStore *store; - GtkTreeSelection *select; - const LinphoneProxyConfig *default_pc = linphone_core_get_default_proxy_config(linphone_gtk_get_core()); - GtkTreePath *default_pc_path = NULL; - - const bctbx_list_t *elem; - if (!model){ - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - /* create the proxy list */ - store = gtk_list_store_new (PROXY_CONFIG_NCOL, G_TYPE_STRING, G_TYPE_POINTER); - - gtk_tree_view_set_model(v,GTK_TREE_MODEL(store)); - g_object_unref(G_OBJECT(store)); - renderer = gtk_cell_renderer_text_new (); - column = gtk_tree_view_column_new_with_attributes (_("Account"), - renderer, - "text", PROXY_CONFIG_IDENTITY, - NULL); - gtk_tree_view_append_column (v, column); - - select = gtk_tree_view_get_selection (v); - gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE); - model=GTK_TREE_MODEL(store); - }else { - store=GTK_LIST_STORE(model); - } - gtk_list_store_clear(store); - for(elem=linphone_core_get_proxy_config_list(linphone_gtk_get_core());elem!=NULL;elem=bctbx_list_next(elem)){ - LinphoneProxyConfig *cfg=(LinphoneProxyConfig*)elem->data; - GtkTreeIter iter; - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,PROXY_CONFIG_IDENTITY,linphone_proxy_config_get_identity(cfg), - PROXY_CONFIG_REF,cfg,-1); - if(cfg == default_pc) default_pc_path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); - } - if(default_pc_path) { - gtk_tree_selection_select_path(gtk_tree_view_get_selection(v), default_pc_path); - gtk_tree_path_free(default_pc_path); - } -} - -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){ - if (was_editing){ - linphone_proxy_config_done(cfg); - }else linphone_proxy_config_destroy(cfg); - } -} - -static void fill_transport_combo_box(GtkWidget *combo, LinphoneTransportType choice, gboolean is_sensitive){ - GtkTreeModel *model; - GtkTreeIter iter; - - if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(combo),"combo-updating"))) return; - - if ((model=gtk_combo_box_get_model(GTK_COMBO_BOX(combo)))==NULL){ - /*case where combo box is created with no model*/ - GtkCellRenderer *renderer=gtk_cell_renderer_text_new(); - model=GTK_TREE_MODEL(gtk_list_store_new(1,G_TYPE_STRING)); - gtk_combo_box_set_model(GTK_COMBO_BOX(combo),model); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo),renderer,TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),renderer,"markup",0,NULL); - } - if (!gtk_tree_model_get_iter_first(model,&iter)){ - gtk_list_store_append(GTK_LIST_STORE(model),&iter); - gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,"UDP",-1); - gtk_list_store_append(GTK_LIST_STORE(model),&iter); - gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,"TCP",-1); - if (linphone_core_sip_transport_supported(linphone_gtk_get_core(),LinphoneTransportTls)){ - gtk_list_store_append(GTK_LIST_STORE(model),&iter); - gtk_list_store_set(GTK_LIST_STORE(model),&iter,0,"TLS",-1); - } - } - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),(int)choice); - gtk_widget_set_sensitive(combo,is_sensitive); -} - -static void update_proxy_transport(GtkWidget *w){ - const char *addr=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy"))); - LinphoneAddress *laddr=linphone_address_new(addr); - if (laddr){ - GtkWidget *combo=linphone_gtk_get_widget(w,"transport"); - if (linphone_address_is_secure(laddr)){ - fill_transport_combo_box(combo,LinphoneTransportTls,FALSE); - }else{ - fill_transport_combo_box(combo,linphone_address_get_transport(laddr),TRUE); - } - linphone_address_unref(laddr); - } -} - -void linphone_gtk_proxy_transport_changed(GtkWidget *combo){ - GtkWidget *w=gtk_widget_get_toplevel(combo); - int index=gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); - GtkWidget *proxy=linphone_gtk_get_widget(w,"proxy"); - const char *addr=gtk_entry_get_text(GTK_ENTRY(proxy)); - LinphoneAddress *laddr; - LinphoneTransportType new_transport=(LinphoneTransportType)index; - - if (index==-1) return; - - g_object_set_data(G_OBJECT(w),"combo-updating",GINT_TO_POINTER(1)); - laddr=linphone_address_new(addr); - if (laddr){ - if (linphone_address_get_transport(laddr)!=new_transport){ - char *newaddr; - linphone_address_set_transport(laddr,new_transport); - newaddr=linphone_address_as_string(laddr); - gtk_entry_set_text(GTK_ENTRY(proxy),newaddr); - ms_free(newaddr); - } - linphone_address_unref(laddr); - } - g_object_set_data(G_OBJECT(w),"combo-updating",GINT_TO_POINTER(0)); -} - -void linphone_gtk_proxy_address_changed(GtkEditable *editable){ - update_proxy_transport(gtk_widget_get_toplevel(GTK_WIDGET(editable))); -} - -void linphone_gtk_show_proxy_config(GtkWidget *pb, LinphoneProxyConfig *cfg){ - GtkWidget *w=linphone_gtk_create_window("sip_account", gtk_widget_get_toplevel(pb)); - const char *tmp; - 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)); - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy")),linphone_proxy_config_get_addr(cfg)); - tmp=linphone_proxy_config_get_route(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)); - - 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); - gtk_widget_show(w); -} - -void linphone_gtk_proxy_cancel(GtkButton *button){ - GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button)); - gtk_widget_destroy(w); -} - -void linphone_gtk_proxy_ok(GtkButton *button){ - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(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=! GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"is_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, - gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"proxy"))))==0){ - if (index!=-1){ - /*make sure transport was added to proxy address*/ - LinphoneAddress *laddr=linphone_address_new(linphone_proxy_config_get_addr(cfg)); - if (laddr){ - if (linphone_address_get_transport(laddr)!=tport){ - char *tmp; - linphone_address_set_transport(laddr,tport); - tmp=linphone_address_as_string(laddr); - linphone_proxy_config_set_server_addr(cfg,tmp); - ms_free(tmp); - } - linphone_address_unref(laddr); - } - } - } - linphone_proxy_config_set_route(cfg, - gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"route")))); - linphone_proxy_config_set_contact_parameters(cfg, - gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"params")))); - linphone_proxy_config_set_expires(cfg, - (int)gtk_spin_button_get_value( - GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"regperiod")))); - linphone_proxy_config_enable_publish(cfg, - gtk_toggle_button_get_active( - GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"publish")))); - linphone_proxy_config_enable_register(cfg, - gtk_toggle_button_get_active( - GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"register")))); - linphone_proxy_config_enable_avpf(cfg, - gtk_toggle_button_get_active( - GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"avpf")))); - linphone_proxy_config_set_avpf_rr_interval(cfg, - (int)gtk_spin_button_get_value( - GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"avpf_rr_interval")))); - - /* check if tls was asked but is not enabled in transport configuration*/ - if (tport==LinphoneTransportTls){ - LCSipTransports tports; - linphone_core_get_sip_transports(lc,&tports); - if (tports.tls_port==LC_SIP_TRANSPORT_DISABLED){ - tports.tls_port=LC_SIP_TRANSPORT_RANDOM; - } - linphone_core_set_sip_transports(lc,&tports); - } - - if (was_editing){ - if (linphone_proxy_config_done(cfg)==-1) - return; - } - else { - if (linphone_core_add_proxy_config(linphone_gtk_get_core(),cfg)==-1) return; - linphone_core_set_default_proxy(linphone_gtk_get_core(),cfg); - } - g_object_set_data(G_OBJECT(w),"config",NULL); - linphone_gtk_show_sip_accounts(GTK_WIDGET(g_object_get_data(G_OBJECT(w),"parameters"))); - gtk_widget_destroy(w); - /* also update the main window's list of identities*/ - linphone_gtk_load_identities(); -} - -static LinphoneProxyConfig *linphone_gtk_get_selected_proxy_config(GtkWidget* pb){ - GtkTreeView *v=GTK_TREE_VIEW(linphone_gtk_get_widget(pb,"proxy_list")); - GtkTreeSelection *selection=gtk_tree_view_get_selection(v); - GtkTreeIter iter; - GtkTreeModel *model; - if (gtk_tree_selection_get_selected(selection,&model,&iter)){ - LinphoneProxyConfig *cfg=NULL; - gtk_tree_model_get(model,&iter,PROXY_CONFIG_REF,&cfg,-1); - return cfg; - } - return NULL; -} - -void linphone_gtk_add_proxy(GtkButton *button){ - linphone_gtk_show_proxy_config(gtk_widget_get_toplevel(GTK_WIDGET(button)),NULL); -} - -void linphone_gtk_remove_proxy(GtkButton *button){ - LinphoneProxyConfig *cfg=linphone_gtk_get_selected_proxy_config( - gtk_widget_get_toplevel(GTK_WIDGET(button))); - if (cfg){ - linphone_core_remove_proxy_config(linphone_gtk_get_core(),cfg); - linphone_gtk_show_sip_accounts(gtk_widget_get_toplevel(GTK_WIDGET(button))); - /* also update the main window's list of identities*/ - linphone_gtk_load_identities(); - } -} - -void linphone_gtk_edit_proxy(GtkButton *button){ - GtkWidget *pb=gtk_widget_get_toplevel(GTK_WIDGET(button)); - LinphoneProxyConfig *cfg=linphone_gtk_get_selected_proxy_config(pb); - if (cfg){ - linphone_gtk_show_proxy_config(pb,cfg); - /* also update the main window's list of identities*/ - linphone_gtk_load_identities(); - } -} - -typedef struct _LangCodes{ - const char *code; - const char *name; -}LangCodes; - -static LangCodes supported_langs[]={ - { "C" , N_("English") }, - { "fr" , N_("French") }, - { "sv" , N_("Swedish") }, - { "it" , N_("Italian") }, - { "es" , N_("Spanish") }, - { "pt_BR" , N_("Brazilian Portugese") }, - { "pl" , N_("Polish") }, - { "de" , N_("German") }, - { "ru" , N_("Russian") }, - { "ja" , N_("Japanese") }, - { "nl" , N_("Dutch") }, - { "hu" , N_("Hungarian") }, - { "cs" , N_("Czech") }, - { "zh_CN" , N_("Chinese") }, - { "zh_TW" , N_("Traditional Chinese") }, - { "nb_NO" , N_("Norwegian") }, - { "he" , N_("Hebrew") }, - { "sr" , N_("Serbian") }, - { "ar" , N_("Arabic") }, - { "tr" , N_("Turkish") }, - { "fi" , N_("Finnish") }, - { "lt" , N_("Lithuanian") }, - { NULL , NULL } -}; - -static const char *lang_get_name(const char *code){ - LangCodes *p=supported_langs; - while(p->code!=NULL){ - if (strcmp(p->code,code)==0) return p->name; - p++; - } - return NULL; -} - -static gboolean lang_equals(const char *l1, const char *l2){ - return ((strncmp(l1,l2,5)==0 || strncmp(l1,l2,2)==0)); -} - -static void linphone_gtk_fill_langs(GtkWidget *pb){ - GtkWidget *combo=linphone_gtk_get_widget(pb,"lang_combo"); - char code[10]; - 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 = g_getenv("LANGUAGE"); - 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. - This dummy text needs to be removed first*/ - gtk_combo_box_remove_text(GTK_COMBO_BOX(combo),0); - while(sscanf(all_langs+i,"%s",code)==1){ - i+=strlen(code); - while(all_langs[i]==' ') ++i; - name=lang_get_name(code); - snprintf(text,sizeof(text)-1,"%s : %s",code,name!=NULL ? _(name) : code); - gtk_combo_box_append_text(GTK_COMBO_BOX(combo),text); - if (cur_lang_index==-1 && lang_equals(cur_lang,code)) - cur_lang_index=index; - index++; - } - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),cur_lang_index); -} - -void linphone_gtk_lang_changed(GtkComboBox *combo){ - const char *selected=gtk_combo_box_get_active_text(combo); - char code[10]; - const char *cur_lang=g_getenv("LANGUAGE"); - if (selected!=NULL){ - sscanf(selected,"%s",code); - if (cur_lang==NULL) cur_lang="C"; - if (!lang_equals(cur_lang,code)){ - GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(combo))), - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_INFO, - GTK_BUTTONS_CLOSE, - "%s", - (const gchar*)_("You need to restart linphone for the new language selection to take effect.")); - /* Destroy the dialog when the user responds to it (e.g. clicks a button) */ - g_signal_connect_swapped (G_OBJECT (dialog), "response", - G_CALLBACK (gtk_widget_destroy), - G_OBJECT (dialog)); - gtk_widget_show(dialog); - linphone_gtk_set_lang(code); - } - } -} - -static void linphone_gtk_ui_level_adapt(GtkWidget *top) { - gboolean ui_advanced; - const char *simple_ui = linphone_gtk_get_ui_config("simple_ui", "parameters.codec_tab parameters.transport_frame parameters.ports_frame parameters.bandwidth_frame"); - - ui_advanced = linphone_gtk_get_ui_config_int("advanced_ui", FALSE); - if (ui_advanced) { - linphone_gtk_visibility_set(simple_ui, "parameters", top, TRUE); - } else { - linphone_gtk_visibility_set(simple_ui, "parameters", top, FALSE); - } -} - -void linphone_gtk_ui_level_toggled(GtkWidget *w) { - gint ui_advanced; - GtkWidget *top; - - top = gtk_widget_get_toplevel(w); - ui_advanced = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)); - linphone_gtk_set_ui_config_int("advanced_ui", ui_advanced); - linphone_gtk_ui_level_adapt(top); -} - -static void linphone_gtk_set_media_encryption_mandatory_sensitive(GtkWidget *propbox, gboolean val){ - GtkWidget *w=linphone_gtk_get_widget(propbox,"media_encryption_mandatory_checkbox"); - gtk_widget_set_sensitive(w,val); -} - -static void linphone_gtk_media_encryption_changed(GtkWidget *combo){ - char *selected=gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo)); - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *toplevel=gtk_widget_get_toplevel(combo); - GtkWidget *mandatory_box = linphone_gtk_get_widget(toplevel,"media_encryption_mandatory_checkbox"); - if (selected!=NULL){ - if (strcasecmp(selected,"SRTP")==0){ - linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionSRTP); - gtk_widget_set_sensitive(mandatory_box,TRUE); - }else if (strcasecmp(selected,"DTLS")==0){ - linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionDTLS); - gtk_widget_set_sensitive(mandatory_box,TRUE); - }else if (strcasecmp(selected,"ZRTP")==0){ - linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionZRTP); - gtk_widget_set_sensitive(mandatory_box,TRUE); - } else { - linphone_core_set_media_encryption(lc,LinphoneMediaEncryptionNone); - gtk_widget_set_sensitive(mandatory_box,FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(mandatory_box), FALSE); - } - g_free(selected); - }else g_warning("gtk_combo_box_get_active_text() returned NULL"); -} - -void linphone_gtk_set_media_encryption_mandatory(GtkWidget *button){ - linphone_core_set_media_encryption_mandatory(linphone_gtk_get_core(),gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))); -} - -void linphone_gtk_lime_changed(GtkComboBoxText *combotext) { - linphone_core_enable_lime(linphone_gtk_get_core(), gtk_combo_box_get_active(GTK_COMBO_BOX(combotext))); -} - -static void linphone_gtk_show_media_encryption(GtkWidget *pb){ - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *combo=linphone_gtk_get_widget(pb,"media_encryption_combo"); - bool_t no_enc=TRUE; - int srtp_id=-1,zrtp_id=-1,dtls_id=-1; - GtkTreeModel *model; - GtkListStore *store; - GtkTreeIter iter; - GtkCellRenderer *renderer=gtk_cell_renderer_text_new(); - - model=GTK_TREE_MODEL((store=gtk_list_store_new(1,G_TYPE_STRING))); - gtk_combo_box_set_model(GTK_COMBO_BOX(combo),model); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo),renderer,TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),renderer,"text",0,NULL); - - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,0,_("None"),-1); - - if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionSRTP)){ - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,0,_("SRTP"),-1); - srtp_id=1; - no_enc=FALSE; - } - if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionDTLS)){ - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,0,_("DTLS"),-1); - if (srtp_id!=-1) dtls_id=2; - else dtls_id=1; - no_enc=FALSE; - } - if (linphone_core_media_encryption_supported(lc,LinphoneMediaEncryptionZRTP)){ - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,0,_("ZRTP"),-1); - no_enc=FALSE; - if (srtp_id!=-1) { - if (dtls_id!=-1) - zrtp_id=3; - else zrtp_id=2; - } else { - if (dtls_id!=-1) - zrtp_id=2; - else zrtp_id=1; - } - } - if (no_enc){ - /*hide this setting*/ - gtk_widget_hide(linphone_gtk_get_widget(pb,"encryption_label")); - gtk_widget_hide(linphone_gtk_get_widget(pb,"encryption_table")); - }else{ - LinphoneMediaEncryption menc=linphone_core_get_media_encryption(lc); - gtk_widget_show(linphone_gtk_get_widget(pb,"encryption_label")); - gtk_widget_show(linphone_gtk_get_widget(pb,"encryption_table")); - - switch(menc){ - case LinphoneMediaEncryptionNone: - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),0); - linphone_gtk_set_media_encryption_mandatory_sensitive(pb,FALSE); - break; - case LinphoneMediaEncryptionSRTP: - if (srtp_id!=-1) { - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),srtp_id); - linphone_gtk_set_media_encryption_mandatory_sensitive(pb,TRUE); - } - break; - case LinphoneMediaEncryptionDTLS: - if (dtls_id!=-1) { - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),dtls_id); - linphone_gtk_set_media_encryption_mandatory_sensitive(pb,TRUE); - } - break; - case LinphoneMediaEncryptionZRTP: - if (zrtp_id!=-1) { - gtk_combo_box_set_active(GTK_COMBO_BOX(combo),zrtp_id); - linphone_gtk_set_media_encryption_mandatory_sensitive(pb,TRUE); - } - break; - } - g_signal_connect(G_OBJECT(combo),"changed",(GCallback)linphone_gtk_media_encryption_changed,NULL); - } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"media_encryption_mandatory_checkbox")), - linphone_core_is_media_encryption_mandatory(lc)); - - gtk_combo_box_set_active(GTK_COMBO_BOX(linphone_gtk_get_widget(pb,"chat_lime_combo")), linphone_core_lime_enabled(lc)); - gtk_widget_set_sensitive(linphone_gtk_get_widget(pb,"chat_lime_combo"), linphone_core_lime_available(lc)); - - g_object_unref(G_OBJECT(model)); -} - -void linphone_gtk_parameters_destroyed(GtkWidget *pb){ - GtkWidget *mw=linphone_gtk_get_main_window(); - g_object_set_data(G_OBJECT(mw),"parameters",NULL); -} - -void linphone_gtk_fill_soundcards(GtkWidget *pb){ - LinphoneCore *lc=linphone_gtk_get_core(); - const char **sound_devices=linphone_core_get_sound_devices(lc); - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"playback_device"), sound_devices, - linphone_core_get_playback_device(lc),CAP_PLAYBACK); - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"ring_device"), sound_devices, - linphone_core_get_ringer_device(lc),CAP_PLAYBACK); - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"capture_device"), sound_devices, - linphone_core_get_capture_device(lc), CAP_CAPTURE); -} - -void linphone_gtk_fill_webcams(GtkWidget *pb){ -#ifdef VIDEO_ENABLED - LinphoneCore *lc=linphone_gtk_get_core(); - linphone_gtk_fill_combo_box(linphone_gtk_get_widget(pb,"webcams"),linphone_core_get_video_devices(lc), - linphone_core_get_video_device(lc),CAP_IGNORE); -#endif -} - -void linphone_gtk_fill_video_renderers(GtkWidget *pb){ -#ifdef VIDEO_ENABLED /* video_stream_get_default_video_renderer requires video enabled */ - LinphoneCore *lc=linphone_gtk_get_core(); - MSFactory *factory = linphone_core_get_ms_factory(lc); - GtkWidget *combo=linphone_gtk_get_widget(pb,"renderers"); - bctbx_list_t *l=ms_factory_lookup_filter_by_interface(factory, MSFilterVideoDisplayInterface); - bctbx_list_t *elem; - int i; - int active=-1; - const char *current_renderer=linphone_core_get_video_display_filter(lc); - GtkListStore *store; - GtkCellRenderer *renderer=gtk_cell_renderer_text_new(); - GtkTreeModel *model=GTK_TREE_MODEL(store=gtk_list_store_new(2,G_TYPE_STRING,G_TYPE_STRING)); - - if (current_renderer==NULL) current_renderer=video_stream_get_default_video_renderer(); - - gtk_combo_box_set_model(GTK_COMBO_BOX(combo),model); - gtk_cell_layout_clear(GTK_CELL_LAYOUT(combo)); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo),renderer,TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo),renderer,"text",1,NULL); - - for(i=0,elem=l;elem!=NULL && i<4 ;elem=elem->next){ - MSFilterDesc *desc=(MSFilterDesc *)elem->data; - GtkTreeIter iter; - - /* do not offer the user to select combo 'decoding/rendering' filter */ - if (desc->enc_fmt != NULL || (desc->flags & MS_FILTER_IS_ENABLED) == 0) - continue; - - gtk_list_store_append(store,&iter); - gtk_list_store_set(store,&iter,0,desc->name,1,desc->text,-1); - if (current_renderer && strcmp(current_renderer,desc->name)==0) - active=i; - - i++; - } - bctbx_list_free(l); - if (active!=-1) gtk_combo_box_set_active(GTK_COMBO_BOX(combo),active); -#endif -} - -void linphone_gtk_fill_video_presets(GtkWidget *pb) { - GtkComboBox *combo = GTK_COMBO_BOX(linphone_gtk_get_widget(pb, "video_preset")); - const char *preset = linphone_core_get_video_preset(linphone_gtk_get_core()); - if (preset == NULL) { - gtk_combo_box_set_active(combo, -1); - gtk_combo_box_set_active(combo, 0); - } else { - gboolean valid; - GtkTreeIter iter; - gchar *str_data; - GtkTreeModel *model = gtk_combo_box_get_model(combo); - valid = gtk_tree_model_get_iter_first(model, &iter); - while (valid) { - gtk_tree_model_get(model, &iter, 0, &str_data, -1); - if (g_strcmp0(preset, str_data) == 0) { - gtk_combo_box_set_active_iter(combo, &iter); - break; - } - valid = gtk_tree_model_iter_next(model, &iter); - } - } -} - -typedef struct { - guint timeout_id; - LCSipTransports tp; -}PortConfigCtx; - -static void port_config_free(PortConfigCtx *ctx){ - g_free(ctx); -} - -static gboolean apply_transports(PortConfigCtx *ctx){ - GtkWidget *mw=linphone_gtk_get_main_window(); - LCSipTransports tp; - LinphoneCore *lc=linphone_gtk_get_core(); - linphone_core_get_sip_transports(lc,&tp); - tp.udp_port=ctx->tp.udp_port; - tp.tcp_port=ctx->tp.tcp_port; - linphone_core_set_sip_transports(lc,&tp); - g_object_set_data(G_OBJECT(mw),"port_config",NULL); - return FALSE; -} - -static PortConfigCtx* get_port_config(void) { - GtkWidget *mw=linphone_gtk_get_main_window(); - PortConfigCtx *cfg=(PortConfigCtx*)g_object_get_data(G_OBJECT(mw),"port_config"); - if (cfg==NULL){ - cfg=g_new0(PortConfigCtx,1); - g_object_set_data_full(G_OBJECT(mw),"port_config",cfg,(GDestroyNotify)port_config_free); - } - if (cfg->timeout_id!=0) { - g_source_remove(cfg->timeout_id); - } - cfg->timeout_id=g_timeout_add_seconds(2,(GSourceFunc)apply_transports,cfg); - return cfg; -} - -static void transport_changed(GtkWidget *parameters){ - PortConfigCtx *cfg = get_port_config(); - - GtkWidget *udp_random_port=linphone_gtk_get_widget(parameters,"random_udp_port"); - GtkWidget *tcp_random_port=linphone_gtk_get_widget(parameters,"random_tcp_port"); - - GtkWidget *sip_udp_port=linphone_gtk_get_widget(parameters,"sip_udp_port"); - GtkWidget *sip_tcp_port=linphone_gtk_get_widget(parameters,"sip_tcp_port"); - - gboolean udp_is_disabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(parameters,"disabled_udp_port"))); - gboolean tcp_is_disabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(parameters,"disabled_tcp_port"))); - - gboolean udp_is_random=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(udp_random_port)); - gboolean tcp_is_random=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tcp_random_port)); - - int udp_port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sip_udp_port)); - int tcp_port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sip_tcp_port)); - - - gtk_widget_set_sensitive(udp_random_port, !udp_is_disabled); - gtk_widget_set_sensitive(tcp_random_port, !tcp_is_disabled); - gtk_widget_set_sensitive(sip_udp_port, !udp_is_disabled && !udp_is_random); - gtk_widget_set_sensitive(sip_tcp_port, !tcp_is_disabled && !tcp_is_random); - - cfg->tp.udp_port=udp_is_disabled?0:udp_is_random?-1:udp_port; - cfg->tp.tcp_port=tcp_is_disabled?0:tcp_is_random?-1:tcp_port; -} - -void linphone_gtk_disabled_udp_port_toggle(GtkCheckButton *button){ - GtkWidget *parameters = gtk_widget_get_toplevel((GtkWidget*)button); - transport_changed(parameters); -} - -void linphone_gtk_random_udp_port_toggle(GtkCheckButton *button){ - GtkWidget *parameters = gtk_widget_get_toplevel((GtkWidget*)button); - transport_changed(parameters); -} - -void linphone_gtk_udp_port_value_changed(GtkSpinButton *button){ - GtkWidget *parameters = gtk_widget_get_toplevel((GtkWidget*)button); - transport_changed(parameters); -} - -void linphone_gtk_disabled_tcp_port_toggle(GtkCheckButton *button){ - GtkWidget *parameters = gtk_widget_get_toplevel((GtkWidget*)button); - transport_changed(parameters); -} - -void linphone_gtk_random_tcp_port_toggle(GtkCheckButton *button){ - GtkWidget *parameters = gtk_widget_get_toplevel((GtkWidget*)button); - transport_changed(parameters); -} - -void linphone_gtk_tcp_port_value_changed(GtkSpinButton *button){ - GtkWidget *parameters = gtk_widget_get_toplevel((GtkWidget*)button); - transport_changed(parameters); -} - -void linphone_gtk_show_parameters(void){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *pb=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters"); - LinphoneCore *lc=linphone_gtk_get_core(); - const char *tmp; - LinphoneAddress *contact; - LinphoneFirewallPolicy pol; - GtkWidget *audio_codec_list; - GtkWidget *video_codec_list; - int mtu; - int ui_advanced; - LCSipTransports tr; - int min_port = 0, max_port = 0; - - if (pb==NULL) { - pb=linphone_gtk_create_window("parameters", linphone_gtk_get_main_window()); - g_object_set_data(G_OBJECT(mw),"parameters",pb); - }else { - gtk_widget_show(pb); - return; - } - audio_codec_list=linphone_gtk_get_widget(pb,"audio_codec_list"); - video_codec_list=linphone_gtk_get_widget(pb,"video_codec_list"); - - /* NETWORK CONFIG */ - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"ipv6_enabled")), - linphone_core_ipv6_enabled(lc)); - linphone_core_get_sip_transports(lc,&tr); - - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"disabled_udp_port")), tr.udp_port==0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"disabled_tcp_port")), tr.tcp_port==0); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"random_udp_port")), tr.udp_port==-1); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"random_tcp_port")), tr.tcp_port==-1); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"sip_udp_port")), tr.udp_port); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"sip_tcp_port")), tr.tcp_port); - - linphone_core_get_audio_port_range(lc, &min_port, &max_port); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port")), min_port); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_max_rtp_port")), max_port); - if (min_port == max_port) { - gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "audio_max_rtp_port")), FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_audio_port")), TRUE); - } - linphone_core_get_video_port_range(lc, &min_port, &max_port); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_min_rtp_port")), min_port); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_max_rtp_port")), max_port); - if (min_port == max_port) { - gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "video_max_rtp_port")), FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_video_port")), TRUE); - } - - linphone_gtk_show_media_encryption(pb); - - tmp=linphone_core_get_nat_address(lc); - if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"nat_address")),tmp); - tmp=linphone_core_get_stun_server(lc); - if (tmp) gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"stun_server")),tmp); - pol=linphone_core_get_firewall_policy(lc); - switch(pol){ - case LinphonePolicyNoFirewall: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"no_nat")),TRUE); - break; - case LinphonePolicyUseNatAddress: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_nat_address")),TRUE); - break; - case LinphonePolicyUseStun: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_stun")),TRUE); - break; - case LinphonePolicyUseIce: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_ice")),TRUE); - break; - case LinphonePolicyUseUpnp: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"use_upnp")),TRUE); - break; - } - if(!linphone_core_upnp_available()) { - gtk_widget_hide(linphone_gtk_get_widget(pb,"use_upnp")); - } - gtk_widget_hide(linphone_gtk_get_widget(pb, "use_nat_address")); - gtk_widget_hide(linphone_gtk_get_widget(pb, "nat_address")); - gtk_widget_hide(linphone_gtk_get_widget(pb, "nat_address_label")); - - mtu=linphone_core_get_mtu(lc); - if (mtu<=0){ - gtk_widget_set_sensitive(linphone_gtk_get_widget(pb,"mtu"),FALSE); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"mtu")),1500); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"mtu_set")),FALSE); - }else{ - gtk_widget_set_sensitive(linphone_gtk_get_widget(pb,"mtu"),TRUE); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"mtu")),mtu); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"mtu_set")),TRUE); - } - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"dtmf_sipinfo")), - linphone_core_get_use_info_for_dtmf(lc)); - /* MUTIMEDIA CONFIG */ - linphone_gtk_fill_soundcards(pb); - linphone_gtk_fill_webcams(pb); - linphone_gtk_fill_video_renderers(pb); - linphone_gtk_fill_video_presets(pb); - linphone_gtk_fill_video_sizes(linphone_gtk_get_widget(pb,"video_size")); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"video_framerate")), - linphone_core_get_preferred_framerate(lc)); -#ifndef VIDEO_ENABLED - gtk_widget_set_visible(linphone_gtk_get_widget(pb, "camera_preview_button"),FALSE); -#endif - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"echo_cancelation")), - linphone_core_echo_cancellation_enabled(lc)); - - gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(linphone_gtk_get_widget(pb,"ring_chooser")), - linphone_core_get_ring(lc)); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"adaptive_rate_control")), - linphone_core_adaptive_rate_control_enabled(lc)); - /* SIP CONFIG */ - contact=linphone_core_get_primary_contact_parsed(lc); - if (contact){ - if (linphone_address_get_display_name(contact)) { - const char *dn=linphone_address_get_display_name(contact); - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"displayname")),dn); - } - if (linphone_address_get_username(contact)) - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(pb,"username")),linphone_address_get_username(contact)); - linphone_address_unref(contact); - } -#ifdef BUILD_WIZARD - gtk_widget_show(linphone_gtk_get_widget(pb,"wizard")); -#else - gtk_widget_hide(linphone_gtk_get_widget(pb,"wizard")); -#endif - linphone_gtk_show_sip_accounts(pb); - /* CODECS CONFIG */ - linphone_gtk_init_codec_list(GTK_TREE_VIEW(audio_codec_list)); - linphone_gtk_init_codec_list(GTK_TREE_VIEW(video_codec_list)); - linphone_gtk_draw_codec_list(GTK_TREE_VIEW(audio_codec_list), 0); - linphone_gtk_draw_codec_list(GTK_TREE_VIEW(video_codec_list), 1); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"download_bw")), - linphone_core_get_download_bandwidth(lc)); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb,"upload_bw")), - linphone_core_get_upload_bandwidth(lc)); - - /* CALL PARAMS CONFIG */ - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "auto_answer_checkbox")), linphone_gtk_auto_answer_enabled()); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "auto_answer_delay_spinbutton")), linphone_gtk_get_ui_config_int("auto_answer_delay", 2000)); - - /* UI CONFIG */ - linphone_gtk_fill_langs(pb); - ui_advanced = linphone_gtk_get_ui_config_int("advanced_ui", 1); - linphone_gtk_set_ui_config_int("advanced_ui", ui_advanced); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb,"ui_level")), - ui_advanced); - linphone_gtk_ui_level_adapt(pb); - - if (linphone_core_tunnel_available()){ - gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_edit_button")), TRUE); - gtk_widget_set_visible(GTK_WIDGET(linphone_gtk_get_widget(pb,"tunnel_label")), TRUE); - } - - /* LDAP CONFIG */ - if( linphone_gtk_is_ldap_supported() ) { // if LDAP provider is available - linphone_gtk_ldap_display(pb); - } else { - // hide the LDAP tab - GtkNotebook* notebook = GTK_NOTEBOOK(linphone_gtk_get_widget(pb, "notebook1")); - gtk_notebook_remove_page(notebook,5); - } - - gtk_widget_show(pb); -} - - -void linphone_gtk_fixed_audio_port_toggle(void) { - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters"); - gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_audio_port"))); - gint min_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_min_rtp_port"))); - gint max_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "audio_max_rtp_port"))); - gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "audio_max_rtp_port")), !fixed); - if (fixed) { - linphone_core_set_audio_port(linphone_gtk_get_core(), min_port); - } else { - linphone_core_set_audio_port_range(linphone_gtk_get_core(), min_port, max_port); - } -} - - -void linphone_gtk_fixed_video_port_toggle(void) { - GtkWidget *mw = linphone_gtk_get_main_window(); - GtkWidget *pb = (GtkWidget *) g_object_get_data(G_OBJECT(mw), "parameters"); - gboolean fixed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(pb, "fixed_video_port"))); - gint min_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_min_rtp_port"))); - gint max_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(pb, "video_max_rtp_port"))); - gtk_widget_set_sensitive(GTK_WIDGET(linphone_gtk_get_widget(pb, "video_max_rtp_port")), !fixed); - if (fixed) { - linphone_core_set_video_port(linphone_gtk_get_core(), min_port); - } else { - linphone_core_set_video_port_range(linphone_gtk_get_core(), min_port, max_port); - } -} - - -void linphone_gtk_edit_tunnel_closed(GtkWidget *button){ - GtkWidget *pb=gtk_widget_get_toplevel(button); - gtk_widget_destroy(pb); -} - -void linphone_gtk_edit_tunnel(GtkButton *button){ - GtkWidget *w=linphone_gtk_create_window("tunnel_config", gtk_widget_get_toplevel(GTK_WIDGET(button))); - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc); - const bctbx_list_t *configs; - const char *host = NULL; - int port=0; - - if (!tunnel) return; - - configs = linphone_tunnel_get_servers(tunnel); - if(configs != NULL) { - LinphoneTunnelConfig *ltc = (LinphoneTunnelConfig *)configs->data; - host = linphone_tunnel_config_get_host(ltc); - port = linphone_tunnel_config_get_port(ltc); - } - - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host")),host); - if (port==0) port=443; - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port")), port); - - switch(linphone_tunnel_get_mode(tunnel)){ - case LinphoneTunnelModeDisable: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_disable")),1); - break; - case LinphoneTunnelModeEnable: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable")),1); - break; - case LinphoneTunnelModeAuto: - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"tunnel_autodetect")),1); - break; - } - { - const char *proxy=NULL,*username=NULL,*password=NULL; - port=0; - linphone_tunnel_get_http_proxy(tunnel,&proxy,&port,&username,&password); - if (proxy) - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"http_host")),proxy); - if (port>0) - gtk_spin_button_set_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"http_port")), port); - if (username) - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"username")),username); - if (password) - gtk_entry_set_text(GTK_ENTRY(linphone_gtk_get_widget(w,"password")),password); - } - - g_object_weak_ref(G_OBJECT(w),(GWeakNotify)linphone_gtk_edit_tunnel_closed,w); - gtk_widget_show(w); -} - -void linphone_gtk_tunnel_ok(GtkButton *button){ - GtkWidget *w=gtk_widget_get_toplevel(GTK_WIDGET(button)); - LinphoneCore *lc=linphone_gtk_get_core(); - LinphoneTunnel *tunnel=linphone_core_get_tunnel(lc); - LinphoneTunnelConfig *config=linphone_tunnel_config_new(); - - gint port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"port"))); - gboolean enabled=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"radio_enable"))); - gboolean autodetect=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w,"tunnel_autodetect"))); - const char *host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"host"))); - const char *http_host=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"http_host"))); - gint http_port = (gint)gtk_spin_button_get_value(GTK_SPIN_BUTTON(linphone_gtk_get_widget(w,"http_port"))); - const char *username=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"username"))); - const char *password=gtk_entry_get_text(GTK_ENTRY(linphone_gtk_get_widget(w,"password"))); - LinphoneTunnelMode mode = LinphoneTunnelModeDisable; - - if (tunnel==NULL) return; - if (host && *host=='\0') host=NULL; - if (http_port==0) http_port=8080; - linphone_tunnel_clean_servers(tunnel); - linphone_tunnel_config_set_host(config, host); - linphone_tunnel_config_set_port(config, port); - linphone_tunnel_add_server(tunnel, config); - - if (enabled){ - mode = LinphoneTunnelModeEnable; - }else if (autodetect){ - mode = LinphoneTunnelModeAuto; - } - linphone_tunnel_set_mode(tunnel, mode); - linphone_tunnel_set_http_proxy(tunnel,http_host,http_port,username,password); - - gtk_widget_destroy(w); -} - - -void linphone_gtk_tunnel_cancel(GtkButton *button){ - -} - -static void show_dscp(GtkWidget *entry, int val){ - char tmp[20]; - snprintf(tmp,sizeof(tmp),"0x%x",val); - gtk_entry_set_text(GTK_ENTRY(entry),tmp); - -} - -static int read_dscp(GtkWidget *entry){ - const char *val=gtk_entry_get_text(GTK_ENTRY(entry)); - const char *begin; - int ret=0; - if (val==NULL || val[0]=='\0') return 0; - /*skip potential 0x*/ - begin=strstr(val,"0x"); - if (begin) begin+=2; - else begin=val; - if (sscanf(begin,"%x",&ret)==1) - return ret; - return -1; -} - -void linphone_gtk_dscp_edit(void){ - LinphoneCore *lc=linphone_gtk_get_core(); - GtkWidget *widget=linphone_gtk_create_window("dscp_settings", linphone_gtk_get_main_window()); - show_dscp(linphone_gtk_get_widget(widget,"sip_dscp"), - linphone_core_get_sip_dscp(lc)); - show_dscp(linphone_gtk_get_widget(widget,"audio_dscp"), - linphone_core_get_audio_dscp(lc)); - show_dscp(linphone_gtk_get_widget(widget,"video_dscp"), - linphone_core_get_video_dscp(lc)); - gtk_widget_show(widget); -} - -void linphone_gtk_dscp_edit_response(GtkWidget *dialog, guint response_id){ - LinphoneCore *lc=linphone_gtk_get_core(); - switch(response_id){ - case GTK_RESPONSE_OK: - linphone_core_set_sip_dscp(lc, - read_dscp(linphone_gtk_get_widget(dialog,"sip_dscp"))); - linphone_core_set_audio_dscp(lc, - read_dscp(linphone_gtk_get_widget(dialog,"audio_dscp"))); - linphone_core_set_video_dscp(lc, - read_dscp(linphone_gtk_get_widget(dialog,"video_dscp"))); - - break; - default: - break; - } - gtk_widget_destroy(dialog); -} - -void linphone_gtk_enable_auto_answer(GtkToggleButton *checkbox, gpointer user_data) { - gboolean auto_answer_enabled = gtk_toggle_button_get_active(checkbox); - linphone_gtk_set_ui_config_int("auto_answer", auto_answer_enabled ? 1 : 0); -} - -gboolean linphone_gtk_auto_answer_enabled(void) { - return (gboolean)linphone_gtk_get_ui_config_int("auto_answer", 0); -} - -void linphone_gtk_auto_answer_delay_changed(GtkSpinButton *spinbutton, gpointer user_data) { - int delay = (int)gtk_spin_button_get_value(spinbutton); - linphone_gtk_set_ui_config_int("auto_answer_delay", delay); -} - -void linphone_gtk_notebook_current_page_changed (GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data) { -#ifndef HAVE_LIBUDEV_H - if (page_num == 1) { - // Multimedia settings - we reload audio and video devices to detect - // hot-plugged devices - g_message("Opened multimedia page... reloading audio and video devices!"); - linphone_gtk_reload_sound_devices(); - linphone_gtk_reload_video_devices(); - } -#endif -} diff --git a/gtk/provisioning-fetch.ui b/gtk/provisioning-fetch.ui deleted file mode 100644 index e2d6a0203..000000000 --- a/gtk/provisioning-fetch.ui +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - False - 5 - Configuring... - dialog - True - Please wait while fetching configuration from server... - - - True - False - 2 - - - True - False - end - - - - - - - - - False - True - end - 0 - - - - - True - False - - - - - - True - True - 2 - - - - - - diff --git a/gtk/regex.h b/gtk/regex.h deleted file mode 100644 index f5b41d40d..000000000 --- a/gtk/regex.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2015 Belledonne Communications - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* - * Regex matching with any URI that respects the RFC 3986 - */ -#define BC_REGEX_URI_PCT_ENCODED "(%[[:xdigit:]]{2})" -#define BC_REGEX_URI_SUB_DELIMS "[!$&'()*+,;=]" -#define BC_REGEX_URI_UNRESERVED "[[:alnum:]\\-._~]" -#define BC_REGEX_URI_PCHAR "(" BC_REGEX_URI_UNRESERVED "|" BC_REGEX_URI_PCT_ENCODED "|" BC_REGEX_URI_SUB_DELIMS "|" "[:@]" ")" -#define BC_REGEX_URI_SCHEME "(" "[[:alpha:]][[:alnum:]+\\-.]*" ")" -#define BC_REGEX_URI_USERINFO "(" "(" BC_REGEX_URI_UNRESERVED "|" BC_REGEX_URI_PCT_ENCODED "|" BC_REGEX_URI_SUB_DELIMS "|" ":" ")*" ")" -#define BC_REGEX_URI_HOST "(" "(" BC_REGEX_URI_UNRESERVED "|" BC_REGEX_URI_PCT_ENCODED "|" BC_REGEX_URI_SUB_DELIMS ")*" ")" -#define BC_REGEX_URI_PORT "(" "[\\d]*" ")" -#define BC_REGEX_URI_AUTHORITY "(" "(" BC_REGEX_URI_USERINFO "@" ")?" BC_REGEX_URI_HOST "(" ":" BC_REGEX_URI_PORT ")?" ")" -#define BC_REGEX_URI_SEGMENT "(" BC_REGEX_URI_PCHAR "*" ")" -#define BC_REGEX_URI_SEGMENT_NZ "(" BC_REGEX_URI_PCHAR "+" ")" -#define BC_REGEX_URI_PATH_ABEMPTY "(" "(" "/" BC_REGEX_URI_SEGMENT ")*" ")" -#define BC_REGEX_URI_PATH_ABSOLUTE "(" "/" "(" BC_REGEX_URI_SEGMENT_NZ "(" "/" BC_REGEX_URI_SEGMENT ")*" ")?" ")" -#define BC_REGEX_URI_PATH_ROOTLESS "(" BC_REGEX_URI_SEGMENT_NZ "(" "/" BC_REGEX_URI_SEGMENT ")*" ")" -#define BC_REGEX_URI_HIER_PART "(" "//" BC_REGEX_URI_AUTHORITY BC_REGEX_URI_PATH_ABEMPTY "|" BC_REGEX_URI_PATH_ABSOLUTE "|" BC_REGEX_URI_PATH_ROOTLESS ")" -#define BC_REGEX_URI_QUERY "(" "(" BC_REGEX_URI_PCHAR "|" "[/?]" ")*" ")" -#define BC_REGEX_URI_FRAGMENT "(" "(" BC_REGEX_URI_PCHAR "|" "[/?]" ")*" ")" -#define BC_REGEX_URI "(" BC_REGEX_URI_SCHEME ":" BC_REGEX_URI_HIER_PART "(" "\\?" BC_REGEX_URI_QUERY ")?" "(" "#" BC_REGEX_URI_FRAGMENT ")?" ")" - -/* - * Regex matching with any domain name (RFC 1034) - */ -#define BC_REGEX_DOMAIN_LDH "[[:alnum:]-]" -#define BC_REGEX_DOMAIN_LABEL "(" "[[:alpha:]]" "(" BC_REGEX_DOMAIN_LDH "*" "[[:alnum:]]" ")?" ")" -#define BC_REGEX_DOMAIN "(" BC_REGEX_DOMAIN_LABEL "(" "\\." BC_REGEX_DOMAIN_LABEL ")*" ")" - -/* - * Regex matching with email addresses (RFC 5322) - */ -#define BC_REGEX_EMAIL_ATEXT "[[:alnum:]!#$%&'*+\\-/=?\\^_`{}|~]" -#define BC_REGEX_EMAIL_DOT_ATOM_TEXT "(" BC_REGEX_EMAIL_ATEXT "+" "(" "." BC_REGEX_EMAIL_ATEXT "+" ")*" ")" -#define BC_REGEX_EMAIL_LOCAL_PART BC_REGEX_EMAIL_DOT_ATOM_TEXT -#define BC_REGEX_EMAIL_DTEXT_NO_OBS "[!-Z\\^-~]" -#define BC_REGEX_EMAIL_DOMAIN "(" BC_REGEX_EMAIL_DOT_ATOM_TEXT "|" "\\[" BC_REGEX_EMAIL_DTEXT_NO_OBS "*" "\\]" ")" -#define BC_REGEX_EMAIL_ADDR_SPEC "(" BC_REGEX_EMAIL_LOCAL_PART "@" BC_REGEX_EMAIL_DOMAIN ")" - -/* - * Regex matching with email addresses but with more constraints than RFC 5322. - * The additionnal constraints are the folowings: - * + the domain part is a domain name as describe in RFC 1034 - * + the domain part must have two label at least - * + the last label of the domain part must have two letter (without digit and hyphen) at least. - */ -#define BC_REGEX_RESTRICTIVE_EMAIL_TLD "(" "[[:alpha:]]" BC_REGEX_DOMAIN_LDH "*" "[[:alnum:]]" ")" -#define BC_REGEX_RESTRICTIVE_EMAIL_ADDR "(" BC_REGEX_EMAIL_LOCAL_PART "@" "(" BC_REGEX_DOMAIN_LABEL "\\." ")+" BC_REGEX_RESTRICTIVE_EMAIL_TLD ")" diff --git a/gtk/setup_wizard.ui b/gtk/setup_wizard.ui deleted file mode 100644 index 95cdcc4e2..000000000 --- a/gtk/setup_wizard.ui +++ /dev/null @@ -1,736 +0,0 @@ - - - - - - False - 8 - SIP account configuration assistant - False - - - - - - - - - - - - - - - - - - - - - - - - - - - True - False - Welcome! -This assistant will help you to use a SIP account for your calls. - - - intro - Welcome to the account setup assistant - True - - - - - True - False - 20 - 30 - 30 - - - True - False - True - - - Create an account on linphone.org - True - True - False - True - True - - - False - True - 0 - - - - - I have already a linphone.org account and I just want to use it - True - True - False - True - radio_create_account - - - False - True - 1 - - - - - I have already a sip account and I just want to use it - True - True - False - True - radio_create_account - - - False - True - 2 - - - - - I want to specify a remote configuration URI - True - True - False - True - radio_create_account - - - False - True - 3 - - - - - - - Account setup assistant - True - - - - - True - False - 0 - 0 - 0.5 - 30 - 10 - 30 - - - True - False - 6 - 2 - 8 - 4 - - - True - False - 8 - Enter your account information - - - 2 - GTK_FILL - - - - - True - False - 1 - Username* - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - True - - True - False - False - True - True - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - False - 1 - Password* - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - True - False - - True - False - False - True - True - - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - False - 1 - Domain* - - - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - True - - True - False - False - True - True - - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - False - 1 - Proxy - - - 4 - 5 - GTK_FILL - GTK_FILL - - - - - True - True - - True - False - False - True - True - - - - 1 - 2 - 4 - 5 - GTK_FILL - GTK_FILL - - - - - True - False - - - - - - 2 - 5 - 6 - GTK_FILL - - - - - - - confirm - Configure your account (step 1/1) - - - - - True - False - 0 - 0.5 - 30 - 10 - 30 - 30 - - - True - False - 8 - 3 - 2 - 8 - 4 - - - True - False - 8 - Enter your linphone.org username - - - 2 - GTK_FILL - - - - - True - False - 1 - Username: - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - True - - True - False - False - True - True - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - False - 1 - Password: - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - True - False - - True - False - False - True - True - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - - - confirm - Enter your sip username (step 1/1) - - - - - True - False - 0 - 0.5 - 10 - 10 - 30 - 30 - - - True - False - 8 - 7 - 3 - 8 - 4 - - - True - False - (*) Required fields - - - 3 - 8 - - - - - True - False - 1 - Email: (*) - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - True - - True - False - False - True - True - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - False - gtk-no - 3 - - - 2 - 3 - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - 1 - Username: (*) - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - True - - True - False - False - True - True - - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - False - gtk-no - 3 - - - 2 - 3 - 2 - 3 - - - - - - - True - False - 1 - Password: (*) - - - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - True - False - - True - False - False - True - True - - - - 1 - 2 - 3 - 4 - GTK_FILL - - - - - True - False - 1 - Confirm your password: (*) - - - 4 - 5 - GTK_FILL - GTK_FILL - - - - - True - True - False - - True - False - False - True - True - - - - 1 - 2 - 4 - 5 - GTK_FILL - - - - - True - False - gtk-no - 3 - - - 2 - 3 - 3 - 5 - - - - - - - True - False - - - - - - 3 - 5 - 6 - - - - - - - - confirm - Enter account information (step 1/2) - - - - - True - False - Your account is being created, please wait. - - - progress - Account creation in progress - - - - - True - False - Please validate your account by clicking on the link we just sent you by email. -Then come back here and press Next button. - - - Validation (step 2/2) - True - - - - - True - False - Checking if your account is been validated, please wait. - - - progress - Account validation check in progress - True - - - - - True - False - Error, account not validated, username already used or server unreachable. -Please go back and try again. - - - Error - - - - - True - False - Thank you. Your account is now configured and ready for use. - - - summary - Terminating - True - - - - diff --git a/gtk/setupwizard.c b/gtk/setupwizard.c deleted file mode 100644 index 4ea81bac9..000000000 --- a/gtk/setupwizard.c +++ /dev/null @@ -1,360 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" -#include "regex.h" -#include -#include - -static const int PASSWORD_MIN_SIZE = 6; -static const int LOGIN_MIN_SIZE = 4; -static GtkWidget *the_assistant = NULL; - - -static LinphoneAccountCreator * linphone_gtk_assistant_get_creator(GtkWidget *w) { - return (LinphoneAccountCreator *)g_object_get_data(G_OBJECT(w), "creator"); -} - -static void linphone_gtk_create_account_cb(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status, const char* resp) { - GtkWidget *assistant = (GtkWidget *)linphone_account_creator_get_user_data(creator); - if (status == LinphoneAccountCreatorStatusAccountCreated) { - // Go to page_6_linphone_account_validation_wait - gtk_assistant_set_current_page(GTK_ASSISTANT(assistant), 6); - } else { // Error when attempting to create the account - // Go to page_8_error - gtk_assistant_set_current_page(GTK_ASSISTANT(assistant), 8); - } - gtk_assistant_commit(GTK_ASSISTANT(assistant)); -} - -static void create_account(GtkWidget *assistant) { - LinphoneAccountCreator *creator = linphone_gtk_assistant_get_creator(assistant); - linphone_account_creator_create_account(creator); -} - -static void linphone_gtk_test_account_validation_cb(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status, const char* resp) { - GtkWidget *assistant = (GtkWidget *)linphone_account_creator_get_user_data(creator); - if (status == LinphoneAccountCreatorStatusAccountActivated) { - // Go to page_9_finish - gtk_assistant_set_current_page(GTK_ASSISTANT(assistant), 9); - } else { - // Go to page_8_error - gtk_assistant_set_current_page(GTK_ASSISTANT(assistant), 8); - } -} - -static void check_account_validation(GtkWidget *assistant) { - LinphoneAccountCreator *creator = linphone_gtk_assistant_get_creator(assistant); - linphone_account_creator_is_account_activated(creator); -} - -void linphone_gtk_assistant_closed(GtkWidget *w) { - linphone_gtk_close_assistant(); -} - -void linphone_gtk_assistant_prepare(GtkWidget *assistant) { - int pagenum = gtk_assistant_get_current_page(GTK_ASSISTANT(assistant)); - - switch (pagenum) { - case 5: - create_account(assistant); - break; - case 7: - check_account_validation(assistant); - break; - case 9: - if (linphone_account_creator_configure(linphone_gtk_assistant_get_creator(assistant)) != NULL) { - linphone_gtk_load_identities(); - } - gtk_assistant_commit(GTK_ASSISTANT(assistant)); - break; - default: - break; - } -} - -static gint destroy_assistant(GtkWidget* w){ - gtk_widget_destroy(w); - the_assistant = NULL; - return FALSE; -} - -static int linphone_gtk_assistant_forward(int curpage, gpointer data) { - GtkWidget *w = GTK_WIDGET(data); - LinphoneAccountCreator *creator = linphone_gtk_assistant_get_creator(w); - - switch (curpage) { - case 0: - curpage = 1; // Go to page_1_choice - break; - case 1: - { - GtkWidget *create_button = linphone_gtk_get_widget(w, "radio_create_account"); - GtkWidget *setup_linphone_account = linphone_gtk_get_widget(w, "radio_setup_lp_account"); - GtkWidget *setup_account = linphone_gtk_get_widget(w, "radio_setup_account"); - GtkWidget *config_uri = linphone_gtk_get_widget(w, "radio_config_uri"); - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(create_button))) { - curpage = 4; // Go to page_4_linphone_account_creation_configuration - } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(setup_linphone_account))) { - curpage = 3; // Go to page_3_linphone_account_configuration - } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(setup_account))) { - curpage = 2; // Go to page_2_external_account_configuration - } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(config_uri))) { - /* Destroy the assistant and popup config-uri dialog */ - gtk_widget_hide(w); - linphone_gtk_set_configuration_uri(); - curpage = 0; - g_idle_add((GSourceFunc)destroy_assistant, w); - } - } - break; - case 2: - { - GtkEntry *username_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p2_entry_username")); - GtkEntry *domain_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p2_entry_domain")); - GtkEntry *proxy_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p2_entry_proxy")); - GtkEntry *password_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p2_entry_password")); - linphone_account_creator_set_username(creator, gtk_entry_get_text(username_entry)); - linphone_account_creator_set_domain(creator, gtk_entry_get_text(domain_entry)); - linphone_account_creator_set_route(creator, gtk_entry_get_text(proxy_entry)); - linphone_account_creator_set_password(creator, gtk_entry_get_text(password_entry)); - curpage = 9; // Go to page_9_finish - break; - } - case 3: - { - GtkEntry *username_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p3_entry_username")); - GtkEntry *password_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p3_entry_password")); - linphone_account_creator_set_username(creator, gtk_entry_get_text(username_entry)); - linphone_account_creator_set_domain(creator, "sip.linphone.org"); - linphone_account_creator_set_route(creator, "sip.linphone.org"); - linphone_account_creator_set_password(creator, gtk_entry_get_text(password_entry)); - curpage = 9; // Go to page_9_finish - break; - } - case 4: - { - GtkEntry *password_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p4_entry_password1")); - GtkEntry *username_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p4_entry_username")); - GtkEntry *email_entry = GTK_ENTRY(linphone_gtk_get_widget(w, "p4_entry_email")); - //GtkToggleButton *newsletter = GTK_TOGGLE_BUTTON(linphone_gtk_get_widget(w, "p4_check_newsletter")); - linphone_account_creator_set_username(creator, gtk_entry_get_text(username_entry)); - linphone_account_creator_set_password(creator, gtk_entry_get_text(password_entry)); - linphone_account_creator_set_email(creator, gtk_entry_get_text(email_entry)); - //linphone_account_creator_enable_newsletter_subscription(creator, gtk_toggle_button_get_active(newsletter)); - curpage = 5; // Go to page_5_linphone_account_creation_in_progress - break; - } - case 6: - curpage = 7; // Go to page_7_linphone_account_validation_check_in_progress - break; - default: - break; - } - return curpage; -} - -static int external_account_configuration_complete(GtkWidget *page) { - GtkWidget *assistant = gtk_widget_get_toplevel(page); - GtkEntry* username = GTK_ENTRY(linphone_gtk_get_widget(assistant, "p2_entry_username")); - GtkEntry* domain = GTK_ENTRY(linphone_gtk_get_widget(assistant, "p2_entry_domain")); - - if ((gtk_entry_get_text_length(username) > 0) - && (gtk_entry_get_text_length(domain) > 0) - && (g_regex_match_simple("^[a-zA-Z0-9+]+[a-zA-Z0-9.\\+\\-_]{2,}$", gtk_entry_get_text(username), 0, 0)) - && (g_regex_match_simple("^(sip:)?([a-zA-Z0-9\\+]+([\\.-][a-zA-Z0-9+]+)*)$", gtk_entry_get_text(domain), 0, 0))) { - return 1; - } - return 0; -} - -void linphone_gtk_external_account_configuration_changed(GtkEntry *entry) { - GtkWidget *assistant = gtk_widget_get_toplevel(GTK_WIDGET(entry)); - gint current_page_num = gtk_assistant_get_current_page(GTK_ASSISTANT(assistant)); - GtkWidget *page = gtk_assistant_get_nth_page(GTK_ASSISTANT(assistant), current_page_num); - gtk_assistant_set_page_complete(GTK_ASSISTANT(assistant), page, external_account_configuration_complete(page) > 0); -} - -static bool_t check_username_validity(const char *username) { - return username && g_regex_match_simple("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{3,}$", username, 0, 0); -} - -void linphone_gtk_account_configuration_changed(GtkEntry *entry, GtkAssistant *assistant) { - gboolean complete = check_username_validity(gtk_entry_get_text(entry)); - GtkWidget *page = gtk_assistant_get_nth_page(assistant, gtk_assistant_get_current_page(assistant)); - gtk_assistant_set_page_complete(assistant, page, complete); -} - -static gboolean linphone_account_creation_configuration_correct(GtkWidget *w) { - gint is_username_available = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "is_username_available")); - gint is_email_correct = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "is_email_correct")); - gint is_password_correct = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w), "is_password_correct")); - return (is_username_available && is_email_correct && is_password_correct); -} - -static gboolean update_interface_with_username_availability(GtkWidget *page) { - GtkWidget *assistant = gtk_widget_get_toplevel(page); - GtkImage* isUsernameOk = GTK_IMAGE(linphone_gtk_get_widget(assistant, "p4_image_username_ok")); - GtkLabel* usernameError = GTK_LABEL(linphone_gtk_get_widget(assistant, "p4_label_error")); - int account_status = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(page), "is_username_used")); - - if (account_status == LinphoneAccountCreatorStatusAccountNotExist) { - g_object_set_data(G_OBJECT(page), "is_username_available", GINT_TO_POINTER(1)); - gtk_image_set_from_stock(isUsernameOk, GTK_STOCK_OK, GTK_ICON_SIZE_LARGE_TOOLBAR); - gtk_label_set_text(usernameError, ""); - } else if (account_status == LinphoneAccountCreatorStatusAccountExist) { - gtk_label_set_text(usernameError, _("Username is already in use!")); - g_object_set_data(G_OBJECT(page), "is_username_available", GINT_TO_POINTER(0)); - gtk_image_set_from_stock(isUsernameOk, GTK_STOCK_NO, GTK_ICON_SIZE_LARGE_TOOLBAR); - } else { - gtk_label_set_text(usernameError, _("Failed to check username availability. Please try again later.")); - g_object_set_data(G_OBJECT(page), "is_username_available", GINT_TO_POINTER(0)); - gtk_image_set_from_stock(isUsernameOk, GTK_STOCK_NO, GTK_ICON_SIZE_LARGE_TOOLBAR); - } - gtk_assistant_set_page_complete(GTK_ASSISTANT(assistant), page, linphone_account_creation_configuration_correct(page) > 0); - return FALSE; -} - -static void linphone_gtk_test_account_existence_cb(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status, const char* resp) { - GtkWidget *assistant = (GtkWidget *)linphone_account_creator_get_user_data(creator); - GtkWidget *page = gtk_assistant_get_nth_page(GTK_ASSISTANT(assistant), gtk_assistant_get_current_page(GTK_ASSISTANT(assistant))); - g_object_set_data(G_OBJECT(page), "is_username_used", GINT_TO_POINTER(status)); - gdk_threads_add_idle((GSourceFunc)update_interface_with_username_availability, page); -} - -static gboolean check_username_availability(GtkWidget *assistant) { - LinphoneAccountCreator *creator = linphone_gtk_assistant_get_creator(assistant); - GtkWidget *page = gtk_assistant_get_nth_page(GTK_ASSISTANT(assistant), gtk_assistant_get_current_page(GTK_ASSISTANT(assistant))); - g_object_set_data(G_OBJECT(page), "usernameAvailabilityTimerID", GUINT_TO_POINTER(0)); - linphone_account_creator_is_account_exist(creator); - return FALSE; -} - -void linphone_gtk_account_creation_username_changed(GtkEntry *entry) { - GtkWidget *assistant = gtk_widget_get_toplevel(GTK_WIDGET(entry)); - GtkEntry* username = GTK_ENTRY(linphone_gtk_get_widget(assistant, "p4_entry_username")); - GtkImage* isUsernameOk = GTK_IMAGE(linphone_gtk_get_widget(assistant, "p4_image_username_ok")); - GtkLabel* usernameError = GTK_LABEL(linphone_gtk_get_widget(assistant, "p4_label_error")); - gint current_page_num = gtk_assistant_get_current_page(GTK_ASSISTANT(assistant)); - GtkWidget *page = gtk_assistant_get_nth_page(GTK_ASSISTANT(assistant), current_page_num); - - LinphoneAccountCreator *creator = linphone_gtk_assistant_get_creator(assistant); - linphone_account_creator_set_username(creator, gtk_entry_get_text(username)); - linphone_account_creator_set_domain(creator, "sip.linphone.org"); - linphone_account_creator_set_route(creator, "sip.linphone.org"); - - if (check_username_validity(gtk_entry_get_text(username))) { - guint timerID = GPOINTER_TO_UINT(g_object_get_data(G_OBJECT(page), "usernameAvailabilityTimerID")); - if (timerID > 0) { - g_source_remove(timerID); - } - timerID = g_timeout_add(500, (GSourceFunc)check_username_availability, assistant); - g_object_set_data(G_OBJECT(page), "usernameAvailabilityTimerID", GUINT_TO_POINTER(timerID)); - } else { - if (gtk_entry_get_text_length(username) < LOGIN_MIN_SIZE) { - gtk_label_set_text(usernameError, "Username is too short"); - } else if (!check_username_validity(gtk_entry_get_text(username))) { - gtk_label_set_text(usernameError, "Unauthorized username"); - } - g_object_set_data(G_OBJECT(page), "is_username_available", GINT_TO_POINTER(0)); - gtk_image_set_from_stock(isUsernameOk, GTK_STOCK_NO, GTK_ICON_SIZE_LARGE_TOOLBAR); - gtk_assistant_set_page_complete(GTK_ASSISTANT(assistant), page, linphone_account_creation_configuration_correct(page) > 0); - } -} - -void linphone_gtk_account_creation_email_changed(GtkEntry *entry) { - GtkWidget *assistant = gtk_widget_get_toplevel(GTK_WIDGET(entry)); - GtkEntry* email = GTK_ENTRY(linphone_gtk_get_widget(assistant, "p4_entry_email")); - GtkImage* isEmailOk = GTK_IMAGE(linphone_gtk_get_widget(assistant, "p4_image_email_ok")); - gint current_page_num = gtk_assistant_get_current_page(GTK_ASSISTANT(assistant)); - GtkWidget *page = gtk_assistant_get_nth_page(GTK_ASSISTANT(assistant), current_page_num); - - if (g_regex_match_simple("^" BC_REGEX_RESTRICTIVE_EMAIL_ADDR "$", gtk_entry_get_text(email), 0, 0)) { - g_object_set_data(G_OBJECT(page), "is_email_correct", GINT_TO_POINTER(1)); - gtk_image_set_from_stock(isEmailOk, GTK_STOCK_OK, GTK_ICON_SIZE_LARGE_TOOLBAR); - } else { - g_object_set_data(G_OBJECT(page), "is_email_correct", GINT_TO_POINTER(0)); - gtk_image_set_from_stock(isEmailOk, GTK_STOCK_NO, GTK_ICON_SIZE_LARGE_TOOLBAR); - } - gtk_assistant_set_page_complete(GTK_ASSISTANT(assistant), page, linphone_account_creation_configuration_correct(page) > 0); -} - -void linphone_gtk_account_creation_password_changed(GtkEntry *entry) { - GtkWidget *assistant = gtk_widget_get_toplevel(GTK_WIDGET(entry)); - GtkEntry* password = GTK_ENTRY(linphone_gtk_get_widget(assistant, "p4_entry_password1")); - GtkEntry* password_confirm = GTK_ENTRY(linphone_gtk_get_widget(assistant, "p4_entry_password2")); - GtkImage* isPasswordOk = GTK_IMAGE(linphone_gtk_get_widget(assistant, "p4_image_password_ok")); - GtkLabel* passwordError = GTK_LABEL(linphone_gtk_get_widget(assistant, "p4_label_error")); - gint current_page_num = gtk_assistant_get_current_page(GTK_ASSISTANT(assistant)); - GtkWidget *page = gtk_assistant_get_nth_page(GTK_ASSISTANT(assistant), current_page_num); - - if ((gtk_entry_get_text_length(password) >= PASSWORD_MIN_SIZE) - && (g_ascii_strcasecmp(gtk_entry_get_text(password), gtk_entry_get_text(password_confirm)) == 0)) { - g_object_set_data(G_OBJECT(page), "is_password_correct", GINT_TO_POINTER(1)); - gtk_image_set_from_stock(isPasswordOk, GTK_STOCK_OK, GTK_ICON_SIZE_LARGE_TOOLBAR); - gtk_label_set_text(passwordError, ""); - } else { - if (gtk_entry_get_text_length(password) < PASSWORD_MIN_SIZE) { - gtk_label_set_text(passwordError, "Password is too short !"); - } else if (g_ascii_strcasecmp(gtk_entry_get_text(password), gtk_entry_get_text(password_confirm)) != 0) { - gtk_label_set_text(passwordError, "Passwords don't match !"); - } - g_object_set_data(G_OBJECT(page), "is_password_correct", GINT_TO_POINTER(0)); - gtk_image_set_from_stock(isPasswordOk, GTK_STOCK_NO, GTK_ICON_SIZE_LARGE_TOOLBAR); - } - gtk_assistant_set_page_complete(GTK_ASSISTANT(assistant), page, linphone_account_creation_configuration_correct(page) > 0); -} - -static void linphone_gtk_assistant_init(GtkWidget *w) { - LinphoneAccountCreator *creator = linphone_account_creator_new(linphone_gtk_get_core(), "https://subscribe.linphone.org:444/wizard.php"); - LinphoneAccountCreatorCbs *cbs = linphone_account_creator_get_callbacks(creator); - linphone_account_creator_set_user_data(creator, w); - linphone_account_creator_cbs_set_is_account_exist(cbs, linphone_gtk_test_account_existence_cb); - linphone_account_creator_cbs_set_is_account_activated(cbs, linphone_gtk_test_account_validation_cb); - linphone_account_creator_cbs_set_create_account(cbs, linphone_gtk_create_account_cb); - g_object_set_data(G_OBJECT(w), "creator", creator); - - gtk_assistant_set_forward_page_func(GTK_ASSISTANT(w), linphone_gtk_assistant_forward, w, NULL); -} - -void linphone_gtk_show_assistant(void) { - if (the_assistant != NULL) return; - the_assistant = linphone_gtk_create_window("setup_wizard", linphone_gtk_get_main_window()); - linphone_gtk_assistant_init(the_assistant); - gtk_widget_show(the_assistant); -} - -void linphone_gtk_close_assistant(void) { - GtkWidget *mw; - if (the_assistant == NULL) { - return; - } - gtk_widget_destroy(the_assistant); - the_assistant = NULL; - - //reload list of proxy configs because a new one was probably created... - mw=linphone_gtk_get_main_window(); - if (mw) { - GtkWidget* pb = (GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters"); - if (pb) { - linphone_gtk_show_sip_accounts(pb); - } - } -} diff --git a/gtk/setupwizard.h b/gtk/setupwizard.h deleted file mode 100644 index ac833f20e..000000000 --- a/gtk/setupwizard.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef SETUP_WIZARD_H -#define SETUP_WIZARD_H - -#include "linphone/sipsetup.h" - -LINPHONE_PUBLIC void linphone_gtk_show_assistant(void); -LINPHONE_PUBLIC void linphone_gtk_assistant_prepare(GtkWidget *assistant); -LINPHONE_PUBLIC void linphone_gtk_assistant_closed(GtkWidget *w); - -LINPHONE_PUBLIC void linphone_gtk_external_account_configuration_changed(GtkEntry* entry); -LINPHONE_PUBLIC void linphone_gtk_account_configuration_changed(GtkEntry *entry, GtkAssistant *assistant); -LINPHONE_PUBLIC void linphone_gtk_account_creation_username_changed(GtkEntry *entry); -LINPHONE_PUBLIC void linphone_gtk_account_creation_password_changed(GtkEntry *entry); -LINPHONE_PUBLIC void linphone_gtk_account_creation_email_changed(GtkEntry *entry); - -#endif diff --git a/gtk/singleinstance.c b/gtk/singleinstance.c deleted file mode 100644 index d41b22bec..000000000 --- a/gtk/singleinstance.c +++ /dev/null @@ -1,127 +0,0 @@ -/* -linphone, gtk interface. -Copyright (C) 2011 Belledonne Communications SARL -Author: Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" - -static ms_thread_t pipe_thread; -static ortp_pipe_t server_pipe=(ortp_pipe_t)-1; -static gboolean server_pipe_running=TRUE; -static char *pipe_name=NULL; - -gchar *make_name(const char *appname){ - const char *username=getenv("USER"); - if (username){ - return g_strdup_printf("%s-%s",appname,username); - } - return g_strdup(appname); -} - -static gboolean execute_wakeup(char *buf){ - char uri[255]={0}; - int option; - - if (strlen(buf)>1) sscanf(buf,"%i%s",&option,uri); - else sscanf(buf,"%i",&option); - - switch(option){ - case START_LINPHONE: - linphone_gtk_show_main_window(); - break; - case START_AUDIO_ASSISTANT: - linphone_gtk_show_audio_assistant(); - break; - case START_LINPHONE_WITH_CALL: - linphone_gtk_refer_received(linphone_gtk_get_core(),uri); - break; - }; - - g_free(buf); - return FALSE; -} - -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){ - char buf[256]={0}; - if (ortp_pipe_read(child,(uint8_t*)buf,sizeof(buf))>0){ - g_message("Received wakeup command with arg %s",buf); - gdk_threads_enter(); - g_timeout_add(20,(GSourceFunc)execute_wakeup,g_strdup(buf)); - gdk_threads_leave(); - } - ortp_server_pipe_close_client(child); - } - }while(server_pipe_running); - ortp_server_pipe_close(server_pipe); - return NULL; -} - -static void linphone_gtk_init_pipe(const char *name){ - server_pipe=ortp_server_pipe_create(name); - if (server_pipe==(ortp_pipe_t)-1){ - g_warning("Fail to create server pipe for name %s: %s",name,strerror(errno)); - return; - } - server_pipe_running=TRUE; - ms_thread_create(&pipe_thread,NULL,server_pipe_thread,NULL); -} - -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); - 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."); - if (addr_to_call!=NULL){ - sprintf((char *)buf,"%i%s",option,addr_to_call); - } else { - sprintf((char *)buf,"%i",option); - } - if (ortp_pipe_write(p,buf,sizeof(buf))==-1){ - g_error("Fail to send wakeup command to running instance: %s",strerror(errno)); - }else{ - g_message("Message to running instance sent."); - } - ortp_client_pipe_close(p); - return FALSE; - }else{ - linphone_gtk_init_pipe(pipe_name); - } - return TRUE; -} - -void linphone_gtk_uninit_instance(void){ - if (server_pipe!=(ortp_pipe_t)-1){ - ortp_pipe_t client; - server_pipe_running=FALSE; - /*this is to unblock the accept() of the server pipe*/ - client=ortp_client_pipe_connect(pipe_name); - ortp_pipe_write(client,(uint8_t*)" ",1); - ortp_client_pipe_close(client); - ms_thread_join(pipe_thread,NULL); - server_pipe=(ortp_pipe_t)-1; - g_free(pipe_name); - pipe_name=NULL; - } -} diff --git a/gtk/sip_account.ui b/gtk/sip_account.ui deleted file mode 100644 index 6d03932d1..000000000 --- a/gtk/sip_account.ui +++ /dev/null @@ -1,395 +0,0 @@ - - - - - - 100000 - 3600 - 1 - 10 - - - 5 - 1 - 5 - 1 - 1 - - - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Linphone - Configure a SIP account - center-on-parent - dialog - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - end - - - gtk-ok - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 0 - - - - - gtk-cancel - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - 2 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Your SIP identity: - right - - - - - 275 - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Looks like sip:<username>@<domain> - sip: - False - False - True - True - - - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - SIP Proxy address: - right - - - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Looks like sip:<proxy hostname> - sip: - False - False - True - True - - - - 1 - 2 - 1 - 2 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - - - 1 - 2 - 4 - 5 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Registration duration (sec): - right - - - 2 - 3 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - adjustment1 - - - 1 - 2 - 2 - 3 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Contact params (optional): - right - - - 5 - 6 - - - - - 275 - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - True - False - False - True - True - - - 1 - 2 - 5 - 6 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - AVPF regular RTCP interval (sec): - right - - - 6 - 7 - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - adjustment2 - - - 1 - 2 - 6 - 7 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Route (optional): - right - - - 4 - 5 - - - - - True - False - Transport - - - 3 - 4 - - - - - True - False - - - - 1 - 2 - 3 - 4 - - - - - True - True - 0 - - - - - Register - True - True - False - False - True - True - - - True - True - 1 - - - - - Publish presence information - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - False - True - 2 - - - - - Enable AVPF - True - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - False - True - 3 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Configure a SIP account - True - - - - - True - True - 1 - - - - - - button6 - button7 - - - diff --git a/gtk/status_icon.c b/gtk/status_icon.c deleted file mode 100644 index 22852f38f..000000000 --- a/gtk/status_icon.c +++ /dev/null @@ -1,546 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2015 Belledonne Communications - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "status_icon.h" -#include "linphone.h" - -#ifdef HAVE_GTK_OSX -#include -#endif - -#if !defined(_WIN32) && !defined(__APPLE__) && GLIB_CHECK_VERSION(2, 26, 0) -#define STATUS_NOTIFIER_IS_USABLE 1 -#endif - -#include "status_notifier.h" -#include - -typedef struct __LinphoneStatusIconDesc _LinphoneStatusIconDesc; - -static LinphoneStatusIcon *_linphone_status_icon_instance = NULL; -static const _LinphoneStatusIconDesc *_linphone_status_icon_selected_desc = NULL; -static GSList *_linphone_status_icon_impls = NULL; - - -struct _LinphoneStatusIconParams { - char *title; - char *desc; - GtkWidget *menu; - LinphoneStatusIconOnClickCallback on_click_cb; - void *user_data; - int ref; -}; - -LinphoneStatusIconParams *linphone_status_icon_params_new(void) { - return g_new0(LinphoneStatusIconParams, 1); -} - -LinphoneStatusIconParams *linphone_status_icon_params_ref(LinphoneStatusIconParams *obj) { - obj->ref++; - return obj; -} - -void linphone_status_icon_params_unref(LinphoneStatusIconParams *obj) { - obj->ref--; - if(obj->ref < 0) { - if(obj->title) g_free(obj->title); - if(obj->menu) g_object_unref(obj->menu); - if(obj->desc) g_free(obj->desc); - g_free(obj); - } -} - -void linphone_status_icon_params_set_title(LinphoneStatusIconParams *obj, const char *title) { - if(obj->title) g_free(obj->title); - if(title) obj->title = g_strdup(title); - else obj->title = NULL; -} - -void linphone_status_icon_params_set_description(LinphoneStatusIconParams *obj, const char *desc) { - if(obj->desc) g_free(obj->desc); - if(desc) obj->desc = g_strdup(desc); - else obj->desc = NULL; -} - -void linphone_status_icon_params_set_menu(LinphoneStatusIconParams *obj, GtkWidget *menu) { - if(obj->menu) g_object_unref(obj->menu); - if(menu) obj->menu = g_object_ref_sink(menu); - else obj->menu = NULL; -} - -void linphone_status_icon_params_set_on_click_cb(LinphoneStatusIconParams *obj, LinphoneStatusIconOnClickCallback cb, void *user_data) { - obj->on_click_cb = cb; - obj->user_data = user_data; -} - - -typedef void (*LinphoneStatusIconDescInitFunc)(LinphoneStatusIcon *obj); -typedef void (*LinphoneStatusIconDescUninitFunc)(LinphoneStatusIcon *obj); -typedef void (*LinphoneStatusIconDescStartFunc)(LinphoneStatusIcon *obj); -typedef void (*LinphoneStatusIconDescEnableBlinkingFunc)(LinphoneStatusIcon *obj, gboolean enable); -typedef void (*LinphoneStatusIconDescIsSupportedResultCb)(const _LinphoneStatusIconDesc *obj, gboolean result, void *user_data); -typedef gboolean (*LinphoneStatusIconDescIsSupportedFunc)( - const _LinphoneStatusIconDesc *desc, - gboolean *result, - LinphoneStatusIconDescIsSupportedResultCb cb, - void *user_data -); -typedef void (*LinphoneStatusIconDescFindResultCb)(const _LinphoneStatusIconDesc *desc, void *user_data); - -struct __LinphoneStatusIconDesc { - const char *impl_name; - LinphoneStatusIconDescInitFunc init; - LinphoneStatusIconDescUninitFunc uninit; - LinphoneStatusIconDescStartFunc start; - LinphoneStatusIconDescEnableBlinkingFunc enable_blinking; - LinphoneStatusIconDescIsSupportedFunc is_supported; -}; - -static gboolean _linphone_status_icon_desc_is_supported( - const _LinphoneStatusIconDesc *desc, - gboolean *result, - LinphoneStatusIconDescIsSupportedResultCb cb, - void *user_data) { - - return desc->is_supported(desc, result, cb, user_data); -} - -typedef struct { - GSList *i; - LinphoneStatusIconDescFindResultCb cb; - void *user_data; -} _LinphoneStatusIconDescSearchCtx; - -static void _linphone_status_icon_desc_is_supported_result_cb( - const _LinphoneStatusIconDesc *desc, - gboolean result, - _LinphoneStatusIconDescSearchCtx *ctx) { - - if(!result) { - ctx->i = g_slist_next(ctx->i); - for(; ctx->i; ctx->i = g_slist_next(ctx->i)) { - if(_linphone_status_icon_desc_is_supported( - (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0), - &result, - (LinphoneStatusIconDescIsSupportedResultCb)_linphone_status_icon_desc_is_supported_result_cb, - ctx)) { - - if(result) break; - } else return; - } - } - - if(ctx->i) { - const _LinphoneStatusIconDesc *desc = (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0); - ms_message("StatusIcon: found implementation: %s", desc->impl_name); - if(ctx->cb) ctx->cb(desc, ctx->user_data); - } else { - g_warning("StatusIcon: no implementation found"); - } - - g_free(ctx); -} - -static gboolean _linphone_status_icon_find_first_available_impl( - const _LinphoneStatusIconDesc **desc, - LinphoneStatusIconDescFindResultCb cb, - void *user_data) { - - gboolean result; - _LinphoneStatusIconDescSearchCtx *ctx = g_new0(_LinphoneStatusIconDescSearchCtx, 1); - ctx->cb = cb; - ctx->user_data = user_data; - - ms_message("StatusIcon: looking for implementation..."); - - for(ctx->i=_linphone_status_icon_impls; ctx->i; ctx->i = g_slist_next(ctx->i)) { - if(_linphone_status_icon_desc_is_supported( - (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0), - &result, - (LinphoneStatusIconDescIsSupportedResultCb)_linphone_status_icon_desc_is_supported_result_cb, - ctx)) { - - if(result) { - *desc = (const _LinphoneStatusIconDesc *)g_slist_nth_data(ctx->i, 0); - ms_message("StatusIcon: found implementation: %s", (*desc)->impl_name); - goto sync_return; - } - } else { - return 0; - } - } - g_warning("StatusIcon: no implementation found"); - *desc = NULL; - -sync_return: - g_free(ctx); - return 1; -} - - -struct _LinphoneStatusIcon { - const _LinphoneStatusIconDesc *desc; - LinphoneStatusIconParams *params; - void *data; -}; - -static LinphoneStatusIcon *_linphone_status_icon_new(const _LinphoneStatusIconDesc *desc) { - LinphoneStatusIcon *si = (LinphoneStatusIcon *)g_new0(LinphoneStatusIcon, 1); - si->desc = desc; - if(desc->init) desc->init(si); - return si; -} - -static void _linphone_status_icon_free(LinphoneStatusIcon *obj) { - if(obj->desc->uninit) obj->desc->uninit(obj); - if(obj->params) linphone_status_icon_params_unref(obj->params); - g_free(obj); -} - -const char *linphone_status_icon_get_implementation_name(const LinphoneStatusIcon *obj) { - return obj->desc->impl_name; -} - -void linphone_status_icon_start(LinphoneStatusIcon *obj, LinphoneStatusIconParams *params) { - ms_message("StatusIcon: starting status icon"); - obj->params = linphone_status_icon_params_ref(params); - if(obj->desc->start) obj->desc->start(obj); -} - -void linphone_status_icon_enable_blinking(LinphoneStatusIcon *obj, gboolean enable) { - ms_message("StatusIcon: blinking set to %s", enable ? "TRUE" : "FALSE"); - if(obj->desc->enable_blinking) obj->desc->enable_blinking(obj, enable); -} - -static void _linphone_status_icon_notify_click(LinphoneStatusIcon *obj) { - if(obj->params->on_click_cb) { - obj->params->on_click_cb(obj, obj->params->user_data); - } -} - - -void _linphone_status_icon_init_cb(const _LinphoneStatusIconDesc *desc, void *user_data) { - void **ctx = (void **)user_data; - LinphoneStatusIconReadyCb cb = (LinphoneStatusIconReadyCb)ctx[0]; - _linphone_status_icon_selected_desc = desc; - if(cb) cb(ctx[1]); - g_free(ctx); -} - -#ifdef STATUS_NOTIFIER_IS_USABLE -static const _LinphoneStatusIconDesc _linphone_status_icon_impl_status_notifier; -#endif -#ifdef HAVE_GTK_OSX -static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtkosx_app_desc; -#else -static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtk_desc; -#endif - -void _linphone_status_icon_create_implementations_list(void) { -#ifdef STATUS_NOTIFIER_IS_USABLE - _linphone_status_icon_impls = g_slist_append(_linphone_status_icon_impls, (void *)&_linphone_status_icon_impl_status_notifier); -#endif -#if HAVE_GTK_OSX - _linphone_status_icon_impls = g_slist_append(_linphone_status_icon_impls, (void *)&_linphone_status_icon_impl_gtkosx_app_desc); -#else - _linphone_status_icon_impls = g_slist_append(_linphone_status_icon_impls, (void *)&_linphone_status_icon_impl_gtk_desc); -#endif -} - -gboolean linphone_status_icon_init(LinphoneStatusIconReadyCb ready_cb, void *user_data) { - const _LinphoneStatusIconDesc *desc; - void **ctx; - - ms_message("StatusIcon: Initialising"); - - _linphone_status_icon_create_implementations_list(); - - ctx = g_new(void *, 2); - ctx[0] = ready_cb; - ctx[1] = user_data; - - if(_linphone_status_icon_find_first_available_impl(&desc, _linphone_status_icon_init_cb, ctx)) { - _linphone_status_icon_selected_desc = desc; - g_free(ctx); - return 1; - } else return 0; -} - -void linphone_status_icon_uninit(void) { - if(_linphone_status_icon_instance) { - _linphone_status_icon_free(_linphone_status_icon_instance); - _linphone_status_icon_instance = NULL; - } - if(_linphone_status_icon_impls) { - g_slist_free(_linphone_status_icon_impls); - _linphone_status_icon_impls = NULL; - } - _linphone_status_icon_selected_desc = NULL; -} - -LinphoneStatusIcon *linphone_status_icon_get(void) { - if(_linphone_status_icon_instance == NULL) { - if(_linphone_status_icon_selected_desc) - ms_message("StatusIcon: instanciating singleton"); - _linphone_status_icon_instance = _linphone_status_icon_new(_linphone_status_icon_selected_desc); - } - return _linphone_status_icon_instance; -} - - -/* GtkStatusIcon implementation */ -#ifndef HAVE_GTK_OSX -static void _linphone_status_icon_impl_gtk_on_click_cb(LinphoneStatusIcon *si) { - _linphone_status_icon_notify_click(si); -} - -static void _linphone_status_icon_impl_gtk_popup_menu(GtkStatusIcon *status_icon, guint button, guint activate_time, LinphoneStatusIcon *si){ - GtkWidget *menu = si->params->menu; - gtk_menu_popup(GTK_MENU(menu),NULL,NULL,gtk_status_icon_position_menu,status_icon,button,activate_time); -} - -static void _linphone_status_icon_impl_gtk_init(LinphoneStatusIcon *si) { - const char *icon_name=linphone_gtk_get_ui_config("icon_name",LINPHONE_ICON_NAME); - const char *blinking_icon_name=linphone_gtk_get_ui_config("binking_status_icon_name","linphone-start-call"); - GtkStatusIcon *icon=gtk_status_icon_new_from_icon_name(icon_name); - g_signal_connect_swapped(G_OBJECT(icon),"activate", G_CALLBACK(_linphone_status_icon_impl_gtk_on_click_cb), si); - g_signal_connect(G_OBJECT(icon), "popup-menu", G_CALLBACK(_linphone_status_icon_impl_gtk_popup_menu), si); - g_object_set_data_full(G_OBJECT(icon), "icon", g_strdup(icon_name), g_free); - g_object_set_data_full(G_OBJECT(icon), "call_icon", g_strdup(blinking_icon_name), g_free); - si->data = icon; -} - -static void _linphone_status_icon_impl_gtk_uninit(LinphoneStatusIcon *si) { - GtkStatusIcon *icon = GTK_STATUS_ICON(si->data); - gtk_status_icon_set_visible(icon, FALSE); -} - -static void _linphone_status_icon_impl_gtk_start(LinphoneStatusIcon *si) { - GtkStatusIcon *icon = GTK_STATUS_ICON(si->data); -#if GTK_CHECK_VERSION(2,20,2) - char *name = g_strdup_printf("%s - %s", si->params->title, si->params->desc); - gtk_status_icon_set_name(icon, name); - g_free(name); -#endif - gtk_status_icon_set_visible(icon,TRUE); -} - -static gboolean _linphone_status_icon_impl_gtk_do_icon_blink_cb(GtkStatusIcon *gi){ - const gchar *call_icon = (const gchar *)g_object_get_data(G_OBJECT(gi),"call_icon"); - const gchar *normal_icon = (const gchar *)g_object_get_data(G_OBJECT(gi),"icon"); - const gchar *cur_icon = (const gchar *)gtk_status_icon_get_icon_name(gi); - if (cur_icon == call_icon){ - gtk_status_icon_set_from_icon_name(gi,normal_icon); - }else{ - gtk_status_icon_set_from_icon_name(gi,call_icon); - } - return TRUE; -} - -static void _linphone_status_icon_impl_enable_blinking(LinphoneStatusIcon *si, gboolean val) { - GtkStatusIcon *icon = GTK_STATUS_ICON(si->data); - guint tout; - tout=(unsigned)GPOINTER_TO_INT(g_object_get_data(G_OBJECT(icon),"timeout")); - if (val && tout==0){ - tout=g_timeout_add(500,(GSourceFunc)_linphone_status_icon_impl_gtk_do_icon_blink_cb,icon); - g_object_set_data(G_OBJECT(icon),"timeout",GINT_TO_POINTER(tout)); - }else if (!val && tout!=0){ - const gchar *normal_icon = (const gchar *)g_object_get_data(G_OBJECT(icon),"icon"); - g_source_remove(tout); - g_object_set_data(G_OBJECT(icon),"timeout",NULL); - gtk_status_icon_set_from_icon_name(icon,normal_icon); - } -} - -static gboolean _linphone_status_icon_impl_is_supported( - const _LinphoneStatusIconDesc *desc, - gboolean *result, - LinphoneStatusIconDescIsSupportedResultCb cb, - void *user_data) { - - *result = 1; - return 1; -} - -static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtk_desc = { - "gtk_status_icon", - _linphone_status_icon_impl_gtk_init, - _linphone_status_icon_impl_gtk_uninit, - _linphone_status_icon_impl_gtk_start, - _linphone_status_icon_impl_enable_blinking, - _linphone_status_icon_impl_is_supported -}; -#endif - - -/* GtkosxApplication implementation */ -#ifdef HAVE_GTK_OSX -static void _linphone_status_icon_impl_gtkosx_app_enable_blinking(LinphoneStatusIcon *si, gboolean val) { - GtkosxApplication *theMacApp=gtkosx_application_get(); - gint *attention_id = (gint *)&si->data; - if (val) { - *attention_id=gtkosx_application_attention_request(theMacApp, CRITICAL_REQUEST); - } else if (*attention_id != 0) { - gtkosx_application_cancel_attention_request(theMacApp, *attention_id); - *attention_id = 0; - } -} - -static gboolean _linphone_status_icon_impl_gtkosx_app_is_supported( - const _LinphoneStatusIconDesc *desc, - gboolean *result, - LinphoneStatusIconDescIsSupportedResultCb cb, - void *user_data) { - - *result = 1; - return 1; -} - -static const _LinphoneStatusIconDesc _linphone_status_icon_impl_gtkosx_app_desc = { - .impl_name = "gtkosx_application", - .init = NULL, - .uninit = NULL, - .start = NULL, - .enable_blinking = _linphone_status_icon_impl_gtkosx_app_enable_blinking, - .is_supported = _linphone_status_icon_impl_gtkosx_app_is_supported -}; -#endif - - -/* Implementation based on the StatusNotifier Freedesktop standard */ -#ifdef STATUS_NOTIFIER_IS_USABLE -typedef struct { - int x; - int y; -} _LinphoneStatusIconPosition; - -static void _linphone_status_icon_impl_sn_init(LinphoneStatusIcon *si) { - si->data = bc_status_notifier_new(); -} - -// static void _linphone_status_icon_impl_sn_uninit(LinphoneStatusIcon *si) { -// bc_status_notifier_unref((BcStatusNotifier *)si->data); -// } - -static void _linphone_status_icon_impl_sn_activated_cb(BcStatusNotifier *sn, int x, int y, void *user_data) { - LinphoneStatusIcon *si = (LinphoneStatusIcon *)user_data; - _linphone_status_icon_notify_click(si); -} - -static void _linphone_status_icon_impr_sn_get_position(GtkMenu *menu, int *x, int *y, gboolean *push_in, gpointer data) { - _LinphoneStatusIconPosition *pos = (_LinphoneStatusIconPosition *)data; - *x = pos->x; - *y = pos->y; - *push_in = TRUE; -} - -static void _linphone_status_icon_impl_sn_menu_called_cb(BcStatusNotifier *sn, int x, int y, void *user_data) { - LinphoneStatusIcon *si = (LinphoneStatusIcon *)user_data; - GtkWidget *menu = si->params->menu; - _LinphoneStatusIconPosition pos = {x, y}; - gtk_menu_popup( - GTK_MENU(menu), - NULL, - NULL, - _linphone_status_icon_impr_sn_get_position, - &pos, - 0, - gtk_get_current_event_time() - ); -} - -static void _linphone_status_icon_impl_sn_start(LinphoneStatusIcon *si) { - BcStatusNotifier *sn = (BcStatusNotifier *)si->data; - BcStatusNotifierParams *params; - BcStatusNotifierToolTip *tooltip = bc_status_notifier_tool_tip_new("linphone", si->params->title, si->params->desc); - BcStatusNotifierSignalsVTable vtable = {NULL}; - - vtable.activate_called_cb = _linphone_status_icon_impl_sn_activated_cb; - vtable.context_menu_called_cb = _linphone_status_icon_impl_sn_menu_called_cb; - - params = bc_status_notifier_params_new(); - bc_status_notifier_params_set_dbus_prefix(params, "org.kde"); - bc_status_notifier_params_set_category(params, BcStatusNotifierCategoryCommunications); - bc_status_notifier_params_set_id(params, "linphone"); - bc_status_notifier_params_set_title(params, si->params->title); - bc_status_notifier_params_set_icon_name(params, "linphone"); - bc_status_notifier_params_set_tool_tip(params, tooltip); - bc_status_notifier_params_set_vtable(params, &vtable, si); - - bc_status_notifier_start(sn, params, NULL, NULL); - - bc_status_notifier_tool_tip_unref(tooltip); - bc_status_notifier_params_unref(params); -} - -static void _linphone_status_icon_impl_sn_enable_blinking(LinphoneStatusIcon *si, gboolean val) { - BcStatusNotifier *sn = (BcStatusNotifier *)si->data; - if(val) { - bc_status_notifier_update_status(sn, BcStatusNotifierStatusNeedsAttention); - } else { - bc_status_notifier_update_status(sn, BcStatusNotifierStatusPassive); - } -} - -static void _linphone_status_icon_impl_is_supported_cb(const char *prefix, gboolean result, void **data) { - _LinphoneStatusIconDesc *desc = (_LinphoneStatusIconDesc *)data[0]; - LinphoneStatusIconDescIsSupportedResultCb cb = (LinphoneStatusIconDescIsSupportedResultCb)data[1]; - if(cb) cb(desc, result, data[2]); - g_free(data); - g_free(desc); -} - -static gboolean _linphone_status_icon_impl_sn_is_supported( - const _LinphoneStatusIconDesc *desc, - gboolean *result, - LinphoneStatusIconDescIsSupportedResultCb cb, - void *user_data) { - - _LinphoneStatusIconDesc *desc2; - void **data; - const char *desktop = g_getenv("XDG_CURRENT_DESKTOP"); - - if(desktop == NULL || g_strcmp0(desktop, "KDE") != 0) { - *result = FALSE; - return TRUE; - } - - desc2 = g_new(_LinphoneStatusIconDesc, 1); - *desc2 = *desc; - data = g_new(void *, 3); - data[0] = desc2; - data[1] = cb; - data[2] = user_data; - bc_status_notifier_is_supported( - "org.kde", - (BcStatusNotifierSupportDetectionCb)_linphone_status_icon_impl_is_supported_cb, - data - ); - return FALSE; -} - -static const _LinphoneStatusIconDesc _linphone_status_icon_impl_status_notifier = { - .impl_name = "status_notifier", - .init = _linphone_status_icon_impl_sn_init, - .uninit = NULL, - .start = _linphone_status_icon_impl_sn_start, - .enable_blinking = _linphone_status_icon_impl_sn_enable_blinking, - .is_supported = _linphone_status_icon_impl_sn_is_supported -}; -#endif diff --git a/gtk/status_icon.h b/gtk/status_icon.h deleted file mode 100644 index 52d28d4e6..000000000 --- a/gtk/status_icon.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2015 Belledonne Communications - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/* - * LinphoneStatusIcon is an singleton interface which abstracts the - * technology used to manage the status icon. - */ - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#ifndef _MSC_VER -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#endif - -#include -#include - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif - - -struct _LinphoneStatusIcon; -typedef void (*LinphoneStatusIconOnClickCallback)(struct _LinphoneStatusIcon *si, void *user_data); - - -typedef struct _LinphoneStatusIconParams LinphoneStatusIconParams; - -LinphoneStatusIconParams *linphone_status_icon_params_new(void); -LinphoneStatusIconParams *linphone_status_icon_params_ref(LinphoneStatusIconParams *obj); -void linphone_status_icon_params_unref(LinphoneStatusIconParams *obj); - -void linphone_status_icon_params_set_title(LinphoneStatusIconParams *obj, const char *title); -void linphone_status_icon_params_set_description(LinphoneStatusIconParams *obj, const char *desc); -void linphone_status_icon_params_set_menu(LinphoneStatusIconParams *obj, GtkWidget *menu); -void linphone_status_icon_params_set_on_click_cb(LinphoneStatusIconParams* obj, LinphoneStatusIconOnClickCallback cb, void *user_data); - - -typedef void (*LinphoneStatusIconReadyCb)(void *user_data); - -typedef struct _LinphoneStatusIcon LinphoneStatusIcon; - -gboolean linphone_status_icon_init(LinphoneStatusIconReadyCb ready_cb, void* user_data); -void linphone_status_icon_uninit(void); -LinphoneStatusIcon *linphone_status_icon_get(void); -const char *linphone_status_icon_get_implementation_name(const LinphoneStatusIcon *obj); -void linphone_status_icon_start(LinphoneStatusIcon *obj, LinphoneStatusIconParams *params); -void linphone_status_icon_enable_blinking(LinphoneStatusIcon *obj, gboolean enable); diff --git a/gtk/status_notifier.c b/gtk/status_notifier.c deleted file mode 100644 index 1cff84f45..000000000 --- a/gtk/status_notifier.c +++ /dev/null @@ -1,643 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2015 Belledonne Communications - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "status_notifier.h" -#include -#include - -#ifdef _MSC_VER -#include -#define getpid() _getpid() -typedef int lppid_t; -#else -#include -typedef pid_t lppid_t; -#endif - -const gchar *bc_status_notifier_category_to_string(BcStatusNotifierCategory c) { - switch(c){ - case BcStatusNotifierCategoryApplicationStatus: - return "ApplicationStatus"; - case BcStatusNotifierCategoryCommunications: - return "Communications"; - case BcStatusNotifierCategorySystemService: - return "SystemServices"; - case BcStatusNotifierCategoryHardware: - return "Hardware"; - } - return "bad category"; -} - -const gchar *bc_status_notifier_status_to_string(BcStatusNotifierStatus s) { - switch(s){ - case BcStatusNotifierStatusPassive: - return "Passive"; - case BcStatusNotifierStatusActive: - return "Active"; - case BcStatusNotifierStatusNeedsAttention: - return "NeedsAttention"; - } - return "badstatus"; -}; - - -struct _BcStatusNotifierToolTip { - char *icon_name; - char *title; - char *text; - int ref; -}; - -BcStatusNotifierToolTip *bc_status_notifier_tool_tip_new(const char *icon_name, const char *title, const char *text) { - BcStatusNotifierToolTip *obj = (BcStatusNotifierToolTip *)g_new0(BcStatusNotifierToolTip, 1); - if(icon_name) obj->icon_name = g_strdup(icon_name); - if(title) obj->title = g_strdup(title); - if(text) obj->text = g_strdup(text); - return obj; -} - -BcStatusNotifierToolTip *bc_status_notifier_tool_tip_ref(BcStatusNotifierToolTip *obj) { - obj->ref++; - return obj; -} - -void bc_status_notifier_tool_tip_unref(BcStatusNotifierToolTip *obj) { - obj->ref--; - if(obj->ref < 0) { - if(obj->icon_name) g_free(obj->icon_name); - if(obj->title) g_free(obj->title); - if(obj->text) g_free(obj->text); - g_free(obj); - } -} - -static GVariant *_bc_status_notifier_tool_tip_to_variant(const BcStatusNotifierToolTip *obj) { - GVariant *attr[] = { - g_variant_new_string(obj->icon_name ? obj->icon_name : ""), - g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0), - g_variant_new_string(obj->title ? obj->title : ""), - g_variant_new_string(obj->text ? obj->text : ""), - }; - return g_variant_new_tuple(attr, 4); -} - - -static const char *_bc_status_notifier_to_string[] = { - "vertical", - "horizontal", - NULL -}; - -static BcStatusNotifierOrientation _bc_status_notifier_orientation_from_string(const char *s) { - int i; - for(i=0; _bc_status_notifier_to_string[i] && g_strcmp0(s, _bc_status_notifier_to_string[i]) == 0; i++); - if(_bc_status_notifier_to_string[i]) return i; - else return BcStatusNotifierOrientationVertical; -} - - -struct _BcStatusNotifierParams{ - char *prefix; - int item_id; - BcStatusNotifierCategory category; - char *id; - char *title; - BcStatusNotifierStatus status; - guint32 window_id; - char *icon_name; - char *overlay_icon_name; - char *attention_icon_name; - char *attention_movie_name; - BcStatusNotifierToolTip *tool_tip; - BcStatusNotifierSignalsVTable vtable; - void *user_data; - int ref; -}; - -#define DEFAULT_PREFIX "org.freedesktop" - -BcStatusNotifierParams *bc_status_notifier_params_new(void) { - BcStatusNotifierParams *obj = (BcStatusNotifierParams *)g_new0(BcStatusNotifierParams, 1); - obj->prefix = g_strdup(DEFAULT_PREFIX); - return obj; -} - -BcStatusNotifierParams *bc_status_notifier_params_ref(BcStatusNotifierParams *obj) { - obj->ref++; - return obj; -} - -void bc_status_notifier_params_unref(BcStatusNotifierParams *obj) { - obj->ref--; - if(obj->ref < 0) { - if(obj->prefix) g_free(obj->prefix); - if(obj->id) g_free(obj->id); - if(obj->title) g_free(obj->title); - if(obj->icon_name) g_free(obj->icon_name); - if(obj->overlay_icon_name) g_free(obj->overlay_icon_name); - if(obj->attention_icon_name) g_free(obj->attention_icon_name); - if(obj->attention_movie_name) g_free(obj->attention_movie_name); - if(obj->tool_tip) bc_status_notifier_tool_tip_unref(obj->tool_tip); - g_free(obj); - } -} - -void bc_status_notifier_params_set_dbus_prefix(BcStatusNotifierParams *obj, const char *prefix) { - if(obj->prefix) g_free(obj->prefix); - if(prefix) obj->prefix = g_strdup(prefix); - else obj->prefix = NULL; -} - -const char *bc_satus_notifier_params_get_dbus_prefix(const BcStatusNotifierParams *obj) { - return obj->prefix; -} - -void bc_status_notifier_params_set_item_id(BcStatusNotifierParams *obj, int item_id) { - obj->item_id = item_id; -} - -int bc_status_notifier_params_get_item_id(const BcStatusNotifierParams *obj) { - return obj->item_id; -} - -void bc_status_notifier_params_set_category(BcStatusNotifierParams *obj, BcStatusNotifierCategory category) { - obj->category = category; -} - -BcStatusNotifierCategory bc_status_notifier_params_get_category(const BcStatusNotifierParams *obj) { - return obj->category; -} - -void bc_status_notifier_params_set_id(BcStatusNotifierParams *obj, const char *id) { - if(obj->id) g_free(obj->id); - if(id) obj->id = g_strdup(id); - else obj->id = NULL; -} - -const char *bc_status_notifier_params_get_id(const BcStatusNotifierParams *obj) { - return obj->id; -} - -void bc_status_notifier_params_set_title(BcStatusNotifierParams *obj, const char *title) { - if(obj->title) g_free(obj->title); - if(title) obj->title = g_strdup(title); - else obj->title = NULL; -} - -const char *bc_status_notifier_params_get_title(const BcStatusNotifierParams *obj) { - return obj->title; -} - -void bc_status_notifier_params_set_status(BcStatusNotifierParams *obj, BcStatusNotifierStatus status) { - obj->status = status; -} - -BcStatusNotifierStatus bc_status_notifier_params_get_status(const BcStatusNotifierParams *obj) { - return obj->status; -} - -void bc_status_notifier_params_set_window_id(BcStatusNotifierParams *obj, guint32 window_id) { - obj->window_id = window_id; -} - -guint32 bc_status_notifier_params_get_window_id(const BcStatusNotifierParams *obj) { - return obj->window_id; -} - -void bc_status_notifier_params_set_icon_name(BcStatusNotifierParams *obj, const char *name) { - if(obj->icon_name) g_free(obj->icon_name); - if(name) obj->icon_name = g_strdup(name); - else obj->icon_name = NULL; -} - -const char *bc_status_notifier_params_get_icon_name(const BcStatusNotifierParams *obj) { - return obj->icon_name; -} - -void bc_status_notifier_params_set_overlay_icon_name(BcStatusNotifierParams *obj, const char *name) { - if(obj->overlay_icon_name) g_free(obj->overlay_icon_name); - if(name) obj->overlay_icon_name = g_strdup(name); - else obj->overlay_icon_name = NULL; -} - -const char *bc_status_notifier_params_get_overlay_icon_name(const BcStatusNotifierParams *obj) { - return obj->overlay_icon_name; -} - -void bc_status_notifier_params_set_attention_icon_name(BcStatusNotifierParams *obj, const char *name) { - if(obj->attention_icon_name) g_free(obj->attention_icon_name); - if(name) obj->attention_icon_name = g_strdup(name); - else obj->attention_icon_name = NULL; -} - -const char *bc_status_notifier_params_get_attention_icon_name(const BcStatusNotifierParams *obj) { - return obj->attention_icon_name; -} - -void bc_status_notifier_params_set_attention_movie_name(BcStatusNotifierParams *obj, const char *name) { - if(obj->attention_movie_name) g_free(obj->attention_movie_name); - if(name) obj->attention_movie_name = g_strdup(name); - else obj->attention_movie_name = NULL; -} - -const char *bc_status_notifier_params_get_attention_movie_name(const BcStatusNotifierParams *obj) { - return obj->attention_movie_name; -} - -void bc_status_notifier_params_set_tool_tip(BcStatusNotifierParams *obj, BcStatusNotifierToolTip *tool_tip) { - if(obj->tool_tip) bc_status_notifier_tool_tip_unref(obj->tool_tip); - if(tool_tip) obj->tool_tip = bc_status_notifier_tool_tip_ref(tool_tip); - else obj->tool_tip = NULL; -} - -const BcStatusNotifierToolTip *bc_status_notifier_params_get_tool_tip(const BcStatusNotifierParams *obj) { - return obj->tool_tip; -} - -void bc_status_notifier_params_set_vtable(BcStatusNotifierParams *obj, const BcStatusNotifierSignalsVTable *vtable, void *user_data) { - obj->vtable = *vtable; - obj->user_data = user_data; -} - - -struct _BcStatusNotifier { - BcStatusNotifierParams *params; - guint bus_owner_id; - GDBusConnection *conn; - BcStatusNotifierState state; - BcStatusNotifierStateVTable vtable; - void *user_data; - int ref; -}; - -#define ITEM_NAME "StatusNotifierItem" -#define WATCHER_NAME "StatusNotifierWatcher" -#define CALL_TIMEOUT 1000 - -#define STATUS_NOTIFIER_INTROSPECTION_DATA \ - " \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - \ - " - -BcStatusNotifier *bc_status_notifier_new(void) { - return (BcStatusNotifier *)g_new0(BcStatusNotifier, 1); -} - -BcStatusNotifier *bc_status_notifier_ref(BcStatusNotifier *obj) { - obj->ref++; - return obj; -} - -void bc_status_notifier_unref(BcStatusNotifier *obj) { - obj->ref--; - if(obj->ref < 0) { - bc_status_notifier_stop(obj); - if(obj->params) bc_status_notifier_params_unref(obj->params); - g_free(obj); - } -} - -static GVariant *_bc_status_notifier_get_property_cb( - GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GError **error, - BcStatusNotifier *sn) { - - - GVariant *value = NULL; - if(g_strcmp0(property_name, "Category") == 0) { - value = g_variant_new_string(bc_status_notifier_category_to_string(sn->params->category)); - } else if(g_strcmp0(property_name, "Id") == 0) { - value = g_variant_new_string(sn->params->id ? sn->params->id : ""); - } else if(g_strcmp0(property_name, "Title") == 0) { - value = g_variant_new_string(sn->params->title ? sn->params->title : ""); - } else if(g_strcmp0(property_name, "Status") == 0) { - value = g_variant_new_string(bc_status_notifier_status_to_string(sn->params->status)); - } else if(g_strcmp0(property_name, "WindowId") == 0) { - value = g_variant_new_uint32(sn->params->window_id); - } else if(g_strcmp0(property_name, "IconName") == 0) { - value = g_variant_new_string(sn->params->icon_name ? sn->params->icon_name : ""); - } else if(g_strcmp0(property_name, "IconPixmap") == 0) { - value = g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0); - } else if(g_strcmp0(property_name, "OverlayIconName") == 0) { - value = g_variant_new_string(sn->params->overlay_icon_name ? sn->params->overlay_icon_name : ""); - } else if(g_strcmp0(property_name, "OverlayIconPixmap") == 0) { - value = g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0); - } else if(g_strcmp0(property_name, "AttentionIconName") == 0) { - value = g_variant_new_string(sn->params->attention_icon_name ? sn->params->attention_icon_name : ""); - } else if(g_strcmp0(property_name, "AttentionIconPixmap") == 0) { - value = g_variant_new_array(G_VARIANT_TYPE_VARIANT, NULL, 0); - } else if(g_strcmp0(property_name, "AttentionMovieName") == 0) { - value = g_variant_new_string(sn->params->attention_movie_name ? sn->params->attention_movie_name : ""); - } else if(g_strcmp0(property_name, "ToolTip") == 0) { - if(sn->params->tool_tip) { - value = _bc_status_notifier_tool_tip_to_variant(sn->params->tool_tip); - } else { - BcStatusNotifierToolTip *tool_tip = bc_status_notifier_tool_tip_new("", "", ""); - value = _bc_status_notifier_tool_tip_to_variant(tool_tip); - bc_status_notifier_tool_tip_unref(tool_tip); - } - } - return value; -} - -static void _bc_status_notifier_method_call_cb( - GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - BcStatusNotifier *sn) { - - if(g_strcmp0(method_name, "ContextMenu") == 0) { - if(sn->params->vtable.context_menu_called_cb) { - int x, y; - g_variant_get_child(parameters, 0, "i", &x); - g_variant_get_child(parameters, 1, "i", &y); - sn->params->vtable.context_menu_called_cb(sn, x, y, sn->params->user_data); - } - } else if(g_strcmp0(method_name, "Activate") == 0) { - if(sn->params->vtable.activate_called_cb) { - int x, y; - g_variant_get_child(parameters, 0, "i", &x); - g_variant_get_child(parameters, 1, "i", &y); - sn->params->vtable.activate_called_cb(sn, x, y, sn->params->user_data); - } - } else if(g_strcmp0(method_name, "SecondaryActivate") == 0) { - if(sn->params->vtable.secondary_activate_called_cb) { - int x, y; - g_variant_get_child(parameters, 0, "i", &x); - g_variant_get_child(parameters, 1, "i", &y); - sn->params->vtable.secondary_activate_called_cb(sn, x, y, sn->params->user_data); - } - } else if(g_strcmp0(method_name, "Scroll") == 0) { - if(sn->params->vtable.scroll_called_cb) { - int delta; - BcStatusNotifierOrientation orient; - char *orient_str; - g_variant_get_child(parameters, 0, "i", &delta); - g_variant_get_child(parameters, 1, "&s", &orient_str); - orient = _bc_status_notifier_orientation_from_string(orient_str); - sn->params->vtable.scroll_called_cb(sn, delta, orient, sn->params->user_data); - } - } - g_dbus_method_invocation_return_value(invocation, NULL); -} - -static void _bc_status_notifier_bus_acquired_cb(GDBusConnection *conn, const gchar *name, BcStatusNotifier *sn) { - char *interface_name = g_strdup_printf("%s.%s", sn->params->prefix, ITEM_NAME); - char *item_path = g_strdup_printf("/%s", ITEM_NAME); - GDBusInterfaceVTable vtable; - GDBusNodeInfo *node_info = g_dbus_node_info_new_for_xml(STATUS_NOTIFIER_INTROSPECTION_DATA, NULL); - GDBusInterfaceInfo *interface = g_dbus_node_info_lookup_interface( - node_info, - interface_name - ); - - memset(&vtable, 0, sizeof(vtable)); - vtable.method_call = (GDBusInterfaceMethodCallFunc)_bc_status_notifier_method_call_cb; - vtable.get_property = (GDBusInterfaceGetPropertyFunc)_bc_status_notifier_get_property_cb; - g_free(interface_name); - - sn->conn = conn; - - g_dbus_connection_register_object( - conn, - item_path, - interface, - &vtable, - bc_status_notifier_ref(sn), - (GDestroyNotify)bc_status_notifier_unref, - NULL - ); - g_free(item_path); - - g_dbus_node_info_unref(node_info); -} - -static void _bc_status_notifier_name_acquired_cb(GDBusConnection *conn, const gchar *name, BcStatusNotifier *sn) { - GVariant *item_name = g_variant_new_string(name); - GVariant *parameters = g_variant_new_tuple(&item_name, 1); - char *watcher_bus_name = g_strdup_printf("%s.%s", sn->params->prefix, WATCHER_NAME); - char *watcher_interface_name = watcher_bus_name; - char *watcher_path = g_strdup_printf("/%s", WATCHER_NAME); - - g_dbus_connection_call( - conn, - watcher_bus_name, - watcher_path, - watcher_interface_name, - "RegisterStatusNotifierItem", - parameters, - NULL, - G_DBUS_CALL_FLAGS_NONE, - CALL_TIMEOUT, - NULL, - NULL, - NULL - ); - g_free(watcher_bus_name); - g_free(watcher_path); - - sn->state = BcStatusNotifierStateRunning; - if(sn->vtable.success) sn->vtable.success(sn, sn->user_data); -} - -static void _bc_status_notifier_name_lost(GDBusConnection *conn, const gchar *name, BcStatusNotifier *sn) { - if(conn == NULL) { - sn->state = BcStatusNotifierStateStopped; - if(sn->vtable.fail) sn->vtable.fail(sn, sn->user_data); - } -} - -void bc_status_notifier_start(BcStatusNotifier* obj, BcStatusNotifierParams* params, const BcStatusNotifierStateVTable *vtable, void *user_data) { - if(obj->state == BcStatusNotifierStateStopped) { - lppid_t pid = getpid(); - char *dbus_name = g_strdup_printf("%s.%s-%d-%d", params->prefix, ITEM_NAME, pid, params->item_id); - - if(obj->params) bc_status_notifier_params_unref(obj->params); - obj->params = bc_status_notifier_params_ref(params); - if(vtable) obj->vtable = *vtable; - else { - obj->vtable.success = NULL; - obj->vtable.fail = NULL; - } - obj->user_data = user_data; - obj->state = BcStatusNotifierStateStarting; - obj->bus_owner_id = g_bus_own_name( - G_BUS_TYPE_SESSION, - dbus_name, - G_BUS_NAME_OWNER_FLAGS_NONE, - (GBusAcquiredCallback)_bc_status_notifier_bus_acquired_cb, - (GBusNameAcquiredCallback)_bc_status_notifier_name_acquired_cb, - (GBusNameLostCallback)_bc_status_notifier_name_lost, - bc_status_notifier_ref(obj), - (GDestroyNotify)bc_status_notifier_unref - ); - g_free(dbus_name); - } -} - -void bc_status_notifier_stop(BcStatusNotifier *obj) { - if(obj->state == BcStatusNotifierStateRunning) { - g_bus_unown_name(obj->bus_owner_id); - obj->bus_owner_id = 0; - obj->conn = NULL; - obj->state = BcStatusNotifierStateStopped; - } -} - -const BcStatusNotifierParams *bc_status_notifier_get_params(const BcStatusNotifier *obj) { - return obj->params; -} - -static void _bc_status_notifier_emit_signal(const BcStatusNotifier *obj, const char *sig_name, GVariant *parameters) { - char *item_interface_name = g_strdup_printf("%s.%s", obj->params->prefix, ITEM_NAME); - char *item_path = g_strdup_printf("/%s", ITEM_NAME); - g_dbus_connection_emit_signal( - obj->conn, - NULL, - item_path, - item_interface_name, - sig_name, - parameters, - NULL - ); - g_free(item_interface_name); - g_free(item_path); -} - -void bc_status_notifier_update_title(BcStatusNotifier *obj, const char *title) { - bc_status_notifier_params_set_title(obj->params, title); - _bc_status_notifier_emit_signal(obj, "NewTitle", NULL); -} - -void bc_status_notifier_update_icon(BcStatusNotifier *obj, const char *icon_name) { - bc_status_notifier_params_set_icon_name(obj->params, icon_name); - _bc_status_notifier_emit_signal(obj, "NewIcon", NULL); -} - -void bc_status_notifier_update_attention_icon(BcStatusNotifier *obj, const char *icon_name) { - bc_status_notifier_params_set_attention_icon_name(obj->params, icon_name); - _bc_status_notifier_emit_signal(obj, "NewAttentionIcon", NULL); -} - -void bc_status_notifier_update_overlay_icon(BcStatusNotifier *obj, const char *icon_name) { - bc_status_notifier_params_set_overlay_icon_name(obj->params, icon_name); - _bc_status_notifier_emit_signal(obj, "NewOverlayIcon", NULL); -} - -void bc_status_notifier_update_tool_tip(BcStatusNotifier *obj, BcStatusNotifierToolTip *tool_tip) { - bc_status_notifier_params_set_tool_tip(obj->params, tool_tip); - _bc_status_notifier_emit_signal(obj, "NewToolTip", NULL); -} - -void bc_status_notifier_update_status(BcStatusNotifier *obj, BcStatusNotifierStatus status) { - GVariant *status_var = g_variant_new_string(bc_status_notifier_status_to_string(status)); - GVariant *parameter = g_variant_new_tuple(&status_var, 1); - bc_status_notifier_params_set_status(obj->params, status); - _bc_status_notifier_emit_signal(obj, "NewStatus", parameter); -} - - -typedef struct _BcWatcherDetectionCtx { - char *prefix; - guint watcher_id; - BcStatusNotifierSupportDetectionCb cb; - void *user_data; -} BcWatcherDetectionCtx; - -static void _bc_watcher_detection_ctx_free(BcWatcherDetectionCtx *obj) { - g_free(obj->prefix); - g_free(obj); -} - -static void _bc_watcher_name_appeared_cb(GDBusConnection *conn, const char *name, const char *name_owner, BcWatcherDetectionCtx *ctx) { - g_bus_unwatch_name(ctx->watcher_id); - if(ctx->cb) ctx->cb(ctx->prefix, 1, ctx->user_data); -} - -static void _bc_watcher_name_vannished_cb(GDBusConnection *conn, const char *name, BcWatcherDetectionCtx *ctx) { - g_bus_unwatch_name(ctx->watcher_id); - if(ctx->cb) ctx->cb(ctx->prefix, 0, ctx->user_data); -} - -void bc_status_notifier_is_supported(const char* prefix, BcStatusNotifierSupportDetectionCb cb, void *user_data) { - char *bus_name = g_strdup_printf("%s.%s", prefix, WATCHER_NAME); - BcWatcherDetectionCtx *ctx = (BcWatcherDetectionCtx *)g_new0(BcWatcherDetectionCtx, 1); - ctx->prefix = g_strdup(prefix); - ctx->cb = cb; - ctx->user_data = user_data; - - ctx->watcher_id = g_bus_watch_name( - G_BUS_TYPE_SESSION, - bus_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - (GBusNameAppearedCallback)_bc_watcher_name_appeared_cb, - (GBusNameVanishedCallback)_bc_watcher_name_vannished_cb, - ctx, - (GDestroyNotify)_bc_watcher_detection_ctx_free - ); - g_free(bus_name); -} diff --git a/gtk/status_notifier.h b/gtk/status_notifier.h deleted file mode 100644 index 22d95ebae..000000000 --- a/gtk/status_notifier.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2015 Belledonne Communications - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -/** - * BcStatusNotifier is an implementation of the StatusNotiferItem standard defined by freedesktop.org. - * It is a new way to manage status icons on GNU/Linux systems by using D-Bus. It is implemented by - * Unity desktop environmemt and it is the only way to create status icons on KDE 5. - * Visit http://freedesktop.org/wiki/Specifications/StatusNotifierItem/ for more information. - */ - -#ifndef STATUS_NOTIFIER_H -#define STATUS_NOTIFIER_H - -#include - -struct _BcStatusNotifier; - - -typedef enum { - BcStatusNotifierCategoryApplicationStatus, - BcStatusNotifierCategoryCommunications, - BcStatusNotifierCategorySystemService, - BcStatusNotifierCategoryHardware -} BcStatusNotifierCategory; - -const gchar *bc_status_notifier_category_to_string(BcStatusNotifierCategory c); - - -typedef enum { - BcStatusNotifierStatusPassive, - BcStatusNotifierStatusActive, - BcStatusNotifierStatusNeedsAttention -} BcStatusNotifierStatus; - -const gchar *bc_status_notifier_status_to_string(BcStatusNotifierStatus s); - - -typedef struct _BcStatusNotifierToolTip BcStatusNotifierToolTip; - -BcStatusNotifierToolTip *bc_status_notifier_tool_tip_new(const char *icon_name, const char *title, const char *text); -BcStatusNotifierToolTip *bc_status_notifier_tool_tip_ref(BcStatusNotifierToolTip *obj); -void bc_status_notifier_tool_tip_unref(BcStatusNotifierToolTip *obj); - - -typedef enum _BcStatusNotifierOrientation { - BcStatusNotifierOrientationVertical, - BcStatusNotifierOrientationHorizontal -} BcStatusNotifierOrientation; - - -typedef void (*BcStatusNotifierContextMenuCalledCb)(struct _BcStatusNotifier *sn, int x, int y, void *user_data); -typedef void (*BcStatusNotifierActivateCalledCb)(struct _BcStatusNotifier *sn, int x, int y, void *user_data); -typedef void (*BcStatusNotifierSecondaryActivateCb)(struct _BcStatusNotifier *sn, int x, int y, void *user_data); -typedef void (*BcStatusNotifierScrollCalledCb)(struct _BcStatusNotifier *sn, int delta, BcStatusNotifierOrientation o, void *user_data); - -typedef struct _BcStatusNotifierSignalsVTable { - BcStatusNotifierContextMenuCalledCb context_menu_called_cb; - BcStatusNotifierActivateCalledCb activate_called_cb; - BcStatusNotifierSecondaryActivateCb secondary_activate_called_cb; - BcStatusNotifierScrollCalledCb scroll_called_cb; -} BcStatusNotifierSignalsVTable; - - -typedef struct _BcStatusNotifierParams BcStatusNotifierParams; - -BcStatusNotifierParams *bc_status_notifier_params_new(void); -BcStatusNotifierParams *bc_status_notifier_params_ref(BcStatusNotifierParams *obj); -void bc_status_notifier_params_unref(BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_dbus_prefix(BcStatusNotifierParams *obj, const char *prefix); -const char *bc_satus_notifier_params_get_dbus_prefix(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_item_id(BcStatusNotifierParams *obj, int item_id); -int bc_status_notifier_params_get_item_id(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_category(BcStatusNotifierParams *obj, BcStatusNotifierCategory category); -BcStatusNotifierCategory bc_status_notifier_params_get_category(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_id(BcStatusNotifierParams *obj, const char *id); -const char *bc_status_notifier_params_get_id(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_title(BcStatusNotifierParams *obj, const char *title); -const char *bc_status_notifier_params_get_title(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_status(BcStatusNotifierParams *obj, BcStatusNotifierStatus status); -BcStatusNotifierStatus bc_status_notifier_params_get_status(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_window_id(BcStatusNotifierParams *obj, guint32 window_id); -guint32 bc_status_notifier_params_get_window_id(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_icon_name(BcStatusNotifierParams *obj, const char *name); -const char *bc_status_notifier_params_get_icon_name(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_overlay_icon_name(BcStatusNotifierParams *obj, const char *name); -const char *bc_status_notifier_params_get_overlay_icon_name(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_attention_icon_name(BcStatusNotifierParams *obj, const char *icon_name); -const char *bc_status_notifier_params_get_attention_icon_name(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_attention_movie_name(BcStatusNotifierParams *obj, const char *name); -const char *bc_status_notifier_params_get_attention_movie_name(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_tool_tip(BcStatusNotifierParams *obj, BcStatusNotifierToolTip *tool_tip); -const BcStatusNotifierToolTip *bc_status_notifier_params_get_tool_tip(const BcStatusNotifierParams *obj); - -void bc_status_notifier_params_set_vtable(BcStatusNotifierParams *obj, const BcStatusNotifierSignalsVTable *vtable, void *user_data); - - -typedef enum _BcStatusNotifierState { - BcStatusNotifierStateStopped, - BcStatusNotifierStateStarting, - BcStatusNotifierStateRunning -} BcStatusNotifierState; - - -typedef void (*BcStatusNotifierStartedCb)(struct _BcStatusNotifier *sn, void *user_data); -typedef void (*BcStatusNotifierStartingFailedCb)(struct _BcStatusNotifier *sn, void *user_data); - -typedef struct _BcStatusNotifierStateVTable { - BcStatusNotifierStartedCb success; - BcStatusNotifierStartingFailedCb fail; -} BcStatusNotifierStateVTable; - - -typedef struct _BcStatusNotifier BcStatusNotifier; - -BcStatusNotifier *bc_status_notifier_new(void); -BcStatusNotifier *bc_status_notifier_ref(BcStatusNotifier *obj); -void bc_status_notifier_unref(BcStatusNotifier *obj); - -void bc_status_notifier_start(BcStatusNotifier* obj, BcStatusNotifierParams* params, const BcStatusNotifierStateVTable* vtable, void* user_data); -void bc_status_notifier_stop(BcStatusNotifier* obj); - -const BcStatusNotifierParams *bc_status_notifier_get_params(const BcStatusNotifier *obj); -void bc_status_notifier_update_title(BcStatusNotifier* obj, const char* title); -void bc_status_notifier_update_icon(BcStatusNotifier* obj, const char* icon_name); -void bc_status_notifier_update_attention_icon(BcStatusNotifier* obj, const char* icon_name); -void bc_status_notifier_update_overlay_icon(BcStatusNotifier* obj, const char* icon_name); -void bc_status_notifier_update_tool_tip(BcStatusNotifier* obj, BcStatusNotifierToolTip* tool_tip); -void bc_status_notifier_update_status(BcStatusNotifier* obj, BcStatusNotifierStatus status); - - -typedef void (*BcStatusNotifierSupportDetectionCb)(const char *prefix, gboolean is_supported, void *user_data); - -void bc_status_notifier_is_supported(const char* prefix, BcStatusNotifierSupportDetectionCb cb, void *user_data); - -#endif \ No newline at end of file diff --git a/gtk/stock_people.png b/gtk/stock_people.png deleted file mode 100644 index ed2d33b9f..000000000 Binary files a/gtk/stock_people.png and /dev/null differ diff --git a/gtk/support.c b/gtk/support.c deleted file mode 100644 index df6006ee0..000000000 --- a/gtk/support.c +++ /dev/null @@ -1,257 +0,0 @@ -#include "linphone.h" - -#include "linphone/lpconfig.h" - -static GList *pixmaps_directories = NULL; - -/* Use this function to set the directory containing installed pixmaps. */ -void -add_pixmap_directory (const gchar *directory) -{ - pixmaps_directories = g_list_prepend (pixmaps_directories, - g_strdup (directory)); -} - -/* This is an internally used function to find pixmap files. */ -static gchar* -find_pixmap_file (const gchar *filename) -{ - GList *elem; - - /* We step through each of the pixmaps directory to find it. */ - elem = pixmaps_directories; - while (elem) - { - gchar *pathname = g_strdup_printf ("%s%s%s", (gchar*)elem->data, - G_DIR_SEPARATOR_S, filename); - if (g_file_test (pathname, G_FILE_TEST_EXISTS)) - return pathname; - g_free (pathname); - elem = elem->next; - } - return NULL; -} - -/* This is an internally used function to create pixmaps. */ -GtkWidget* -create_pixmap (const gchar *filename) -{ - gchar *pathname = NULL; - GtkWidget *pixmap; - - if (!filename || !filename[0]) - return gtk_image_new (); - - pathname = find_pixmap_file (filename); - - if (!pathname) - { - g_warning (_("Couldn't find pixmap file: %s"), filename); - return gtk_image_new (); - } - - pixmap = gtk_image_new_from_file (pathname); - g_free (pathname); - return pixmap; -} - -/* This is an internally used function to create pixmaps. */ -GdkPixbuf* -create_pixbuf (const gchar *filename) -{ - gchar *pathname = NULL; - GdkPixbuf *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_new_from_file (pathname, &error); - if (!pixbuf) - { - fprintf (stderr, "Failed to load pixbuf file: %s: %s\n", - pathname, error->message); - g_error_free (error); - } - g_free (pathname); - return pixbuf; -} - -/* This is an internally used function to create animations */ -GdkPixbufAnimation * -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", - pathname, error->message); - g_error_free (error); - } - g_free (pathname); - return pixbuf; -} - - - -/* This is used to set ATK action descriptions. */ -void -glade_set_atk_action_description (AtkAction *action, - const gchar *action_name, - const gchar *description) -{ - gint n_actions, i; - - n_actions = atk_action_get_n_actions (action); - for (i = 0; i < n_actions; i++) - { - if (!strcmp (atk_action_get_name (action, i), action_name)) - atk_action_set_description (action, i, description); - } -} - - -static char linphone_lang[256]={0}; - -/*lang has to be read before the config file is parsed...*/ -const char *linphone_gtk_get_lang(const char *config_file){ - FILE *f=fopen(config_file,"r"); - if (f){ - char tmp[256]; - while(fgets(tmp,sizeof(tmp),f)!=NULL){ - char *p; - if ((p=strstr(tmp,"lang="))!=NULL){ - p+=5; - sscanf(p,"%s",linphone_lang); - g_message("Found lang %s",linphone_lang); - break; - } - } - fclose(f); - } - return linphone_lang; -} - -void linphone_gtk_set_lang(const char *code){ - LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core()); - const char *curlang=g_getenv("LANGUAGE"); - if (curlang!=NULL && strncmp(curlang,code,2)==0) { - /* do not loose the _territory@encoding part*/ - return; - } - lp_config_set_string(cfg,"GtkUi","lang",code); - g_setenv("LANGUAGE",code,1); -} - -const gchar *linphone_gtk_get_ui_config(const char *key, const char *def){ - LinphoneCore *lc=linphone_gtk_get_core(); - if (lc){ - LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core()); - return lp_config_get_string(cfg,"GtkUi",key,def); - }else{ - g_error ("Cannot read config, no core created yet."); - return NULL; - } -} - -int linphone_gtk_get_ui_config_int(const char *key, int def){ - LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core()); - return lp_config_get_int(cfg,"GtkUi",key,def); -} - -void linphone_gtk_set_ui_config_int(const char *key , int val){ - LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core()); - lp_config_set_int(cfg,"GtkUi",key,val); -} - -void linphone_gtk_set_ui_config(const char *key , const char * val){ - LpConfig *cfg=linphone_core_get_config(linphone_gtk_get_core()); - lp_config_set_string(cfg,"GtkUi",key,val); -} - -const char *linphone_gtk_get_sound_path(const char *name){ - static char *ret=NULL; - const char *file; - const char *sound_dir; - LinphoneFactory *factory = linphone_factory_get(); - - file=linphone_gtk_get_ui_config(name,NULL); - if (file==NULL){ - char *dirname=g_path_get_dirname(name); - if (strcmp(dirname,".")!=0){ - g_free(dirname); - return name; - } - g_free(dirname); - file=name; - } - if (ret){ - g_free(ret); - ret=NULL; - } - sound_dir = linphone_factory_get_sound_resources_dir(factory); - ret=g_build_filename(sound_dir,name,NULL); - return ret; -} - -static void parse_item(const char *item, const char *window_name, GtkWidget *w, gboolean show){ - char tmp[64]; - char *dot; - strcpy(tmp,item); - dot=strchr(tmp,'.'); - if (dot){ - *dot='\0'; - dot++; - if (strcmp(window_name,tmp)==0){ - GtkWidget *wd=linphone_gtk_get_widget(w,dot); - if (wd) { - if (!show) gtk_widget_hide(wd); - else gtk_widget_show(wd); - } - } - } -} - -void linphone_gtk_visibility_set(const char *hiddens, const char *window_name, GtkWidget *w, gboolean show){ - char item[64]; - const char *i; - const char *b; - int len; - for(b=i=hiddens;*i!='\0';++i){ - if (*i==' '){ - len=MIN(i-b,(int)sizeof(item)-1); - strncpy(item,b,len); - item[len]='\0'; - b=i+1; - parse_item(item,window_name,w,show); - } - } - len=MIN(i-b,(int)sizeof(item)-1); - if (len>0){ - strncpy(item,b,len); - item[len]='\0'; - parse_item(item,window_name,w,show); - } -} - diff --git a/gtk/tunnel_config.ui b/gtk/tunnel_config.ui deleted file mode 100644 index af7eafd29..000000000 --- a/gtk/tunnel_config.ui +++ /dev/null @@ -1,407 +0,0 @@ - - - - - - 1 - 65535 - 443 - 1 - 10 - - - 1 - 65535 - 8080 - 1 - 10 - - - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - Configure VoIP tunnel - center-on-parent - dialog - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - none - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 5 - 2 - True - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Host - right - - - - - 275 - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - False - True - True - - - 1 - 2 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Port - right - - - 1 - 2 - - - - - True - True - - False - False - True - True - adjustment1 - - - 1 - 2 - 1 - 2 - - - - - Enabled - True - True - False - False - 0 - True - True - radio_disable - - - 1 - 2 - 2 - 3 - - - - - Disabled - True - True - False - False - 0 - True - True - radio_enable - - - 1 - 2 - 4 - 5 - - - - - Enable on purpose - True - True - False - False - 0 - True - True - radio_enable - - - 1 - 2 - 3 - 4 - - - - - - - - - - - - - - True - True - 0 - - - - - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - <b>VoIP anti-blocking (tunnel server)</b> - True - - - - - False - True - 0 - - - - - True - False - 0 - none - - - True - False - 12 - - - True - False - 4 - 2 - True - - - True - False - Host - - - - - True - False - Port - - - 1 - 2 - - - - - True - False - Username - - - 2 - 3 - - - - - True - False - Password - - - 3 - 4 - - - - - True - True - - False - False - True - True - adjustment2 - - - 1 - 2 - 1 - 2 - - - - - True - True - - False - False - True - True - - - 1 - 2 - - - - - True - True - - False - False - True - True - - - 1 - 2 - 2 - 3 - - - - - True - True - False - - False - False - True - True - - - 1 - 2 - 3 - 4 - - - - - - - - - True - False - <b>Http proxy (optional)</b> - True - - - - - True - True - 1 - - - - - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - end - - - gtk-ok - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 0 - - - - - gtk-cancel - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - False - True - - - - False - False - 1 - - - - - False - True - end - 2 - - - - - - button6 - button7 - - - diff --git a/gtk/update.c b/gtk/update.c deleted file mode 100644 index 9704b6c9e..000000000 --- a/gtk/update.c +++ /dev/null @@ -1,157 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" - -#ifdef _WIN32 - -#include - -static int linphone_gtk_create_version(const char *version_url, char *version, size_t size){ - DWORD dwDownloaded = 0; - HINTERNET hSession = NULL, hConnect = NULL; - int ret=-1; - - hSession=InternetOpen("Linphone",INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,0); - - if (hSession==NULL) return -1; - - hConnect=InternetOpenUrl(hSession,version_url,NULL,0,0,0); - - if (hConnect==NULL) { - InternetCloseHandle(hSession); - return -1; - } - dwDownloaded=0; - if (InternetReadFile(hConnect,version,size,&dwDownloaded) && dwDownloaded>0){ - version[dwDownloaded]='\0'; - ms_message("Got response: %s", version); - /*check this not just html containing 404 not found*/ - if (strstr(version,"html")==0) - ret=0; - } - - // Close any open handles. - if (hConnect) InternetCloseHandle(hConnect); - if (hSession) InternetCloseHandle(hSession); - return ret; -} - -#else - -static int linphone_gtk_create_version(const char *url, char *version, size_t size){ - - return -1; -} - -#endif - -static void new_version_response(GtkWidget *dialog, int response_id, gpointer download_site){ - if (response_id==GTK_RESPONSE_YES){ - linphone_gtk_open_browser((const char*)download_site); - } - gtk_widget_destroy(dialog); -} - -static gboolean popup_new_version(const char *download_site){ - GtkWidget *dialog; - /* draw a question box. link to dialog_click callback */ - dialog = gtk_message_dialog_new ( - GTK_WINDOW(linphone_gtk_get_main_window()), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_QUESTION, - GTK_BUTTONS_YES_NO, - _("A more recent version is availalble from %s.\nWould you like to open a browser to download it ?"), - download_site); - g_signal_connect(G_OBJECT (dialog), "response", - G_CALLBACK (new_version_response), - (gpointer)download_site); - /* actually show the box */ - gtk_widget_show(dialog); - return FALSE; -} - -static gboolean popup_version_ok(void){ - linphone_gtk_display_something(GTK_MESSAGE_INFO,_("You are running the lastest version.")); - return FALSE; -} - -static int copytilldot(char *n, const char *v){ - int ret=0; - while(*v!='\0' && *v!='.' && *v!='-' && *v!='\n' && *v!='\r' && *v!='\t'){ - *n=*v; - ret++; - v++; - n++; - } - *n='\0'; - if (*v!='\0') ret=ret+1; - return ret; -} - -static int version_compare(const char *v1, const char *v2){ - char n1[16]; - char n2[16]; - int ret; - if (*v1=='\0' && *v2=='\0') return 0; - v1+=copytilldot(n1,v1); - v2+=copytilldot(n2,v2); - ms_message("Comparing %s <> %s",n1,n2); - ret=strcmp(n1,n2); - if (ret==0) return version_compare(v1,v2); - else return ret; -} - -static void *check_for_new_version(void *d){ - const char *version_url=(const char *)d; - char version[256]; - if (linphone_gtk_create_version(version_url,version,sizeof(version))==0){ - if (version_compare(version,LINPHONE_VERSION)>0){ - const char *download_site=linphone_gtk_get_ui_config("download_site",NULL); - if (download_site) { - gdk_threads_enter(); - g_idle_add((GSourceFunc)popup_new_version,(gpointer)download_site); - gdk_threads_leave(); - } - }else{ - if (linphone_gtk_get_ui_config_int("update_check_menu",0)){ - gdk_threads_enter(); - g_idle_add((GSourceFunc)popup_version_ok,NULL); - gdk_threads_leave(); - } - } - } - return NULL; -} - -void linphone_gtk_check_for_new_version(void){ - ortp_thread_t thread; - static gboolean done=FALSE; - const char *version_url; - if (done) return; - done=TRUE; - version_url=linphone_gtk_get_ui_config("last_version_url",NULL); - if (version_url==NULL) return ; - ortp_thread_create(&thread,NULL,check_for_new_version,(void*)version_url); -} - -/*called when the user clicks on the "Check for updates" menu item */ -void linphone_gtk_check_for_updates(void){ - linphone_gtk_check_for_new_version(); -} diff --git a/gtk/utils.c b/gtk/utils.c deleted file mode 100644 index f3e19efda..000000000 --- a/gtk/utils.c +++ /dev/null @@ -1,178 +0,0 @@ -/* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" - -static void run_gtk(void){ - while (gtk_events_pending ()) - gtk_main_iteration (); - -} - -void *linphone_gtk_wait(LinphoneCore *lc, void *ctx, LinphoneWaitingState ws, const char *purpose, float progress){ - GtkWidget *w; - switch(ws){ - case LinphoneWaitingStart: - gdk_threads_enter(); - w=linphone_gtk_create_window("waiting", NULL); - gtk_window_set_transient_for(GTK_WINDOW(w),GTK_WINDOW(linphone_gtk_get_main_window())); - gtk_window_set_position(GTK_WINDOW(w),GTK_WIN_POS_CENTER_ON_PARENT); - if (purpose) { - gtk_progress_bar_set_text( - GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")), - purpose); - } - gtk_widget_show(w); - /*g_message("Creating waiting window");*/ - run_gtk(); - gdk_threads_leave(); - return w; - break; - case LinphoneWaitingProgress: - w=(GtkWidget*)ctx; - gdk_threads_enter(); - if (progress>=0){ - gtk_progress_bar_set_fraction( - GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")), - progress); - - - }else { - gtk_progress_bar_pulse( - GTK_PROGRESS_BAR(linphone_gtk_get_widget(w,"progressbar")) - ); - } - /*g_message("Updating progress");*/ - run_gtk(); - gdk_threads_leave(); - g_usleep(50000); - return w; - break; - case LinphoneWaitingFinished: - w=(GtkWidget*)ctx; - gdk_threads_enter(); - gtk_widget_destroy(w); - run_gtk(); - gdk_threads_leave(); - return NULL; - break; - } - return NULL; -} - -GdkPixbuf *_gdk_pixbuf_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio){ - GInputStream *stream=g_memory_input_stream_new_from_data (data,len,NULL); - GError *error=NULL; - - GdkPixbuf *pbuf=gdk_pixbuf_new_from_stream_at_scale (stream,w,h,preserve_ratio,NULL,&error); - g_input_stream_close(stream,NULL,NULL); - g_object_unref(G_OBJECT(stream)); - if (pbuf==NULL){ - g_warning("Could not open image from memory"); - } - return pbuf; -} - -GtkWidget * _gtk_image_new_from_memory_at_scale(const void *data, gint len, gint w, gint h, gboolean preserve_ratio){ - GtkWidget *image; - GdkPixbuf *pbuf=_gdk_pixbuf_new_from_memory_at_scale(data,len,w,h,preserve_ratio); - if (pbuf==NULL) return NULL; - image=gtk_image_new_from_pixbuf(pbuf); - g_object_unref(G_OBJECT(pbuf)); - return image; -} - -void linphone_gtk_reload_sound_devices(void){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *pb=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters"); - linphone_core_reload_sound_devices(linphone_gtk_get_core()); - if (pb) linphone_gtk_fill_soundcards(pb); -} - -void linphone_gtk_reload_video_devices(void){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *pb=(GtkWidget*)g_object_get_data(G_OBJECT(mw),"parameters"); - linphone_core_reload_video_devices(linphone_gtk_get_core()); - if (pb) linphone_gtk_fill_webcams(pb); -} - -bool_t linphone_gtk_is_friend(LinphoneCore *lc, const char *contact) { - LinphoneAddress *addr = linphone_core_interpret_url(lc, contact); - if (addr) { - char *uri = linphone_address_as_string_uri_only(addr); - LinphoneFriend *lf = linphone_core_get_friend_by_address(lc, uri); - linphone_address_unref(addr); - if (uri) ms_free(uri); - if (lf) return TRUE; - } - return FALSE; -} - -#ifdef HAVE_LIBUDEV_H - -static struct udev *udevroot=NULL; -static struct udev_monitor *monitor=NULL; -static GIOChannel *monitor_channel=NULL; -static guint monitor_src_id; - -#include - -static gboolean on_monitor_data(GIOChannel *chan, GIOCondition cond, void *userdata){ - struct udev_device *dev=udev_monitor_receive_device(monitor); - const char *subsys=udev_device_get_subsystem(dev); - const char *type=udev_device_get_action(dev); - g_message("USB event arrived for class %s of action type %s",subsys,type); - if (strcmp(subsys,"sound")==0) linphone_gtk_reload_sound_devices(); - if (strcmp(subsys,"video4linux")==0) linphone_gtk_reload_video_devices(); - udev_device_unref(dev); - return TRUE; -} - -void linphone_gtk_monitor_usb(void){ - int fd; - udevroot=udev_new(); - if (!udevroot) return; - monitor=udev_monitor_new_from_netlink(udevroot,"udev"); - udev_monitor_filter_add_match_subsystem_devtype(monitor,"sound",NULL); - udev_monitor_filter_add_match_subsystem_devtype(monitor,"video4linux",NULL); - fd=udev_monitor_get_fd(monitor); - monitor_channel=g_io_channel_unix_new(fd); - monitor_src_id=g_io_add_watch(monitor_channel,G_IO_IN,on_monitor_data,NULL); - udev_monitor_enable_receiving(monitor); -} - -void linphone_gtk_unmonitor_usb(void){ - if (monitor) udev_monitor_unref(monitor); - if (udevroot) udev_unref(udevroot); - if (monitor_channel) { - g_source_remove(monitor_src_id); - g_io_channel_unref(monitor_channel); - } -} - -#else - -void linphone_gtk_monitor_usb(void){ -} -void linphone_gtk_unmonitor_usb(void){ -} - -#endif - - diff --git a/gtk/videowindow.c b/gtk/videowindow.c deleted file mode 100644 index f7077041b..000000000 --- a/gtk/videowindow.c +++ /dev/null @@ -1,394 +0,0 @@ -/* -linphone, gtk interface. -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#include "linphone.h" - -#ifdef GDK_WINDOWING_X11 -#include -#elif defined(_WIN32) -#include -#elif defined(__APPLE__) -extern void *gdk_quartz_window_get_nswindow(GdkWindow *window); -extern void *gdk_quartz_window_get_nsview(GdkWindow *window); -#endif - -#include - -enum { - TARGET_STRING, - TARGET_TEXT, - TARGET_URILIST -}; - -static GtkTargetEntry targets[] = { - { "text/uri-list", GTK_TARGET_OTHER_APP, TARGET_URILIST }, -}; - -static void set_video_controls_position(GtkWidget *video_window); - -static void on_end_of_play(LinphonePlayer *player){ - linphone_player_close(player); -} - -static void drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, - GtkSelectionData *selection_data, guint target_type, guint time, gpointer user_data){ - int datalen=gtk_selection_data_get_length(selection_data); - const void *data=gtk_selection_data_get_data(selection_data); - LinphoneCall *call=g_object_get_data(G_OBJECT(widget),"call"); - - ms_message("target_type=%i, datalen=%i, data=%p",target_type,datalen,data); - if (target_type==TARGET_URILIST && data){ - LinphonePlayer *player=linphone_call_get_player(call); - char *path=ms_strdup(data); - while (datalen&&(path[datalen-1]=='\r'||path[datalen-1]=='\n')) { - path[datalen-1]='\0'; - datalen--; - } - if (player){ - LinphonePlayerCbs *cbs = linphone_player_get_callbacks(player); - linphone_player_cbs_set_eof_reached(cbs, on_end_of_play); - const char* filepath = (strstr(path,"file://")==path) ? path+strlen("file://") : path; - if (linphone_player_open(player,filepath)==0){ - - linphone_player_start(player); - }else{ - GtkWidget *warn=gtk_message_dialog_new(GTK_WINDOW(widget),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, - _("Cannot play %s."),filepath); - g_signal_connect(warn,"response",(GCallback)gtk_widget_destroy,NULL); - gtk_widget_show(warn); - } - } - ms_free(path); - } - gtk_drag_finish (context, TRUE, FALSE, time); -} - -static gboolean drag_drop(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, guint time, gpointer user_data){ -#if GTK_CHECK_VERSION(2,21,0) - GList *l=gdk_drag_context_list_targets(drag_context); - GList *elem; - - if (l){ - ms_message("drag_drop"); - /* Choose the best target type */ - for(elem=l;elem!=NULL;elem=g_list_next(elem)){ - char *name=gdk_atom_name(GDK_POINTER_TO_ATOM(elem->data)); - ms_message("target: %s",name); - g_free(name); - } - }else{ - ms_warning("drag_drop no targets"); - return FALSE; - } -#endif - return TRUE; -} - -static void *get_native_handle(GdkWindow *gdkw){ -#ifdef GDK_WINDOWING_X11 - return (void *)GDK_WINDOW_XID(gdkw); -#elif defined(_WIN32) - return (void *)GDK_WINDOW_HWND(gdkw); -#elif defined(__APPLE__) - return (void *)gdk_quartz_window_get_nsview(gdkw); -#endif - g_warning("No way to get the native handle from gdk window"); - return 0; -} - -static void _resize_video_window(GtkWidget *video_window, MSVideoSize vsize){ - MSVideoSize cur; - gtk_window_get_size(GTK_WINDOW(video_window),&cur.width,&cur.height); - if (vsize.width*vsize.height > cur.width*cur.height || - ms_video_size_get_orientation(vsize)!=ms_video_size_get_orientation(cur) ){ - gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height); - } -} - -static gboolean resize_video_window(LinphoneCall *call){ - const LinphoneCallParams *params=linphone_call_get_current_params(call); - if (params){ - MSVideoSize vsize=linphone_call_params_get_received_video_size(params); - if (vsize.width>0 && vsize.height>0){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window"); - if (video_window){ - _resize_video_window(video_window,vsize); - } - } - } - return TRUE; -} - -static void on_video_window_destroy(GtkWidget *w, guint timeout){ - g_source_remove(timeout); - linphone_core_set_native_video_window_id(linphone_gtk_get_core(),LINPHONE_VIDEO_DISPLAY_NONE); -} - -static void video_window_set_fullscreen(GtkWidget *w, gboolean val){ - if (val){ - g_object_set_data(G_OBJECT(w),"fullscreen",GINT_TO_POINTER(1)); - gtk_window_fullscreen(GTK_WINDOW(w)); - }else{ - g_object_set_data(G_OBJECT(w),"fullscreen",GINT_TO_POINTER(0)); - gtk_window_unfullscreen(GTK_WINDOW(w)); - } -} -/*old names in old version of gdk*/ -#ifndef GDK_KEY_Escape -#define GDK_KEY_Escape GDK_Escape -#define GDK_KEY_F GDK_F -#define GDK_KEY_f GDK_f -#endif - -static void on_video_window_key_press(GtkWidget *w, GdkEvent *ev, gpointer up){ - g_message("Key press event"); - switch(ev->key.keyval){ - case GDK_KEY_f: - case GDK_KEY_F: - video_window_set_fullscreen(w,TRUE); - break; - case GDK_KEY_Escape: - video_window_set_fullscreen(w,FALSE); - break; - } -} - -static void on_controls_response(GtkWidget *dialog, int response_id, GtkWidget *video_window){ - - gtk_widget_destroy(dialog); - switch(response_id){ - case GTK_RESPONSE_YES: - video_window_set_fullscreen(video_window,TRUE); - break; - case GTK_RESPONSE_NO: - video_window_set_fullscreen(video_window,FALSE); - break; - case GTK_RESPONSE_REJECT: - { - LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(video_window),"call"); - linphone_call_terminate(call); - } - break; - case GTK_RESPONSE_APPLY: - { - LinphoneCall *call=(LinphoneCall*)g_object_get_data(G_OBJECT(video_window),"call"); - char *path = (char *)linphone_gtk_get_snapshot_path(); - linphone_call_take_video_snapshot(call, path); - } - } - -} - -static gboolean on_controls_destroy(GtkWidget *w){ - GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(w),"video_window"); - gint timeout=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"timeout")); - if (timeout!=0){ - g_source_remove(timeout); - g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(0)); - } - if (video_window) { - g_object_set_data(G_OBJECT(video_window),"controls",NULL); - } - return FALSE; -} - -static gboolean _set_video_controls_position(GtkWidget *video_window){ - GtkWidget *w=(GtkWidget*)g_object_get_data(G_OBJECT(video_window),"controls"); - if (w){ - gint vw,vh; - gint cw,ch; - gint x,y; - gtk_window_get_size(GTK_WINDOW(video_window),&vw,&vh); - gtk_window_get_position(GTK_WINDOW(video_window),&x,&y); - gtk_window_get_size(GTK_WINDOW(w),&cw,&ch); - gtk_window_move(GTK_WINDOW(w),x+vw/2 - cw/2, y + vh - ch); - } - return FALSE; -} - -static void set_video_controls_position(GtkWidget *video_window){ - /*do it a first time*/ - _set_video_controls_position(video_window); - /*and schedule to do it a second time in order to workaround a bug in fullscreen mode, where poistion is not taken into account the first time*/ - g_timeout_add(0,(GSourceFunc)_set_video_controls_position,video_window); -} - -static gboolean video_window_moved(GtkWidget *widget, GdkEvent *event, gpointer user_data){ - /*Workaround to Video window bug on Windows. */ - /* set_video_controls_position(widget); */ - return FALSE; -} - -static gint do_gtk_widget_destroy(GtkWidget *w){ - gtk_widget_destroy(w); - return FALSE; -} - -static void schedule_video_controls_disapearance(GtkWidget *w){ - gint timeout=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"timeout")); - if (timeout != 0) g_source_remove(timeout); - timeout=g_timeout_add(3000,(GSourceFunc)do_gtk_widget_destroy,w); - g_object_set_data(G_OBJECT(w),"timeout",GINT_TO_POINTER(timeout)); -} - -static GtkWidget *show_video_controls(GtkWidget *video_window){ - GtkWidget *w; - w=(GtkWidget*)g_object_get_data(G_OBJECT(video_window),"controls"); - if (!w){ - gboolean isfullscreen=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(video_window),"fullscreen")); - const char *stock_button=isfullscreen ? GTK_STOCK_LEAVE_FULLSCREEN : GTK_STOCK_FULLSCREEN; - gint response_id=isfullscreen ? GTK_RESPONSE_NO : GTK_RESPONSE_YES ; - GtkWidget *image = gtk_image_new_from_icon_name(linphone_gtk_get_ui_config("stop_call_icon_name","linphone-stop-call"), GTK_ICON_SIZE_BUTTON); - GtkWidget *button; - w=gtk_dialog_new_with_buttons("",GTK_WINDOW(video_window),GTK_DIALOG_DESTROY_WITH_PARENT,stock_button,response_id,NULL); - gtk_window_set_opacity(GTK_WINDOW(w),0.5); - gtk_window_set_decorated(GTK_WINDOW(w),FALSE); - button=gtk_button_new_with_label(_("Hang up")); - gtk_button_set_image(GTK_BUTTON(button), image); - gtk_widget_show(button); - gtk_dialog_add_action_widget(GTK_DIALOG(w),button,GTK_RESPONSE_REJECT); - button=gtk_button_new_with_label(_("Take screenshot")); - image = gtk_image_new_from_icon_name("linphone-take-screenshot", GTK_ICON_SIZE_BUTTON); - gtk_button_set_image(GTK_BUTTON(button), image); - gtk_widget_show(button); - gtk_dialog_add_action_widget(GTK_DIALOG(w),button,GTK_RESPONSE_APPLY); - g_signal_connect(w,"response",(GCallback)on_controls_response,video_window); - schedule_video_controls_disapearance(w); - g_signal_connect(w,"destroy",(GCallback)on_controls_destroy,NULL); - g_object_set_data(G_OBJECT(w),"video_window",video_window); - g_object_set_data(G_OBJECT(video_window),"controls",w); - set_video_controls_position(video_window); - gtk_widget_show(w); - }else{ - schedule_video_controls_disapearance(w); - } - return w; -} - -static GtkWidget *create_video_window(LinphoneCall *call){ - char *remote,*title; - GtkWidget *video_window; - const LinphoneAddress *addr; - guint timeout; - MSVideoSize vsize={MS_VIDEO_SIZE_CIF_W,MS_VIDEO_SIZE_CIF_H}; - GdkColor color; - - addr=linphone_call_get_remote_address(call); - remote=linphone_gtk_address(addr); - video_window=gtk_window_new(GTK_WINDOW_TOPLEVEL); - /*gtk_window_set_transient_for(GTK_WINDOW(video_window), GTK_WINDOW(linphone_gtk_get_main_window()));*/ - title=g_strdup_printf("%s - Video call with %s",linphone_gtk_get_ui_config("title","Linphone"),remote); - ms_free(remote); - gtk_window_set_title(GTK_WINDOW(video_window),title); - g_free(title); - gtk_window_resize(GTK_WINDOW(video_window),vsize.width,vsize.height); - gdk_color_parse("black",&color); - gtk_widget_modify_bg(video_window,GTK_STATE_NORMAL,&color); - - gtk_drag_dest_set(video_window, GTK_DEST_DEFAULT_ALL, targets, sizeof(targets)/sizeof(GtkTargetEntry), GDK_ACTION_COPY); - gtk_widget_show(video_window); - gdk_window_set_events(gtk_widget_get_window(video_window), - gdk_window_get_events(gtk_widget_get_window(video_window)) | GDK_POINTER_MOTION_MASK); - timeout=g_timeout_add(500,(GSourceFunc)resize_video_window,call); - g_signal_connect(video_window,"destroy",(GCallback)on_video_window_destroy,GINT_TO_POINTER(timeout)); - g_signal_connect(video_window,"key-press-event",(GCallback)on_video_window_key_press,NULL); - g_signal_connect_swapped(video_window,"motion-notify-event",(GCallback)show_video_controls,video_window); - g_signal_connect(video_window,"configure-event",(GCallback)video_window_moved,NULL); - g_signal_connect(video_window, "drag-data-received",(GCallback)drag_data_received, NULL); - g_signal_connect(video_window, "drag-drop",(GCallback)drag_drop, NULL); - g_object_set_data(G_OBJECT(video_window),"call",call); - return video_window; -} - -void linphone_gtk_in_call_show_video(LinphoneCall *call){ - GtkWidget *callview=(GtkWidget*)linphone_call_get_user_pointer(call); - GtkWidget *video_window=(GtkWidget*)g_object_get_data(G_OBJECT(callview),"video_window"); - const LinphoneCallParams *params=linphone_call_get_current_params(call); - LinphoneCore *lc=linphone_gtk_get_core(); - - if (((bool_t)lp_config_get_int(linphone_core_get_config(lc), "video", "rtp_io", FALSE)) == FALSE) { - if (linphone_call_get_state(call)!=LinphoneCallPaused && params && linphone_call_params_video_enabled(params)){ - if (video_window==NULL){ - video_window=create_video_window(call); - g_object_set_data(G_OBJECT(callview),"video_window",video_window); - } - linphone_core_set_native_video_window_id(lc,get_native_handle(gtk_widget_get_window(video_window))); - gtk_window_present(GTK_WINDOW(video_window)); - }else{ - if (video_window){ - gtk_widget_destroy(video_window); - g_object_set_data(G_OBJECT(callview),"video_window",NULL); - } - } - } -} - -static void on_video_preview_destroyed(GtkWidget *video_preview, GtkWidget *mw){ - LinphoneCore *lc=linphone_gtk_get_core(); - guint timeout_id=GPOINTER_TO_INT(g_object_get_data(G_OBJECT(video_preview),"timeout-id")); - g_object_set_data(G_OBJECT(mw),"video_preview",NULL); - linphone_core_enable_video_preview(lc,FALSE); - linphone_core_set_native_preview_window_id(lc,(void *)(unsigned long)-1); - g_source_remove(timeout_id); -} - -GtkWidget *linphone_gtk_get_camera_preview_window(void){ - return (GtkWidget *)g_object_get_data(G_OBJECT(linphone_gtk_get_main_window()),"video_preview"); -} - -static gboolean check_preview_size(GtkWidget *video_preview){ - MSVideoSize vsize=linphone_core_get_current_preview_video_size(linphone_gtk_get_core()); - if (vsize.width && vsize.height){ - MSVideoSize cur; - gtk_window_get_size(GTK_WINDOW(video_preview),&cur.width,&cur.height); - if (cur.width!=vsize.width || cur.height!=vsize.height){ - gtk_window_resize(GTK_WINDOW(video_preview),vsize.width,vsize.height); - } - } - return TRUE; -} - -void linphone_gtk_show_camera_preview_clicked(GtkButton *button){ - GtkWidget *mw=linphone_gtk_get_main_window(); - GtkWidget *video_preview=(GtkWidget *)g_object_get_data(G_OBJECT(mw),"video_preview"); - - if (!video_preview){ - gchar *title; - LinphoneCore *lc=linphone_gtk_get_core(); - GdkColor color; - guint tid; - - video_preview=gtk_window_new(GTK_WINDOW_TOPLEVEL); - title=g_strdup_printf("%s - Video preview",linphone_gtk_get_ui_config("title","Linphone")); - gtk_window_set_title(GTK_WINDOW(video_preview),title); - gdk_color_parse("black",&color); - gtk_widget_modify_bg(video_preview,GTK_STATE_NORMAL,&color); - g_free(title); - g_object_set_data(G_OBJECT(mw),"video_preview",video_preview); - g_signal_connect(video_preview,"destroy",(GCallback)on_video_preview_destroyed,mw); - gtk_widget_show(video_preview); - linphone_core_set_native_preview_window_id(lc,get_native_handle(gtk_widget_get_window(video_preview))); - linphone_core_enable_video_preview(lc,TRUE); - tid=g_timeout_add(100,(GSourceFunc)check_preview_size,video_preview); - g_object_set_data(G_OBJECT(video_preview),"timeout-id",GINT_TO_POINTER(tid)); - } -} - diff --git a/gtk/waiting.ui b/gtk/waiting.ui deleted file mode 100644 index d2ca9ad89..000000000 --- a/gtk/waiting.ui +++ /dev/null @@ -1,56 +0,0 @@ - - - - - Linphone - False - True - GTK_WIN_POS_CENTER_ON_PARENT - False - - - True - 0 - - - True - 12 - - - True - 5 - - - True - gtk-dialog-info - - - False - False - - - - - True - - - 5 - 1 - - - - - - - - - True - Please wait - True - GTK_JUSTIFY_CENTER - - - - - - diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 7ef51e9c8..3c289a42b 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -1,8 +1,8 @@ -############################################################################ +################################################################################ # CMakeLists.txt -# Copyright (C) 2010-2016 Belledonne Communications, Grenoble France +# Copyright (C) 2017 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 @@ -18,25 +18,23 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -############################################################################ +################################################################################ -set(HEADER_FILES - account_creator.h +set(ROOT_HEADER_FILES account_creator_service.h - address.h + account_creator.h auth_info.h buffer.h - call.h - callbacks.h call_log.h call_params.h call_stats.h + call.h + callbacks.h chat.h conference.h contactprovider.h - content.h - core.h core_utils.h + core.h defs.h dictionary.h error_info.h @@ -44,6 +42,7 @@ set(HEADER_FILES factory.h friend.h friendlist.h + headers.h im_encryption_engine.h im_notif_policy.h info_message.h @@ -64,24 +63,100 @@ set(HEADER_FILES video_definition.h wrapper_utils.h xmlrpc.h - headers.h # Deprecated header files - linphonecore.h - linphonecore_utils.h - linphonefriend.h - linphonepresence.h linphone_proxy_config.h linphone_tunnel.h + linphonecore_utils.h + linphonecore.h + linphonefriend.h + linphonepresence.h ) -set(LINPHONE_HEADER_FILES ) -foreach(HEADER_FILE ${HEADER_FILES}) - list(APPEND LINPHONE_HEADER_FILES "${CMAKE_CURRENT_LIST_DIR}/linphone/${HEADER_FILE}") -endforeach() -set(LINPHONE_HEADER_FILES ${LINPHONE_HEADER_FILES} PARENT_SCOPE) +set(C_API_HEADER_FILES + c-address.h + c-api.h + c-call-cbs.h + c-call-stats.h + c-call.h + c-callbacks.h + c-chat-message-cbs.h + c-chat-message.h + c-chat-room-cbs.h + c-chat-room.h + c-content.h + c-dial-plan.h + c-event-log.h + c-magic-search.h + c-participant.h + c-participant-imdn-state.h + c-search-result.h + c-types.h +) -install(FILES ${LINPHONE_HEADER_FILES} - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/linphone +set(ENUMS_HEADER_FILES + call-enums.h + chat-message-enums.h + chat-room-enums.h + event-log-enums.h +) + +set(UTILS_HEADER_FILES + algorithm.h + enum-generator.h + enum-mask.h + fs.h + general.h + magic-macros.h + traits.h + utils.h +) + +# ------------------------------------------------------------------------------ + +function (PREPEND OUT_LIST PREFIX) + set(TMP_LIST ) + foreach (FILENAME ${ARGN}) + list(APPEND TMP_LIST "${PREFIX}/${FILENAME}") + endforeach () + set(${OUT_LIST} "${TMP_LIST}" PARENT_SCOPE) +endfunction () + +# ------------------------------------------------------------------------------ + +set(SRC_ROOT_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/linphone") + +PREPEND(ROOT_HEADER_FILES "${SRC_ROOT_DIRECTORY}" ${ROOT_HEADER_FILES}) +PREPEND(C_API_HEADER_FILES "${SRC_ROOT_DIRECTORY}/api" ${C_API_HEADER_FILES}) +PREPEND(ENUMS_HEADER_FILES "${SRC_ROOT_DIRECTORY}/enums" ${ENUMS_HEADER_FILES}) +PREPEND(UTILS_HEADER_FILES "${SRC_ROOT_DIRECTORY}/utils" ${UTILS_HEADER_FILES}) + +set(LINPHONE_HEADER_FILES ${ROOT_HEADER_FILES} ${C_API_HEADER_FILES} ${ENUMS_HEADER_FILES} ${UTILS_HEADER_FILES} PARENT_SCOPE) +set(LINPHONE_HEADER_ROOT_DIR "${CMAKE_CURRENT_LIST_DIR}" PARENT_SCOPE) + +# ------------------------------------------------------------------------------ +if (IOS AND ENABLE_SHARED) + #cmake 3.10 seems not able to handle subdirectories for PUBLIC_HEADER. My be rework in the futur + set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_PREFIX}/Frameworks/linphone.framework/Headers") +else() + set(DEST_ROOT_DIRECTORY "${CMAKE_INSTALL_INCLUDEDIR}/linphone") +endif() + +install(FILES ${ROOT_HEADER_FILES} + DESTINATION "${DEST_ROOT_DIRECTORY}" + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ +) + +install(FILES ${C_API_HEADER_FILES} + DESTINATION "${DEST_ROOT_DIRECTORY}/api" + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ +) +install(FILES ${ENUMS_HEADER_FILES} + DESTINATION "${DEST_ROOT_DIRECTORY}/enums" + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ +) + +install(FILES ${UTILS_HEADER_FILES} + DESTINATION "${DEST_ROOT_DIRECTORY}/utils" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) diff --git a/include/linphone/Makefile.am b/include/linphone/Makefile.am index dc9488e0b..56c2c3dda 100644 --- a/include/linphone/Makefile.am +++ b/include/linphone/Makefile.am @@ -14,7 +14,6 @@ linphone_include_HEADERS=\ chat.h \ conference.h \ contactprovider.h \ - content.h \ core.h \ core_utils.h \ defs.h \ diff --git a/include/linphone/account_creator.h b/include/linphone/account_creator.h index bf5e5fc5a..3d1a7644b 100644 --- a/include/linphone/account_creator.h +++ b/include/linphone/account_creator.h @@ -1,6 +1,6 @@ /* account_creator.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -33,302 +33,302 @@ extern "C" { /** * Callback to notify a response of server. - * @param[in] creator LinphoneAccountCreator object - * @param[in] status The status of the LinphoneAccountCreator test existence operation that has just finished + * @param[in] creator #LinphoneAccountCreator object + * @param[in] status The status of the #LinphoneAccountCreator test existence operation that has just finished **/ typedef void (*LinphoneAccountCreatorCbsStatusCb)(LinphoneAccountCreator *creator, LinphoneAccountCreatorStatus status, const char* resp); /************************** Start Account Creator data **************************/ /** - * Create a LinphoneAccountCreator and set Linphone Request callbacks. - * @param[in] core The LinphoneCore used for the XML-RPC communication + * Create a #LinphoneAccountCreator and set Linphone Request callbacks. + * @param[in] core The #LinphoneCore used for the XML-RPC communication * @param[in] xmlrpc_url The URL to the XML-RPC server. Must be NON NULL. - * @return The new LinphoneAccountCreator object. + * @return The new #LinphoneAccountCreator object. **/ LINPHONE_PUBLIC LinphoneAccountCreator * linphone_account_creator_new(LinphoneCore *core, const char *xmlrpc_url); /** * Reset the account creator entries like username, password, phone number... - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object **/ LINPHONE_PUBLIC void linphone_account_creator_reset(LinphoneAccountCreator *creator); /** * Send a request to know the existence of account on server. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_exist(LinphoneAccountCreator *creator); /** * Send a request to create an account on server. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_create_account(LinphoneAccountCreator *creator); /** * Send a request to know if an account is activated on server. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_activated(LinphoneAccountCreator *creator); /** * Send a request to activate an account on server. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_account(LinphoneAccountCreator *creator); /** * Send a request to link an account to an alias. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_link_account(LinphoneAccountCreator *creator); /** * Send a request to activate an alias. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_activate_alias(LinphoneAccountCreator *creator); /** * Send a request to know if an alias is used. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_alias_used(LinphoneAccountCreator *creator); /** * Send a request to know if an account is linked. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_is_account_linked(LinphoneAccountCreator *creator); /** * Send a request to recover an account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_recover_account(LinphoneAccountCreator *creator); /** * Send a request to update an account. - * @param[in] creator LinphoneAccountCreator object - * @return LinphoneAccountCreatorStatusRequestOk if the request has been sent, LinphoneAccountCreatorStatusRequestFailed otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return #LinphoneAccountCreatorStatusRequestOk if the request has been sent, #LinphoneAccountCreatorStatusRequestFailed otherwise **/ LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_update_account(LinphoneAccountCreator *creator); /** * Acquire a reference to the LinphoneAccountCreator. - * @param[in] creator LinphoneAccountCreator object. - * @return The same LinphoneAccountCreator object. + * @param[in] creator #LinphoneAccountCreator object. + * @return The same #LinphoneAccountCreator object. **/ LINPHONE_PUBLIC LinphoneAccountCreator * linphone_account_creator_ref(LinphoneAccountCreator *creator); /** * Release reference to the LinphoneAccountCreator. - * @param[in] creator LinphoneAccountCreator object. + * @param[in] creator #LinphoneAccountCreator object. **/ LINPHONE_PUBLIC void linphone_account_creator_unref(LinphoneAccountCreator *creator); /** * Retrieve the user pointer associated with the LinphoneAccountCreator. - * @param[in] creator LinphoneAccountCreator object. + * @param[in] creator #LinphoneAccountCreator object. * @return The user pointer associated with the LinphoneAccountCreator. **/ LINPHONE_PUBLIC void *linphone_account_creator_get_user_data(const LinphoneAccountCreator *creator); /** * Assign a user pointer to the LinphoneAccountCreator. - * @param[in] creator LinphoneAccountCreator object. + * @param[in] creator #LinphoneAccountCreator object. * @param[in] ud The user pointer to associate with the LinphoneAccountCreator. **/ LINPHONE_PUBLIC void linphone_account_creator_set_user_data(LinphoneAccountCreator *creator, void *ud); /** * Set the username. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] username The username to set - * @return LinphoneAccountCreatorUsernameStatusOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorUsernameStatusOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorUsernameStatus linphone_account_creator_set_username(LinphoneAccountCreator *creator, const char *username); /** * Get the username. - * @param[in] creator LinphoneAccountCreator object - * @return The username of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The username of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_username(const LinphoneAccountCreator *creator); /** * Set the phone number normalized. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] phone_number The phone number to set * @param[in] country_code Country code to associate phone number with - * @return LinphoneAccountCreatorPhoneNumberStatusOk if everything is OK, or specific(s) error(s) otherwise. + * @return #LinphoneAccountCreatorPhoneNumberStatusOk if everything is OK, or specific(s) error(s) otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorPhoneNumberStatusMask linphone_account_creator_set_phone_number(LinphoneAccountCreator *creator, const char *phone_number, const char *country_code); /** * Get the RFC 3966 normalized phone number. - * @param[in] creator LinphoneAccountCreator object - * @return The phone number of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The phone number of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_phone_number(const LinphoneAccountCreator *creator); /** * Set the password. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] password The password to set - * @return LinphoneAccountCreatorPasswordStatusOk if everything is OK, or specific(s) error(s) otherwise. + * @return #LinphoneAccountCreatorPasswordStatusOk if everything is OK, or specific(s) error(s) otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorPasswordStatus linphone_account_creator_set_password(LinphoneAccountCreator *creator, const char *password); /** * Get the password. - * @param[in] creator LinphoneAccountCreator object - * @return The password of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The password of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_password(const LinphoneAccountCreator *creator); /** * Set the ha1. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] ha1 The ha1 to set - * @return LinphoneAccountCreatorPasswordStatusOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorPasswordStatusOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorPasswordStatus linphone_account_creator_set_ha1(LinphoneAccountCreator *creator, const char *ha1); /** * Get the ha1. - * @param[in] creator LinphoneAccountCreator object - * @return The ha1 of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The ha1 of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_ha1(const LinphoneAccountCreator *creator); /** * Set the activation code. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] activation_code The activation code to set - * @return LinphoneAccountCreatorActivationCodeStatusOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorActivationCodeStatusOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorActivationCodeStatus linphone_account_creator_set_activation_code(LinphoneAccountCreator *creator, const char *activation_code); /** * Get the activation code. - * @param[in] creator LinphoneAccountCreator object - * @return The activation code of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The activation code of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_activation_code(const LinphoneAccountCreator *creator); /** * Set the language to use in email or SMS if supported. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] lang The language to use - * @return LinphoneAccountCreatorLanguageStatusOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorLanguageStatusOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorLanguageStatus linphone_account_creator_set_language(LinphoneAccountCreator *creator, const char *lang); /** * Get the language use in email of SMS. - * @param[in] creator LinphoneAccountCreator object - * @return The language of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The language of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_language(const LinphoneAccountCreator *creator); /** * Set the display name. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] display_name The display name to set - * @return LinphoneAccountCreatorUsernameStatusOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorUsernameStatusOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorUsernameStatus linphone_account_creator_set_display_name(LinphoneAccountCreator *creator, const char *display_name); /** * Get the display name. - * @param[in] creator LinphoneAccountCreator object - * @return The display name of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The display name of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_display_name(const LinphoneAccountCreator *creator); /** * Set the email. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] email The email to set - * @return LinphoneAccountCreatorEmailStatusOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorEmailStatusOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorEmailStatus linphone_account_creator_set_email(LinphoneAccountCreator *creator, const char *email); /** * Get the email. - * @param[in] creator LinphoneAccountCreator object - * @return The email of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The email of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_email(const LinphoneAccountCreator *creator); /** * Set the domain. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] domain The domain to set - * @return LinphoneAccountCreatorDomainOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorDomainOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorDomainStatus linphone_account_creator_set_domain(LinphoneAccountCreator *creator, const char *domain); /** * Get the domain. - * @param[in] creator LinphoneAccountCreator object - * @return The domain of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The domain of the #LinphoneAccountCreator **/ LINPHONE_PUBLIC const char * linphone_account_creator_get_domain(const LinphoneAccountCreator *creator); /** * Set Transport - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] transport The transport to set - * @return LinphoneAccountCreatorTransportOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorTransportOk if everything is OK, or a specific error otherwise. **/ LINPHONE_PUBLIC LinphoneAccountCreatorTransportStatus linphone_account_creator_set_transport(LinphoneAccountCreator *creator, LinphoneTransportType transport); /** * get Transport - * @param[in] creator LinphoneAccountCreator object - * @return The transport of LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The transport of #LinphoneAccountCreator **/ LINPHONE_PUBLIC LinphoneTransportType linphone_account_creator_get_transport(const LinphoneAccountCreator *creator); /** * Set the route. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object * @param[in] route The route to set - * @return LinphoneAccountCreatorStatusRequestOk if everything is OK, or a specific error otherwise. + * @return #LinphoneAccountCreatorStatusRequestOk if everything is OK, or a specific error otherwise. **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneAccountCreatorStatus linphone_account_creator_set_route(LinphoneAccountCreator *creator, const char *route); /** * Get the route. - * @param[in] creator LinphoneAccountCreator object - * @return The route of the LinphoneAccountCreator + * @param[in] creator #LinphoneAccountCreator object + * @return The route of the #LinphoneAccountCreator **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC const char * linphone_account_creator_get_route(const LinphoneAccountCreator *creator); /** - * Get the LinphoneAccountCreatorCbs object associated with a LinphoneAccountCreator. - * @param[in] creator LinphoneAccountCreator object - * @return The LinphoneAccountCreatorCbs object associated with the LinphoneAccountCreator. + * Get the #LinphoneAccountCreatorCbs object associated with a LinphoneAccountCreator. + * @param[in] creator #LinphoneAccountCreator object + * @return The #LinphoneAccountCreatorCbs object associated with the LinphoneAccountCreator. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbs * linphone_account_creator_get_callbacks(const LinphoneAccountCreator *creator); /** - * Get the LinphoneAccountCreatorService object associated with a LinphoneAccountCreator. - * @param[in] creator LinphoneAccountCreator object - * @return The LinphoneAccountCreatorService object associated with the LinphoneAccountCreator. + * Get the #LinphoneAccountCreatorService object associated with a LinphoneAccountCreator. + * @param[in] creator #LinphoneAccountCreator object + * @return The #LinphoneAccountCreatorService object associated with the LinphoneAccountCreator. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorService * linphone_account_creator_get_service(const LinphoneAccountCreator *creator); @@ -338,168 +338,168 @@ LINPHONE_PUBLIC LinphoneAccountCreatorService * linphone_account_creator_get_ser /************************** Start Account Creator Cbs **************************/ /** - * Acquire a reference to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. - * @return The same LinphoneAccountCreatorCbs object. + * Acquire a reference to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. + * @return The same #LinphoneAccountCreatorCbs object. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbs * linphone_account_creator_cbs_ref(LinphoneAccountCreatorCbs *cbs); /** - * Release a reference to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Release a reference to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_unref(LinphoneAccountCreatorCbs *cbs); /** - * Retrieve the user pointer associated with a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. - * @return The user pointer associated with the LinphoneAccountCreatorCbs object. + * Retrieve the user pointer associated with a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. + * @return The user pointer associated with the #LinphoneAccountCreatorCbs object. **/ LINPHONE_PUBLIC void *linphone_account_creator_cbs_get_user_data(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. - * @param[in] ud The user pointer to associate with the LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. + * @param[in] ud The user pointer to associate with the #LinphoneAccountCreatorCbs object. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_user_data(LinphoneAccountCreatorCbs *cbs, void *ud); /** * Get the create account request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current create account request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_create_account(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The create account request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_create_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the is account exist request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current is account exist request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_exist(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The is account exist request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_is_account_exist(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the activate account request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current activate account request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_activate_account(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The activate account request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_activate_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the is account activated request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current is account activated request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_activated(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The is account activated request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_is_account_activated(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the link account request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current link account request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_link_account(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The link account request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_link_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the activate alias request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current link account request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_activate_alias(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The activate alias request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_activate_alias(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the is alias used request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current is alias used request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_alias_used(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The is alias used request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_is_alias_used(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the is account linked request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current is account linked request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_is_account_linked(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The is account linked request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_is_account_linked(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the recover account request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current recover account request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_recover_account(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The recover account request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_recover_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); /** * Get the update account request. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @return The current update account request. **/ LINPHONE_PUBLIC LinphoneAccountCreatorCbsStatusCb linphone_account_creator_cbs_get_update_account(const LinphoneAccountCreatorCbs *cbs); /** - * Assign a user pointer to a LinphoneAccountCreatorCbs object. - * @param[in] cbs LinphoneAccountCreatorCbs object. + * Assign a user pointer to a #LinphoneAccountCreatorCbs object. + * @param[in] cbs #LinphoneAccountCreatorCbs object. * @param[in] cb The update account request to be used. **/ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_update_account(LinphoneAccountCreatorCbs *cbs, LinphoneAccountCreatorCbsStatusCb cb); @@ -508,15 +508,15 @@ LINPHONE_PUBLIC void linphone_account_creator_cbs_set_update_account(LinphoneAcc /** * Create and configure a proxy config and a authentication info for an account creator - * @param[in] creator LinphoneAccountCreator object - * @return A LinphoneProxyConfig object if successful, NULL otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return A #LinphoneProxyConfig object if successful, NULL otherwise **/ LINPHONE_PUBLIC LinphoneProxyConfig * linphone_account_creator_create_proxy_config(const LinphoneAccountCreator *creator); /** * Configure an account (create a proxy config and authentication info for it). - * @param[in] creator LinphoneAccountCreator object - * @return A LinphoneProxyConfig object if successful, NULL otherwise + * @param[in] creator #LinphoneAccountCreator object + * @return A #LinphoneProxyConfig object if successful, NULL otherwise **/ LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneProxyConfig * linphone_account_creator_configure(const LinphoneAccountCreator *creator); diff --git a/include/linphone/account_creator_service.h b/include/linphone/account_creator_service.h index 1896dee92..f21650088 100644 --- a/include/linphone/account_creator_service.h +++ b/include/linphone/account_creator_service.h @@ -28,7 +28,7 @@ extern "C" { /** * Function to set custom server request. - * @param[in] creator LinphoneAccountCreator object + * @param[in] creator #LinphoneAccountCreator object */ typedef LinphoneAccountCreatorStatus (*LinphoneAccountCreatorRequestFunc)(LinphoneAccountCreator *creator); @@ -40,46 +40,46 @@ typedef LinphoneAccountCreatorStatus (*LinphoneAccountCreatorRequestFunc)(Linpho /************************** Start Account Creator Requests **************************/ /** - * Create a new LinphoneAccountCreatorService object. - * @return a new LinphoneAccountCreatorService object. + * Create a new #LinphoneAccountCreatorService object. + * @return a new #LinphoneAccountCreatorService object. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorService * linphone_account_creator_service_new(void); /** - * Acquire a reference to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. - * @return The same LinphoneAccountCreatorService object. + * Acquire a reference to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. + * @return The same #LinphoneAccountCreatorService object. * @donotwrap **/ LinphoneAccountCreatorService * linphone_account_creator_service_ref(LinphoneAccountCreatorService *service); /** - * Release a reference to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Release a reference to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @donotwrap **/ void linphone_account_creator_service_unref(LinphoneAccountCreatorService *service); /** - * Retrieve the user pointer associated with a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. - * @return The user pointer associated with the LinphoneAccountCreatorService object. + * Retrieve the user pointer associated with a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. + * @return The user pointer associated with the #LinphoneAccountCreatorService object. * @donotwrap **/ LINPHONE_PUBLIC void *linphone_account_creator_service_get_user_data(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. - * @param[in] ud The user pointer to associate with the LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. + * @param[in] ud The user pointer to associate with the #LinphoneAccountCreatorService object. * @donotwrap **/ LINPHONE_PUBLIC void linphone_account_creator_service_set_user_data(LinphoneAccountCreatorService *service, void *ud); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The constructor of account creator requests. * @donotwrap **/ @@ -87,15 +87,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_constructor_cb(Linphon /** * Get the constructor of account creator requests. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current constructor of create account request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_constructor_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The destructor. * @donotwrap **/ @@ -103,7 +103,7 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_destructor_cb(Linphone /** * Get the destructor of create account request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current destructor of create account request. * @donotwrap **/ @@ -111,15 +111,15 @@ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_servi /** * Get the create account request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current create account request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_create_account_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The create account request to be used. * @donotwrap **/ @@ -127,15 +127,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_create_account_cb(Linp /** * Get the is account exist request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current is account exist request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_is_account_exist_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The is account exist request to be used. * @donotwrap **/ @@ -143,15 +143,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_is_account_exist_cb(Li /** * Get the activate account request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current activate account request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_activate_account_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The activate account request to be used. * @donotwrap **/ @@ -159,15 +159,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_activate_account_cb(Li /** * Get the is account activated request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current is account activated request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_is_account_activated_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The is account activated request to be used. * @donotwrap **/ @@ -175,15 +175,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_is_account_activated_c /** * Get the link account request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current link account request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_link_account_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The link account request to be used. * @donotwrap **/ @@ -191,15 +191,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_link_account_cb(Linpho /** * Get the activate alias request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current link account request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_activate_alias_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The activate alias request to be used. * @donotwrap **/ @@ -207,15 +207,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_activate_alias_cb(Linp /** * Get the is alias used request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current is alias used request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_is_alias_used_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The is alias used request to be used. * @donotwrap **/ @@ -223,15 +223,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_is_alias_used_cb(Linph /** * Get the is account linked request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current is account linked request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_is_account_linked_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The is account linked request to be used. * @donotwrap **/ @@ -239,15 +239,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_is_account_linked_cb(L /** * Get the recover account request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current recover account request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_recover_account_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The recover account request to be used. * @donotwrap **/ @@ -255,15 +255,15 @@ LINPHONE_PUBLIC void linphone_account_creator_service_set_recover_account_cb(Lin /** * Get the update account request. - * @param[in] service LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @return The current update account request. * @donotwrap **/ LINPHONE_PUBLIC LinphoneAccountCreatorRequestFunc linphone_account_creator_service_get_update_account_cb(const LinphoneAccountCreatorService *service); /** - * Assign a user pointer to a LinphoneAccountCreatorService object. - * @param[in] service LinphoneAccountCreatorService object. + * Assign a user pointer to a #LinphoneAccountCreatorService object. + * @param[in] service #LinphoneAccountCreatorService object. * @param[in] cb The update account request to be used. * @donotwrap **/ diff --git a/include/linphone/address.h b/include/linphone/address.h deleted file mode 100644 index f92ff36f3..000000000 --- a/include/linphone/address.h +++ /dev/null @@ -1,241 +0,0 @@ -/* -address.h -Copyright (C) 2010-2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef LINPHONE_ADDRESS_H -#define LINPHONE_ADDRESS_H - -#include "linphone/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @addtogroup linphone_address - * @{ - */ - -/** - * Constructs a LinphoneAddress object by parsing the user supplied address, - * given as a string. -**/ -LINPHONE_PUBLIC LinphoneAddress * linphone_address_new(const char *addr); - -/** - * Clones a LinphoneAddress object. -**/ -LINPHONE_PUBLIC LinphoneAddress * linphone_address_clone(const LinphoneAddress *addr); - -/** - * Increment reference count of LinphoneAddress object. -**/ -LINPHONE_PUBLIC LinphoneAddress * linphone_address_ref(LinphoneAddress *addr); - -/** - * Decrement reference count of LinphoneAddress object. When dropped to zero, memory is freed. -**/ -LINPHONE_PUBLIC void linphone_address_unref(LinphoneAddress *addr); - -/** - * Returns the address scheme, normally "sip". -**/ -LINPHONE_PUBLIC const char *linphone_address_get_scheme(const LinphoneAddress *u); - -/** - * Returns the display name. -**/ -LINPHONE_PUBLIC const char *linphone_address_get_display_name(const LinphoneAddress* u); - -/** - * Returns the username. -**/ -LINPHONE_PUBLIC const char *linphone_address_get_username(const LinphoneAddress *u); - -/** - * Returns the domain name. -**/ -LINPHONE_PUBLIC const char *linphone_address_get_domain(const LinphoneAddress *u); - -/** - * Get port number as an integer value, 0 if not present. - */ -LINPHONE_PUBLIC int linphone_address_get_port(const LinphoneAddress *u); - -/** - * Sets the display name. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_display_name(LinphoneAddress *u, const char *display_name); - -/** - * Sets the username. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_username(LinphoneAddress *uri, const char *username); - -/** - * Sets the domain. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_domain(LinphoneAddress *uri, const char *host); - -/** - * Sets the port number. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_port(LinphoneAddress *uri, int port); - -/** - * Set a transport. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_address_set_transport(LinphoneAddress *uri,LinphoneTransportType type); - -/** - * Removes address's tags and uri headers so that it is displayable to the user. -**/ -LINPHONE_PUBLIC void linphone_address_clean(LinphoneAddress *uri); - -/** - * Returns true if address refers to a secure location (sips) - * @deprecated use linphone_address_get_secure() - * @donotwrap -**/ -LINPHONE_DEPRECATED LINPHONE_PUBLIC bool_t linphone_address_is_secure(const LinphoneAddress *addr); - -/** - * Returns true if address refers to a secure location (sips) -**/ -LINPHONE_PUBLIC bool_t linphone_address_get_secure(const LinphoneAddress *addr); - -/** - * Make the address refer to a secure location (sips scheme) - * @param[in] addr A #LinphoneAddress object - * @param[in] enabled TRUE if address is requested to be secure. -**/ -LINPHONE_PUBLIC void linphone_address_set_secure(LinphoneAddress *addr, bool_t enabled); - -/** - * returns true if address is a routable sip address - */ -LINPHONE_PUBLIC bool_t linphone_address_is_sip(const LinphoneAddress *uri); - -/** - * Get the transport. -**/ -LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport(const LinphoneAddress *uri); - -/** - * Get the value of the method parameter -**/ -LINPHONE_PUBLIC const char *linphone_address_get_method_param(const LinphoneAddress *addr); - -/** - * Set the value of the method parameter -**/ -LINPHONE_PUBLIC void linphone_address_set_method_param(LinphoneAddress *addr, const char *method); - -/** - * Returns the address as a string. - * The returned char * must be freed by the application. Use ms_free(). -**/ -LINPHONE_PUBLIC char *linphone_address_as_string(const LinphoneAddress *u); - -/** - * Returns the SIP uri only as a string, that is display name is removed. - * The returned char * must be freed by the application. Use ms_free(). -**/ -LINPHONE_PUBLIC char *linphone_address_as_string_uri_only(const LinphoneAddress *u); - -/** - * Compare two LinphoneAddress ignoring tags and headers, basically just domain, username, and port. - * @param[in] a1 LinphoneAddress object - * @param[in] a2 LinphoneAddress object - * @return Boolean value telling if the LinphoneAddress objects are equal. - * @see linphone_address_equal() -**/ -LINPHONE_PUBLIC bool_t linphone_address_weak_equal(const LinphoneAddress *a1, const LinphoneAddress *a2); - -/** - * Compare two LinphoneAddress taking the tags and headers into account. - * @param[in] a1 LinphoneAddress object - * @param[in] a2 LinphoneAddress object - * @return Boolean value telling if the LinphoneAddress objects are equal. - * @see linphone_address_weak_equal() - */ -LINPHONE_PUBLIC bool_t linphone_address_equal(const LinphoneAddress *a1, const LinphoneAddress *a2); - -/** - * Set the password encoded in the address. - * It is used for basic authentication (not recommended). - * @param addr the LinphoneAddress - * @param passwd the password to set. -**/ -LINPHONE_PUBLIC void linphone_address_set_password(LinphoneAddress *addr, const char *passwd); - -/** - * Get the password encoded in the address. - * It is used for basic authentication (not recommended). - * @param addr the address - * @return the password, if any, NULL otherwise. -**/ -LINPHONE_PUBLIC const char *linphone_address_get_password(const LinphoneAddress *addr); - -/** - * Set a header into the address. - * Headers appear in the URI with '?', such as \. - * @param addr the address - * @param header_name the header name - * @param header_value the header value -**/ -LINPHONE_PUBLIC void linphone_address_set_header(LinphoneAddress *addr, const char *header_name, const char *header_value); - -/** - * Get the header encoded in the address. - * @param addr the address -**/ -LINPHONE_PUBLIC const char * linphone_address_get_header(const LinphoneAddress *addr, const char *name); - -LINPHONE_PUBLIC bool_t linphone_address_has_param(const LinphoneAddress *addr, const char *name); - -LINPHONE_PUBLIC const char * linphone_address_get_param(const LinphoneAddress *addr, const char *name); - -LINPHONE_PUBLIC void linphone_address_set_param(LinphoneAddress *addr, const char *name, const char *value); - -LINPHONE_PUBLIC void linphone_address_set_params(LinphoneAddress *addr, const char *params); - -LINPHONE_PUBLIC void linphone_address_set_uri_param(LinphoneAddress *addr, const char *name, const char *value); - -LINPHONE_PUBLIC void linphone_address_set_uri_params(LinphoneAddress *addr, const char *params); - -LINPHONE_PUBLIC bool_t linphone_address_has_uri_param(const LinphoneAddress *addr, const char *name); - -LINPHONE_PUBLIC const char * linphone_address_get_uri_param(const LinphoneAddress *addr, const char *name); - -/** - * Destroys a LinphoneAddress object (actually calls linphone_address_unref()). - * @deprecated Use linphone_address_unref() instead - * @donotwrap -**/ -LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_address_destroy(LinphoneAddress *u); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* LINPHONE_ADDRESS_H */ diff --git a/include/linphone/api/c-address.h b/include/linphone/api/c-address.h new file mode 100644 index 000000000..d4716c5b8 --- /dev/null +++ b/include/linphone/api/c-address.h @@ -0,0 +1,286 @@ +/* + * c-address.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_ADDRESS_H_ +#define _L_C_ADDRESS_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup linphone_address + * @{ + */ + +/** + * Constructs a #LinphoneAddress object by parsing the user supplied address, + * given as a string. + **/ +LINPHONE_PUBLIC LinphoneAddress *linphone_address_new (const char *address); + +/** + * Clones a #LinphoneAddress object. + **/ +LINPHONE_PUBLIC LinphoneAddress *linphone_address_clone (const LinphoneAddress *address); + +/** + * Increment reference count of #LinphoneAddress object. + **/ +LINPHONE_PUBLIC LinphoneAddress *linphone_address_ref (LinphoneAddress *address); + +/** + * Decrement reference count of #LinphoneAddress object. When dropped to zero, memory is freed. + **/ +LINPHONE_PUBLIC void linphone_address_unref (LinphoneAddress *address); + +/** + * Returns the address scheme, normally "sip". + **/ +LINPHONE_PUBLIC const char *linphone_address_get_scheme (const LinphoneAddress *address); + +/** + * Returns the display name. + **/ +LINPHONE_PUBLIC const char *linphone_address_get_display_name (const LinphoneAddress *address); + +/** + * Sets the display name. + **/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_display_name (LinphoneAddress *address, const char *display_name); + +/** + * Returns the username. + **/ +LINPHONE_PUBLIC const char *linphone_address_get_username (const LinphoneAddress *address); + +/** + * Sets the username. + **/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_username (LinphoneAddress *address, const char *username); + +/** + * Returns the domain name. + **/ +LINPHONE_PUBLIC const char *linphone_address_get_domain (const LinphoneAddress *address); + +/** + * Sets the domain. + **/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_domain (LinphoneAddress *address, const char *domain); + +/** + * Get port number as an integer value, 0 if not present. + */ +LINPHONE_PUBLIC int linphone_address_get_port (const LinphoneAddress *address); + +/** + * Sets the port number. + **/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_port (LinphoneAddress *address, int port); + +/** + * Get the transport. + **/ +LINPHONE_PUBLIC LinphoneTransportType linphone_address_get_transport (const LinphoneAddress *address); + +/** + * Set a transport. + **/ +LINPHONE_PUBLIC LinphoneStatus linphone_address_set_transport (LinphoneAddress *address, LinphoneTransportType transport); + +/** + * Returns true if address refers to a secure location (sips) + **/ +LINPHONE_PUBLIC bool_t linphone_address_get_secure (const LinphoneAddress *address); + +/** + * Make the address refer to a secure location (sips scheme) + * @param[in] address A #LinphoneAddress object + * @param[in] enabled TRUE if address is requested to be secure. + **/ +LINPHONE_PUBLIC void linphone_address_set_secure (LinphoneAddress *address, bool_t enabled); + +/** + * returns true if address is a routable sip address + */ +LINPHONE_PUBLIC bool_t linphone_address_is_sip (const LinphoneAddress *address); + +/** + * Get the value of the method parameter + **/ +LINPHONE_PUBLIC const char *linphone_address_get_method_param (const LinphoneAddress *address); + +/** + * Set the value of the method parameter + **/ +LINPHONE_PUBLIC void linphone_address_set_method_param (LinphoneAddress *address, const char *method_param); + +/** + * Get the password encoded in the address. + * It is used for basic authentication (not recommended). + * @param address the address + * @return the password, if any, NULL otherwise. + **/ +LINPHONE_PUBLIC const char *linphone_address_get_password (const LinphoneAddress *address); + +/** + * Set the password encoded in the address. + * It is used for basic authentication (not recommended). + * @param address the #LinphoneAddress + * @param password the password to set. + **/ +LINPHONE_PUBLIC void linphone_address_set_password (LinphoneAddress *address, const char *password); + +/** + * Removes address's tags and uri headers so that it is displayable to the user. + **/ +LINPHONE_PUBLIC void linphone_address_clean (LinphoneAddress *address); + +/** + * Returns the address as a string. + * The returned char * must be freed by the application. Use ms_free(). + **/ +LINPHONE_PUBLIC char *linphone_address_as_string (const LinphoneAddress *address); + +/** + * Returns the SIP uri only as a string, that is display name is removed. + * The returned char * must be freed by the application. Use ms_free(). + **/ +LINPHONE_PUBLIC char *linphone_address_as_string_uri_only (const LinphoneAddress *address); + +/** + * Compare two #LinphoneAddress ignoring tags and headers, basically just domain, username, and port. + * @param[in] address1 #LinphoneAddress object + * @param[in] address2 #LinphoneAddress object + * @return Boolean value telling if the #LinphoneAddress objects are equal. + * @see linphone_address_equal() + **/ +LINPHONE_PUBLIC bool_t linphone_address_weak_equal (const LinphoneAddress *address1, const LinphoneAddress *address2); + +/** + * Compare two #LinphoneAddress taking the tags and headers into account. + * @param[in] address1 #LinphoneAddress object + * @param[in] address2 #LinphoneAddress object + * @return Boolean value telling if the #LinphoneAddress objects are equal. + * @see linphone_address_weak_equal() + */ +LINPHONE_PUBLIC bool_t linphone_address_equal (const LinphoneAddress *address1, const LinphoneAddress *address2); + +/** + * Get the header encoded in the address. + * @param header_name the header name +**/ +LINPHONE_PUBLIC const char *linphone_address_get_header (const LinphoneAddress *address, const char *header_name); + +/** + * Set a header into the address. + * Headers appear in the URI with '?', such as \. + * @param address the address + * @param header_name the header name + * @param header_value the header value + **/ +LINPHONE_PUBLIC void linphone_address_set_header (LinphoneAddress *address, const char *header_name, const char *header_value); + +/** + * Tell whether a parameter is present in the address + * @param[in] address #LinphoneAddress object + * @param[in] param_name The name of the parameter + * @return A boolean value telling whether the parameter is present in the address + */ +LINPHONE_PUBLIC bool_t linphone_address_has_param (const LinphoneAddress *address, const char *param_name); + +/** + * Get the value of a parameter of the address + * @param[in] address #LinphoneAddress object + * @param[in] param_name The name of the parameter + * @return The value of the parameter + */ +LINPHONE_PUBLIC const char *linphone_address_get_param (const LinphoneAddress *address, const char *param_name); + +/** + * Set the value of a parameter of the address + * @param[in] address #LinphoneAddress object + * @param[in] param_name The name of the parameter + * @param[in] param_value The new value of the parameter + */ +LINPHONE_PUBLIC void linphone_address_set_param (LinphoneAddress *address, const char *param_name, const char *param_value); + +LINPHONE_PUBLIC void linphone_address_set_params (LinphoneAddress *address, const char *params); + +/** + * Tell whether a parameter is present in the URI of the address + * @param[in] address #LinphoneAddress object + * @param[in] uri_param_name The name of the parameter + * @return A boolean value telling whether the parameter is present in the URI of the address + */ +LINPHONE_PUBLIC bool_t linphone_address_has_uri_param (const LinphoneAddress *address, const char *uri_param_name); + +/** + * Get the value of a parameter of the URI of the address + * @param[in] address #LinphoneAddress object + * @param[in] uri_param_name The name of the parameter + * @return The value of the parameter + */ +LINPHONE_PUBLIC const char *linphone_address_get_uri_param (const LinphoneAddress *address, const char *uri_param_name); + +/** + * Set the value of a parameter of the URI of the address + * @param[in] address #LinphoneAddress object + * @param[in] uri_param_name The name of the parameter + * @param[in] uri_param_value The new value of the parameter + */ +LINPHONE_PUBLIC void linphone_address_set_uri_param (LinphoneAddress *address, const char *uri_param_name, const char *uri_param_value); + +LINPHONE_PUBLIC void linphone_address_set_uri_params (LinphoneAddress *address, const char *params); + +/** + * Removes the value of a parameter of the URI of the address + * @param[in] address #LinphoneAddress object + * @param[in] uri_param_name The name of the parameter + */ +LINPHONE_PUBLIC void linphone_address_remove_uri_param (LinphoneAddress *address, const char *uri_param_name); + +/** + * Destroys a #LinphoneAddress object (actually calls linphone_address_unref()). + * @deprecated Use linphone_address_unref() instead + * @donotwrap + **/ +LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_address_destroy (LinphoneAddress *address); + +/** + * Returns true if address refers to a secure location (sips) + * @deprecated use linphone_address_get_secure() + * @donotwrap + **/ +LINPHONE_DEPRECATED LINPHONE_PUBLIC bool_t linphone_address_is_secure (const LinphoneAddress *address); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_ADDRESS_H_ diff --git a/include/linphone/api/c-api.h b/include/linphone/api/c-api.h new file mode 100644 index 000000000..3cae0b5c2 --- /dev/null +++ b/include/linphone/api/c-api.h @@ -0,0 +1,43 @@ +/* + * c-api.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_API_H_ +#define _L_C_API_H_ + +#include "linphone/utils/general.h" + +#include "linphone/api/c-address.h" +#include "linphone/api/c-call-cbs.h" +#include "linphone/api/c-call-stats.h" +#include "linphone/api/c-call.h" +#include "linphone/api/c-callbacks.h" +#include "linphone/api/c-chat-message-cbs.h" +#include "linphone/api/c-chat-message.h" +#include "linphone/api/c-chat-room-cbs.h" +#include "linphone/api/c-chat-room.h" +#include "linphone/api/c-content.h" +#include "linphone/api/c-dial-plan.h" +#include "linphone/api/c-event-log.h" +#include "linphone/api/c-participant.h" +#include "linphone/api/c-participant-imdn-state.h" +#include "linphone/api/c-magic-search.h" +#include "linphone/api/c-search-result.h" +#include "linphone/api/c-types.h" + +#endif // ifndef _L_C_API_H_ diff --git a/include/linphone/api/c-call-cbs.h b/include/linphone/api/c-call-cbs.h new file mode 100644 index 000000000..2cdd6de49 --- /dev/null +++ b/include/linphone/api/c-call-cbs.h @@ -0,0 +1,212 @@ +/* + * c-call-cbs.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CALL_CBS_H_ +#define _L_C_CALL_CBS_H_ + +#include "linphone/api/c-callbacks.h" +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup call_control + * @{ + */ + +/** + * Acquire a reference to the #LinphoneCallCbs object. + * @param[in] cbs #LinphoneCallCbs object. + * @return The same #LinphoneCallCbs object. + */ +LINPHONE_PUBLIC LinphoneCallCbs *linphone_call_cbs_ref (LinphoneCallCbs *cbs); + +/** + * Release reference to the #LinphoneCallCbs object. + * @param[in] cbs #LinphoneCallCbs object. + */ +LINPHONE_PUBLIC void linphone_call_cbs_unref (LinphoneCallCbs *cbs); + +/** + * Retrieve the user pointer associated with the #LinphoneCallCbs object. + * @param[in] cbs #LinphoneCallCbs object. + * @return The user pointer associated with the #LinphoneCallCbs object. + */ +LINPHONE_PUBLIC void *linphone_call_cbs_get_user_data (const LinphoneCallCbs *cbs); + +/** + * Assign a user pointer to the #LinphoneCallCbs object. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] ud The user pointer to associate with the #LinphoneCallCbs object. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_user_data (LinphoneCallCbs *cbs, void *ud); + +/** + * Get the dtmf received callback. + * @param[in] cbs #LinphoneCallCbs object. + * @return The current dtmf received callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsDtmfReceivedCb linphone_call_cbs_get_dtmf_received (LinphoneCallCbs *cbs); + +/** + * Set the dtmf received callback. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] cb The dtmf received callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_dtmf_received (LinphoneCallCbs *cbs, LinphoneCallCbsDtmfReceivedCb cb); + +/** + * Get the encryption changed callback. + * @param[in] cbs #LinphoneCallCbs object. + * @return The current encryption changed callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsEncryptionChangedCb linphone_call_cbs_get_encryption_changed (LinphoneCallCbs *cbs); + +/** + * Set the encryption changed callback. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] cb The encryption changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_encryption_changed (LinphoneCallCbs *cbs, LinphoneCallCbsEncryptionChangedCb cb); + +/** + * Get the info message received callback. + * @param[in] cbs #LinphoneCallCbs object. + * @return The current info message received callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsInfoMessageReceivedCb linphone_call_cbs_get_info_message_received (LinphoneCallCbs *cbs); + +/** + * Set the info message received callback. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] cb The info message received callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_info_message_received (LinphoneCallCbs *cbs, LinphoneCallCbsInfoMessageReceivedCb cb); + +/** + * Get the state changed callback. + * @param[in] cbs #LinphoneCallCbs object. + * @return The current state changed callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsStateChangedCb linphone_call_cbs_get_state_changed (LinphoneCallCbs *cbs); + +/** + * Set the state changed callback. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] cb The state changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_state_changed (LinphoneCallCbs *cbs, LinphoneCallCbsStateChangedCb cb); + +/** + * Get the stats updated callback. + * @param[in] cbs #LinphoneCallCbs object. + * @return The current stats updated callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsStatsUpdatedCb linphone_call_cbs_get_stats_updated (LinphoneCallCbs *cbs); + +/** + * Set the stats updated callback. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] cb The stats updated callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_stats_updated (LinphoneCallCbs *cbs, LinphoneCallCbsStatsUpdatedCb cb); + +/** + * Get the transfer state changed callback. + * @param[in] cbs #LinphoneCallCbs object. + * @return The current transfer state changed callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsTransferStateChangedCb linphone_call_cbs_get_transfer_state_changed (LinphoneCallCbs *cbs); + +/** + * Set the transfer state changed callback. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] cb The transfer state changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_transfer_state_changed (LinphoneCallCbs *cbs, LinphoneCallCbsTransferStateChangedCb cb); + +/** + * Get the ACK processing callback. + * @param[in] cbs #LinphoneCallCbs object. + * @return The current ack processing callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_processing (LinphoneCallCbs *cbs); + +/** + * Set ACK processing callback. + * @param[in] cbs #LinphoneCallCbs object. + * @param[in] cb The ack processing callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_ack_processing (LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb); + +/** + * Get the TMMBR received callback. + * @param[in] cbs LinphoneCallCbs object. + * @return The current TMMBR received callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsTmmbrReceivedCb linphone_call_cbs_get_tmmbr_received(LinphoneCallCbs *cbs); + +/** + * Set the TMMBR received callback. + * @param[in] cbs LinphoneCallCbs object. + * @param[in] cb The TMMBR received callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_tmmbr_received(LinphoneCallCbs *cbs, LinphoneCallCbsTmmbrReceivedCb cb); + +/** + * Get the snapshot taken callback. + * @param[in] cbs LinphoneCallCbs object. + * @return The current snapshot taken callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsSnapshotTakenCb linphone_call_cbs_get_snapshot_taken(LinphoneCallCbs *cbs); + +/** + * Set the snapshot taken callback. + * @param[in] cbs LinphoneCallCbs object. + * @param[in] cb The snapshot taken callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_snapshot_taken(LinphoneCallCbs *cbs, LinphoneCallCbsSnapshotTakenCb cb); + + /** + * Get the next video frame decoded callback. + * @param[in] cbs LinphoneCallCbs object. + * @return The current next video frame decoded callback. + */ +LINPHONE_PUBLIC LinphoneCallCbsNextVideoFrameDecodedCb linphone_call_cbs_get_next_video_frame_decoded(LinphoneCallCbs *cbs); + +/** + * Set the next video frame decoded callback. + * @param[in] cbs LinphoneCallCbs object. + * @param[in] cb The next video frame decoded callback to be used. + */ +LINPHONE_PUBLIC void linphone_call_cbs_set_next_video_frame_decoded(LinphoneCallCbs *cbs, LinphoneCallCbsNextVideoFrameDecodedCb cb); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CALL_CBS_H_ diff --git a/include/linphone/api/c-call-stats.h b/include/linphone/api/c-call-stats.h new file mode 100644 index 000000000..c2d18e815 --- /dev/null +++ b/include/linphone/api/c-call-stats.h @@ -0,0 +1,211 @@ +/* + * c-call-stats.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CALL_STATS_H_ +#define _L_C_CALL_STATS_H_ + +#include + +#include "linphone/api/c-callbacks.h" +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup call_misc + * @{ + */ + +#define LINPHONE_CALL_STATS_AUDIO ((int)LinphoneStreamTypeAudio) +#define LINPHONE_CALL_STATS_VIDEO ((int)LinphoneStreamTypeVideo) +#define LINPHONE_CALL_STATS_TEXT ((int)LinphoneStreamTypeText) + +#define LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE (1 << 0) /**< received_rtcp field of LinphoneCallStats object has been updated */ +#define LINPHONE_CALL_STATS_SENT_RTCP_UPDATE (1 << 1) /**< sent_rtcp field of LinphoneCallStats object has been updated */ +#define LINPHONE_CALL_STATS_PERIODICAL_UPDATE (1 << 2) /**< Every seconds LinphoneCallStats object has been updated */ + +/** + * Increment refcount. + * @param[in] stats #LinphoneCallStats object + * @ingroup misc +**/ +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_stats_ref (LinphoneCallStats *stats); + +/** + * Decrement refcount and possibly free the object. + * @param[in] stats #LinphoneCallStats object + * @ingroup misc +**/ +LINPHONE_PUBLIC void linphone_call_stats_unref (LinphoneCallStats *stats); + +/** + * Gets the user data in the #LinphoneCallStats object + * @param[in] stats the #LinphoneCallStats + * @return the user data + * @ingroup misc +*/ +LINPHONE_PUBLIC void *linphone_call_stats_get_user_data (const LinphoneCallStats *stats); + +/** + * Sets the user data in the #LinphoneCallStats object + * @param[in] stats the #LinphoneCallStats object + * @param[in] data the user data + * @ingroup misc +*/ +LINPHONE_PUBLIC void linphone_call_stats_set_user_data (LinphoneCallStats *stats, void *data); + +/** + * Get the type of the stream the stats refer to. + * @param[in] stats #LinphoneCallStats object + * @return The type of the stream the stats refer to + */ +LINPHONE_PUBLIC LinphoneStreamType linphone_call_stats_get_type (const LinphoneCallStats *stats); + +/** + * Get the local loss rate since last report + * @return The sender loss rate +**/ +LINPHONE_PUBLIC float linphone_call_stats_get_sender_loss_rate (const LinphoneCallStats *stats); + +/** + * Gets the remote reported loss rate since last report + * @return The receiver loss rate +**/ +LINPHONE_PUBLIC float linphone_call_stats_get_receiver_loss_rate (const LinphoneCallStats *stats); + +/** + * Get the local loss rate since last report + * @return The local loss rate +**/ +LINPHONE_PUBLIC float linphone_call_stats_get_local_loss_rate (const LinphoneCallStats *stats); + +/** + * Gets the local late rate since last report + * @return The local late rate +**/ +LINPHONE_PUBLIC float linphone_call_stats_get_local_late_rate (const LinphoneCallStats *stats); + +/** + * Gets the local interarrival jitter + * @param[in] stats #LinphoneCallStats object + * @return The interarrival jitter at last emitted sender report +**/ +LINPHONE_PUBLIC float linphone_call_stats_get_sender_interarrival_jitter (const LinphoneCallStats *stats); + +/** + * Gets the remote reported interarrival jitter + * @param[in] stats #LinphoneCallStats object + * @return The interarrival jitter at last received receiver report +**/ +LINPHONE_PUBLIC float linphone_call_stats_get_receiver_interarrival_jitter (const LinphoneCallStats *stats); + +LINPHONE_PUBLIC const rtp_stats_t *linphone_call_stats_get_rtp_stats (const LinphoneCallStats *stats); + +/** + * Gets the cumulative number of late packets + * @param[in] stats #LinphoneCallStats object + * @return The cumulative number of late packets +**/ +LINPHONE_PUBLIC uint64_t linphone_call_stats_get_late_packets_cumulative_number (const LinphoneCallStats *stats); + +/** + * 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. + */ +LINPHONE_PUBLIC float linphone_call_stats_get_download_bandwidth (const LinphoneCallStats *stats); + +/** + * 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. + */ +LINPHONE_PUBLIC float linphone_call_stats_get_upload_bandwidth (const LinphoneCallStats *stats); + +/** + * Get the bandwidth measurement of the received RTCP, expressed in kbit/s, including IP/UDP/RTP headers. + * @param[in] stats #LinphoneCallStats object + * @return The bandwidth measurement of the received RTCP in kbit/s. + */ +LINPHONE_PUBLIC float linphone_call_stats_get_rtcp_download_bandwidth (const LinphoneCallStats *stats); + +/** + * Get the bandwidth measurement of the sent RTCP, expressed in kbit/s, including IP/UDP/RTP headers. + * @param[in] stats #LinphoneCallStats object + * @return The bandwidth measurement of the sent RTCP in kbit/s. + */ +LINPHONE_PUBLIC float linphone_call_stats_get_rtcp_upload_bandwidth( const LinphoneCallStats *stats); + +/** + * Get the state of ICE processing. + * @param[in] stats #LinphoneCallStats object + * @return The state of ICE processing. + */ +LINPHONE_PUBLIC LinphoneIceState linphone_call_stats_get_ice_state (const LinphoneCallStats *stats); + +/** + * Get the state of uPnP processing. + * @param[in] stats #LinphoneCallStats object + * @return The state of uPnP processing. + */ +LINPHONE_PUBLIC LinphoneUpnpState linphone_call_stats_get_upnp_state (const LinphoneCallStats *stats); + +/** + * Get the IP address family of the remote peer. + * @param[in] stats #LinphoneCallStats object + * @return The IP address family of the remote peer. + */ +LINPHONE_PUBLIC LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remote (const LinphoneCallStats *stats); + +/** + * Get the jitter buffer size in ms. + * @param[in] stats #LinphoneCallStats object + * @return The jitter buffer size in ms. + */ +LINPHONE_PUBLIC float linphone_call_stats_get_jitter_buffer_size_ms (const LinphoneCallStats *stats); + +/** + * Get the round trip delay in s. + * @param[in] stats #LinphoneCallStats object + * @return The round trip delay in s. + */ +LINPHONE_PUBLIC float linphone_call_stats_get_round_trip_delay (const LinphoneCallStats *stats); + +/** + * Get the estimated bandwidth measurement of the received stream, expressed in kbit/s, including IP/UDP/RTP headers. + * @param[in] stats #LinphoneCallStats object + * @return The estimated bandwidth measurement of the received stream in kbit/s. + */ +LINPHONE_PUBLIC float linphone_call_stats_get_estimated_download_bandwidth(const LinphoneCallStats *stats); + +void linphone_call_stats_set_estimated_download_bandwidth(LinphoneCallStats *stats, float estimated_value); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CALL_STATS_H_ diff --git a/include/linphone/api/c-call.h b/include/linphone/api/c-call.h new file mode 100644 index 000000000..e1010580b --- /dev/null +++ b/include/linphone/api/c-call.h @@ -0,0 +1,808 @@ +/* + * c-call.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CALL_H_ +#define _L_C_CALL_H_ + +#include + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup call_control + * @{ + */ + +/** + * Acquire a reference to the call. + * 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(). + * @param[in] call The call. + * @return The same call. +**/ +LINPHONE_PUBLIC LinphoneCall *linphone_call_ref (LinphoneCall *call); + +/** + * Release reference to the call. + * @param[in] call The call. +**/ +LINPHONE_PUBLIC void linphone_call_unref (LinphoneCall *call); + +/** + * Retrieve the user pointer associated with the call. + * @param[in] call The call. + * @return The user pointer associated with the call. +**/ +LINPHONE_PUBLIC void *linphone_call_get_user_data (const LinphoneCall *call); + +/** + * Assign a user pointer to the call. + * @param[in] call The call. + * @param[in] ud The user pointer to associate with the call. +**/ +LINPHONE_PUBLIC void linphone_call_set_user_data (LinphoneCall *call, void *ud); + +/** + * Get the core that has created the specified call. + * @param[in] call #LinphoneCall object + * @return The #LinphoneCore object that has created the specified call. + */ +LINPHONE_PUBLIC LinphoneCore * linphone_call_get_core (const LinphoneCall *call); + +/** + * Retrieves the call's current state. +**/ +LINPHONE_PUBLIC LinphoneCallState linphone_call_get_state (const LinphoneCall *call); + +/** + * Tell whether a call has been asked to autoanswer + * @param[in] call #LinphoneCall object + * @return A boolean value telling whether the call has been asked to autoanswer +**/ +LINPHONE_PUBLIC bool_t linphone_call_asked_to_autoanswer (LinphoneCall *call); + +/** + * Returns the remote address associated to this call +**/ +LINPHONE_PUBLIC const LinphoneAddress *linphone_call_get_remote_address (const LinphoneCall *call); + +/** + * Returns the to address with its headers associated to this call +**/ +LINPHONE_PUBLIC const LinphoneAddress *linphone_call_get_to_address (const LinphoneCall * call); + +/** + * Returns the value of the header name +**/ +LINPHONE_PUBLIC const char *linphone_call_get_to_header (const LinphoneCall *call, const char *name); + +/** + * Returns the remote address associated to this call as a string. + * The result string must be freed by user using ms_free(). +**/ +LINPHONE_PUBLIC char *linphone_call_get_remote_address_as_string (const LinphoneCall *call); + +/** + * Returns the diversion address associated to this call +**/ +LINPHONE_PUBLIC const LinphoneAddress * linphone_call_get_diversion_address (const LinphoneCall *call); + +/** + * Returns direction of the call (incoming or outgoing). +**/ +LINPHONE_PUBLIC LinphoneCallDir linphone_call_get_dir (const LinphoneCall *call); + +/** + * Gets the call log associated to this call. + * @param[in] call #LinphoneCall object + * @return The #LinphoneCallLog associated with the specified #LinphoneCall +**/ +LINPHONE_PUBLIC LinphoneCallLog *linphone_call_get_call_log (const LinphoneCall *call); + +/** + * Gets the refer-to uri (if the call was transfered). + * @param[in] call #LinphoneCall object + * @return The refer-to uri of the call (if it was transfered) +**/ +LINPHONE_PUBLIC const char *linphone_call_get_refer_to (const LinphoneCall *call); + +/** + * Returns true if this calls has received a transfer that has not been + * executed yet. + * Pending transfers are executed when this call is being paused or closed, + * locally or by remote endpoint. + * If the call is already paused while receiving the transfer request, the + * transfer immediately occurs. +**/ +LINPHONE_PUBLIC bool_t linphone_call_has_transfer_pending (const LinphoneCall *call); + +/** + * Gets the transferer if this call was started automatically as a result of an incoming transfer request. + * The call in which the transfer request was received is returned in this case. + * @param[in] call #LinphoneCall object + * @return The transferer call if the specified call was started automatically as a result of an incoming transfer request, NULL otherwise +**/ +LINPHONE_PUBLIC LinphoneCall *linphone_call_get_transferer_call (const LinphoneCall *call); + +/** + * When this call has received a transfer request, returns the new call that was automatically created as a result of the transfer. +**/ +LINPHONE_PUBLIC LinphoneCall *linphone_call_get_transfer_target_call (const LinphoneCall *call); + +/** + * Returns the call object this call is replacing, if any. + * Call replacement can occur during call transfers. + * By default, the core automatically terminates the replaced call and accept the new one. + * This function allows the application to know whether a new incoming call is a one that replaces another one. +**/ +LINPHONE_PUBLIC LinphoneCall *linphone_call_get_replaced_call (LinphoneCall *call); + +/** + * Returns call's duration in seconds. +**/ +LINPHONE_PUBLIC int linphone_call_get_duration (const LinphoneCall *call); + +/** + * Returns current parameters associated to the call. +**/ +LINPHONE_PUBLIC const LinphoneCallParams *linphone_call_get_current_params (LinphoneCall *call); + +/** + * Returns call parameters proposed by remote. + * + * This is useful when receiving an incoming call, to know whether the remote party + * supports video, encryption or whatever. +**/ +LINPHONE_PUBLIC const LinphoneCallParams *linphone_call_get_remote_params (LinphoneCall *call); + +/** + * Indicate whether camera input should be sent to remote end. +**/ +LINPHONE_PUBLIC void linphone_call_enable_camera (LinphoneCall *lc, bool_t enabled); + +/** + * Returns TRUE if camera pictures are allowed to be sent to the remote party. +**/ +LINPHONE_PUBLIC bool_t linphone_call_camera_enabled (const LinphoneCall *lc); + +/** + * Take a photo of currently received video and write it into a jpeg 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). +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_take_video_snapshot (LinphoneCall *call, const char *file); + +/** + * Take a photo of currently captured video and write it into a jpeg 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). +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_take_preview_snapshot (LinphoneCall *call, const char *file); + +/** + * Returns the reason for a call termination (either error or normal termination) +**/ +LINPHONE_PUBLIC LinphoneReason linphone_call_get_reason (const LinphoneCall *call); + +/** + * Returns full details about call errors or termination reasons. + * @param call #LinphoneCall object on which we want the information error + * @return #LinphoneErrorInfo object holding the reason error. + */ +LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_get_error_info (const LinphoneCall *call); + +/** + * Returns the far end's user agent description string, if available. +**/ +LINPHONE_PUBLIC const char *linphone_call_get_remote_user_agent (LinphoneCall *call); + +/** + * Returns the far end's sip contact as a string, if available. +**/ +LINPHONE_PUBLIC const char *linphone_call_get_remote_contact (LinphoneCall *call); + +/** + * Returns the ZRTP authentication token to verify. + * @param call the #LinphoneCall + * @return the authentication token to verify. +**/ +LINPHONE_PUBLIC const char *linphone_call_get_authentication_token (LinphoneCall *call); + +/** + * Returns whether ZRTP authentication token is verified. + * If not, it must be verified by users as described in ZRTP procedure. + * Once done, the application must inform of the results with linphone_call_set_authentication_token_verified(). + * @param call the #LinphoneCall + * @return TRUE if authentication token is verifed, false otherwise. +**/ +LINPHONE_PUBLIC bool_t linphone_call_get_authentication_token_verified (const LinphoneCall *call); + +/** + * Set the result of ZRTP short code verification by user. + * If remote party also does the same, it will update the ZRTP cache so that user's verification will not be required for the two users. + * @param call the #LinphoneCall + * @param verified whether the ZRTP SAS is verified. +**/ +LINPHONE_PUBLIC void linphone_call_set_authentication_token_verified (LinphoneCall *call, bool_t verified); + +/** + * Request remote side to send us a Video Fast Update. +**/ +LINPHONE_PUBLIC void linphone_call_send_vfu_request (LinphoneCall *call); + +/** + * Request the callback passed to linphone_call_cbs_set_next_video_frame_decoded() to be called the next time the video decoder properly decodes a video frame. + * @param call the #LinphoneCall +**/ +LINPHONE_PUBLIC void linphone_call_request_notify_next_video_frame_decoded(LinphoneCall *call); + +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_call_set_next_video_frame_decoded_callback (LinphoneCall *call, LinphoneCallCbFunc cb, void *ud); + +/** + * Returns the current transfer state, if a transfer has been initiated from this call. + * @see linphone_core_transfer_call() , linphone_core_transfer_call_to_another() +**/ +LINPHONE_PUBLIC LinphoneCallState linphone_call_get_transfer_state (LinphoneCall *call); + +/** + * Perform a zoom of the video displayed during a call. + * @param call the call. + * @param zoom_factor a floating point number describing the zoom factor. A value 1.0 corresponds to no zoom applied. + * @param cx a floating point number pointing the horizontal center of the zoom to be applied. This value should be between 0.0 and 1.0. + * @param cy a floating point number pointing the vertical center of the zoom to be applied. This value should be between 0.0 and 1.0. + * @deprecated use linphone_call_zoom instead + * cx and cy are updated in return in case their coordinates were too excentrated for the requested zoom factor. The zoom ensures that all the screen is fullfilled with the video. +**/ +LINPHONE_PUBLIC void linphone_call_zoom_video (LinphoneCall *call, float zoom_factor, float *cx, float *cy); + +/** + * Perform a zoom of the video displayed during a call. + * The zoom ensures that all the screen is fullfilled with the video. + * @param call the call. + * @param zoom_factor a floating point number describing the zoom factor. A value 1.0 corresponds to no zoom applied. + * @param cx a floating point number pointing the horizontal center of the zoom to be applied. This value should be between 0.0 and 1.0. + * @param cy a floating point number pointing the vertical center of the zoom to be applied. This value should be between 0.0 and 1.0. +**/ +LINPHONE_PUBLIC void linphone_call_zoom (LinphoneCall *call, float zoom_factor, float cx, float cy); + +/** + * Send the specified dtmf. + * + * The dtmf is automatically played to the user. + * @param call The #LinphoneCall object + * @param dtmf The dtmf name specified as a char, such as '0', '#' etc... + * @return 0 if successful, -1 on error. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_send_dtmf (LinphoneCall *call, char dtmf); + +/** + * Send a list of dtmf. + * + * The dtmfs are automatically sent to remote, separated by some needed customizable delay. + * Sending is canceled if the call state changes to something not LinphoneCallStreamsRunning. + * @param call The #LinphoneCall object + * @param dtmfs A dtmf sequence such as '123#123123' + * @return -2 if there is already a DTMF sequence, -1 if call is not ready, 0 otherwise. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_send_dtmfs (LinphoneCall *call, const char *dtmfs); + +/** + * Stop current DTMF sequence sending. + * + * Please note that some DTMF could be already sent, + * depending on when this function call is delayed from #linphone_call_send_dtmfs. This + * function will be automatically called if call state change to anything but LinphoneCallStreamsRunning. + * @param call The #LinphoneCall object +**/ +LINPHONE_PUBLIC void linphone_call_cancel_dtmfs (LinphoneCall *call); + +/** + * Return TRUE if this call is currently part of a conference + * @param call #LinphoneCall + * @return TRUE if part of a conference. + * @deprecated Use linphone_call_get_conference() instead. + * @donotwrap + */ +LINPHONE_PUBLIC LINPHONE_DEPRECATED bool_t linphone_call_is_in_conference (const LinphoneCall *call); + +/** + * Return the associated conference object + * @param call #LinphoneCall + * @return A pointer on #LinphoneConference or NULL if the call is not part of any conference. + */ +LINPHONE_PUBLIC LinphoneConference *linphone_call_get_conference (const LinphoneCall *call); + +/** + * Change the playback output device (currently only used for blackberry) + * @param call + * @param route the wanted audio route (earpiece, speaker, ...) + * @donotwrap +**/ +LINPHONE_PUBLIC void linphone_call_set_audio_route (LinphoneCall *call, LinphoneAudioRoute route); + +/** + * Returns the number of stream for the given call. + * Currently there is only two (Audio, Video), but later there will be more. + * @param call + * @return 2 +**/ +LINPHONE_PUBLIC int linphone_call_get_stream_count (const LinphoneCall *call); + +/** + * @brief Returns the type of stream for the given stream index. + * @return the type (MSAudio, MSVideo, MSText) of the stream of given index. + * @donotwrap +**/ +LINPHONE_PUBLIC MSFormatType linphone_call_get_stream_type (const LinphoneCall *call, int stream_index); + +/** + * @brief Returns the meta rtp transport for the given stream index. + * @return a pointer to the meta rtp transport if it exists, NULL otherwise. + * @donotwrap +**/ +LINPHONE_PUBLIC RtpTransport *linphone_call_get_meta_rtp_transport (const LinphoneCall *call, int stream_index); + +/** + * @brief Returns the meta rtcp transport for the given stream index. + * @return a pointer to the meta rtcp transport if it exists, NULL otherwise. + * @donotwrap +**/ +LINPHONE_PUBLIC RtpTransport *linphone_call_get_meta_rtcp_transport (const LinphoneCall *call, int stream_index); + +/** + * Pauses the call. If a music file has been setup using linphone_core_set_play_file(), + * this file will be played to the remote user. + * The only way to resume a paused call is to call linphone_call_resume(). + * @param[in] call #LinphoneCall object + * @return 0 on success, -1 on failure + * @see linphone_call_resume() +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_pause (LinphoneCall *call); + +/** + * Resumes a call. + * The call needs to have been paused previously with linphone_call_pause(). + * @param[in] call #LinphoneCall object + * @return 0 on success, -1 on failure + * @see linphone_call_pause() +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_resume (LinphoneCall *call); + +/** + * Terminates a call. + * @param[in] call #LinphoneCall object + * @return 0 on success, -1 on failure +**/LINPHONE_PUBLIC LinphoneStatus linphone_call_terminate (LinphoneCall *call); + +/** + * Terminates a call. + * @param[in] call #LinphoneCall object + * @param[in] ei #LinphoneErrorInfo + * @return 0 on success, -1 on failure +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_terminate_with_error_info (LinphoneCall *call, const LinphoneErrorInfo *ei); + +/** + * Redirect the specified call to the given redirect URI. + * @param[in] call A #LinphoneCall object + * @param[in] redirect_uri The URI to redirect the call to + * @return 0 if successful, -1 on error. + */ +LINPHONE_PUBLIC LinphoneStatus linphone_call_redirect (LinphoneCall *call, const char *redirect_uri); + +/** + * Decline a pending incoming call, with a reason. + * @param[in] call A #LinphoneCall object that must be in the IncomingReceived state + * @param[in] reason The reason for rejecting the call: #LinphoneReasonDeclined or #LinphoneReasonBusy + * @return 0 on success, -1 on failure +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_decline (LinphoneCall *call, LinphoneReason reason); + +/** + * Decline a pending incoming call, with a #LinphoneErrorInfo object. + * @param[in] call A #LinphoneCall object that must be in the IncomingReceived state + * @param[in] ei #LinphoneErrorInfo containing more information on the call rejection. + * @return 0 on success, -1 on failure + */ +LINPHONE_PUBLIC int linphone_call_decline_with_error_info (LinphoneCall *call, const LinphoneErrorInfo *ei); + +/** + * Accept an incoming call. + * + * Basically the application is notified of incoming calls within the + * call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive + * a #LinphoneCallIncoming event with the associated #LinphoneCall object. + * The application can later accept the call using this method. + * @param[in] call A #LinphoneCall object + * @return 0 on success, -1 on failure +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_accept (LinphoneCall *call); + +/** + * Accept an incoming call, with parameters. + * + * Basically the application is notified of incoming calls within the + * call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive + * a #LinphoneCallIncoming event with the associated #LinphoneCall object. + * The application can later accept the call using this method. + * @param[in] call A #LinphoneCall object + * @param[in] params The specific parameters for this call, for example whether video is accepted or not. Use NULL to use default parameters + * @return 0 on success, -1 on failure +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_with_params (LinphoneCall *call, const LinphoneCallParams *params); + +/** + * Accept an early media session for an incoming call. + * This is identical as calling linphone_call_accept_early_media_with_params() with NULL parameters. + * @param[in] call A #LinphoneCall object + * @return 0 if successful, -1 otherwise + * @see linphone_call_accept_early_media_with_params() +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_early_media (LinphoneCall *call); + +/** + * 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. + * However, unlike after call acceptance, mic and camera input are not sent during early-media, though received audio & video are played normally. + * The call can then later be fully accepted using linphone_call_accept() or linphone_call_accept_with_params(). + * @param[in] call A #LinphoneCall object + * @param[in] params The call parameters to use (can be NULL) + * @return 0 if successful, -1 otherwise +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_early_media_with_params (LinphoneCall *call, const LinphoneCallParams *params); + +/** + * Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore. + * It triggers a SIP reINVITE in order to perform a new offer/answer of media capabilities. + * Changing the size of the transmitted video after calling #linphone_core_set_preferred_video_size() can be used by passing NULL as params argument. + * In case no changes are requested through the #LinphoneCallParams argument, then this argument can be omitted and set to NULL. + * WARNING: Updating a call in the #LinphoneCallPaused state will still result in a paused call even if the media directions set in the + * params are sendrecv. To resume a paused call, you need to call linphone_call_resume(). + * + * @param[in] call A #LinphoneCall object + * @param[in] params The new call parameters to use (may be NULL) + * @return 0 if successful, -1 otherwise. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_update (LinphoneCall *call, const LinphoneCallParams *params); + +/** + * When receiving a #LinphoneCallUpdatedByRemote state notification, prevent #LinphoneCore from performing an automatic answer. + * + * When receiving a #LinphoneCallUpdatedByRemote state notification (ie an incoming reINVITE), the default behaviour of + * #LinphoneCore is defined by the "defer_update_default" option of the "sip" section of the config. If this option is 0 (the default) + * then the #LinphoneCore automatically answers the reINIVTE with call parameters unchanged. + * However when for example when the remote party updated the call to propose a video stream, it can be useful + * to prompt the user before answering. This can be achieved by calling linphone_core_defer_call_update() during + * the call state notification, to deactivate the automatic answer that would just confirm the audio but reject the video. + * Then, when the user responds to dialog prompt, it becomes possible to call linphone_call_accept_update() to answer + * the reINVITE, with eventually video enabled in the #LinphoneCallParams argument. + * + * The #LinphoneCallUpdatedByRemote notification can also arrive when receiving an INVITE without SDP. In such case, an unchanged offer is made + * in the 200Ok, and when the ACK containing the SDP answer is received, #LinphoneCallUpdatedByRemote is triggered to notify the application of possible + * changes in the media session. However in such case defering the update has no meaning since we just generating an offer. + * + * @param[in] call A #LinphoneCall object + * @return 0 if successful, -1 if the linphone_call_defer_update() was done outside a valid #LinphoneCallUpdatedByRemote notification +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_defer_update (LinphoneCall *call); + +/** + * Accept call modifications initiated by other end. + * + * This call may be performed in response to a #LinphoneCallUpdatedByRemote state notification. + * When such notification arrives, the application can decide to call linphone_call_defer_update() so that it can + * have the time to prompt the user. linphone_call_get_remote_params() can be used to get information about the call parameters + * requested by the other party, such as whether a video stream is requested. + * + * When the user accepts or refuse the change, linphone_call_accept_update() can be done to answer to the other party. + * If params is NULL, then the same call parameters established before the update request will continue to be used (no change). + * If params is not NULL, then the update will be accepted according to the parameters passed. + * Typical example is when a user accepts to start video, then params should indicate that video stream should be used + * (see linphone_call_params_enable_video()). + * @param[in] call A #LinphoneCall object + * @param[in] params A #LinphoneCallParams object describing the call parameters to accept + * @return 0 if successful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state) +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_update (LinphoneCall *call, const LinphoneCallParams *params); + +/** + * Performs a simple call transfer to the specified destination. + * The remote endpoint is expected to issue a new call to the specified destination. + * The current call remains active and thus can be later paused or terminated. + * It is possible to follow the progress of the transfer provided that transferee sends notification about it. + * In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party. + * The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallConnected. + * @param[in] call The call to be transfered + * @param[in] refer_to The destination the call is to be refered to + * @return 0 on success, -1 on failure +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_transfer (LinphoneCall *call, const char *refer_to); + +/** + * Transfers a call to destination of another running call. This is used for "attended transfer" scenarios. + * The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately. + * The destination call is a call previously established to introduce the transfered person. + * This method will send a transfer request to the transfered person. The phone of the transfered is then + * expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically + * close the call with us (the 'dest' call). + * It is possible to follow the progress of the transfer provided that transferee sends notification about it. + * In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party. + * The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallConnected. + * @param[in] call A running call you want to transfer + * @param[in] dest A running call whose remote person will receive the transfer + * @return 0 on success, -1 on failure +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_transfer_to_another (LinphoneCall *call, LinphoneCall *dest); + +/** + * @} + */ + +/** + * @addtogroup media_parameters + * @{ + */ + +/** + * Get the native window handle of the video window, casted as an unsigned long. +**/ +LINPHONE_PUBLIC void * linphone_call_get_native_video_window_id(const LinphoneCall *call); + +/** + * Set the native video window id where the video is to be displayed. + * For MacOS, Linux, Windows: if not set or 0 a window will be automatically created, unless the special id -1 is given. +**/ +LINPHONE_PUBLIC void linphone_call_set_native_video_window_id(LinphoneCall *call, void * id); + +/** + * Enables or disable echo cancellation for this call + * @param call + * @param val +**/ +LINPHONE_PUBLIC void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t val) ; + +/** + * Returns TRUE if echo cancellation is enabled. +**/ +LINPHONE_PUBLIC bool_t linphone_call_echo_cancellation_enabled(const LinphoneCall *call); + +/** + * Enables or disable echo limiter for this call + * @param call + * @param val +**/ +LINPHONE_PUBLIC void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val); + +/** + * Returns TRUE if echo limiter is enabled. +**/ +LINPHONE_PUBLIC bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call); + +/** + * @} + */ + +/** + * @addtogroup call_misc + * @{ + */ + +/** + * Create a new chat room for messaging from a call if not already existing, else return existing one. + * No reference is given to the caller: the chat room will be deleted when the call is ended. + * @param call #LinphoneCall object + * @return #LinphoneChatRoom where messaging can take place. + */ +LINPHONE_PUBLIC LinphoneChatRoom * linphone_call_get_chat_room(LinphoneCall *call); + +/** + * Get the mesured playback volume level (received from remote) in dbm0. + * @param call The call. + * @return float Volume level in percentage. + */ +LINPHONE_PUBLIC float linphone_call_get_play_volume(const LinphoneCall *call); + +/** + * Get the mesured record volume level (sent to remote) in dbm0. + * @param call The call. + * @return float Volume level in percentage. + */ +LINPHONE_PUBLIC float linphone_call_get_record_volume(const LinphoneCall *call); + +/** + * Get speaker volume gain. + * If the sound backend supports it, the returned gain is equal to the gain set + * with the system mixer. + * @param call The call. + * @return Percenatge of the max supported volume gain. Valid values are in [ 0.0 : 1.0 ]. + * In case of failure, a negative value is returned + */ +LINPHONE_PUBLIC float linphone_call_get_speaker_volume_gain(const LinphoneCall *call); + +/** + * Set speaker volume gain. + * If the sound backend supports it, the new gain will synchronized with the system mixer. + * @param call The call. + * @param volume Percentage of the max supported gain. Valid values are in [ 0.0 : 1.0 ]. + */ +LINPHONE_PUBLIC void linphone_call_set_speaker_volume_gain(LinphoneCall *call, float volume); + +/** + * Get microphone volume gain. + * If the sound backend supports it, the returned gain is equal to the gain set + * with the system mixer. + * @param call The call. + * @return double Percenatge of the max supported volume gain. Valid values are in [ 0.0 : 1.0 ]. + * In case of failure, a negative value is returned + */ +LINPHONE_PUBLIC float linphone_call_get_microphone_volume_gain(const LinphoneCall *call); + +/** + * Set microphone volume gain. + * If the sound backend supports it, the new gain will synchronized with the system mixer. + * @param call The call. + * @param volume Percentage of the max supported gain. Valid values are in [ 0.0 : 1.0 ]. + */ +LINPHONE_PUBLIC void linphone_call_set_microphone_volume_gain(LinphoneCall *call, float volume); + +/** + * Obtain real-time quality rating of the call + * + * Based on local RTP statistics and RTCP feedback, a quality rating is computed and updated + * during all the duration of the call. This function returns its value at the time of the function call. + * It is expected that the rating is updated at least every 5 seconds or so. + * The rating is a floating point number comprised between 0 and 5. + * + * 4-5 = good quality
+ * 3-4 = average quality
+ * 2-3 = poor quality
+ * 1-2 = very poor quality
+ * 0-1 = can't be worse, mostly unusable
+ * + * @return The function returns -1 if no quality measurement is available, for example if no + * active audio stream exist. Otherwise it returns the quality rating. +**/ +LINPHONE_PUBLIC float linphone_call_get_current_quality(const LinphoneCall *call); + +/** + * Returns call quality averaged over all the duration of the call. + * + * See linphone_call_get_current_quality() for more details about quality measurement. +**/ +LINPHONE_PUBLIC float linphone_call_get_average_quality(const LinphoneCall *call); + +/** + * Start call recording. + * The output file where audio is recorded must be previously specified with linphone_call_params_set_record_file(). +**/ +LINPHONE_PUBLIC void linphone_call_start_recording(LinphoneCall *call); + +/** + * Stop call recording. +**/ +LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call); + +/** + * Get a player associated with the call to play a local file and stream it to the remote peer. + * @param[in] call #LinphoneCall object + * @return A #LinphonePlayer object + */ +LINPHONE_PUBLIC LinphonePlayer * linphone_call_get_player(LinphoneCall *call); + +/** + * Indicates whether an operation is in progress at the media side. + * It can be a bad idea to initiate signaling operations (adding video, pausing the call, removing video, changing video parameters) while + * the media is busy in establishing the connection (typically ICE connectivity checks). It can result in failures generating loss of time + * in future operations in the call. + * Applications are invited to check this function after each call state change to decide whether certain operations are permitted or not. + * @param call the call + * @return TRUE if media is busy in establishing the connection, FALSE otherwise. +**/ +LINPHONE_PUBLIC bool_t linphone_call_media_in_progress(const LinphoneCall *call); + +/** + * Call generic OpenGL render for a given call. + * @param call The call. + */ +LINPHONE_PUBLIC void linphone_call_ogl_render(const LinphoneCall *call); + +/** + * Send a #LinphoneInfoMessage through an established call + * @param call the call + * @param info the info message +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info); + +/** + * Return a copy of the call statistics for a particular stream type. + * @param call the call + * @param type the stream type +**/ +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type); + +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call); + +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call); + +LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call); + +/** + * Add a listener in order to be notified of #LinphoneCall events. Once an event is received, registred #LinphoneCallCbs are + * invoked sequencially. + * @param[in] call #LinphoneCall object to monitor. + * @param[in] cbs A #LinphoneCallCbs object holding the callbacks you need. A reference is taken by the #LinphoneCall until you invoke linphone_call_remove_callbacks(). + */ +LINPHONE_PUBLIC void linphone_call_add_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs); + +/** + * Remove a listener from a #LinphoneCall + * @param[in] call #LinphoneCall object + * @param[in] cbs #LinphoneCallCbs object to remove. + */ +LINPHONE_PUBLIC void linphone_call_remove_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs); + +/** + * Gets the current LinphoneCallCbs. + * This is meant only to be called from a callback to be able to get the user_data associated with the #LinphoneCallCbs that is calling the callback. + * @param[in] call #LinphoneCall object + * @return The #LinphoneCallCbs that has called the last callback + */ +LINPHONE_PUBLIC LinphoneCallCbs *linphone_call_get_current_callbacks(const LinphoneCall *call); + +/** + * Set call parameters - advanced and not recommended feature - use with caution. + * Local call parameters applicable to an outgoing or incoming shall usually be passed to linphone_core_invite_address_with_params() or + * linphone_call_accept_with_params(). + * However, in some cases it might be desirable from a software design standpoint to modify local parameters outside of the application layer, typically + * in the purpose of implementing a custom logic including special headers in INVITE or 200Ok requests, driven by a call_state_changed listener method. + * This function accepts to assign a new #LinphoneCallParams only in #LinphoneCallOutgoingInit and #LinphoneCallIncomingReceived states. + * @param call the #LinphoneCall object +**/ +LINPHONE_PUBLIC void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params); + +/** + * Returns local parameters associated with the call. + * This is typically the parameters passed at call initiation to linphone_core_invite_address_with_params() or linphone_call_accept_with_params(), or some default + * parameters if no #LinphoneCallParams was explicitely passed during call initiation. + * @param call the #LinphoneCall object + * @return the call's local parameters. + **/ +LINPHONE_PUBLIC const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CALL_H_ diff --git a/include/linphone/api/c-callbacks.h b/include/linphone/api/c-callbacks.h new file mode 100644 index 000000000..f60dfb469 --- /dev/null +++ b/include/linphone/api/c-callbacks.h @@ -0,0 +1,321 @@ +/* + * c-callbacks.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CALLBACKS_H_ +#define _L_C_CALLBACKS_H_ + +// TODO: Remove me in the future. +#include "linphone/callbacks.h" +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup call_control + * @{ +**/ + +/** + * Callback for being notified of received DTMFs. + * @param call #LinphoneCall object that received the dtmf + * @param dtmf The ascii code of the dtmf + */ +typedef void (*LinphoneCallCbsDtmfReceivedCb)(LinphoneCall *call, int dtmf); + +/** + * Call encryption changed callback. + * @param call #LinphoneCall object whose encryption is changed. + * @param on Whether encryption is activated. + * @param authentication_token An authentication_token, currently set for ZRTP kind of encryption only. + */ +typedef void (*LinphoneCallCbsEncryptionChangedCb)(LinphoneCall *call, bool_t on, const char *authentication_token); + +/** + * Callback for receiving info messages. + * @param call #LinphoneCall whose info message belongs to. + * @param msg #LinphoneInfoMessage object. + */ +typedef void (*LinphoneCallCbsInfoMessageReceivedCb)(LinphoneCall *call, const LinphoneInfoMessage *msg); + +/** + * Call state notification callback. + * @param call #LinphoneCall whose state is changed. + * @param cstate The new state of the call + * @param message An informational message about the state. + */ +typedef void (*LinphoneCallCbsStateChangedCb)(LinphoneCall *call, LinphoneCallState cstate, const char *message); + +/** + * Callback for receiving quality statistics for calls. + * @param call #LinphoneCall object whose statistics are notified + * @param stats #LinphoneCallStats object + */ +typedef void (*LinphoneCallCbsStatsUpdatedCb)(LinphoneCall *call, const LinphoneCallStats *stats); + +/** + * Callback for notifying progresses of transfers. + * @param call #LinphoneCall that was transfered + * @param cstate The state of the call to transfer target at the far end. + */ +typedef void (*LinphoneCallCbsTransferStateChangedCb)(LinphoneCall *call, LinphoneCallState cstate); + +/** + * Callback for notifying the processing SIP ACK messages. + * @param call #LinphoneCall for which an ACK is being received or sent + * @param ack the ACK message + * @param is_received if TRUE this ACK is an incoming one, otherwise it is an ACK about to be sent. + */ +typedef void (*LinphoneCallCbsAckProcessingCb)(LinphoneCall *call, LinphoneHeaders *ack, bool_t is_received); + +/** + * Callback for notifying a received TMMBR. + * @param call LinphoneCall for which the TMMBR has changed + * @param stream_index the index of the current stream + * @param tmmbr the value of the received TMMBR + */ +typedef void (*LinphoneCallCbsTmmbrReceivedCb)(LinphoneCall *call, int stream_index, int tmmbr); + +/** + * Callback for notifying a snapshot taken. + * @param call LinphoneCall for which the snapshot was taken + * @param filepath the name of the saved file + */ +typedef void (*LinphoneCallCbsSnapshotTakenCb)(LinphoneCall *call, const char *filepath); + + /** + * Callback to notify a next video frame has been decoded + * @param call LinphoneCall for which the next video frame has been decoded + */ +typedef void (*LinphoneCallCbsNextVideoFrameDecodedCb)(LinphoneCall *call); + +/** + * @} +**/ + + +/** + * @addtogroup chatroom + * @{ + */ + + /** + * Call back used to notify message delivery status + * @param msg #LinphoneChatMessage object + * @param status #LinphoneChatMessageState + * @param ud application user data + * @deprecated Use #LinphoneChatMessageCbsMsgStateChangedCb instead. + * @donotwrap + */ +typedef void (*LinphoneChatMessageStateChangedCb)(LinphoneChatMessage* msg, LinphoneChatMessageState state, void* ud); + +/** + * Call back used to notify message delivery status + * @param msg #LinphoneChatMessage object + * @param status #LinphoneChatMessageState + */ +typedef void (*LinphoneChatMessageCbsMsgStateChangedCb)(LinphoneChatMessage* msg, LinphoneChatMessageState state); + +/** + * Call back used to notify participant IMDN state + * @param msg #LinphoneChatMessage object + * @param state #LinphoneParticipantImdnState + */ +typedef void (*LinphoneChatMessageCbsParticipantImdnStateChangedCb)(LinphoneChatMessage* msg, const LinphoneParticipantImdnState *state); + +/** + * File transfer receive callback prototype. This function is called by the core upon an incoming File transfer is started. This function may be call several time for the same file in case of large file. + * @param message #LinphoneChatMessage message from which the body is received. + * @param content #LinphoneContent incoming content information + * @param buffer #LinphoneBuffer holding the received data. Empty buffer means end of file. + */ +typedef void (*LinphoneChatMessageCbsFileTransferRecvCb)(LinphoneChatMessage *message, const LinphoneContent* content, const LinphoneBuffer *buffer); + +/** + * File transfer send callback prototype. This function is called by the core when an outgoing file transfer is started. This function is called until size is set to 0. + * @param message #LinphoneChatMessage message from which the body is received. + * @param content #LinphoneContent outgoing content + * @param offset the offset in the file from where to get the data to be sent + * @param size the number of bytes expected by the framework + * @return A #LinphoneBuffer object holding the data written by the application. An empty buffer means end of file. + */ +typedef LinphoneBuffer * (*LinphoneChatMessageCbsFileTransferSendCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t size); + +/** + * File transfer progress indication callback prototype. + * @param message #LinphoneChatMessage message from which the body is received. + * @param content #LinphoneContent incoming content information + * @param offset The number of bytes sent/received since the beginning of the transfer. + * @param total The total number of bytes to be sent/received. + */ +typedef void (*LinphoneChatMessageCbsFileTransferProgressIndicationCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total); + +/** + * Is composing notification callback prototype. + * @param[in] cr #LinphoneChatRoom involved in the conversation + * @param[in] remoteAddr The address that has sent the is-composing notification + * @param[in] isComposing A boolean value telling whether the remote is composing or not + */ +typedef void (*LinphoneChatRoomCbsIsComposingReceivedCb) (LinphoneChatRoom *cr, const LinphoneAddress *remoteAddr, bool_t isComposing); + +/** + * Callback used to notify a chat room that a message has been received. + * @param[in] cr #LinphoneChatRoom object + * @param[in] msg The #LinphoneChatMessage that has been received + */ +typedef void (*LinphoneChatRoomCbsMessageReceivedCb) (LinphoneChatRoom *cr, LinphoneChatMessage *msg); + +/** + * Callback used to notify a chat room that a chat message has been received. + * @param[in] cr #LinphoneChatRoom object + * @param[in] event_log The #LinphoneChatMessage event log that has been received + */ +typedef void (*LinphoneChatRoomCbsChatMessageReceivedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room that a chat message is being sent. + * @param[in] cr #LinphoneChatRoom object + * @param[in] event_log The #LinphoneChatMessage event log that is being sent + */ +typedef void (*LinphoneChatRoomCbsChatMessageSentCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room that a participant has been added. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participant The #LinphoneParticipant that has been added to the chat room + */ +typedef void (*LinphoneChatRoomCbsParticipantAddedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room that a participant has been removed. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participant The #LinphoneParticipant that has been removed from the chat room + */ +typedef void (*LinphoneChatRoomCbsParticipantRemovedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room that the admin status of a participant has been changed. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participant The #LinphoneParticipant for which the admin status has been changed + * @param[in] isAdmin The new admin status of the participant + */ +typedef void (*LinphoneChatRoomCbsParticipantAdminStatusChangedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room state has changed. + * @param[in] cr #LinphoneChatRoom object + * @param[in] newState The new state of the chat room + */ +typedef void (*LinphoneChatRoomCbsStateChangedCb) (LinphoneChatRoom *cr, LinphoneChatRoomState newState); + +/** + * Callback used to notify that the subject of a chat room has changed. + * @param[in] cr #LinphoneChatRoom object + * @param[in] subject The new subject of the chat room + */ +typedef void (*LinphoneChatRoomCbsSubjectChangedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room that a message has been received but we were unable to decrypt it + * @param cr #LinphoneChatRoom involved in this conversation + * @param msg The #LinphoneChatMessage that has been received + */ +typedef void (*LinphoneChatRoomCbsUndecryptableMessageReceivedCb) (LinphoneChatRoom *cr, LinphoneChatMessage *msg); + +/** + * Callback used to notify a chat room that a participant has been added. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participant The #LinphoneParticipant that has been added to the chat room + */ +typedef void (*LinphoneChatRoomCbsParticipantDeviceAddedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room that a participant has been removed. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participant The #LinphoneParticipant that has been removed from the chat room + */ +typedef void (*LinphoneChatRoomCbsParticipantDeviceRemovedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *event_log); + +/** + * Callback used to notify a chat room has been joined. + * @param[in] cr #LinphoneChatRoom object + */ +typedef void (*LinphoneChatRoomCbsConferenceJoinedCb) (LinphoneChatRoom *cr, const LinphoneEventLog *eventLog); + +/** + * Callback used to notify a chat room has been left. + * @param[in] cr #LinphoneChatRoom object + */ +typedef void (*LinphoneChatRoomCbsConferenceLeftCb) (LinphoneChatRoom *cr, const LinphoneEventLog *eventLog); + +/** + * Callback used when a group chat room is created server-side to generate the address of the chat room. + * The function linphone_chat_room_set_conference_address() needs to be called by this callback. + * @param[in] cr #LinphoneChatRoom object + */ +typedef void (*LinphoneChatRoomCbsConferenceAddressGenerationCb) (LinphoneChatRoom *cr); + +/** + * Callback used when a group chat room server is adding participant to fetch all device information from participant. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participantAddr #LinphoneAddress object + */ +typedef void (*LinphoneChatRoomCbsParticipantDeviceFetchRequestedCb) (LinphoneChatRoom *cr, const LinphoneAddress *participantAddr); + +/** + * Callback used when a group chat room server is checking participants capabilities. + * @param[in] cr #LinphoneChatRoom object + * @param[in] deviceAddr #LinphoneAddress object + * @param[in] participantsAddr \bctbx_list{LinphoneAddress} + */ +typedef void (*LinphoneChatRoomCbsParticipantsCapabilitiesCheckedCb) (LinphoneChatRoom *cr, const LinphoneAddress *deviceAddr, const bctbx_list_t *participantsAddr); + +/** + * Callback used when a group chat room server is subscribing to registration state of a participant. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participantAddr #LinphoneAddress object + */ +typedef void (*LinphoneChatRoomCbsParticipantRegistrationSubscriptionRequestedCb) (LinphoneChatRoom *cr, const LinphoneAddress *participantAddr); + +/** + * Callback used when a group chat room server is unsubscribing to registration state of a participant. + * @param[in] cr #LinphoneChatRoom object + * @param[in] participantAddr #LinphoneAddress object + */ +typedef void (*LinphoneChatRoomCbsParticipantRegistrationUnsubscriptionRequestedCb) (LinphoneChatRoom *cr, const LinphoneAddress *participantAddr); + +/** + * Callback used to tell the core whether or not to store the incoming message in db or not using linphone_chat_message_set_to_be_stored(). + * @param[in] cr #LinphoneChatRoom object + * @param[in] msg The #LinphoneChatMessage that is being received + */ +typedef void (*LinphoneChatRoomCbsShouldChatMessageBeStoredCb) (LinphoneChatRoom *cr, LinphoneChatMessage *msg); + +/** + * @} +**/ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CALLBACKS_H_ diff --git a/include/linphone/api/c-chat-message-cbs.h b/include/linphone/api/c-chat-message-cbs.h new file mode 100644 index 000000000..35dc2ff19 --- /dev/null +++ b/include/linphone/api/c-chat-message-cbs.h @@ -0,0 +1,144 @@ +/* + * c-chat-message-cbs.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CHAT_MESSAGE_CBS_H_ +#define _L_C_CHAT_MESSAGE_CBS_H_ + +#include "linphone/api/c-callbacks.h" +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup chatroom + * @{ + */ + +LinphoneChatMessageCbs *linphone_chat_message_cbs_new (void); + +/** + * Acquire a reference to the chat room callbacks object. + * @param[in] cbs The chat room callbacks object + * @return The same chat room callbacks object +**/ +LINPHONE_PUBLIC LinphoneChatMessageCbs * linphone_chat_message_cbs_ref (LinphoneChatMessageCbs *cbs); + +/** + * Release reference to the chat room callbacks object. + * @param[in] cr The chat room callbacks object +**/ +LINPHONE_PUBLIC void linphone_chat_message_cbs_unref (LinphoneChatMessageCbs *cbs); + +/** + * Retrieve the user pointer associated with the chat room callbacks object. + * @param[in] cr The chat room callbacks object + * @return The user pointer associated with the chat room callbacks object +**/ +LINPHONE_PUBLIC void * linphone_chat_message_cbs_get_user_data (const LinphoneChatMessageCbs *cbs); + +/** + * Assign a user pointer to the chat room callbacks object. + * @param[in] cr The chat room callbacks object + * @param[in] ud The user pointer to associate with the chat room callbacks object +**/ +LINPHONE_PUBLIC void linphone_chat_message_cbs_set_user_data (LinphoneChatMessageCbs *cbs, void *ud); + +/** + * Get the message state changed callback. + * @param[in] cbs #LinphoneChatMessageCbs object. + * @return The current message state changed callback. + */ +LINPHONE_PUBLIC LinphoneChatMessageCbsMsgStateChangedCb linphone_chat_message_cbs_get_msg_state_changed (const LinphoneChatMessageCbs *cbs); + +/** + * Set the message state changed callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @param[in] cb The message state changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_message_cbs_set_msg_state_changed (LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsMsgStateChangedCb cb); + +/** + * Get the file transfer receive callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @return The current file transfer receive callback. + */ +LINPHONE_PUBLIC LinphoneChatMessageCbsFileTransferRecvCb linphone_chat_message_cbs_get_file_transfer_recv (const LinphoneChatMessageCbs *cbs); + +/** + * Set the file transfer receive callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @param[in] cb The file transfer receive callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_message_cbs_set_file_transfer_recv (LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsFileTransferRecvCb cb); + +/** + * Get the file transfer send callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @return The current file transfer send callback. + */ +LINPHONE_PUBLIC LinphoneChatMessageCbsFileTransferSendCb linphone_chat_message_cbs_get_file_transfer_send (const LinphoneChatMessageCbs *cbs); + +/** + * Set the file transfer send callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @param[in] cb The file transfer send callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_message_cbs_set_file_transfer_send (LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsFileTransferSendCb cb); + +/** + * Get the file transfer progress indication callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @return The current file transfer progress indication callback. + */ +LINPHONE_PUBLIC LinphoneChatMessageCbsFileTransferProgressIndicationCb linphone_chat_message_cbs_get_file_transfer_progress_indication (const LinphoneChatMessageCbs *cbs); + +/** + * Set the file transfer progress indication callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @param[in] cb The file transfer progress indication callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_message_cbs_set_file_transfer_progress_indication (LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsFileTransferProgressIndicationCb cb); + +/** + * Get the participant IMDN state changed callback. + * @param[in] cbs #LinphoneChatMessageCbs object. + * @return The current participant IMDN state changed callback. + */ +LINPHONE_PUBLIC LinphoneChatMessageCbsParticipantImdnStateChangedCb linphone_chat_message_cbs_get_participant_imdn_state_changed (const LinphoneChatMessageCbs *cbs); + +/** + * Set the participant IMDN state changed callback. + * @param[in] cbs LinphoneChatMessageCbs object. + * @param[in] cb The participant IMDN state changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_message_cbs_set_participant_imdn_state_changed (LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsParticipantImdnStateChangedCb cb); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CHAT_MESSAGE_CBS_H_ diff --git a/include/linphone/api/c-chat-message.h b/include/linphone/api/c-chat-message.h new file mode 100644 index 000000000..25f202f82 --- /dev/null +++ b/include/linphone/api/c-chat-message.h @@ -0,0 +1,400 @@ +/* + * c-chat-message.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CHAT_MESSAGE_H_ +#define _L_C_CHAT_MESSAGE_H_ + +#include "linphone/api/c-chat-message-cbs.h" +#include "linphone/api/c-types.h" + +#ifdef SQLITE_STORAGE_ENABLED + #include +#endif // ifdef SQLITE_STORAGE_ENABLED + +// ============================================================================= + +typedef enum _LinphoneChatMessageDir{ + LinphoneChatMessageIncoming, + LinphoneChatMessageOutgoing +} LinphoneChatMessageDir; + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup chatmessage + * @{ + */ + +/** + * Acquire a reference to the chat message. + * @param[in] msg #LinphoneChatMessage object. + * @return The same chat message. + */ +LINPHONE_PUBLIC LinphoneChatMessage *linphone_chat_message_ref (LinphoneChatMessage *msg); + +/** + * Release reference to the chat message. + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC void linphone_chat_message_unref (LinphoneChatMessage *msg); + +/** + * Retrieve the user pointer associated with the chat message. + * @param[in] msg #LinphoneChatMessage object. + * @return The user pointer associated with the chat message. + */ +LINPHONE_PUBLIC void *linphone_chat_message_get_user_data (const LinphoneChatMessage *msg); + +/** + * Assign a user pointer to the chat message. + * @param[in] msg #LinphoneChatMessage object. + * @param[in] ud The user pointer to associate with the chat message. + */ +LINPHONE_PUBLIC void linphone_chat_message_set_user_data (LinphoneChatMessage *msg, void *ud); + +// ============================================================================= + +LINPHONE_PUBLIC const char *linphone_chat_message_get_external_body_url (const LinphoneChatMessage *msg); + +LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url (LinphoneChatMessage *msg, const char *external_body_url); + +/** + * Get the time the message was sent. + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC time_t linphone_chat_message_get_time (const LinphoneChatMessage *msg); + +/** + * Returns TRUE if the message has been sent, returns FALSE if the message has been received. + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_is_outgoing (LinphoneChatMessage *msg); + +/** + * Get origin of the message + * @param[in] msg #LinphoneChatMessage object. + * @return #LinphoneAddress + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_chat_message_get_from_address (LinphoneChatMessage *msg); + +/** + * Get destination of the message + * @param[in] msg #LinphoneChatMessage object. + * @return #LinphoneAddress + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_chat_message_get_to_address (LinphoneChatMessage *msg); + +/** + * Get the content type of a chat message. + * @param[in] msg #LinphoneChatMessage object. + * @return The content type of the chat message + */ +LINPHONE_PUBLIC const char *linphone_chat_message_get_content_type (LinphoneChatMessage *msg); + +/** + * Set the content type of a chat message. + * This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml. + * @param[in] msg #LinphoneChatMessage object. + * @param[in] content_type The new content type of the chat message + */ +LINPHONE_PUBLIC void linphone_chat_message_set_content_type (LinphoneChatMessage *msg, const char *content_type); + +/** + * Get text part of this message + * @param[in] msg #LinphoneChatMessage object. + * @return text or NULL if no text. + * @deprecated use getTextContent() instead + */ +LINPHONE_PUBLIC const char *linphone_chat_message_get_text (LinphoneChatMessage* msg); + +/** + * Get the message identifier. + * It is used to identify a message so that it can be notified as delivered and/or displayed. + * @param[in] msg #LinphoneChatMessage object. + * @return The message identifier. + */ +LINPHONE_PUBLIC const char *linphone_chat_message_get_message_id (const LinphoneChatMessage *msg); + +/** + * Linphone message has an app-specific field that can store a text. The application might want + * to use it for keeping data over restarts, like thumbnail image path. + * @param[in] msg #LinphoneChatMessage object. + * @return the application-specific data or NULL if none has been stored. + */ +LINPHONE_PUBLIC const char *linphone_chat_message_get_appdata (const LinphoneChatMessage *msg); + +/** + * Linphone message has an app-specific field that can store a text. The application might want + * to use it for keeping data over restarts, like thumbnail image path. + * + * Invoking this function will attempt to update the message storage to reflect the changeif it is + * enabled. + * + * @param[in] msg #LinphoneChatMessage object. + * @param data the data to store into the message + */ +LINPHONE_PUBLIC void linphone_chat_message_set_appdata (LinphoneChatMessage *msg, const char *data); + +/** + * Returns the chatroom this message belongs to. + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC LinphoneChatRoom *linphone_chat_message_get_chat_room (const LinphoneChatMessage *msg); + +/** + * Get the path to the file to read from or write to during the file transfer. + * @param[in] msg #LinphoneChatMessage object + * @return The path to the file to use for the file transfer. + */ +LINPHONE_PUBLIC const char *linphone_chat_message_get_file_transfer_filepath (LinphoneChatMessage *msg); + +// ============================================================================= + +/** + * Get if a chat message is to be stored. + * @param[in] msg #LinphoneChatMessage object. + * @return Whether or not the message is to be stored + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_get_to_be_stored (const LinphoneChatMessage *msg); + +/** + * Set if a chat message is to be stored. + * This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml. + * @param[in] msg #LinphoneChatMessage object. + * @param[in] to_be_stored Whether or not the chat message is to be stored + */ +LINPHONE_PUBLIC void linphone_chat_message_set_to_be_stored (LinphoneChatMessage *msg, bool_t to_be_stored); + +LINPHONE_PUBLIC unsigned int linphone_chat_message_store (LinphoneChatMessage *msg); + +/** + * Get the state of the message + * @param[in] msg #LinphoneChatMessage object. + * @return #LinphoneChatMessageState + */ +LINPHONE_PUBLIC LinphoneChatMessageState linphone_chat_message_get_state (const LinphoneChatMessage *msg); + +/** + * Get if the message was encrypted when transfered + * @param[in] msg #LinphoneChatMessage object. + * @return whether the message was encrypted when transfered or not + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_is_secured (LinphoneChatMessage *msg); + +/** + * Linphone message can carry external body as defined by rfc2017 + * @param[in] msg #LinphoneChatMessage object. + * @return external body url or NULL if not present. + */ +LINPHONE_PUBLIC const char *linphone_chat_message_get_external_body_url (const LinphoneChatMessage *msg); + +/** + * Linphone message can carry external body as defined by rfc2017 + * + * @param[in] msg #LinphoneChatMessage object. + * @param url ex: access-type=URL; URL="http://www.foo.com/file" + */ +LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url (LinphoneChatMessage *msg,const char *url); + +/** + * Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer) + * + * @param[in] msg #LinphoneChatMessage object. + * @return a pointer to the #LinphoneContent structure or NULL if not present. + */ +LINPHONE_PUBLIC LinphoneContent *linphone_chat_message_get_file_transfer_information (LinphoneChatMessage *msg); + +/** + * Return whether or not a chat message is a file tranfer. + * @param[in] msg #LinphoneChatMessage object + * @return Whether or not the message is a file tranfer + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer (LinphoneChatMessage *msg); + +/** + * Return whether or not a chat message is a text. + * @param[in] msg #LinphoneChatMessage object. + * @return Whether or not the message is a text + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_is_text (LinphoneChatMessage *msg); + +/** + * Start the download of the file from remote server + * + * @param[in] msg #LinphoneChatMessage object. + * @param status_cb #LinphoneChatMessageStateChangeCb status callback invoked when file is downloaded or could not be downloaded + * @param ud user data + * @deprecated Use linphone_chat_message_download_file() instead. + * @donotwrap + */ +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_message_start_file_download ( + LinphoneChatMessage *msg, + LinphoneChatMessageStateChangedCb status_cb, + void *ud +); + +/** + * Start the download of the file referenced in a #LinphoneChatMessage from remote server. + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_download_file (LinphoneChatMessage *msg); + +/** + * Cancel an ongoing file transfer attached to this message.(upload or download) + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC void linphone_chat_message_cancel_file_transfer (LinphoneChatMessage *msg); + +/** + * Send a chat message. + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC void linphone_chat_message_send (LinphoneChatMessage *msg); + +/** + * Resend a chat message if it is in the 'not delivered' state for whatever reason. + * @param[in] msg #LinphoneChatMessage object. + * @deprecated Use linphone_chat_message_send instead. + * @donotwrap + */ +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_message_resend (LinphoneChatMessage *msg); + +LINPHONE_PUBLIC const LinphoneAddress *linphone_chat_message_get_peer_address (LinphoneChatMessage *msg); + +/** + * Returns the origin address of a message if it was a outgoing message, or the destination address if it was an incoming message. + * @param[in] msg #LinphoneChatMessage object. + * @return #LinphoneAddress + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_chat_message_get_local_address (LinphoneChatMessage *msg); + +/** + * Add custom headers to the message. + * @param[in] msg #LinphoneChatMessage object. + * @param header_name name of the header + * @param header_value header value + */ +LINPHONE_PUBLIC void linphone_chat_message_add_custom_header ( + LinphoneChatMessage *msg, + const char *header_name, + const char *header_value +); + +/** + * Retrieve a custom header value given its name. + * @param[in] msg #LinphoneChatMessage object. + * @param header_name header name searched + */ +LINPHONE_PUBLIC const char * linphone_chat_message_get_custom_header (LinphoneChatMessage *msg, const char *header_name); + +/** + * Removes a custom header from the message. + * @param[in] msg #LinphoneChatMessage object. + * @param header_name name of the header to remove + */ +LINPHONE_PUBLIC void linphone_chat_message_remove_custom_header (LinphoneChatMessage *msg, const char *header_name); + +/** + * Returns TRUE if the message has been read, otherwise returns FALSE. + * @param[in] msg #LinphoneChatMessage object. + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_is_read (LinphoneChatMessage *msg); + +LINPHONE_PUBLIC LinphoneReason linphone_chat_message_get_reason (LinphoneChatMessage *msg); + +/** + * Get full details about delivery error of a chat message. + * @param[in] msg #LinphoneChatMessage object. + * @return a #LinphoneErrorInfo describing the details. + */ +LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_chat_message_get_error_info (const LinphoneChatMessage *msg); + +/** + * Set the path to the file to read from or write to during the file transfer. + * @param[in] msg #LinphoneChatMessage object. + * @param[in] filepath The path to the file to use for the file transfer. + */ +LINPHONE_PUBLIC void linphone_chat_message_set_file_transfer_filepath (LinphoneChatMessage *msg, const char *filepath); + +/** + * Fulfill a chat message char by char. Message linked to a Real Time Text Call send char in realtime following RFC 4103/T.140 + * To commit a message, use #linphone_chat_room_send_message + * @param[in] msg #LinphoneChatMessage object. + * @param[in] character T.140 char + * @returns 0 if succeed. + */ +LINPHONE_PUBLIC LinphoneStatus linphone_chat_message_put_char (LinphoneChatMessage *msg, uint32_t character); + +/** + * Get the #LinphoneChatMessageCbs object associated with the LinphoneChatMessage. + * @param[in] msg #LinphoneChatMessage object. + * @return The #LinphoneChatMessageCbs object associated with the LinphoneChatMessage. + */ +LINPHONE_PUBLIC LinphoneChatMessageCbs *linphone_chat_message_get_callbacks (const LinphoneChatMessage *msg); + +/** + * Adds a content to the ChatMessage + * @param[in] msg #LinphoneChatMessage object. + * @param[in] c_content #LinphoneContent object + */ +LINPHONE_PUBLIC void linphone_chat_message_add_text_content (LinphoneChatMessage *msg, const char *c_content); + +/** + * Returns true if the chat message has a text content + * @param[in] msg #LinphoneChatMessage object. + * @return true if it has one, false otherwise + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_has_text_content (const LinphoneChatMessage *msg); + +/** + * Gets the text content if available as a string + * @param[in] msg #LinphoneChatMessage object. + * @return the #LinphoneContent buffer if available, null otherwise + */ +LINPHONE_PUBLIC const char *linphone_chat_message_get_text_content (const LinphoneChatMessage *msg); + +/** + * Gets whether or not a file is currently being downloaded or uploaded + * @param[in] msg #LinphoneChatMessage object. + * @return true if download or upload is in progress, false otherwise + */ +LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer_in_progress (LinphoneChatMessage *msg); + +/** + * Gets the list of participants for which the imdn state has reached the specified state and the time at which they did. + * @param[in] msg #LinphoneChatMessage object. + * @param[in] state The LinphoneChatMessageState the imdn have reached (only use LinphoneChatMessageStateDelivered, + * LinphoneChatMessageStateDeliveredToUser, LinphoneChatMessageStateDisplayed and LinphoneChatMessageStateNotDelivered) + * @return \bctbx_list{LinphoneParticipantImdnState} + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_message_get_participants_by_imdn_state (const LinphoneChatMessage *msg, LinphoneChatMessageState state); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CHAT_MESSAGE_H_ diff --git a/include/linphone/api/c-chat-room-cbs.h b/include/linphone/api/c-chat-room-cbs.h new file mode 100644 index 000000000..b60a1d1b1 --- /dev/null +++ b/include/linphone/api/c-chat-room-cbs.h @@ -0,0 +1,351 @@ +/* + * c-chat-room-cbs.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CHAT_ROOM_CBS_H_ +#define _L_C_CHAT_ROOM_CBS_H_ + +#include "linphone/api/c-callbacks.h" +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup chatroom + * @{ + */ + +/** + * Acquire a reference to the chat room callbacks object. + * @param[in] cbs The chat room callbacks object + * @return The same chat room callbacks object +**/ +LINPHONE_PUBLIC LinphoneChatRoomCbs * linphone_chat_room_cbs_ref (LinphoneChatRoomCbs *cbs); + +/** + * Release reference to the chat room callbacks object. + * @param[in] cr The chat room callbacks object +**/ +LINPHONE_PUBLIC void linphone_chat_room_cbs_unref (LinphoneChatRoomCbs *cbs); + +/** + * Retrieve the user pointer associated with the chat room callbacks object. + * @param[in] cr The chat room callbacks object + * @return The user pointer associated with the chat room callbacks object +**/ +LINPHONE_PUBLIC void * linphone_chat_room_cbs_get_user_data (const LinphoneChatRoomCbs *cbs); + +/** + * Assign a user pointer to the chat room callbacks object. + * @param[in] cr The chat room callbacks object + * @param[in] ud The user pointer to associate with the chat room callbacks object +**/ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_user_data (LinphoneChatRoomCbs *cbs, void *ud); + +/** + * Get the is-composing received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current is-composing received callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsIsComposingReceivedCb linphone_chat_room_cbs_get_is_composing_received (const LinphoneChatRoomCbs *cbs); + +/** + * Set the is-composing received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The is-composing received callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_is_composing_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsIsComposingReceivedCb cb); + +/** + * Get the message received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current message received callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsMessageReceivedCb linphone_chat_room_cbs_get_message_received (const LinphoneChatRoomCbs *cbs); + +/** + * Set the message received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The message received callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_message_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsMessageReceivedCb cb); + +/** + * Get the chat message received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current chat message received callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsChatMessageReceivedCb linphone_chat_room_cbs_get_chat_message_received (const LinphoneChatRoomCbs *cbs); + +/** + * Set the chat message received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The chat message received callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_chat_message_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsChatMessageReceivedCb cb); + +/** + * Get the chat message sent callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current chat message sent callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsChatMessageSentCb linphone_chat_room_cbs_get_chat_message_sent (const LinphoneChatRoomCbs *cbs); + +/** + * Set the chat message sent callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The chat message sent callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_chat_message_sent (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsChatMessageSentCb cb); + +/** + * Get the participant added callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current participant added callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantAddedCb linphone_chat_room_cbs_get_participant_added (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant added callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The participant added callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_added (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantAddedCb cb); + +/** + * Get the participant removed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current participant removed callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantRemovedCb linphone_chat_room_cbs_get_participant_removed (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant removed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The participant removed callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_removed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantRemovedCb cb); + +/** + * Get the participant admin status changed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current participant admin status changed callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantAdminStatusChangedCb linphone_chat_room_cbs_get_participant_admin_status_changed (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant admin status changed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The participant admin status changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_admin_status_changed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantAdminStatusChangedCb cb); + +/** + * Get the state changed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current state changed callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsStateChangedCb linphone_chat_room_cbs_get_state_changed (const LinphoneChatRoomCbs *cbs); + +/** + * Set the state changed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The state changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_state_changed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsStateChangedCb cb); + +/** + * Get the subject changed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current subject changed callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsSubjectChangedCb linphone_chat_room_cbs_get_subject_changed (const LinphoneChatRoomCbs *cbs); + +/** + * Set the subject changed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The subject changed callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_subject_changed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsSubjectChangedCb cb); + +/** + * Get the undecryptable message received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current undecryptable message received callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsUndecryptableMessageReceivedCb linphone_chat_room_cbs_get_undecryptable_message_received (const LinphoneChatRoomCbs *cbs); + +/** + * Set the undecryptable message received callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The undecryptable message received callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_undecryptable_message_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsUndecryptableMessageReceivedCb cb); + +/** + * Get the participant device added callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current participant device added callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantDeviceAddedCb linphone_chat_room_cbs_get_participant_device_added (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant device added callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The participant device added callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_device_added (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantDeviceAddedCb cb); + +/** + * Get the participant device removed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @return The current participant device removed callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantDeviceRemovedCb linphone_chat_room_cbs_get_participant_device_removed (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant device removed callback. + * @param[in] cbs #LinphoneChatRoomCbs object. + * @param[in] cb The participant device removed callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_device_removed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantDeviceRemovedCb cb); + +/** + * Get the conference joined callback. + * @param[in] cbs LinphoneChatRoomCbs object. + * @return The current conference joined callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsConferenceJoinedCb linphone_chat_room_cbs_get_conference_joined (const LinphoneChatRoomCbs *cbs); + +/** + * Set the conference joined callback. + * @param[in] cbs LinphoneChatRoomCbs object. + * @param[in] cb The conference joined callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_conference_joined (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsConferenceJoinedCb cb); + +/** + * Get the conference left callback. + * @param[in] cbs LinphoneChatRoomCbs object. + * @return The current conference left callback. + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsConferenceLeftCb linphone_chat_room_cbs_get_conference_left (const LinphoneChatRoomCbs *cbs); + +/** + * Set the conference left callback. + * @param[in] cbs LinphoneChatRoomCbs object. + * @param[in] cb The conference left callback to be used. + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_conference_left (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsConferenceLeftCb cb); + +/** + * Get the conference address generation callback. + * @param[in] cbs #LinphoneChatRoomCbs object + * @return The current conference address generation callback + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsConferenceAddressGenerationCb linphone_chat_room_cbs_get_conference_address_generation (const LinphoneChatRoomCbs *cbs); + +/** + * Set the conference address generation callback. + * @param[in] cbs #LinphoneChatRoomCbs object + * @param[in] cb The conference address generation callback to be used + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_conference_address_generation (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsConferenceAddressGenerationCb cb); + +/** + * Get the participant device fetching callback. + * @param[in] cbs #LinphoneChatRoomCbs object + * @return The participant device fetching callback + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantDeviceFetchRequestedCb linphone_chat_room_cbs_get_participant_device_fetch_requested (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant device fetching callback. + * @param[in] cbs #LinphoneChatRoomCbs object + * @param[in] cb The participant device fetching callback to be used + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_device_fetch_requested (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantDeviceFetchRequestedCb cb); + +/** + * Get the participants capabilities callback. + * @param[in] cbs #LinphoneChatRoomCbs object + * @return The participants capabilities getting callback + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantsCapabilitiesCheckedCb linphone_chat_room_cbs_get_participants_capabilities_checked (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participants capabilities callback. + * @param[in] cbs #LinphoneChatRoomCbs object + * @param[in] cb The participants capabilities callback to be used + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participants_capabilities_checked (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantsCapabilitiesCheckedCb cb); + +/** + * Get the participant registration subscription callback. + * @param[in] cbs LinphoneChatRoomCbs object + * @return The participant registration subscription callback + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantRegistrationSubscriptionRequestedCb linphone_chat_room_cbs_get_participant_registration_subscription_requested (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant registration subscription callback. + * @param[in] cbs LinphoneChatRoomCbs object + * @param[in] cb The participant registration subscription callback to be used + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_registration_subscription_requested (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantRegistrationSubscriptionRequestedCb cb); + +/** + * Get the participant registration unsubscription callback. + * @param[in] cbs LinphoneChatRoomCbs object + * @return The participant registration unsubscription callback + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsParticipantRegistrationUnsubscriptionRequestedCb linphone_chat_room_cbs_get_participant_registration_unsubscription_requested (const LinphoneChatRoomCbs *cbs); + +/** + * Set the participant registration unsubscription callback. + * @param[in] cbs LinphoneChatRoomCbs object + * @param[in] cb The participant registration unsubscription callback to be used + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_participant_registration_unsubscription_requested (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantRegistrationUnsubscriptionRequestedCb cb); + +/** + * Get the message should be stored callback. + * @param[in] cbs LinphoneChatRoomCbs object + * @return The message should be stored getting callback + */ +LINPHONE_PUBLIC LinphoneChatRoomCbsShouldChatMessageBeStoredCb linphone_chat_room_cbs_get_chat_message_should_be_stored( LinphoneChatRoomCbs *cbs); +/** + * Set the message should be stored callback. + * @param[in] cbs LinphoneChatRoomCbs object + * @param[in] cb The message should be stored callback to be used + */ +LINPHONE_PUBLIC void linphone_chat_room_cbs_set_chat_message_should_be_stored( LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsShouldChatMessageBeStoredCb cb); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CHAT_ROOM_CBS_H_ diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h new file mode 100644 index 000000000..b3a98453c --- /dev/null +++ b/include/linphone/api/c-chat-room.h @@ -0,0 +1,503 @@ +/* + * c-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CHAT_ROOM_H_ +#define _L_C_CHAT_ROOM_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup chatroom + * @{ + */ + +/** + * Acquire a reference to the chat room. + * @param[in] cr The chat room. + * @return The same chat room. +**/ +LINPHONE_PUBLIC LinphoneChatRoom *linphone_chat_room_ref(LinphoneChatRoom *cr); + +/** + * Release reference to the chat room. + * @param[in] cr The chat room. +**/ +LINPHONE_PUBLIC void linphone_chat_room_unref(LinphoneChatRoom *cr); + +/** + * Retrieve the user pointer associated with the chat room. + * @param[in] cr The chat room. + * @return The user pointer associated with the chat room. +**/ +LINPHONE_PUBLIC void *linphone_chat_room_get_user_data(const LinphoneChatRoom *cr); + +/** + * Assign a user pointer to the chat room. + * @param[in] cr The chat room. + * @param[in] ud The user pointer to associate with the chat room. +**/ +LINPHONE_PUBLIC void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud); + +/** + * Create a message attached to a dedicated chat room; + * @param cr the chat room. + * @param message text message, NULL if absent. + * @return a new #LinphoneChatMessage + */ +LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr,const char* message); + +/** + * Create a message attached to a dedicated chat room; + * @param cr the chat room. + * @param message text message, NULL if absent. + * @param external_body_url the URL given in external body or NULL. + * @param state the LinphoneChatMessage.State of the message. + * @param time the time_t at which the message has been received/sent. + * @param is_read TRUE if the message should be flagged as read, FALSE otherwise. + * @param is_incoming TRUE if the message has been received, FALSE otherwise. + * @return a new #LinphoneChatMessage + * @deprecated Use #linphone_chat_room_create_message() instead. Deprecated since 2017-11-14. + * @donotwrap + */ +LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message_2(LinphoneChatRoom *cr, const char* message, const char* external_body_url, LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming); + + /** + * Create a message attached to a dedicated chat room with a particular content. + * Use #linphone_chat_room_send_message to initiate the transfer + * @param cr the chat room. + * @param initial_content #LinphoneContent initial content. #LinphoneCoreVTable.file_transfer_send is invoked later to notify file transfer progress and collect next chunk of the message if LinphoneContent.data is NULL. + * @return a new #LinphoneChatMessage + */ +LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent* initial_content); + +/** + * get peer address \link linphone_core_get_chat_room() associated to \endlink this #LinphoneChatRoom + * @param cr #LinphoneChatRoom object + * @return #LinphoneAddress peer address + */ +LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr); + +/** + * get local address \link linphone_core_get_chat_room() associated to \endlink this #LinphoneChatRoom + * @param cr #LinphoneChatRoom object + * @return #LinphoneAddress local address + */ +LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_room_get_local_address(LinphoneChatRoom *cr); + + +/** + * Send a message to peer member of this chat room. + * @deprecated Use linphone_chat_message_send() instead. + * @param cr #LinphoneChatRoom object + * @param msg message to be sent + * @donotwrap + */ +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg); + +/** + * Send a message to peer member of this chat room. + * @param[in] cr #LinphoneChatRoom object + * @param[in] msg #LinphoneChatMessage object + * The state of the message sending will be notified via the callbacks defined in the #LinphoneChatMessageCbs object that can be obtained + * by calling linphone_chat_message_get_callbacks(). + * The #LinphoneChatMessage reference is transfered to the function and thus doesn't need to be unref'd by the application. + * @deprecated Use linphone_chat_message_send() instead. + * @donotwrap + */ +LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_room_send_chat_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); + +/** + * Used to receive a chat message when using async mechanism with IM encryption engine + * @param[in] cr #LinphoneChatRoom object + * @param[in] msg #LinphoneChatMessage object + */ +LINPHONE_PUBLIC void linphone_chat_room_receive_chat_message (LinphoneChatRoom *cr, LinphoneChatMessage *msg); + +/** + * Mark all messages of the conversation as read + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. + */ +LINPHONE_PUBLIC void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr); + +/** + * Delete a message from the chat room history. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. + * @param[in] msg The #LinphoneChatMessage object to remove. + */ + +LINPHONE_PUBLIC void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); + +/** + * Delete all messages from the history + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. + */ +LINPHONE_PUBLIC void linphone_chat_room_delete_history(LinphoneChatRoom *cr); + +/** + * Gets the number of messages in a chat room. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which size has to be computed + * @return the number of messages. + */ +LINPHONE_PUBLIC int linphone_chat_room_get_history_size(LinphoneChatRoom *cr); + +/** + * Gets nb_message most recent messages from cr chat room, sorted from oldest to most recent. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which messages should be retrieved + * @param[in] nb_message Number of message to retrieve. 0 means everything. + * @return \bctbx_list{LinphoneChatMessage} + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history (LinphoneChatRoom *cr,int nb_message); + +/** + * Gets the partial list of messages in the given range, sorted from oldest to most recent. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which messages should be retrieved + * @param[in] begin The first message of the range to be retrieved. History most recent message has index 0. + * @param[in] end The last message of the range to be retrieved. History oldest message has index of history size - 1 (use #linphone_chat_room_get_history_size to retrieve history size) + * @return \bctbx_list{LinphoneChatMessage} + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end); + +/** + * Gets nb_events most recent chat message events from cr chat room, sorted from oldest to most recent. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which events should be retrieved + * @param[in] nb_events Number of events to retrieve. 0 means everything. + * @return \bctbx_list{LinphoneEventLog} + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history_message_events (LinphoneChatRoom *cr, int nb_events); + +/** + * Gets the partial list of chat message events in the given range, sorted from oldest to most recent. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which events should be retrieved + * @param[in] begin The first event of the range to be retrieved. History most recent event has index 0. + * @param[in] end The last event of the range to be retrieved. History oldest event has index of history size - 1 + * @return \bctbx_list{LinphoneEventLog} + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history_range_message_events (LinphoneChatRoom *cr, int begin, int end); + +/** + * Gets nb_events most recent events from cr chat room, sorted from oldest to most recent. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which events should be retrieved + * @param[in] nb_events Number of events to retrieve. 0 means everything. + * @return \bctbx_list{LinphoneEventLog} + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history_events (LinphoneChatRoom *cr, int nb_events); + +/** + * Gets the partial list of events in the given range, sorted from oldest to most recent. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which events should be retrieved + * @param[in] begin The first event of the range to be retrieved. History most recent event has index 0. + * @param[in] end The last event of the range to be retrieved. History oldest event has index of history size - 1 + * @return \bctbx_list{LinphoneEventLog} + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history_range_events (LinphoneChatRoom *cr, int begin, int end); + +/** + * Gets the number of events in a chat room. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which size has to be computed + * @return the number of events. + */ +LINPHONE_PUBLIC int linphone_chat_room_get_history_events_size(LinphoneChatRoom *cr); + +/** + * Gets the last chat message sent or received in this chat room + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which last message should be retrieved + * @return the latest #LinphoneChatMessage + */ +LINPHONE_PUBLIC LinphoneChatMessage *linphone_chat_room_get_last_message_in_history(LinphoneChatRoom *cr); + +/** + * Gets the chat message sent or received in this chat room that matches the message_id + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which the message should be retrieved + * @param[in] message_id The id of the message to find + * @return the #LinphoneChatMessage + */ +LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, const char *message_id); + +/** + * Notifies the destination of the chat message being composed that the user is typing a new message. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which a new message is being typed. + */ +LINPHONE_PUBLIC void linphone_chat_room_compose(LinphoneChatRoom *cr); + +/** + * Tells whether the remote is currently composing a message. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. + * @return TRUE if the remote is currently composing a message, FALSE otherwise. + */ +LINPHONE_PUBLIC bool_t linphone_chat_room_is_remote_composing(const LinphoneChatRoom *cr); + +/** + * Gets the number of unread messages in the chatroom. + * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. + * @return the number of unread messages. + */ +LINPHONE_PUBLIC int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr); + +/** + * Returns back pointer to #LinphoneCore object. +**/ +LINPHONE_PUBLIC LinphoneCore* linphone_chat_room_get_core(const LinphoneChatRoom *cr); + +/** + * When realtime text is enabled #linphone_call_params_realtime_text_enabled, #LinphoneCoreIsComposingReceivedCb is call everytime a char is received from peer. + * At the end of remote typing a regular #LinphoneChatMessage is received with committed data from #LinphoneCoreMessageReceivedCb. + * @param[in] cr #LinphoneChatRoom object + * @returns RFC 4103/T.140 char + */ +LINPHONE_PUBLIC uint32_t linphone_chat_room_get_char(const LinphoneChatRoom *cr); + +/** + * Returns true if lime is available for given peer + * + * @return true if zrtp secrets have already been shared and ready to use + */ +LINPHONE_PUBLIC bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr); + +/** + * get Curent Call associated to this chatroom if any + * To commit a message, use #linphone_chat_room_send_message + * @param[in] room #LinphoneChatRomm + * @returns #LinphoneCall or NULL. + */ +LINPHONE_PUBLIC LinphoneCall *linphone_chat_room_get_call(const LinphoneChatRoom *room); + +/** + * Add a listener in order to be notified of #LinphoneChatRoom events. Once an event is received, registred #LinphoneChatRoomCbs are + * invoked sequencially. + * @param[in] call #LinphoneChatRoom object to monitor. + * @param[in] cbs A #LinphoneChatRoomCbs object holding the callbacks you need. A reference is taken by the #LinphoneChatRoom until you invoke linphone_call_remove_callbacks(). + */ +LINPHONE_PUBLIC void linphone_chat_room_add_callbacks(LinphoneChatRoom *cr, LinphoneChatRoomCbs *cbs); + +/** + * Remove a listener from a LinphoneChatRoom + * @param[in] call LinphoneChatRoom object + * @param[in] cbs LinphoneChatRoomCbs object to remove. + */ +LINPHONE_PUBLIC void linphone_chat_room_remove_callbacks(LinphoneChatRoom *cr, LinphoneChatRoomCbs *cbs); + +/** + * Gets the current LinphoneChatRoomCbs. + * This is meant only to be called from a callback to be able to get the user_data associated with the LinphoneChatRoomCbs that is calling the callback. + * @param[in] call LinphoneChatRoom object + * @return The LinphoneChatRoomCbs that has called the last callback + */ +LINPHONE_PUBLIC LinphoneChatRoomCbs *linphone_chat_room_get_current_callbacks(const LinphoneChatRoom *cr); + +/** + * Get the state of the chat room. + * @param[in] cr #LinphoneChatRoom object + * @return The state of the chat room + */ +LINPHONE_PUBLIC LinphoneChatRoomState linphone_chat_room_get_state (const LinphoneChatRoom *cr); + +/** + * Return whether or not the chat room has been left. + * @param[in] cr #LinphoneChatRoom object + * @return whether or not the chat room has been left + */ +LINPHONE_PUBLIC bool_t linphone_chat_room_has_been_left (const LinphoneChatRoom *cr); + +/** + * Return the last updated time for the chat room + * @param[in] cr LinphoneChatRoom object + * @return the last updated time + */ +LINPHONE_PUBLIC time_t linphone_chat_room_get_last_update_time(const LinphoneChatRoom *cr); + +/** + * Add a participant to a chat room. This may fail if this type of chat room does not handle participants. + * Use linphone_chat_room_can_handle_participants() to know if this chat room handles participants. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] addr The address of the participant to add to the chat room + */ +LINPHONE_PUBLIC void linphone_chat_room_add_participant (LinphoneChatRoom *cr, const LinphoneAddress *addr); + +/** + * Add several participants to a chat room at once. This may fail if this type of chat room does not handle participants. + * Use linphone_chat_room_can_handle_participants() to know if this chat room handles participants. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] addresses \bctbx_list{LinphoneAddress} + */ +LINPHONE_PUBLIC void linphone_chat_room_add_participants (LinphoneChatRoom *cr, const bctbx_list_t *addresses); + +/** + * Tells whether a chat room is able to handle participants. + * @param[in] cr A #LinphoneChatRoom object + * @return A boolean value telling whether the chat room can handle participants or not + */ +LINPHONE_PUBLIC bool_t linphone_chat_room_can_handle_participants (const LinphoneChatRoom *cr); + +/** + * Find a participant of a chat room from its address. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] addr The address to search in the list of participants of the chat room + * @return The participant if found, NULL otherwise. + */ +LINPHONE_PUBLIC LinphoneParticipant *linphone_chat_room_find_participant (const LinphoneChatRoom *cr, const LinphoneAddress *addr); + +/** + * Get the capabilities of a chat room. + * @param[in] cr A #LinphoneChatRoom object + * @return The capabilities of the chat room + */ +LINPHONE_PUBLIC LinphoneChatRoomCapabilitiesMask linphone_chat_room_get_capabilities (const LinphoneChatRoom *cr); + +/** + * Check if a chat room has given capabilities. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] mask A Capabilities mask + * @return True if the mask matches, false otherwise + */ +LINPHONE_PUBLIC bool_t linphone_chat_room_has_capability(const LinphoneChatRoom *cr, int mask); + +/** + * Get the conference address of the chat room. + * @param[in] cr A #LinphoneChatRoom object + * @return The conference address of the chat room or NULL if this type of chat room is not conference based + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_chat_room_get_conference_address (const LinphoneChatRoom *cr); + +/** + * Get the participant representing myself in the chat room. + * @param[in] cr A #LinphoneChatRoom object + * @return The participant representing myself in the conference. + */ +LINPHONE_PUBLIC LinphoneParticipant *linphone_chat_room_get_me (const LinphoneChatRoom *cr); + +/** + * Get the number of participants in the chat room (that is without ourselves). + * @param[in] cr A #LinphoneChatRoom object + * @return The number of participants in the chat room + */ +LINPHONE_PUBLIC int linphone_chat_room_get_nb_participants (const LinphoneChatRoom *cr); + +/** + * Get the list of participants of a chat room. + * @param[in] cr A #LinphoneChatRoom object + * @return \bctbx_list{LinphoneParticipant} + */ +LINPHONE_PUBLIC bctbx_list_t * linphone_chat_room_get_participants (const LinphoneChatRoom *cr); + +/** + * Get the subject of a chat room. + * @param[in] cr A #LinphoneChatRoom object + * @return The subject of the chat room + */ +LINPHONE_PUBLIC const char * linphone_chat_room_get_subject (const LinphoneChatRoom *cr); + +/** + * Leave a chat room. + * @param[in] cr A #LinphoneChatRoom object + */ +LINPHONE_PUBLIC void linphone_chat_room_leave (LinphoneChatRoom *cr); + +/** + * Remove a participant of a chat room. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] participant The participant to remove from the chat room + */ +LINPHONE_PUBLIC void linphone_chat_room_remove_participant (LinphoneChatRoom *cr, LinphoneParticipant *participant); + +/** + * Remove several participants of a chat room at once. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] participants \bctbx_list{LinphoneParticipant} + */ +LINPHONE_PUBLIC void linphone_chat_room_remove_participants (LinphoneChatRoom *cr, const bctbx_list_t *participants); + +/** + * Change the admin status of a participant of a chat room (you need to be an admin yourself to do this). + * @param[in] cr A #LinphoneChatRoom object + * @param[in] participant The Participant for which to change the admin status + * @param[in] isAdmin A boolean value telling whether the participant should now be an admin or not + */ +LINPHONE_PUBLIC void linphone_chat_room_set_participant_admin_status (LinphoneChatRoom *cr, LinphoneParticipant *participant, bool_t isAdmin); + +/** + * Set the subject of a chat room. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] subject The new subject to set for the chat room + */ +LINPHONE_PUBLIC void linphone_chat_room_set_subject (LinphoneChatRoom *cr, const char *subject); + +/** + * Gets the list of participants that are currently composing + * @param[in] cr A #LinphoneChatRoom object + * @return \bctbx_list{LinphoneAddress} list of addresses that are in the is_composing state + */ +LINPHONE_PUBLIC const bctbx_list_t * linphone_chat_room_get_composing_addresses(LinphoneChatRoom *cr); + +/** + * Set the conference address of a group chat room. This function needs to be called from the + * #LinphoneChatRoomCbsConferenceAddressGenerationCb callback and only there. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] confAddr The conference address to be used by the group chat room + */ +LINPHONE_PUBLIC void linphone_chat_room_set_conference_address (LinphoneChatRoom *cr, const LinphoneAddress *confAddr); + +/** + * Set the participant device. This function needs to be called from the + * #LinphoneChatRoomCbsParticipantDeviceFetchRequestedCb callback and only there. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] partAddr The participant address + * @param[in] partDevices \bctbx_list{LinphoneAddress} list of the participant devices to be used by the group chat room + */ +LINPHONE_PUBLIC void linphone_chat_room_set_participant_devices (LinphoneChatRoom *cr, const LinphoneAddress *partAddr, const bctbx_list_t *partDevices); + +/** + * Add a participant device. + * This is to used if a new device registers itself after the chat room creation. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] participantAddress The address of the participant for which a new device is to be added + * @param[in] deviceAddress The address of the new device to be added + */ +LINPHONE_PUBLIC void linphone_chat_room_add_participant_device (LinphoneChatRoom *cr, const LinphoneAddress *participantAddress, const LinphoneAddress *deviceAddress); + +/** + * Set the participant device. This function needs to be called from the + * #LinphoneChatRoomCbsParticipantsCapabilitiesCheckedCb callback and only there. + * @param[in] cr A #LinphoneChatRoom object + * @param[in] deviceAddr The device address + * @param[in] participantsCompatible \bctbx_list{LinphoneAddress} + */ +LINPHONE_PUBLIC void linphone_chat_room_add_compatible_participants (LinphoneChatRoom *cr, const LinphoneAddress *deviceAddr, const bctbx_list_t *participantsCompatible); + +/** + * Returns back pointer to #LinphoneCore object. + * @deprecated use linphone_chat_room_get_core() + * @donotwrap +**/ +LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneCore* linphone_chat_room_get_lc(const LinphoneChatRoom *cr); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CHAT_ROOM_H_ diff --git a/include/linphone/api/c-content.h b/include/linphone/api/c-content.h new file mode 100644 index 000000000..48e3a5ccb --- /dev/null +++ b/include/linphone/api/c-content.h @@ -0,0 +1,247 @@ +/* + * c-content.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_CONTENT_H_ +#define _L_C_CONTENT_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup misc + * @{ + */ + +/** + * Acquire a reference to the content. + * @param[in] content #LinphoneContent object. + * @return The same #LinphoneContent object. +**/ +LINPHONE_PUBLIC LinphoneContent *linphone_content_ref (LinphoneContent *content); + +/** + * Release reference to the content. + * @param[in] content #LinphoneContent object. +**/ +LINPHONE_PUBLIC void linphone_content_unref (LinphoneContent *content); + +/** + * Retrieve the user pointer associated with the content. + * @param[in] content #LinphoneContent object. + * @return The user pointer associated with the content. +**/ +LINPHONE_PUBLIC void *linphone_content_get_user_data (const LinphoneContent *content); + +/** + * Assign a user pointer to the content. + * @param[in] content #LinphoneContent object. + * @param[in] ud The user pointer to associate with the content. +**/ +LINPHONE_PUBLIC void linphone_content_set_user_data (LinphoneContent *content, void *user_data); + +/** + * Get the mime type of the content data. + * @param[in] content #LinphoneContent object. + * @return The mime type of the content data, for example "application". + */ +LINPHONE_PUBLIC const char *linphone_content_get_type (const LinphoneContent *content); + +/** + * Set the mime type of the content data. + * @param[in] content #LinphoneContent object. + * @param[in] type The mime type of the content data, for example "application". + */ +LINPHONE_PUBLIC void linphone_content_set_type (LinphoneContent *content, const char *type); + +/** + * Get the mime subtype of the content data. + * @param[in] content #LinphoneContent object. + * @return The mime subtype of the content data, for example "html". + */ +LINPHONE_PUBLIC const char *linphone_content_get_subtype (const LinphoneContent *content); + +/** + * Set the mime subtype of the content data. + * @param[in] content #LinphoneContent object. + * @param[in] subtype The mime subtype of the content data, for example "html". + */ +LINPHONE_PUBLIC void linphone_content_set_subtype (LinphoneContent *content, const char *subtype); + +/** + * Adds a parameter to the ContentType header. + * @param[in] content LinphoneContent object. + * @param[in] name the name of the parameter to add. + * @param[in] value the value of the parameter to add. + */ +LINPHONE_PUBLIC void linphone_content_add_content_type_parameter ( + LinphoneContent *content, + const char *name, + const char *value +); + +/** + * Get the content data buffer, usually a string. + * @param[in] content #LinphoneContent object. + * @return The content data buffer. + */ +LINPHONE_PUBLIC const uint8_t *linphone_content_get_buffer (const LinphoneContent *content); + +/** + * Set the content data buffer, usually a string. + * @param[in] content #LinphoneContent object. + * @param[in] buffer The content data buffer. + * @param[in] size The size of the content data buffer. + */ +LINPHONE_PUBLIC void linphone_content_set_buffer (LinphoneContent *content, const uint8_t *buffer, size_t size); + +/** + * Get the string content data buffer. + * @param[in] content #LinphoneContent object + * @return The string content data buffer. + */ +LINPHONE_PUBLIC const char *linphone_content_get_string_buffer (const LinphoneContent *content); + +/** + * Set the string content data buffer. + * @param[in] content #LinphoneContent object. + * @param[in] buffer The string content data buffer. + */ +LINPHONE_PUBLIC void linphone_content_set_string_buffer (LinphoneContent *content, const char *buffer); + +/** + * Get the content data buffer size, excluding null character despite null character is always set for convenience. + * @param[in] content #LinphoneContent object. + * @return The content data buffer size. + */ +LINPHONE_PUBLIC size_t linphone_content_get_size (const LinphoneContent *content); + +/** + * Get the file size if content is either a FileContent or a FileTransferContent. + * @param[in] content #LinphoneContent object. + * @return The represented file size. + */ +LINPHONE_PUBLIC size_t linphone_content_get_file_size(const LinphoneContent *content); + +/** + * Set the content data size, excluding null character despite null character is always set for convenience. + * @param[in] content #LinphoneContent object + * @param[in] size The content data buffer size. + */ +LINPHONE_PUBLIC void linphone_content_set_size (LinphoneContent *content, size_t size); + +/** + * Get the encoding of the data buffer, for example "gzip". + * @param[in] content #LinphoneContent object. + * @return The encoding of the data buffer. + */ +LINPHONE_PUBLIC const char *linphone_content_get_encoding (const LinphoneContent *content); + +/** + * Set the encoding of the data buffer, for example "gzip". + * @param[in] content #LinphoneContent object. + * @param[in] encoding The encoding of the data buffer. + */ +LINPHONE_PUBLIC void linphone_content_set_encoding (LinphoneContent *content, const char *encoding); + +/** + * Get the name associated with a RCS file transfer message. It is used to store the original filename of the file to be downloaded from server. + * @param[in] content #LinphoneContent object. + * @return The name of the content. + */ +LINPHONE_PUBLIC const char *linphone_content_get_name (const LinphoneContent *content); + +/** + * Set the name associated with a RCS file transfer message. It is used to store the original filename of the file to be downloaded from server. + * @param[in] content #LinphoneContent object. + * @param[in] name The name of the content. + */ +LINPHONE_PUBLIC void linphone_content_set_name (LinphoneContent *content, const char *name); + +/** + * Tell whether a content is a multipart content. + * @param[in] content #LinphoneContent object. + * @return A boolean value telling whether the content is multipart or not. + */ +LINPHONE_PUBLIC bool_t linphone_content_is_multipart (const LinphoneContent *content); + +/** + * Get a part from a multipart content according to its index. + * @param[in] content #LinphoneContent object. + * @param[in] idx The index of the part to get. + * @return A #LinphoneContent object holding the part if found, NULL otherwise. + */ +LINPHONE_PUBLIC LinphoneContent *linphone_content_get_part (const LinphoneContent *content, int idx); + +/** + * Find a part from a multipart content looking for a part header with a specified value. + * @param[in] content #LinphoneContent object. + * @param[in] header_name The name of the header to look for. + * @param[in] header_value The value of the header to look for. + * @return A #LinphoneContent object object the part if found, NULL otherwise. + */ +LINPHONE_PUBLIC LinphoneContent *linphone_content_find_part_by_header ( + const LinphoneContent *content, + const char *header_name, + const char *header_value +); + +/** + * Get a custom header value of a content. + * @param[in] content #LinphoneContent object. + * @param[in] header_name The name of the header to get the value from. + * @return The value of the header if found, NULL otherwise. + */ +LINPHONE_PUBLIC const char *linphone_content_get_custom_header (const LinphoneContent *content, const char *header_name); + +/** + * Get the key associated with a RCS file transfer message if encrypted + * @param[in] content #LinphoneContent object. + * @return The key to encrypt/decrypt the file associated to this content. + */ +LINPHONE_PUBLIC const char *linphone_content_get_key (const LinphoneContent *content); + +/** + * Get the size of key associated with a RCS file transfer message if encrypted + * @param[in] content #LinphoneContent object. + * @return The key size in bytes + */ +LINPHONE_PUBLIC size_t linphone_content_get_key_size (const LinphoneContent *content); + +/** + * Set the key associated with a RCS file transfer message if encrypted + * @param[in] content #LinphoneContent object. + * @param[in] key The key to be used to encrypt/decrypt file associated to this content. + * @param[in] key_length The lengh of the key. + */ +LINPHONE_PUBLIC void linphone_content_set_key (LinphoneContent *content, const char *key, const size_t key_length); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_CONTENT_H_ diff --git a/include/linphone/api/c-dial-plan.h b/include/linphone/api/c-dial-plan.h new file mode 100644 index 000000000..5f1aae2e0 --- /dev/null +++ b/include/linphone/api/c-dial-plan.h @@ -0,0 +1,116 @@ +/* + * c-dial-plan.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_DIAL_PLAN_H_ +#define _L_C_DIAL_PLAN_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup misc + * @{ + */ + + /** + * Returns the country name of the dialplan + * @return the country name + */ + LINPHONE_PUBLIC const char * linphone_dial_plan_get_country(const LinphoneDialPlan *dp); + + /** + * Returns the iso country code of the dialplan + * @return the iso country code + */ + LINPHONE_PUBLIC const char * linphone_dial_plan_get_iso_country_code(const LinphoneDialPlan *dp); + + /** + * Returns the country calling code of the dialplan + * @return the country calling code + */ + LINPHONE_PUBLIC const char * linphone_dial_plan_get_country_calling_code(const LinphoneDialPlan *dp); + + /** + * Returns the national number length of the dialplan + * @return the national number length + */ + LINPHONE_PUBLIC int linphone_dial_plan_get_national_number_length(const LinphoneDialPlan *dp); + + /** + * Returns the international call prefix of the dialplan + * @return the international call prefix + */ + LINPHONE_PUBLIC const char * linphone_dial_plan_get_international_call_prefix(const LinphoneDialPlan *dp); + + /** + *Function to get call country code from ISO 3166-1 alpha-2 code, ex: FR returns 33 + *@param iso country code alpha2 + *@return call country code or -1 if not found + */ +LINPHONE_PUBLIC int linphone_dial_plan_lookup_ccc_from_iso(const char* iso); + +/** + *Function to get call country code from an e164 number, ex: +33952650121 will return 33 + *@param e164 phone number + *@return call country code or -1 if not found + */ +LINPHONE_PUBLIC int linphone_dial_plan_lookup_ccc_from_e164(const char* e164); + +/** + * Return NULL-terminated array of all known dial plans + * @deprecated use linphone_dial_plan_get_all_list instead, this method will always return NULL + * @donotwrap +**/ +LINPHONE_PUBLIC const LinphoneDialPlan* linphone_dial_plan_get_all(void); + +/** + * @return \bctbx_list{LinphoneDialPlan} of all known dial plans +**/ +LINPHONE_PUBLIC const bctbx_list_t * linphone_dial_plan_get_all_list(void); + +/** + * Find best match for given CCC + * @return Return matching dial plan, or a generic one if none found +**/ +LINPHONE_PUBLIC const LinphoneDialPlan* linphone_dial_plan_by_ccc(const char *ccc); +/** + * Find best match for given CCC + * @return Return matching dial plan, or a generic one if none found + **/ +LINPHONE_PUBLIC const LinphoneDialPlan* linphone_dial_plan_by_ccc_as_int(int ccc); + +/** + * Return if given plan is generic +**/ +LINPHONE_PUBLIC bool_t linphone_dial_plan_is_generic(const LinphoneDialPlan *ccc); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_DIAL_PLAN_H_ diff --git a/include/linphone/api/c-event-log.h b/include/linphone/api/c-event-log.h new file mode 100644 index 000000000..f35c7a6e1 --- /dev/null +++ b/include/linphone/api/c-event-log.h @@ -0,0 +1,162 @@ +/* + * c-event-log.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_EVENT_LOG_H_ +#define _L_C_EVENT_LOG_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup events + * @{ + */ + +// ----------------------------------------------------------------------------- +// EventLog. +// ----------------------------------------------------------------------------- + +/** + * Increment reference count of #LinphoneEventLog object. + **/ +LINPHONE_PUBLIC LinphoneEventLog *linphone_event_log_ref (LinphoneEventLog *event_log); + +/** + * Decrement reference count of #LinphoneEventLog object. When dropped to zero, memory is freed. + **/ +LINPHONE_PUBLIC void linphone_event_log_unref (LinphoneEventLog *event_log); + +/** + * Returns the type of a event log. + * @param[in] event_log A #LinphoneEventLog object + * @return The event type + */ +LINPHONE_PUBLIC LinphoneEventLogType linphone_event_log_get_type (const LinphoneEventLog *event_log); + +/** + * Returns the creation time of a event log. + * @param[in] event_log A #LinphoneEventLog object + * @return The event creation time + */ +LINPHONE_PUBLIC time_t linphone_event_log_get_creation_time (const LinphoneEventLog *event_log); + +/** + * Delete event log from database. + * @param[in] event_log A #LinphoneEventLog object + */ +LINPHONE_PUBLIC void linphone_event_log_delete_from_database (LinphoneEventLog *event_log); + +// ----------------------------------------------------------------------------- +// ConferenceEvent. +// ----------------------------------------------------------------------------- + +/** + * Returns the peer address of a conference event. + * @param[in] event_log A #LinphoneEventLog object. + * @return The peer address. + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_event_log_get_peer_address (const LinphoneEventLog *event_log); + +/** + * Returns the local address of a conference event. + * @param[in] event_log A #LinphoneEventLog object. + * @return The local address. + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_event_log_get_local_address (const LinphoneEventLog *event_log); + +// ----------------------------------------------------------------------------- +// ConferenceNotifiedEvent. +// ----------------------------------------------------------------------------- + +/** + * Returns the notify id of a conference notified event. + * @param[in] event_log A #LinphoneEventLog object. + * @return The conference notify id. + */ +LINPHONE_PUBLIC unsigned int linphone_event_log_get_notify_id (const LinphoneEventLog *event_log); + +// ----------------------------------------------------------------------------- +// ConferenceCallEvent. +// ----------------------------------------------------------------------------- + +/** + * Returns the call of a conference call event. + * @param[in] event_log A #LinphoneEventLog object. + * @return The conference call. + */ +LINPHONE_PUBLIC LinphoneCall *linphone_event_log_get_call (const LinphoneEventLog *event_log); + +// ----------------------------------------------------------------------------- +// ConferenceChatMessageEvent. +// ----------------------------------------------------------------------------- + +/** + * Returns the chat message of a conference chat message event. + * @param[in] event_log A #LinphoneEventLog object. + * @return The conference chat message. + */ +LINPHONE_PUBLIC LinphoneChatMessage *linphone_event_log_get_chat_message (const LinphoneEventLog *event_log); + +// ----------------------------------------------------------------------------- +// ConferenceParticipantEvent. +// ----------------------------------------------------------------------------- + +/** + * Returns the participant address of a conference participant event. + * @param[in] event_log A ConferenceParticipantEvent object. + * @return The conference participant address. + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_event_log_get_participant_address (const LinphoneEventLog *event_log); + +// ----------------------------------------------------------------------------- +// ConferenceParticipantDeviceEvent. +// ----------------------------------------------------------------------------- + +/** + * Returns the device address of a conference participant device event. + * @param[in] event_log A #LinphoneEventLog object. + * @return The conference device address. + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_event_log_get_device_address (const LinphoneEventLog *event_log); + +// ----------------------------------------------------------------------------- +// ConferenceSubjectEvent. +// ----------------------------------------------------------------------------- + +/** + * Returns the subject of a conference subject event. + * @param[in] event_log A #LinphoneEventLog object. + * @return The conference subject. + */ +LINPHONE_PUBLIC const char *linphone_event_log_get_subject (const LinphoneEventLog *event_log); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_EVENT_LOG_H_ diff --git a/include/linphone/api/c-magic-search.h b/include/linphone/api/c-magic-search.h new file mode 100644 index 000000000..92b667346 --- /dev/null +++ b/include/linphone/api/c-magic-search.h @@ -0,0 +1,149 @@ +/* + * c-magic-search.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_MAGIC_SEARCH_H_ +#define _L_C_MAGIC_SEARCH_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup misc + * @{ + */ + +/** + * Constructs a LinphoneMagicSearch object + **/ +LINPHONE_PUBLIC LinphoneMagicSearch *linphone_magic_search_new (LinphoneCore *lc); + +/** + * Increment reference count of LinphoneMagicSearch object. + **/ +LINPHONE_PUBLIC LinphoneMagicSearch *linphone_magic_search_ref (LinphoneMagicSearch *magic_search); + +/** + * Decrement reference count of LinphoneMagicSearch object. When dropped to zero, memory is freed. + **/ +LINPHONE_PUBLIC void linphone_magic_search_unref (LinphoneMagicSearch *magic_search); + +/** + * Set the minimum value used to calculate the weight in search + * @param[in] weight minimum weight + **/ +LINPHONE_PUBLIC void linphone_magic_search_set_min_weight (LinphoneMagicSearch *magic_search, unsigned int weight); + +/** + * @return the minimum value used to calculate the weight in search + **/ +LINPHONE_PUBLIC unsigned int linphone_magic_search_get_min_weight (const LinphoneMagicSearch *magic_search); + +/** + * Set the maximum value used to calculate the weight in search + * @param[in] weight maximum weight + **/ +LINPHONE_PUBLIC void linphone_magic_search_set_max_weight (LinphoneMagicSearch *magic_search, unsigned int weight); + +/** + * @return the maximum value used to calculate the weight in search + **/ +LINPHONE_PUBLIC unsigned int linphone_magic_search_get_max_weight (const LinphoneMagicSearch *magic_search); + +/** + * @return the delimiter used to find matched filter word + **/ +LINPHONE_PUBLIC const char *linphone_magic_search_get_delimiter (const LinphoneMagicSearch *magic_search); + +/** + * Set the delimiter used to find matched filter word + * @param[in] delimiter delimiter (example "-_.,") + **/ +LINPHONE_PUBLIC void linphone_magic_search_set_delimiter (LinphoneMagicSearch *magic_search, const char *delimiter); + +/** + * @return if the delimiter search is used + **/ +LINPHONE_PUBLIC bool_t linphone_magic_search_get_use_delimiter (LinphoneMagicSearch *magic_search); + +/** + * Enable or disable the delimiter in search + * @param[in] enable + **/ +LINPHONE_PUBLIC void linphone_magic_search_set_use_delimiter (LinphoneMagicSearch *magic_search, bool_t enable); + +/** + * @return the number of the maximum SearchResult which will be return + **/ +LINPHONE_PUBLIC unsigned int linphone_magic_search_get_search_limit (const LinphoneMagicSearch *magic_search); + +/** + * Set the number of the maximum SearchResult which will be return + * @param[in] limit + **/ +LINPHONE_PUBLIC void linphone_magic_search_set_search_limit (LinphoneMagicSearch *magic_search, unsigned int limit); + +/** + * @return if the search is limited + **/ +LINPHONE_PUBLIC bool_t linphone_magic_search_get_limited_search (const LinphoneMagicSearch *magic_search); + +/** + * Enable or disable the limited search + * @param[in] limited + **/ +LINPHONE_PUBLIC void linphone_magic_search_set_limited_search (LinphoneMagicSearch *magic_search, bool_t limited); + +/** + * Reset the cache to begin a new search + **/ +LINPHONE_PUBLIC void linphone_magic_search_reset_search_cache (LinphoneMagicSearch *magic_search); + +/** + * Create a sorted list of SearchResult from SipUri, Contact name, + * Contact displayname, Contact phone number, which match with a filter word + * The last item list will be an address formed with "filter" if a proxy config exist + * During the first search, a cache is created and used for the next search + * Use linphone_magic_search_reset_search_cache() to begin a new search + * @param[in] filter word we search + * @param[in] domain domain which we want to search only + * - "" for searching in all contact + * - "*" for searching in contact with sip SipUri + * - "yourdomain" for searching in contact from "yourdomain" domain + * @return sorted list of \bctbx_list{LinphoneSearchResult} + **/ +LINPHONE_PUBLIC bctbx_list_t* linphone_magic_search_get_contact_list_from_filter ( + LinphoneMagicSearch *magic_search, + const char *filter, + const char *domain +); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif // _L_C_MAGIC_SEARCH_H_ diff --git a/include/linphone/api/c-participant-imdn-state.h b/include/linphone/api/c-participant-imdn-state.h new file mode 100644 index 000000000..041dd2efc --- /dev/null +++ b/include/linphone/api/c-participant-imdn-state.h @@ -0,0 +1,91 @@ +/* + * c-participant-imdn-state.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_PARTICIPANT_IMDN_STATE_H_ +#define _L_C_PARTICIPANT_IMDN_STATE_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup misc + * @{ + */ + +/** + * Increment reference count of LinphoneParticipantImdnState object. + **/ +LINPHONE_PUBLIC LinphoneParticipantImdnState *linphone_participant_imdn_state_ref (LinphoneParticipantImdnState *state); + +/** + * Decrement reference count of LinphoneParticipantImdnState object. + **/ +LINPHONE_PUBLIC void linphone_participant_imdn_state_unref (LinphoneParticipantImdnState *state); + +/** + * Retrieve the user pointer associated with a LinphoneParticipantImdnState. + * @param[in] state A LinphoneParticipantImdnState object + * @return The user pointer associated with the LinphoneParticipantImdnState. +**/ +LINPHONE_PUBLIC void *linphone_participant_imdn_state_get_user_data(const LinphoneParticipantImdnState *state); + +/** + * Assign a user pointer to a LinphoneParticipantImdnState. + * @param[in] state A LinphoneParticipantImdnState object + * @param[in] ud The user pointer to associate with the LinphoneParticipantImdnState +**/ +LINPHONE_PUBLIC void linphone_participant_imdn_state_set_user_data(LinphoneParticipantImdnState *state, void *ud); + +/** + * Get the participant concerned by a LinphoneParticipantImdnState. + * @param[in] state A LinphoneParticipantImdnState object + * @return The participant concerned by the LinphoneParticipantImdnState + */ +LINPHONE_PUBLIC const LinphoneParticipant *linphone_participant_imdn_state_get_participant ( + const LinphoneParticipantImdnState *state +); + +/** + * Get the chat message state the participant is in. + * @param state A LinphoneParticipantImdnState object + * @return The chat message state the participant is in + */ +LINPHONE_PUBLIC LinphoneChatMessageState linphone_participant_imdn_state_get_state (const LinphoneParticipantImdnState *state); + +/** + * Get the timestamp at which a participant has reached the state described by a LinphoneParticipantImdnState. + * @param[in] state A LinphoneParticipantImdnState object + * @return The timestamp at which the participant has reached the state described in the LinphoneParticipantImdnState + */ +LINPHONE_PUBLIC time_t linphone_participant_imdn_state_get_state_change_time (const LinphoneParticipantImdnState *state); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_PARTICIPANT_IMDN_STATE_H_ diff --git a/include/linphone/api/c-participant.h b/include/linphone/api/c-participant.h new file mode 100644 index 000000000..93e20d2c8 --- /dev/null +++ b/include/linphone/api/c-participant.h @@ -0,0 +1,82 @@ +/* + * c-participant.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_PARTICIPANT_H_ +#define _L_C_PARTICIPANT_H_ + +#include "linphone/api/c-types.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +/** + * @addtogroup misc + * @{ + */ + +/** + * Increment reference count of #LinphoneParticipant object. + **/ +LINPHONE_PUBLIC LinphoneParticipant *linphone_participant_ref (LinphoneParticipant *participant); + +/** + * Decrement reference count of #LinphoneParticipant object. + **/ +LINPHONE_PUBLIC void linphone_participant_unref (LinphoneParticipant *participant); + +/** + * Retrieve the user pointer associated with the conference participant. + * @param[in] participant A #LinphoneParticipant object + * @return The user pointer associated with the participant. +**/ +LINPHONE_PUBLIC void * linphone_participant_get_user_data(const LinphoneParticipant *participant); + +/** + * Assign a user pointer to the conference participant. + * @param[in] participant A #LinphoneParticipant object + * @param[in] ud The user pointer to associate with the participant +**/ +LINPHONE_PUBLIC void linphone_participant_set_user_data(LinphoneParticipant *participant, void *ud); + +/** + * Get the address of a conference participant. + * @param[in] participant A #LinphoneParticipant object + * @return The address of the participant + */ +LINPHONE_PUBLIC const LinphoneAddress * linphone_participant_get_address (const LinphoneParticipant *participant); + +/** + * Tells whether a conference participant is an administrator of the conference. + * @param[in] participant A #LinphoneParticipant object + * @return A boolean value telling whether the participant is an administrator + */ +LINPHONE_PUBLIC bool_t linphone_participant_is_admin (const LinphoneParticipant *participant); + +/** + * @} + */ + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_PARTICIPANT_H_ diff --git a/include/linphone/api/c-search-result.h b/include/linphone/api/c-search-result.h new file mode 100644 index 000000000..8730d90ec --- /dev/null +++ b/include/linphone/api/c-search-result.h @@ -0,0 +1,72 @@ +/* + * c-search-result.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_SEARCH_RESULT_H_ +#define _L_C_SEARCH_RESULT_H_ + +#include "linphone/api/c-types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup misc + * @{ + */ + +/** + * Increment reference count of LinphoneSearchResult object. + **/ +LINPHONE_PUBLIC LinphoneSearchResult *linphone_search_result_ref(LinphoneSearchResult *searchResult); + +/** + * Decrement reference count of LinphoneSearchResult object. When dropped to zero, memory is freed. + **/ +LINPHONE_PUBLIC void linphone_search_result_unref(LinphoneSearchResult *searchResult); + +/** + * @return LinphoneFriend associed + **/ +LINPHONE_PUBLIC const LinphoneFriend* linphone_search_result_get_friend(const LinphoneSearchResult *searchResult); + +/** + * @return LinphoneAddress associed + **/ +LINPHONE_PUBLIC const LinphoneAddress* linphone_search_result_get_address(const LinphoneSearchResult *searchResult); + +/** + * @return Phone Number associed + **/ +LINPHONE_PUBLIC const char* linphone_search_result_get_phone_number(const LinphoneSearchResult *searchResult); + +/** + * @return the result weight + **/ +LINPHONE_PUBLIC unsigned int linphone_search_result_get_weight(const LinphoneSearchResult *searchResult); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif // _L_C_SEARCH_RESULT_H_ diff --git a/include/linphone/api/c-types.h b/include/linphone/api/c-types.h new file mode 100644 index 000000000..a74df54c0 --- /dev/null +++ b/include/linphone/api/c-types.h @@ -0,0 +1,261 @@ +/* + * c-types.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_TYPES_H_ +#define _L_C_TYPES_H_ + +// TODO: Remove me in the future. +#include "linphone/types.h" + +#include "linphone/enums/call-enums.h" +#include "linphone/enums/chat-message-enums.h" +#include "linphone/enums/chat-room-enums.h" +#include "linphone/enums/event-log-enums.h" +#include "linphone/utils/enum-generator.h" + +// ============================================================================= + +#ifdef __cplusplus + extern "C" { +#endif // ifdef __cplusplus + +// ============================================================================= +// Misc. +// ============================================================================= + +#ifdef TRUE + #undef TRUE +#endif + +#ifdef FALSE + #undef FALSE +#endif + +#define TRUE 1 +#define FALSE 0 + +// ============================================================================= +// C Structures. +// ============================================================================= + +// ----------------------------------------------------------------------------- +// Address. +// ----------------------------------------------------------------------------- + +/** + * Object that represents a SIP address. + * + * The #LinphoneAddress is an opaque object to represents SIP addresses, ie + * the content of SIP's 'from' and 'to' headers. + * A SIP address is made of display name, username, domain name, port, and various + * uri headers (such as tags). It looks like 'Alice '. + * The #LinphoneAddress has methods to extract and manipulate all parts of the address. + * When some part of the address (for example the username) is empty, the accessor methods + * return NULL. + * @ingroup linphone_address + */ +typedef struct _LinphoneAddress LinphoneAddress; + +// ----------------------------------------------------------------------------- +// Call. +// ----------------------------------------------------------------------------- + +/** + * The #LinphoneCall object represents a call issued or received by the #LinphoneCore + * @ingroup call_control + */ +typedef struct _LinphoneCall LinphoneCall; + +/** Callback prototype */ +typedef void (*LinphoneCallCbFunc) (LinphoneCall *call, void *ud); + +/** + * That class holds all the callbacks which are called by #LinphoneCall objects. + * + * Use linphone_factory_create_call_cbs() to create an instance. Then, call the + * callback setters on the events you need to monitor and pass the object to + * a #LinphoneCall instance through linphone_call_add_callbacks(). + * @ingroup call_control + */ +typedef struct _LinphoneCallCbs LinphoneCallCbs; + +// ----------------------------------------------------------------------------- +// ChatRoom. +// ----------------------------------------------------------------------------- + +/** + * An chat message is the object that is sent and received through LinphoneChatRooms. + * @ingroup chatroom + */ +typedef struct _LinphoneChatMessage LinphoneChatMessage; + +/** + * An object to handle the callbacks for the handling a #LinphoneChatMessage objects. + * @ingroup chatroom + */ +typedef struct _LinphoneChatMessageCbs LinphoneChatMessageCbs; + +/** + * A chat room is the place where text messages are exchanged. + * Can be created by linphone_core_create_chat_room(). + * @ingroup chatroom + */ +typedef struct _LinphoneChatRoom LinphoneChatRoom; + +/** + * A mask of #LinphoneChatRoomCapabilities + * @ingroup chatroom + */ +typedef int LinphoneChatRoomCapabilitiesMask; + +/** + * An object to handle the callbacks for the handling a #LinphoneChatRoom objects. + * @ingroup chatroom + */ +typedef struct _LinphoneChatRoomCbs LinphoneChatRoomCbs; + +// ----------------------------------------------------------------------------- +// EventLog. +// ----------------------------------------------------------------------------- + +/** + * Base object of events. + * @ingroup events + */ +typedef struct _LinphoneEventLog LinphoneEventLog; + +// ----------------------------------------------------------------------------- +// Misc. +// ----------------------------------------------------------------------------- + +/** + * The LinphoneContent object holds data that can be embedded in a signaling message. + * @ingroup misc + */ +typedef struct _LinphoneContent LinphoneContent; + +/** + * Represents a dial plan + * @ingroup misc + */ +typedef struct _LinphoneDialPlan LinphoneDialPlan; + +/** + * A #LinphoneMagicSearch is used to do specifics searchs + * @ingroup misc + */ +typedef struct _LinphoneMagicSearch LinphoneMagicSearch; + +/** + * @ingroup misc + */ +typedef struct _LinphoneParticipant LinphoneParticipant; + +/** + * The LinphoneParticipantImdnState object represents the state of chat message for a participant of a conference chat room. + * @ingroup misc + */ +typedef struct _LinphoneParticipantImdnState LinphoneParticipantImdnState; + +/** + * The LinphoneSearchResult object represents a result of a search + * @ingroup misc + */ +typedef struct _LinphoneSearchResult LinphoneSearchResult; + +// ============================================================================= +// C Enums. +// ============================================================================= + +// ----------------------------------------------------------------------------- +// How-to: Declare one enum +// +// 1. Declare a macro like this example in include/linphone/enums/chat-message-enums.h: +// +// #define L_ENUM_VALUES_CHAT_MESSAGE_DIRECTION(F) \ // +// F(Incoming /**< Incoming message */) \ // +// F(Outgoing /**< Outgoing message */) +// +// 2. And in this file, call L_DECLARE_C_ENUM with the enum name and values as params: +// +// L_DECLARE_C_ENUM(ChatMessageDirection, L_ENUM_VALUES_CHAT_MESSAGE_DIRECTION); +// +// 3. Do not forget to replace each single quote (with ') or other special char like +// to an escaped sequence. Otherwise you get this error at compilation: +// +// [ 99%] Building CXX object wrappers/cpp/CMakeFiles/linphone++.dir/src/linphone++.cc.o +// c++: error: WORK/desktop/Build/linphone/wrappers/cpp/src/linphone++.cc: No such file or directory +// c++: fatal error: no input files +// compilation terminated. +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Call. +// ----------------------------------------------------------------------------- + +/** + * #LinphoneCallState enum represents the different state a call can reach into. + * The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback. + * @ingroup call_control + */ +L_DECLARE_C_ENUM(CallState, L_ENUM_VALUES_CALL_SESSION_STATE); + +// ----------------------------------------------------------------------------- +// ChatRoom. +// ----------------------------------------------------------------------------- + +/** + * #LinphoneChatMessageDirection is used to indicate if a message is outgoing or incoming. + * @ingroup chatroom + */ +L_DECLARE_C_ENUM(ChatMessageDirection, L_ENUM_VALUES_CHAT_MESSAGE_DIRECTION); + +/** + * #LinphoneChatMessageState is used to notify if messages have been succesfully delivered or not. + * @ingroup chatroom + */ +L_DECLARE_C_ENUM(ChatMessageState, L_ENUM_VALUES_CHAT_MESSAGE_STATE); + +/** + * #LinphoneChatRoomCapabilities is used to indicated the capabilities of a chat room. + * @ingroup chatroom + */ +L_DECLARE_C_ENUM_FIXED_VALUES(ChatRoomCapabilities, L_ENUM_VALUES_CHAT_ROOM_CAPABILITIES); + +/** + * #LinphoneChatRoomState is used to indicate the current state of a chat room. + * @ingroup chatroom + */ +L_DECLARE_C_ENUM(ChatRoomState, L_ENUM_VALUES_CHAT_ROOM_STATE); + +// ----------------------------------------------------------------------------- +// EventLog. +// ----------------------------------------------------------------------------- + +/** + * #LinphoneEventLogType is used to indicate the type of an event. Useful for cast. + * @ingroup events + */ +L_DECLARE_C_ENUM(EventLogType, L_ENUM_VALUES_EVENT_LOG_TYPE); + +#ifdef __cplusplus + } +#endif // ifdef __cplusplus + +#endif // ifndef _L_C_TYPES_H_ diff --git a/include/linphone/auth_info.h b/include/linphone/auth_info.h index cb338f73a..72ef24d93 100644 --- a/include/linphone/auth_info.h +++ b/include/linphone/auth_info.h @@ -29,7 +29,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /** - * Safely cast a belle_sip_object_t into LinphoneAuthInfo + * Safely cast a belle_sip_object_t into #LinphoneAuthInfo */ #define LINPHONE_AUTH_INFO(obj) BELLE_SIP_CAST(obj, LinphoneAuthInfo) @@ -48,15 +48,30 @@ extern "C" { * @param ha1 The ha1-encrypted password if password is not given in clear text. * @param realm The authentication domain (which can be larger than the sip domain. Unfortunately many SIP servers don't use this parameter. * @param domain The SIP domain for which this authentication information is valid, if it has to be restricted for a single SIP domain. - * @return A #LinphoneAuthInfo object. linphone_auth_info_destroy() must be used to destroy it when no longer needed. The LinphoneCore makes a copy of LinphoneAuthInfo + * @return A #LinphoneAuthInfo object. linphone_auth_info_destroy() must be used to destroy it when no longer needed. The #LinphoneCore makes a copy of #LinphoneAuthInfo * passed through linphone_core_add_auth_info(). **/ -LINPHONE_PUBLIC LinphoneAuthInfo *linphone_auth_info_new(const char *username, const char *userid, - const char *passwd, const char *ha1,const char *realm, const char *domain); +LINPHONE_PUBLIC LinphoneAuthInfo *linphone_auth_info_new( + const char *username, + const char *userid, + const char *passwd, + const char *ha1, + const char *rfealm, + const char *domain +); + +LINPHONE_PUBLIC LinphoneAuthInfo *linphone_auth_info_new_for_algorithm( + const char *username, + const char *userid, + const char *passwd, + const char *ha1, + const char *realm, + const char *domain, + const char *algorithm +); /** * Instantiates a new auth info with values from source. - * * @param[in] source The #LinphoneAuthInfo object to be cloned * @return The newly created #LinphoneAuthInfo object. */ @@ -76,9 +91,17 @@ LINPHONE_PUBLIC void linphone_auth_info_unref(LinphoneAuthInfo *info); * Sets the password. * @param[in] info The #LinphoneAuthInfo object * @param[in] passwd The password. + * @deprecated, use linphone_auth_info_set_password instead **/ LINPHONE_PUBLIC void linphone_auth_info_set_passwd(LinphoneAuthInfo *info, const char *passwd); +/** + * Sets the password. + * @param[in] info The #LinphoneAuthInfo object + * @param[in] passwd The password. +**/ +LINPHONE_PUBLIC void linphone_auth_info_set_password(LinphoneAuthInfo *info, const char *passwd); + /** * Sets the username. * @param[in] info The #LinphoneAuthInfo object @@ -155,9 +178,18 @@ LINPHONE_PUBLIC const char *linphone_auth_info_get_username(const LinphoneAuthIn * Gets the password. * @param[in] info The #LinphoneAuthInfo object * @return The password. + * @deprecated, use linphone_auth_info_get_password instead */ LINPHONE_PUBLIC const char *linphone_auth_info_get_passwd(const LinphoneAuthInfo *info); +/** + * Gets the password. + * @param[in] info The #LinphoneAuthInfo object + * @return The password. + */ +LINPHONE_PUBLIC const char *linphone_auth_info_get_password(const LinphoneAuthInfo *info); + + /** * Gets the userid. * @param[in] info The #LinphoneAuthInfo object diff --git a/include/linphone/buffer.h b/include/linphone/buffer.h index bb7450666..9377546c6 100644 --- a/include/linphone/buffer.h +++ b/include/linphone/buffer.h @@ -35,63 +35,63 @@ extern "C" { */ /** - * Create a new empty LinphoneBuffer object. - * @return A new LinphoneBuffer object. + * Create a new empty #LinphoneBuffer object. + * @return A new #LinphoneBuffer object. */ LINPHONE_PUBLIC LinphoneBuffer * linphone_buffer_new(void); /** - * Create a new LinphoneBuffer object from existing data. + * Create a new #LinphoneBuffer object from existing data. * @param[in] data The initial data to store in the LinphoneBuffer. * @param[in] size The size of the initial data to stroe in the LinphoneBuffer. - * @return A new LinphoneBuffer object. + * @return A new #LinphoneBuffer object. */ LINPHONE_PUBLIC LinphoneBuffer * linphone_buffer_new_from_data(const uint8_t *data, size_t size); /** - * Create a new LinphoneBuffer object from a string. + * Create a new #LinphoneBuffer object from a string. * @param[in] data The initial string content of the LinphoneBuffer. - * @return A new LinphoneBuffer object. + * @return A new #LinphoneBuffer object. */ LINPHONE_PUBLIC LinphoneBuffer * linphone_buffer_new_from_string(const char *data); /** * Acquire a reference to the buffer. - * @param[in] buffer LinphoneBuffer object. - * @return The same LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. + * @return The same #LinphoneBuffer object. **/ LINPHONE_PUBLIC LinphoneBuffer * linphone_buffer_ref(LinphoneBuffer *buffer); /** * Release reference to the buffer. - * @param[in] buffer LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. **/ LINPHONE_PUBLIC void linphone_buffer_unref(LinphoneBuffer *buffer); /** * Retrieve the user pointer associated with the buffer. - * @param[in] buffer LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. * @return The user pointer associated with the buffer. **/ LINPHONE_PUBLIC void *linphone_buffer_get_user_data(const LinphoneBuffer *buffer); /** * Assign a user pointer to the buffer. - * @param[in] buffer LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. * @param[in] ud The user pointer to associate with the buffer. **/ LINPHONE_PUBLIC void linphone_buffer_set_user_data(LinphoneBuffer *buffer, void *ud); /** * Get the content of the data buffer. - * @param[in] buffer LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. * @return The content of the data buffer. */ LINPHONE_PUBLIC const uint8_t * linphone_buffer_get_content(const LinphoneBuffer *buffer); /** * Set the content of the data buffer. - * @param[in] buffer LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. * @param[in] content The content of the data buffer. * @param[in] size The size of the content of the data buffer. */ @@ -99,36 +99,36 @@ LINPHONE_PUBLIC void linphone_buffer_set_content(LinphoneBuffer *buffer, const u /** * Get the string content of the data buffer. - * @param[in] buffer LinphoneBuffer object + * @param[in] buffer #LinphoneBuffer object * @return The string content of the data buffer. */ LINPHONE_PUBLIC const char * linphone_buffer_get_string_content(const LinphoneBuffer *buffer); /** * Set the string content of the data buffer. - * @param[in] buffer LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. * @param[in] content The string content of the data buffer. */ LINPHONE_PUBLIC void linphone_buffer_set_string_content(LinphoneBuffer *buffer, const char *content); /** * Get the size of the content of the data buffer. - * @param[in] buffer LinphoneBuffer object. + * @param[in] buffer #LinphoneBuffer object. * @return The size of the content of the data buffer. */ LINPHONE_PUBLIC size_t linphone_buffer_get_size(const LinphoneBuffer *buffer); /** * Set the size of the content of the data buffer. - * @param[in] buffer LinphoneBuffer object + * @param[in] buffer #LinphoneBuffer object * @param[in] size The size of the content of the data buffer. */ LINPHONE_PUBLIC void linphone_buffer_set_size(LinphoneBuffer *buffer, size_t size); /** - * Tell whether the LinphoneBuffer is empty. - * @param[in] buffer LinphoneBuffer object - * @return A boolean value telling whether the LinphoneBuffer is empty or not. + * Tell whether the #LinphoneBuffer is empty. + * @param[in] buffer #LinphoneBuffer object + * @return A boolean value telling whether the #LinphoneBuffer is empty or not. */ LINPHONE_PUBLIC bool_t linphone_buffer_is_empty(const LinphoneBuffer *buffer); diff --git a/include/linphone/call.h b/include/linphone/call.h index bbc19929a..990d2b360 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -20,956 +20,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef LINPHONE_CALL_H #define LINPHONE_CALL_H -#include -#include "linphone/types.h" - -/** - * @addtogroup call_control - * @{ - */ - -/** Callback prototype */ -typedef void (*LinphoneCallCbFunc)(LinphoneCall *call, void *user_data); - - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Acquire a reference to the call. - * 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(). - * @param[in] call The call. - * @return The same call. -**/ -LINPHONE_PUBLIC LinphoneCall * linphone_call_ref(LinphoneCall *call); - -/** - * Release reference to the call. - * @param[in] call The call. -**/ -LINPHONE_PUBLIC void linphone_call_unref(LinphoneCall *call); - -/** - * Retrieve the user pointer associated with the call. - * @param[in] call The call. - * @return The user pointer associated with the call. -**/ -LINPHONE_PUBLIC void * linphone_call_get_user_data(const LinphoneCall *call); - -/** - * Assign a user pointer to the call. - * @param[in] call The call. - * @param[in] ud The user pointer to associate with the call. -**/ -LINPHONE_PUBLIC void linphone_call_set_user_data(LinphoneCall *call, void *ud); - -/** - * Get the core that has created the specified call. - * @param[in] call LinphoneCall object - * @return The LinphoneCore object that has created the specified call. - */ -LINPHONE_PUBLIC LinphoneCore * linphone_call_get_core(const LinphoneCall *call); - -/** - * Retrieves the call's current state. -**/ -LINPHONE_PUBLIC LinphoneCallState linphone_call_get_state(const LinphoneCall *call); - -/** - * Tell whether a call has been asked to autoanswer - * @param[in] call LinphoneCall object - * @return A boolean value telling whether the call has been asked to autoanswer -**/ -LINPHONE_PUBLIC bool_t linphone_call_asked_to_autoanswer(LinphoneCall *call); - -/** - * Returns the remote address associated to this call -**/ -LINPHONE_PUBLIC const LinphoneAddress * linphone_call_get_remote_address(const LinphoneCall *call); - -/** - * Returns the to address with its headers associated to this call -**/ -LINPHONE_PUBLIC const LinphoneAddress * linphone_call_get_to_address(const LinphoneCall * call); - -/** - * Returns the value of the header name -**/ -LINPHONE_PUBLIC const char * linphone_call_get_to_header(const LinphoneCall *call, const char *name); - -/** - * Returns the remote address associated to this call as a string. - * The result string must be freed by user using ms_free(). -**/ -LINPHONE_PUBLIC char * linphone_call_get_remote_address_as_string(const LinphoneCall *call); - -/** - * Returns the diversion address associated to this call -**/ -LINPHONE_PUBLIC const LinphoneAddress * linphone_call_get_diversion_address(const LinphoneCall *call); - -/** - * Returns direction of the call (incoming or outgoing). -**/ -LINPHONE_PUBLIC LinphoneCallDir linphone_call_get_dir(const LinphoneCall *call); - -/** - * Gets the call log associated to this call. - * @param[in] call LinphoneCall object - * @return The LinphoneCallLog associated with the specified LinphoneCall -**/ -LINPHONE_PUBLIC LinphoneCallLog * linphone_call_get_call_log(const LinphoneCall *call); - -/** - * Gets the refer-to uri (if the call was transfered). - * @param[in] call LinphoneCall object - * @return The refer-to uri of the call (if it was transfered) -**/ -LINPHONE_PUBLIC const char * linphone_call_get_refer_to(const LinphoneCall *call); - -/** - * Returns true if this calls has received a transfer that has not been - * executed yet. - * Pending transfers are executed when this call is being paused or closed, - * locally or by remote endpoint. - * If the call is already paused while receiving the transfer request, the - * transfer immediately occurs. -**/ -LINPHONE_PUBLIC bool_t linphone_call_has_transfer_pending(const LinphoneCall *call); - -/** - * Gets the transferer if this call was started automatically as a result of an incoming transfer request. - * The call in which the transfer request was received is returned in this case. - * @param[in] call LinphoneCall object - * @return The transferer call if the specified call was started automatically as a result of an incoming transfer request, NULL otherwise -**/ -LINPHONE_PUBLIC LinphoneCall * linphone_call_get_transferer_call(const LinphoneCall *call); - -/** - * When this call has received a transfer request, returns the new call that was automatically created as a result of the transfer. -**/ -LINPHONE_PUBLIC LinphoneCall * linphone_call_get_transfer_target_call(const LinphoneCall *call); - -/** - * Returns the call object this call is replacing, if any. - * Call replacement can occur during call transfers. - * By default, the core automatically terminates the replaced call and accept the new one. - * This function allows the application to know whether a new incoming call is a one that replaces another one. -**/ -LINPHONE_PUBLIC LinphoneCall * linphone_call_get_replaced_call(LinphoneCall *call); - -/** - * Returns call's duration in seconds. -**/ -LINPHONE_PUBLIC int linphone_call_get_duration(const LinphoneCall *call); - -/** - * Returns current parameters associated to the call. -**/ -LINPHONE_PUBLIC const LinphoneCallParams * linphone_call_get_current_params(LinphoneCall *call); - -/** - * Returns call parameters proposed by remote. - * - * This is useful when receiving an incoming call, to know whether the remote party - * supports video, encryption or whatever. -**/ -LINPHONE_PUBLIC const LinphoneCallParams * linphone_call_get_remote_params(LinphoneCall *call); - -/** - * Indicate whether camera input should be sent to remote end. -**/ -LINPHONE_PUBLIC void linphone_call_enable_camera(LinphoneCall *lc, bool_t enabled); - -/** - * Returns TRUE if camera pictures are allowed to be sent to the remote party. -**/ -LINPHONE_PUBLIC bool_t linphone_call_camera_enabled(const LinphoneCall *lc); - -/** - * Take a photo of currently received video and write it into a jpeg 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). -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_take_video_snapshot(LinphoneCall *call, const char *file); - -/** - * Take a photo of currently captured video and write it into a jpeg 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). -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_take_preview_snapshot(LinphoneCall *call, const char *file); - -/** - * Returns the reason for a call termination (either error or normal termination) -**/ -LINPHONE_PUBLIC LinphoneReason linphone_call_get_reason(const LinphoneCall *call); - - -/** - * Returns full details about call errors or termination reasons. - * @param call LinphoneCall object on which we want the information error - * @return LinphoneErrorInfo object holding the reason error. - */ -LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call); - -/** - * Returns the far end's user agent description string, if available. -**/ -LINPHONE_PUBLIC const char *linphone_call_get_remote_user_agent(LinphoneCall *call); - -/** - * Returns the far end's sip contact as a string, if available. -**/ -LINPHONE_PUBLIC const char *linphone_call_get_remote_contact(LinphoneCall *call); - -/** - * Returns the ZRTP authentication token to verify. - * @param call the LinphoneCall - * @return the authentication token to verify. -**/ -LINPHONE_PUBLIC const char * linphone_call_get_authentication_token(LinphoneCall *call); - -/** - * Returns whether ZRTP authentication token is verified. - * If not, it must be verified by users as described in ZRTP procedure. - * Once done, the application must inform of the results with linphone_call_set_authentication_token_verified(). - * @param call the LinphoneCall - * @return TRUE if authentication token is verifed, false otherwise. -**/ -LINPHONE_PUBLIC bool_t linphone_call_get_authentication_token_verified(LinphoneCall *call); - -/** - * Set the result of ZRTP short code verification by user. - * If remote party also does the same, it will update the ZRTP cache so that user's verification will not be required for the two users. - * @param call the LinphoneCall - * @param verified whether the ZRTP SAS is verified. -**/ -LINPHONE_PUBLIC void linphone_call_set_authentication_token_verified(LinphoneCall *call, bool_t verified); - -/** - * Request remote side to send us a Video Fast Update. -**/ -LINPHONE_PUBLIC void linphone_call_send_vfu_request(LinphoneCall *call); - -/** @deprecated Use linphone_call_get_user_data() instead. */ -#define linphone_call_get_user_pointer(call) linphone_call_get_user_data(call) - -/** @deprecated Use linphone_call_set_user_data() instead. */ -#define linphone_call_set_user_pointer(call, ud) linphone_call_set_user_data(call, ud) - -LINPHONE_PUBLIC void linphone_call_set_next_video_frame_decoded_callback(LinphoneCall *call, LinphoneCallCbFunc cb, void *user_data); - -/** - * Returns the current transfer state, if a transfer has been initiated from this call. - * @see linphone_core_transfer_call() , linphone_core_transfer_call_to_another() -**/ -LINPHONE_PUBLIC LinphoneCallState linphone_call_get_transfer_state(LinphoneCall *call); - -/** - * Perform a zoom of the video displayed during a call. - * @param call the call. - * @param zoom_factor a floating point number describing the zoom factor. A value 1.0 corresponds to no zoom applied. - * @param cx a floating point number pointing the horizontal center of the zoom to be applied. This value should be between 0.0 and 1.0. - * @param cy a floating point number pointing the vertical center of the zoom to be applied. This value should be between 0.0 and 1.0. - * - * cx and cy are updated in return in case their coordinates were too excentrated for the requested zoom factor. The zoom ensures that all the screen is fullfilled with the video. -**/ -LINPHONE_PUBLIC void linphone_call_zoom_video(LinphoneCall *call, float zoom_factor, float *cx, float *cy); - -/** - * Send the specified dtmf. - * - * The dtmf is automatically played to the user. - * @param call The LinphoneCall object - * @param dtmf The dtmf name specified as a char, such as '0', '#' etc... - * @return 0 if successful, -1 on error. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_send_dtmf(LinphoneCall *call, char dtmf); - -/** - * Send a list of dtmf. - * - * The dtmfs are automatically sent to remote, separated by some needed customizable delay. - * Sending is canceled if the call state changes to something not LinphoneCallStreamsRunning. - * @param call The LinphoneCall object - * @param dtmfs A dtmf sequence such as '123#123123' - * @return -2 if there is already a DTMF sequence, -1 if call is not ready, 0 otherwise. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_send_dtmfs(LinphoneCall *call, const char *dtmfs); - -/** - * Stop current DTMF sequence sending. - * - * Please note that some DTMF could be already sent, - * depending on when this function call is delayed from #linphone_call_send_dtmfs. This - * function will be automatically called if call state change to anything but LinphoneCallStreamsRunning. - * @param call The LinphoneCall object -**/ -LINPHONE_PUBLIC void linphone_call_cancel_dtmfs(LinphoneCall *call); - -/** - * Return TRUE if this call is currently part of a conference - * @param call #LinphoneCall - * @return TRUE if part of a conference. - * @deprecated Use linphone_call_get_conference() instead. - * @donotwrap - */ -LINPHONE_PUBLIC LINPHONE_DEPRECATED bool_t linphone_call_is_in_conference(const LinphoneCall *call); - -/** - * Return the associated conference object - * @param call #LinphoneCall - * @return A pointer on #LinphoneConference or NULL if the call is not part of any conference. - */ -LINPHONE_PUBLIC LinphoneConference * linphone_call_get_conference(const LinphoneCall *call); - -/** - * Change the playback output device (currently only used for blackberry) - * @param call - * @param route the wanted audio route (earpiece, speaker, ...) - * @donotwrap -**/ -LINPHONE_PUBLIC void linphone_call_set_audio_route(LinphoneCall *call, LinphoneAudioRoute route); - -/** - * Returns the number of stream for the given call. - * Currently there is only two (Audio, Video), but later there will be more. - * @param call - * @return 2 -**/ -LINPHONE_PUBLIC int linphone_call_get_stream_count(LinphoneCall *call); - -/** - * Returns the type of stream for the given stream index. - * @param call - * @param stream_index - * @return the type (MSAudio, MSVideo, MSText) of the stream of given index. -**/ -LINPHONE_PUBLIC MSFormatType linphone_call_get_stream_type(LinphoneCall *call, int stream_index); - -/** - * Returns the meta rtp transport for the given stream index. - * @param call - * @param stream_index - * @return a pointer to the meta rtp transport if it exists, NULL otherwise -**/ -LINPHONE_PUBLIC RtpTransport * linphone_call_get_meta_rtp_transport(LinphoneCall *call, int stream_index); - -/** - * Returns the meta rtcp transport for the given stream index. - * @param call - * @param stream_index - * @return a pointer to the meta rtcp transport if it exists, NULL otherwise -**/ -LINPHONE_PUBLIC RtpTransport * linphone_call_get_meta_rtcp_transport(LinphoneCall *call, int stream_index); - -/** - * Pauses the call. If a music file has been setup using linphone_core_set_play_file(), - * this file will be played to the remote user. - * The only way to resume a paused call is to call linphone_call_resume(). - * @param[in] call LinphoneCall object - * @return 0 on success, -1 on failure - * @see linphone_call_resume() -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_pause(LinphoneCall *call); - -/** - * Resumes a call. - * The call needs to have been paused previously with linphone_call_pause(). - * @param[in] call LinphoneCall object - * @return 0 on success, -1 on failure - * @see linphone_call_pause() -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_resume(LinphoneCall *call); - -/** - * Terminates a call. - * @param[in] call LinphoneCall object - * @return 0 on success, -1 on failure -**/LINPHONE_PUBLIC LinphoneStatus linphone_call_terminate(LinphoneCall *call); - - -/** - * Terminates a call. - * @param[in] call LinphoneCall object - * @param[in] ei LinphoneErrorInfo - * @return 0 on success, -1 on failure -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_terminate_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei); - -/** - * Redirect the specified call to the given redirect URI. - * @param[in] call A LinphoneCall object - * @param[in] redirect_uri The URI to redirect the call to - * @return 0 if successful, -1 on error. - */ -LINPHONE_PUBLIC LinphoneStatus linphone_call_redirect(LinphoneCall *call, const char *redirect_uri); - -/** - * Decline a pending incoming call, with a reason. - * @param[in] call A LinphoneCall object that must be in the IncomingReceived state - * @param[in] reason The reason for rejecting the call: LinphoneReasonDeclined or LinphoneReasonBusy - * @return 0 on success, -1 on failure -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_decline(LinphoneCall * call, LinphoneReason reason); - -/** - * Decline a pending incoming call, with a LinphoneErrorInfo object. - * @param[in] call A LinphoneCall object that must be in the IncomingReceived state - * @param[in] ei LinphoneErrorInfo containing more information on the call rejection. - * @return 0 on success, -1 on failure - */ -LINPHONE_PUBLIC int linphone_call_decline_with_error_info(LinphoneCall * call, const LinphoneErrorInfo *ei); - -/** - * Accept an incoming call. - * - * Basically the application is notified of incoming calls within the - * call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive - * a LinphoneCallIncoming event with the associated LinphoneCall object. - * The application can later accept the call using this method. - * @param[in] call A LinphoneCall object - * @return 0 on success, -1 on failure -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_accept(LinphoneCall *call); - -/** - * Accept an incoming call, with parameters. - * - * Basically the application is notified of incoming calls within the - * call_state_changed callback of the #LinphoneCoreVTable structure, where it will receive - * a LinphoneCallIncoming event with the associated LinphoneCall object. - * The application can later accept the call using this method. - * @param[in] call A LinphoneCall object - * @param[in] params The specific parameters for this call, for example whether video is accepted or not. Use NULL to use default parameters - * @return 0 on success, -1 on failure -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_with_params(LinphoneCall *call, const LinphoneCallParams *params); - -/** - * Accept an early media session for an incoming call. - * This is identical as calling linphone_call_accept_early_media_with_params() with NULL parameters. - * @param[in] call A LinphoneCall object - * @return 0 if successful, -1 otherwise - * @see linphone_call_accept_early_media_with_params() -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_early_media(LinphoneCall *call); - -/** - * 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. - * However, unlike after call acceptance, mic and camera input are not sent during early-media, though received audio & video are played normally. - * The call can then later be fully accepted using linphone_call_accept() or linphone_call_accept_with_params(). - * @param[in] call A LinphoneCall object - * @param[in] params The call parameters to use (can be NULL) - * @return 0 if successful, -1 otherwise -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_early_media_with_params(LinphoneCall *call, const LinphoneCallParams *params); - -/** - * Updates a running call according to supplied call parameters or parameters changed in the LinphoneCore. - * It triggers a SIP reINVITE in order to perform a new offer/answer of media capabilities. - * Changing the size of the transmitted video after calling linphone_core_set_preferred_video_size() can be used by passing NULL as params argument. - * In case no changes are requested through the LinphoneCallParams argument, then this argument can be omitted and set to NULL. - * WARNING: Updating a call in the LinphoneCallPaused state will still result in a paused call even if the media directions set in the - * params are sendrecv. To resume a paused call, you need to call linphone_call_resume(). - * - * @param[in] call A LinphoneCall object - * @param[in] params The new call parameters to use (may be NULL) - * @return 0 if successful, -1 otherwise. -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_update(LinphoneCall *call, const LinphoneCallParams *params); - -/** - * When receiving a #LinphoneCallUpdatedByRemote state notification, prevent LinphoneCore from performing an automatic answer. - * - * When receiving a #LinphoneCallUpdatedByRemote state notification (ie an incoming reINVITE), the default behaviour of - * LinphoneCore is defined by the "defer_update_default" option of the "sip" section of the config. If this option is 0 (the default) - * then the LinphoneCore automatically answers the reINIVTE with call parameters unchanged. - * However when for example when the remote party updated the call to propose a video stream, it can be useful - * to prompt the user before answering. This can be achieved by calling linphone_core_defer_call_update() during - * the call state notification, to deactivate the automatic answer that would just confirm the audio but reject the video. - * Then, when the user responds to dialog prompt, it becomes possible to call linphone_call_accept_update() to answer - * the reINVITE, with eventually video enabled in the LinphoneCallParams argument. - * - * The #LinphoneCallUpdatedByRemote notification can also arrive when receiving an INVITE without SDP. In such case, an unchanged offer is made - * in the 200Ok, and when the ACK containing the SDP answer is received, #LinphoneCallUpdatedByRemote is triggered to notify the application of possible - * changes in the media session. However in such case defering the update has no meaning since we just generating an offer. - * - * @param[in] call A LinphoneCall object - * @return 0 if successful, -1 if the linphone_call_defer_update() was done outside a valid #LinphoneCallUpdatedByRemote notification -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_defer_update(LinphoneCall *call); - -/** - * Accept call modifications initiated by other end. - * - * This call may be performed in response to a #LinphoneCallUpdatedByRemote state notification. - * When such notification arrives, the application can decide to call linphone_call_defer_update() so that it can - * have the time to prompt the user. linphone_call_get_remote_params() can be used to get information about the call parameters - * requested by the other party, such as whether a video stream is requested. - * - * When the user accepts or refuse the change, linphone_call_accept_update() can be done to answer to the other party. - * If params is NULL, then the same call parameters established before the update request will continue to be used (no change). - * If params is not NULL, then the update will be accepted according to the parameters passed. - * Typical example is when a user accepts to start video, then params should indicate that video stream should be used - * (see linphone_call_params_enable_video()). - * @param[in] call A LinphoneCall object - * @param[in] params A LinphoneCallParams object describing the call parameters to accept - * @return 0 if successful, -1 otherwise (actually when this function call is performed outside ot #LinphoneCallUpdatedByRemote state) -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *params); - -/** - * Performs a simple call transfer to the specified destination. - * The remote endpoint is expected to issue a new call to the specified destination. - * The current call remains active and thus can be later paused or terminated. - * It is possible to follow the progress of the transfer provided that transferee sends notification about it. - * In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party. - * The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallConnected. - * @param[in] call The call to be transfered - * @param[in] refer_to The destination the call is to be refered to - * @return 0 on success, -1 on failure -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_transfer(LinphoneCall *call, const char *refer_to); - -/** - * Transfers a call to destination of another running call. This is used for "attended transfer" scenarios. - * The transfered call is supposed to be in paused state, so that it is able to accept the transfer immediately. - * The destination call is a call previously established to introduce the transfered person. - * This method will send a transfer request to the transfered person. The phone of the transfered is then - * expected to automatically call to the destination of the transfer. The receiver of the transfer will then automatically - * close the call with us (the 'dest' call). - * It is possible to follow the progress of the transfer provided that transferee sends notification about it. - * In this case, the transfer_state_changed callback of the #LinphoneCoreVTable is invoked to notify of the state of the new call at the other party. - * The notified states are #LinphoneCallOutgoingInit , #LinphoneCallOutgoingProgress, #LinphoneCallOutgoingRinging and #LinphoneCallConnected. - * @param[in] call A running call you want to transfer - * @param[in] dest A running call whose remote person will receive the transfer - * @return 0 on success, -1 on failure -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_transfer_to_another(LinphoneCall *call, LinphoneCall *dest); - - -/** - * Acquire a reference to the LinphoneCallCbs object. - * @param[in] cbs LinphoneCallCbs object. - * @return The same LinphoneCallCbs object. - */ -LINPHONE_PUBLIC LinphoneCallCbs *linphone_call_cbs_ref(LinphoneCallCbs *cbs); - -/** - * Release reference to the LinphoneCallCbs object. - * @param[in] cbs LinphoneCallCbs object. - */ -LINPHONE_PUBLIC void linphone_call_cbs_unref(LinphoneCallCbs *cbs); - -/** - * Retrieve the user pointer associated with the LinphoneCallCbs object. - * @param[in] cbs LinphoneCallCbs object. - * @return The user pointer associated with the LinphoneCallCbs object. - */ -LINPHONE_PUBLIC void *linphone_call_cbs_get_user_data(const LinphoneCallCbs *cbs); - -/** - * Assign a user pointer to the LinphoneCallCbs object. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] ud The user pointer to associate with the LinphoneCallCbs object. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_user_data(LinphoneCallCbs *cbs, void *user_data); - -/** - * Get the dtmf received callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current dtmf received callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsDtmfReceivedCb linphone_call_cbs_get_dtmf_received(LinphoneCallCbs *cbs); - -/** - * Set the dtmf received callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The dtmf received callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_dtmf_received(LinphoneCallCbs *cbs, LinphoneCallCbsDtmfReceivedCb cb); - -/** - * Get the encryption changed callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current encryption changed callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsEncryptionChangedCb linphone_call_cbs_get_encryption_changed(LinphoneCallCbs *cbs); - -/** - * Set the encryption changed callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The encryption changed callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_encryption_changed(LinphoneCallCbs *cbs, LinphoneCallCbsEncryptionChangedCb cb); - -/** - * Get the info message received callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current info message received callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsInfoMessageReceivedCb linphone_call_cbs_get_info_message_received(LinphoneCallCbs *cbs); - -/** - * Set the info message received callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The info message received callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_info_message_received(LinphoneCallCbs *cbs, LinphoneCallCbsInfoMessageReceivedCb cb); - -/** - * Get the state changed callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current state changed callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsStateChangedCb linphone_call_cbs_get_state_changed(LinphoneCallCbs *cbs); - -/** - * Set the state changed callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The state changed callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsStateChangedCb cb); - -/** - * Get the stats updated callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current stats updated callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsStatsUpdatedCb linphone_call_cbs_get_stats_updated(LinphoneCallCbs *cbs); - -/** - * Set the stats updated callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The stats updated callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_stats_updated(LinphoneCallCbs *cbs, LinphoneCallCbsStatsUpdatedCb cb); - -/** - * Get the transfer state changed callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current transfer state changed callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsTransferStateChangedCb linphone_call_cbs_get_transfer_state_changed(LinphoneCallCbs *cbs); - -/** - * Set the transfer state changed callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The transfer state changed callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_transfer_state_changed(LinphoneCallCbs *cbs, LinphoneCallCbsTransferStateChangedCb cb); - -/** - * Get the ACK processing callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current ack processing callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_processing(LinphoneCallCbs *cbs); - -/** - * Set ACK processing callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The ack processing callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_ack_processing(LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb); - -/** - * Get the TMMBR received callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current TMMBR received callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsTmmbrReceivedCb linphone_call_cbs_get_tmmbr_received(LinphoneCallCbs *cbs); - -/** - * Set the TMMBR received callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The TMMBR received callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_tmmbr_received(LinphoneCallCbs *cbs, LinphoneCallCbsTmmbrReceivedCb cb); - -/** - * Get the snapshot taken callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current snapshot taken callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsSnapshotTakenCb linphone_call_cbs_get_snapshot_taken(LinphoneCallCbs *cbs); - -/** - * Set the snapshot taken callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The snapshot taken callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_snapshot_taken(LinphoneCallCbs *cbs, LinphoneCallCbsSnapshotTakenCb cb); - -/** - * Get the next video frame decoded callback. - * @param[in] cbs LinphoneCallCbs object. - * @return The current next video frame decoded callback. - */ -LINPHONE_PUBLIC LinphoneCallCbsNextVideoFrameDecodedCb linphone_call_cbs_get_next_video_frame_decoded(LinphoneCallCbs *cbs); - -/** - * Set the next video frame decoded callback. - * @param[in] cbs LinphoneCallCbs object. - * @param[in] cb The next video frame decoded callback to be used. - */ -LINPHONE_PUBLIC void linphone_call_cbs_set_next_video_frame_decoded(LinphoneCallCbs *cbs, LinphoneCallCbsNextVideoFrameDecodedCb cb); - -/** - * @} - */ - - -/** - * @addtogroup media_parameters - * @{ - */ - -/** - * Get the native window handle of the video window, casted as an unsigned long. -**/ -LINPHONE_PUBLIC void * linphone_call_get_native_video_window_id(const LinphoneCall *call); - -/** - * Set the native video window id where the video is to be displayed. - * For MacOS, Linux, Windows: if not set or 0 a window will be automatically created, unless the special id -1 is given. -**/ -LINPHONE_PUBLIC void linphone_call_set_native_video_window_id(LinphoneCall *call, void * id); - -/** - * Enables or disable echo cancellation for this call - * @param call - * @param val -**/ -LINPHONE_PUBLIC void linphone_call_enable_echo_cancellation(LinphoneCall *call, bool_t val) ; - -/** - * Returns TRUE if echo cancellation is enabled. -**/ -LINPHONE_PUBLIC bool_t linphone_call_echo_cancellation_enabled(LinphoneCall *lc); - -/** - * Enables or disable echo limiter for this call - * @param call - * @param val -**/ -LINPHONE_PUBLIC void linphone_call_enable_echo_limiter(LinphoneCall *call, bool_t val); - -/** - * Returns TRUE if echo limiter is enabled. -**/ -LINPHONE_PUBLIC bool_t linphone_call_echo_limiter_enabled(const LinphoneCall *call); - -/** - * @} - */ - -/** - * @addtogroup call_misc - * @{ - */ - -/** - * Create a new chat room for messaging from a call if not already existing, else return existing one. - * No reference is given to the caller: the chat room will be deleted when the call is ended. - * @param call #LinphoneCall object - * @return #LinphoneChatRoom where messaging can take place. - */ -LINPHONE_PUBLIC LinphoneChatRoom * linphone_call_get_chat_room(LinphoneCall *call); - -/** - * Get the mesured playback volume level (received from remote) in dbm0. - * @param call The call. - * @return float Volume level in percentage. - */ -LINPHONE_PUBLIC float linphone_call_get_play_volume(LinphoneCall *call); - -/** - * Get the mesured record volume level (sent to remote) in dbm0. - * @param call The call. - * @return float Volume level in percentage. - */ -LINPHONE_PUBLIC float linphone_call_get_record_volume(LinphoneCall *call); - -/** - * Get speaker volume gain. - * If the sound backend supports it, the returned gain is equal to the gain set - * with the system mixer. - * @param call The call. - * @return Percenatge of the max supported volume gain. Valid values are in [ 0.0 : 1.0 ]. - * In case of failure, a negative value is returned - */ -LINPHONE_PUBLIC float linphone_call_get_speaker_volume_gain(const LinphoneCall *call); - -/** - * Set speaker volume gain. - * If the sound backend supports it, the new gain will synchronized with the system mixer. - * @param call The call. - * @param volume Percentage of the max supported gain. Valid values are in [ 0.0 : 1.0 ]. - */ -LINPHONE_PUBLIC void linphone_call_set_speaker_volume_gain(LinphoneCall *call, float volume); - -/** - * Get microphone volume gain. - * If the sound backend supports it, the returned gain is equal to the gain set - * with the system mixer. - * @param call The call. - * @return double Percenatge of the max supported volume gain. Valid values are in [ 0.0 : 1.0 ]. - * In case of failure, a negative value is returned - */ -LINPHONE_PUBLIC float linphone_call_get_microphone_volume_gain(const LinphoneCall *call); - -/** - * Set microphone volume gain. - * If the sound backend supports it, the new gain will synchronized with the system mixer. - * @param call The call. - * @param volume Percentage of the max supported gain. Valid values are in [ 0.0 : 1.0 ]. - */ -LINPHONE_PUBLIC void linphone_call_set_microphone_volume_gain(LinphoneCall *call, float volume); - -/** - * Obtain real-time quality rating of the call - * - * Based on local RTP statistics and RTCP feedback, a quality rating is computed and updated - * during all the duration of the call. This function returns its value at the time of the function call. - * It is expected that the rating is updated at least every 5 seconds or so. - * The rating is a floating point number comprised between 0 and 5. - * - * 4-5 = good quality
- * 3-4 = average quality
- * 2-3 = poor quality
- * 1-2 = very poor quality
- * 0-1 = can't be worse, mostly unusable
- * - * @return The function returns -1 if no quality measurement is available, for example if no - * active audio stream exist. Otherwise it returns the quality rating. -**/ -LINPHONE_PUBLIC float linphone_call_get_current_quality(LinphoneCall *call); - -/** - * Returns call quality averaged over all the duration of the call. - * - * See linphone_call_get_current_quality() for more details about quality measurement. -**/ -LINPHONE_PUBLIC float linphone_call_get_average_quality(LinphoneCall *call); - -/** - * Start call recording. - * The output file where audio is recorded must be previously specified with linphone_call_params_set_record_file(). -**/ -LINPHONE_PUBLIC void linphone_call_start_recording(LinphoneCall *call); - -/** - * Stop call recording. -**/ -LINPHONE_PUBLIC void linphone_call_stop_recording(LinphoneCall *call); - -/** - * Get a player associated with the call to play a local file and stream it to the remote peer. - * @param[in] call LinphoneCall object - * @return A LinphonePlayer object - */ -LINPHONE_PUBLIC LinphonePlayer * linphone_call_get_player(LinphoneCall *call); - -/** - * Indicates whether an operation is in progress at the media side. - * It can be a bad idea to initiate signaling operations (adding video, pausing the call, removing video, changing video parameters) while - * the media is busy in establishing the connection (typically ICE connectivity checks). It can result in failures generating loss of time - * in future operations in the call. - * Applications are invited to check this function after each call state change to decide whether certain operations are permitted or not. - * @param call the call - * @return TRUE if media is busy in establishing the connection, FALSE otherwise. -**/ -LINPHONE_PUBLIC bool_t linphone_call_media_in_progress(LinphoneCall *call); - -/** - * Call generic OpenGL render for a given call. - * @param call The call. - */ -LINPHONE_PUBLIC void linphone_call_ogl_render(const LinphoneCall *call); - - - -/** - * Send a LinphoneInfoMessage through an established call - * @param call the call - * @param info the info message -**/ -LINPHONE_PUBLIC LinphoneStatus linphone_call_send_info_message(LinphoneCall *call, const LinphoneInfoMessage *info); - -/** - * Return a copy of the call statistics for a particular stream type. - * @param call the call - * @param type the stream type -**/ -LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_stats(LinphoneCall *call, LinphoneStreamType type); - -LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_audio_stats(LinphoneCall *call); - -LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_video_stats(LinphoneCall *call); - -LINPHONE_PUBLIC LinphoneCallStats *linphone_call_get_text_stats(LinphoneCall *call); - -/** - * Add a listener in order to be notified of LinphoneCall events. Once an event is received, registred LinphoneCallCbs are - * invoked sequencially. - * @param[in] call LinphoneCall object to monitor. - * @param[in] cbs A LinphoneCallCbs object holding the callbacks you need. A reference is taken by the LinphoneCall until you invoke linphone_call_remove_callbacks(). - */ -LINPHONE_PUBLIC void linphone_call_add_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs); - -/** - * Remove a listener from a LinphoneCall - * @param[in] call LinphoneCall object - * @param[in] cbs LinphoneCallCbs object to remove. - */ -LINPHONE_PUBLIC void linphone_call_remove_callbacks(LinphoneCall *call, LinphoneCallCbs *cbs); - -/** - * Gets the current LinphoneCallCbs. - * This is meant only to be called from a callback to be able to get the user_data associated with the LinphoneCallCbs that is calling the callback. - * @param[in] call LinphoneCall object - * @return The LinphoneCallCbs that has called the last callback - */ -LINPHONE_PUBLIC LinphoneCallCbs *linphone_call_get_current_callbacks(const LinphoneCall *call); - -/** - * Set call parameters - advanced and not recommended feature - use with caution. - * Local call parameters applicable to an outgoing or incoming shall usually be passed to linphone_core_invite_address_with_params() or - * linphone_call_accept_with_params(). - * However, in some cases it might be desirable from a software design standpoint to modify local parameters outside of the application layer, typically - * in the purpose of implementing a custom logic including special headers in INVITE or 200Ok requests, driven by a call_state_changed listener method. - * This function accepts to assign a new LinphoneCallParams only in LinphoneCallOutgoingInit and LinphoneCallIncomingReceived states. - * @param call the LinphoneCall object -**/ -LINPHONE_PUBLIC void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params); - -/** - * Returns local parameters associated with the call. - * This is typically the parameters passed at call initiation to linphone_core_invite_address_with_params() or linphone_call_accept_with_params(), or some default - * parameters if no LinphoneCallParams was explicitely passed during call initiation. - * @param call the LinphoneCall object - * @return the call's local parameters. - **/ -LINPHONE_PUBLIC const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif +#include "linphone/api/c-call.h" +#include "linphone/api/c-call-cbs.h" +#include "linphone/api/c-call-stats.h" #endif /* LINPHONE_CALL_H */ diff --git a/include/linphone/call_log.h b/include/linphone/call_log.h index d1610c577..5e0d84e52 100644 --- a/include/linphone/call_log.h +++ b/include/linphone/call_log.h @@ -38,45 +38,46 @@ extern "C" { /** * Get the call ID used by the call. - * @param[in] cl LinphoneCallLog object + * @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 + * @param[in] cl #LinphoneCallLog object * @return The direction of the call. **/ -LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(LinphoneCallLog *cl); +LINPHONE_PUBLIC LinphoneCallDir linphone_call_log_get_dir(const LinphoneCallLog *cl); /** * Get the duration of the call since connected. - * @param[in] cl LinphoneCallLog object + * @param[in] cl #LinphoneCallLog object * @return The duration of the call in seconds. **/ -LINPHONE_PUBLIC int linphone_call_log_get_duration(LinphoneCallLog *cl); +LINPHONE_PUBLIC int linphone_call_log_get_duration(const LinphoneCallLog *cl); /** * Get the origin address (ie from) of the call. - * @param[in] cl LinphoneCallLog object + * @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); +LINPHONE_PUBLIC const LinphoneAddress * linphone_call_log_get_from_address(const LinphoneCallLog *cl); /** * Get the RTP statistics computed locally regarding the call. - * @param[in] cl LinphoneCallLog object + * @param[in] cl #LinphoneCallLog object * @return The RTP statistics that have been computed locally for the call. + * @donotwrap **/ 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 + * @param[in] cl #LinphoneCallLog object * @return The overall quality indication of the call. **/ -LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl); +LINPHONE_PUBLIC float linphone_call_log_get_quality(const LinphoneCallLog *cl); /** * Get the persistent reference key associated to the call log. @@ -84,46 +85,54 @@ LINPHONE_PUBLIC float linphone_call_log_get_quality(LinphoneCallLog *cl); * 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] 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). + * Get the local address (that is from or to depending on call direction) * @param[in] cl LinphoneCallLog object + * @return The local address of the call + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_call_log_get_local_address(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); +LINPHONE_PUBLIC const LinphoneAddress * linphone_call_log_get_remote_address(const 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 + * @param[in] cl #LinphoneCallLog object * @return The RTP statistics that have been computed by the remote end for the call. + * @donotwrap **/ 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 + * @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); +LINPHONE_PUBLIC time_t linphone_call_log_get_start_date(const LinphoneCallLog *cl); /** * Get the status of the call. - * @param[in] cl LinphoneCallLog object + * @param[in] cl #LinphoneCallLog object * @return The status of the call. **/ -LINPHONE_PUBLIC LinphoneCallStatus linphone_call_log_get_status(LinphoneCallLog *cl); +LINPHONE_PUBLIC LinphoneCallStatus linphone_call_log_get_status(const LinphoneCallLog *cl); /** * Get the destination address (ie to) of the call. - * @param[in] cl LinphoneCallLog object + * @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); +LINPHONE_PUBLIC const LinphoneAddress * linphone_call_log_get_to_address(const LinphoneCallLog *cl); /** * Associate a persistent reference key to the call log. @@ -131,39 +140,39 @@ LINPHONE_PUBLIC LinphoneAddress * linphone_call_log_get_to_address(LinphoneCallL * 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] 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 + * @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); +LINPHONE_PUBLIC bool_t linphone_call_log_video_enabled(const 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 + * @param[in] cl #LinphoneCallLog object * @return A human readable string describing the call. **/ -LINPHONE_PUBLIC char * linphone_call_log_to_str(LinphoneCallLog *cl); +LINPHONE_PUBLIC char * linphone_call_log_to_str(const LinphoneCallLog *cl); /** * Tells whether that call was a call to a conference server * @param[in] cl #LinphoneCallLog object * @return TRUE if the call was a call to a conference server */ -LINPHONE_PUBLIC bool_t linphone_call_log_was_conference(LinphoneCallLog *cl); +LINPHONE_PUBLIC bool_t linphone_call_log_was_conference(const LinphoneCallLog *cl); /** * When the call was failed, return an object describing the failure. * @param[in] cl #LinphoneCallLog object * @return information about the error encountered by the call associated with this call log. **/ -LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_log_get_error_info(LinphoneCallLog *cl); +LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_log_get_error_info(const LinphoneCallLog *cl); /******************************************************************************* @@ -172,28 +181,28 @@ LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_log_get_error_info(Linpho /** * Get the user data associated with the call log. - * @param[in] cl LinphoneCallLog object + * @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] 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 + * @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 + * @param[in] cl #LinphoneCallLog object **/ LINPHONE_PUBLIC void linphone_call_log_unref(LinphoneCallLog *cl); @@ -233,7 +242,7 @@ LINPHONE_PUBLIC LinphoneCallLog *linphone_core_create_call_log(LinphoneCore *lc, /** * Destroy a LinphoneCallLog. - * @param cl LinphoneCallLog object + * @param cl #LinphoneCallLog object * @deprecated Use linphone_call_log_unref() instead. * @donotwrap */ diff --git a/include/linphone/call_params.h b/include/linphone/call_params.h index 173cca313..37cf092dc 100644 --- a/include/linphone/call_params.h +++ b/include/linphone/call_params.h @@ -48,22 +48,22 @@ extern "C" { 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. + * 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 + * @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] 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); @@ -73,21 +73,21 @@ LINPHONE_PUBLIC void linphone_call_params_enable_early_media_sending(LinphoneCal * 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] 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 audio stream. - * @param[in] cp LinphoneCallParams object + * @param[in] cp #LinphoneCallParams object * @param[in] enabled A boolean value telling whether to enable audio or not. **/ LINPHONE_PUBLIC void linphone_call_params_enable_audio(LinphoneCallParams *cp, bool_t enabled); /** * Enable video stream. - * @param[in] cp LinphoneCallParams object + * @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); @@ -106,50 +106,51 @@ LINPHONE_PUBLIC const char *linphone_call_params_get_custom_header(const Linphon * that function does not return TRUE even if the conference is running.
* If you want to test whether the conference is running, you should test * whether linphone_core_get_conference() return a non-null pointer. - * @param[in] cp LinphoneCallParams object + * @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 + * @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 + * @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 + * @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 definition of the received video. - * @param[in] cp LinphoneCallParams object - * @return The received LinphoneVideoDefinition + * @param[in] cp #LinphoneCallParams object + * @return The received #LinphoneVideoDefinition */ LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_call_params_get_received_video_definition(const LinphoneCallParams *cp); /** - * Get the size of the video that is received. - * @param[in] cp LinphoneCallParams object + * @brief 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. - * @deprecated Use linphone_call_params_get_received_video_definition() instead + * @deprecated Use #linphone_call_params_get_received_video_definition() instead. Deprecated since 2017-03-28. + * @donotwrap */ LINPHONE_PUBLIC LINPHONE_DEPRECATED 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 + * @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); @@ -163,30 +164,31 @@ LINPHONE_PUBLIC const char * linphone_call_params_get_rtp_profile(const Linphone /** * Get the framerate of the video that is sent. - * @param[in] cp LinphoneCallParams object + * @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); /** * Get the definition of the sent video. - * @param[in] cp LinphoneCallParams object - * @return The sent LinphoneVideoDefinition + * @param[in] cp #LinphoneCallParams object + * @return The sent #LinphoneVideoDefinition */ LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_call_params_get_sent_video_definition(const LinphoneCallParams *cp); /** - * Gets the size of the video that is sent. - * @param[in] cp LinphoneCalParams object + * @brief 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. - * @deprecated Use linphone_call_params_get_sent_video_definition() instead + * @deprecated Use #linphone_call_params_get_sent_video_definition() instead. Deprecated since 2017-03-28. + * @donotwrap */ LINPHONE_PUBLIC LINPHONE_DEPRECATED 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 + * @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); @@ -248,7 +250,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const OrtpPayloadType *linphone_call_params_ * 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 + * @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); @@ -256,14 +258,14 @@ LINPHONE_PUBLIC bool_t linphone_call_params_low_bandwidth_enabled(const Linphone /** * 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] 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] 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); @@ -271,7 +273,7 @@ LINPHONE_PUBLIC void linphone_call_params_set_media_encryption(LinphoneCallParam /** * Set requested level of privacy for the call. * \xmlonly javascript \endxmlonly - * @param[in] cp LinphoneCallParams object + * @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 *cp, LinphonePrivacyMask privacy); @@ -281,7 +283,7 @@ LINPHONE_PUBLIC void linphone_call_params_set_privacy(LinphoneCallParams *cp, Li * 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] 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. **/ @@ -290,82 +292,92 @@ LINPHONE_PUBLIC void linphone_call_params_set_record_file(LinphoneCallParams *cp /** * 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] 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 audio is enabled or not. - * @param[in] cp LinphoneCallParams object + * @param[in] cp #LinphoneCallParams object * @return A boolean value telling whether audio is enabled or not. **/ LINPHONE_PUBLIC bool_t linphone_call_params_audio_enabled(const LinphoneCallParams *cp); /** * Tell whether video is enabled or not. - * @param[in] cp LinphoneCallParams object + * @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); /** * Get the audio stream direction. - * @param[in] cp LinphoneCallParams object + * @param[in] cp #LinphoneCallParams object * @return The audio stream direction associated with the call params. **/ LINPHONE_PUBLIC LinphoneMediaDirection linphone_call_params_get_audio_direction(const LinphoneCallParams *cp); /** * Get the video stream direction. - * @param[in] cp LinphoneCallParams object + * @param[in] cp #LinphoneCallParams object * @return The video stream direction associated with the call params. **/ LINPHONE_PUBLIC LinphoneMediaDirection linphone_call_params_get_video_direction(const LinphoneCallParams *cp); /** * Set the audio stream direction. - * @param[in] cp LinphoneCallParams object + * @param[in] cp #LinphoneCallParams object * @param[in] dir The audio stream direction associated with this call params. **/ LINPHONE_PUBLIC void linphone_call_params_set_audio_direction(LinphoneCallParams *cp, LinphoneMediaDirection dir); /** * Set the video stream direction. - * @param[in] cp LinphoneCallParams object + * @param[in] cp #LinphoneCallParams object * @param[in] dir The video stream direction associated with this call params. **/ LINPHONE_PUBLIC void linphone_call_params_set_video_direction(LinphoneCallParams *cp, LinphoneMediaDirection dir); +int linphone_call_params_get_audio_bandwidth_limit(const LinphoneCallParams *params); +bool_t linphone_call_params_real_early_media_enabled(const LinphoneCallParams *params); +bool_t linphone_call_params_avpf_enabled(const LinphoneCallParams *params); +void linphone_call_params_enable_avpf(LinphoneCallParams *params, bool_t enable); +bool_t linphone_call_params_mandatory_media_encryption_enabled(const LinphoneCallParams *params); +void linphone_call_params_enable_mandatory_media_encryption(LinphoneCallParams *params, bool_t value); +uint16_t linphone_call_params_get_avpf_rr_interval(const LinphoneCallParams *params); +void linphone_call_params_set_avpf_rr_interval(LinphoneCallParams *params, uint16_t value); + + /******************************************************************************* * Reference and user data handling functions * ******************************************************************************/ /** * Get the user data associated with the call params. - * @param[in] cp LinphoneCallParams object + * @param[in] cp #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] cp LinphoneCallParams object + * @param[in] cp #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] cp LinphoneCallParams object - * @return The same LinphoneCallParams object + * @param[in] cp #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] cp LinphoneCallParams object + * @param[in] cp #LinphoneCallParams object **/ LINPHONE_PUBLIC void linphone_call_params_unref(LinphoneCallParams *cp); @@ -485,8 +497,8 @@ LINPHONE_PUBLIC void linphone_call_params_clear_custom_sdp_media_attributes(Linp #define linphone_call_params_local_conference_mode linphone_call_params_get_local_conference_mode /** - * Destroy a LinphoneCallParams object. - * @param[in] cp LinphoneCallParams object + * Destroy a #LinphoneCallParams object. + * @param[in] cp #LinphoneCallParams object * @deprecated Use linphone_call_params_unref() instead. * @donotwrap **/ diff --git a/include/linphone/call_stats.h b/include/linphone/call_stats.h index b86219cfd..bbed92e75 100644 --- a/include/linphone/call_stats.h +++ b/include/linphone/call_stats.h @@ -20,171 +20,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef LINPHONE_CALL_STATS_H #define LINPHONE_CALL_STATS_H -#include "linphone/types.h" +#include "linphone/api/c-call-stats.h" -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @addtogroup call_misc - * @{ - */ - -#define LINPHONE_CALL_STATS_AUDIO ((int)LinphoneStreamTypeAudio) -#define LINPHONE_CALL_STATS_VIDEO ((int)LinphoneStreamTypeVideo) -#define LINPHONE_CALL_STATS_TEXT ((int)LinphoneStreamTypeText) - -#define LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE (1 << 0) /**< received_rtcp field of LinphoneCallStats object has been updated */ -#define LINPHONE_CALL_STATS_SENT_RTCP_UPDATE (1 << 1) /**< sent_rtcp field of LinphoneCallStats object has been updated */ -#define LINPHONE_CALL_STATS_PERIODICAL_UPDATE (1 << 2) /**< Every seconds LinphoneCallStats object has been updated */ - -/** - * Increment refcount. - * @param[in] stats LinphoneCallStats object - * @ingroup misc -**/ -LINPHONE_PUBLIC LinphoneCallStats *linphone_call_stats_ref(LinphoneCallStats *stats); - -/** - * Decrement refcount and possibly free the object. - * @param[in] stats LinphoneCallStats object - * @ingroup misc -**/ -LINPHONE_PUBLIC void linphone_call_stats_unref(LinphoneCallStats *stats); - -/** - * Gets the user data in the LinphoneCallStats object - * @param[in] stats the LinphoneCallStats - * @return the user data - * @ingroup misc -*/ -LINPHONE_PUBLIC void *linphone_call_stats_get_user_data(const LinphoneCallStats *stats); - -/** - * Sets the user data in the LinphoneCallStats object - * @param[in] stats the LinphoneCallStats object - * @param[in] data the user data - * @ingroup misc -*/ -LINPHONE_PUBLIC void linphone_call_stats_set_user_data(LinphoneCallStats *stats, void *data); - -/** - * Get the type of the stream the stats refer to. - * @param[in] stats LinphoneCallStats object - * @return The type of the stream the stats refer to - */ -LINPHONE_PUBLIC LinphoneStreamType linphone_call_stats_get_type(const LinphoneCallStats *stats); - -/** - * Get the local loss rate since last report - * @return The sender loss rate -**/ -LINPHONE_PUBLIC float linphone_call_stats_get_sender_loss_rate(const LinphoneCallStats *stats); - -/** - * Gets the remote reported loss rate since last report - * @return The receiver loss rate -**/ -LINPHONE_PUBLIC float linphone_call_stats_get_receiver_loss_rate(const LinphoneCallStats *stats); - -/** - * Get the local loss rate since last report - * @return The local loss rate -**/ -LINPHONE_PUBLIC float linphone_call_stats_get_local_loss_rate(const LinphoneCallStats *stats); - -/** - * Gets the local late rate since last report - * @return The local late rate -**/ -LINPHONE_PUBLIC float linphone_call_stats_get_local_late_rate(const LinphoneCallStats *stats); - -/** - * Gets the local interarrival jitter - * @param[in] stats LinphoneCallStats object - * @return The interarrival jitter at last emitted sender report -**/ -LINPHONE_PUBLIC float linphone_call_stats_get_sender_interarrival_jitter(const LinphoneCallStats *stats); - -/** - * Gets the remote reported interarrival jitter - * @param[in] stats LinphoneCallStats object - * @return The interarrival jitter at last received receiver report -**/ -LINPHONE_PUBLIC float linphone_call_stats_get_receiver_interarrival_jitter(const LinphoneCallStats *stats); - -LINPHONE_PUBLIC const rtp_stats_t *linphone_call_stats_get_rtp_stats(const LinphoneCallStats *stats); - -/** - * Gets the cumulative number of late packets - * @param[in] stats LinphoneCallStats object - * @return The cumulative number of late packets -**/ -LINPHONE_PUBLIC uint64_t linphone_call_stats_get_late_packets_cumulative_number(const LinphoneCallStats *stats); - -/** - * 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. - */ -LINPHONE_PUBLIC float linphone_call_stats_get_download_bandwidth(const LinphoneCallStats *stats); - -/** - * 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. - */ -LINPHONE_PUBLIC float linphone_call_stats_get_upload_bandwidth(const LinphoneCallStats *stats); - -/** - * Get the estimated bandwidth measurement of the received stream, expressed in kbit/s, including IP/UDP/RTP headers. - * @param[in] stats LinphoneCallStats object - * @return The estimated bandwidth measurement of the received stream in kbit/s. - */ -LINPHONE_PUBLIC float linphone_call_stats_get_estimated_download_bandwidth(const LinphoneCallStats *stats); - -/** - * Get the state of ICE processing. - * @param[in] stats LinphoneCallStats object - * @return The state of ICE processing. - */ -LINPHONE_PUBLIC LinphoneIceState linphone_call_stats_get_ice_state(const LinphoneCallStats *stats); - -/** - * Get the state of uPnP processing. - * @param[in] stats LinphoneCallStats object - * @return The state of uPnP processing. - */ -LINPHONE_PUBLIC LinphoneUpnpState linphone_call_stats_get_upnp_state(const LinphoneCallStats *stats); - -/** - * Get the IP address family of the remote peer. - * @param[in] stats LinphoneCallStats object - * @return The IP address family of the remote peer. - */ -LINPHONE_PUBLIC LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remote(const LinphoneCallStats *stats); - -/** - * Get the jitter buffer size in ms. - * @param[in] stats LinphoneCallStats object - * @return The jitter buffer size in ms. - */ -LINPHONE_PUBLIC float linphone_call_stats_get_jitter_buffer_size_ms(const LinphoneCallStats *stats); - -/** - * Get the round trip delay in s. - * @param[in] stats LinphoneCallStats object - * @return The round trip delay in s. - */ -LINPHONE_PUBLIC float linphone_call_stats_get_round_trip_delay(const LinphoneCallStats *stats); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* LINPHONE_ADDRESS_H */ +#endif /* LINPHONE_CALL_STATS_H */ diff --git a/include/linphone/callbacks.h b/include/linphone/callbacks.h index c5fe71136..dbc06de32 100644 --- a/include/linphone/callbacks.h +++ b/include/linphone/callbacks.h @@ -1,6 +1,6 @@ /* callbacks.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/types.h" +#include "linphone/api/c-callbacks.h" /** @@ -29,132 +30,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * @{ */ -/** - * Call back used to notify message delivery status - * @param msg #LinphoneChatMessage object - * @param status LinphoneChatMessageState - * @param ud application user data - * @deprecated Use LinphoneChatMessageCbsMsgStateChangedCb instead. - * @donotwrap - */ -typedef void (*LinphoneChatMessageStateChangedCb)(LinphoneChatMessage* msg,LinphoneChatMessageState state,void* ud); - -/** - * Call back used to notify message delivery status - * @param msg #LinphoneChatMessage object - * @param status LinphoneChatMessageState - */ -typedef void (*LinphoneChatMessageCbsMsgStateChangedCb)(LinphoneChatMessage* msg, LinphoneChatMessageState state); - -/** - * File transfer receive callback prototype. This function is called by the core upon an incoming File transfer is started. This function may be call several time for the same file in case of large file. - * @param message #LinphoneChatMessage message from which the body is received. - * @param content #LinphoneContent incoming content information - * @param buffer #LinphoneBuffer holding the received data. Empty buffer means end of file. - */ -typedef void (*LinphoneChatMessageCbsFileTransferRecvCb)(LinphoneChatMessage *message, const LinphoneContent* content, const LinphoneBuffer *buffer); - -/** - * File transfer send callback prototype. This function is called by the core when an outgoing file transfer is started. This function is called until size is set to 0. - * @param message #LinphoneChatMessage message from which the body is received. - * @param content #LinphoneContent outgoing content - * @param offset the offset in the file from where to get the data to be sent - * @param size the number of bytes expected by the framework - * @return A LinphoneBuffer object holding the data written by the application. An empty buffer means end of file. - */ -typedef LinphoneBuffer * (*LinphoneChatMessageCbsFileTransferSendCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t size); - -/** - * File transfer progress indication callback prototype. - * @param message #LinphoneChatMessage message from which the body is received. - * @param content #LinphoneContent incoming content information - * @param offset The number of bytes sent/received since the beginning of the transfer. - * @param total The total number of bytes to be sent/received. - */ -typedef void (*LinphoneChatMessageCbsFileTransferProgressIndicationCb)(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t total); - -/** - * @} -**/ - -/** - * @addtogroup call_control - * @{ -**/ - -/** - * Callback for being notified of received DTMFs. - * @param call LinphoneCall object that received the dtmf - * @param dtmf The ascii code of the dtmf - */ -typedef void (*LinphoneCallCbsDtmfReceivedCb)(LinphoneCall *call, int dtmf); - -/** - * Call encryption changed callback. - * @param call LinphoneCall object whose encryption is changed. - * @param on Whether encryption is activated. - * @param authentication_token An authentication_token, currently set for ZRTP kind of encryption only. - */ -typedef void (*LinphoneCallCbsEncryptionChangedCb)(LinphoneCall *call, bool_t on, const char *authentication_token); - -/** - * Callback for receiving info messages. - * @param call LinphoneCall whose info message belongs to. - * @param msg LinphoneInfoMessage object. - */ -typedef void (*LinphoneCallCbsInfoMessageReceivedCb)(LinphoneCall *call, const LinphoneInfoMessage *msg); - -/** - * Call state notification callback. - * @param call LinphoneCall whose state is changed. - * @param cstate The new state of the call - * @param message An informational message about the state. - */ -typedef void (*LinphoneCallCbsStateChangedCb)(LinphoneCall *call, LinphoneCallState cstate, const char *message); - -/** - * Callback for receiving quality statistics for calls. - * @param call LinphoneCall object whose statistics are notified - * @param stats LinphoneCallStats object - */ -typedef void (*LinphoneCallCbsStatsUpdatedCb)(LinphoneCall *call, const LinphoneCallStats *stats); - -/** - * Callback for notifying progresses of transfers. - * @param call LinphoneCall that was transfered - * @param cstate The state of the call to transfer target at the far end. - */ -typedef void (*LinphoneCallCbsTransferStateChangedCb)(LinphoneCall *call, LinphoneCallState cstate); - -/** - * Callback for notifying the processing SIP ACK messages. - * @param call LinphoneCall for which an ACK is being received or sent - * @param ack the ACK message - * @param is_received if TRUE this ACK is an incoming one, otherwise it is an ACK about to be sent. - */ -typedef void (*LinphoneCallCbsAckProcessingCb)(LinphoneCall *call, LinphoneHeaders *ack, bool_t is_received); - -/** - * Callback for notifying a received TMMBR. - * @param call LinphoneCall for which the TMMBR has changed - * @param stream_index the index of the current stream - * @param tmmbr the value of the received TMMBR - */ -typedef void (*LinphoneCallCbsTmmbrReceivedCb)(LinphoneCall *call, int stream_index, int tmmbr); - -/** - * Callback for notifying a snapshot taken. - * @param call LinphoneCall for which the snapshot was taken - * @param filepath the name of the saved file - */ -typedef void (*LinphoneCallCbsSnapshotTakenCb)(LinphoneCall *call, const char *filepath); - -/** - * Callback to notify a next video frame has been decoded - * @param call LinphoneCall for which the next video frame has been decoded - */ -typedef void (*LinphoneCallCbsNextVideoFrameDecodedCb)(LinphoneCall *call); - /** * @} **/ @@ -165,9 +40,9 @@ typedef void (*LinphoneCallCbsNextVideoFrameDecodedCb)(LinphoneCall *call); **/ /** - * Callback notifying that a new LinphoneCall (either incoming or outgoing) has been created. - * @param[in] lc LinphoneCore object that has created the call - * @param[in] call The newly created LinphoneCall object + * Callback notifying that a new #LinphoneCall (either incoming or outgoing) has been created. + * @param[in] lc #LinphoneCore object that has created the call + * @param[in] call The newly created #LinphoneCall object */ typedef void (*LinphoneCoreCbsCallCreatedCb)(LinphoneCore *lc, LinphoneCall *call); @@ -186,7 +61,7 @@ typedef LinphoneCoreCbsGlobalStateChangedCb LinphoneCoreGlobalStateChangedCb; /** * Call state notification callback. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param call the call object whose state is changed. * @param cstate the new state of the call * @param message a non NULL informational message about the state. @@ -200,7 +75,7 @@ typedef LinphoneCoreCbsCallStateChangedCb LinphoneCoreCallStateChangedCb; /** * Call encryption changed callback. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param call the call on which encryption is changed. * @param on whether encryption is activated. * @param authentication_token an authentication_token, currently set for ZRTP kind of encryption only. @@ -265,7 +140,7 @@ typedef LinphoneCoreCbsNewSubscriptionRequestedCb LinphoneCoreNewSubscriptionReq /** * Callback for requesting authentication information to application or user. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param realm the realm (domain) on which authentication is required. * @param username the username that needs to be authenticated. * @param domain the domain on which authentication is required. @@ -275,8 +150,8 @@ typedef void (*LinphoneCoreAuthInfoRequestedCb)(LinphoneCore *lc, const char *re /** * Callback for requesting authentication information to application or user. - * @param lc the LinphoneCore - * @param auth_info a LinphoneAuthInfo pre-filled with username, realm and domain values as much as possible + * @param lc the #LinphoneCore + * @param auth_info a #LinphoneAuthInfo pre-filled with username, realm and domain values as much as possible * @param method the type of authentication requested * Application shall reply to this callback using linphone_core_add_auth_info(). */ @@ -290,7 +165,7 @@ typedef LinphoneCoreCbsAuthenticationRequestedCb LinphoneCoreAuthenticationReque /** * Callback to notify a new call-log entry has been added. * This is done typically when a call terminates. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param newcl the new call log entry added. */ typedef void (*LinphoneCoreCbsCallLogUpdatedCb)(LinphoneCore *lc, LinphoneCallLog *newcl); @@ -315,7 +190,7 @@ typedef void (*LinphoneCoreTextMessageReceivedCb)(LinphoneCore *lc, LinphoneChat * Chat message callback prototype * @param lc #LinphoneCore object * @param room #LinphoneChatRoom involved in this conversation. Can be be created by the framework in case \link #LinphoneAddress the from \endlink is not present in any chat room. - * @param LinphoneChatMessage incoming message + * @param #LinphoneChatMessage incoming message */ typedef void (*LinphoneCoreCbsMessageReceivedCb)(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message); @@ -328,7 +203,7 @@ typedef LinphoneCoreCbsMessageReceivedCb LinphoneCoreMessageReceivedCb; * Chat message not decrypted callback prototype * @param lc #LinphoneCore object * @param room #LinphoneChatRoom involved in this conversation. Can be be created by the framework in case \link #LinphoneAddress the from \endlink is not present in any chat room. - * @param LinphoneChatMessage incoming message + * @param #LinphoneChatMessage incoming message */ typedef void (*LinphoneCoreCbsMessageReceivedUnableDecryptCb)(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage *message); @@ -406,7 +281,7 @@ typedef LinphoneCoreCbsBuddyInfoUpdatedCb LinphoneCoreBuddyInfoUpdatedCb; /** * Callback for notifying progresses of transfers. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param transfered the call that was transfered * @param new_call_state the state of the call to transfer target at the far end. */ @@ -419,7 +294,7 @@ typedef LinphoneCoreCbsTransferStateChangedCb LinphoneCoreTransferStateChangedCb /** * Callback for receiving quality statistics for calls. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param call the call * @param stats the call statistics. */ @@ -432,7 +307,7 @@ typedef LinphoneCoreCbsCallStatsUpdatedCb LinphoneCoreCallStatsUpdatedCb; /** * Callback prototype for receiving info messages. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param call the call whose info message belongs to. * @param msg the info message. */ @@ -445,7 +320,7 @@ typedef LinphoneCoreCbsInfoReceivedCb LinphoneCoreInfoReceivedCb; /** * Callback prototype for configuring status changes notification - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param message informational message. */ typedef void (*LinphoneCoreCbsConfiguringStatusCb)(LinphoneCore *lc, LinphoneConfiguringState status, const char *message); @@ -457,7 +332,7 @@ typedef LinphoneCoreCbsConfiguringStatusCb LinphoneCoreConfiguringStatusCb; /** * Callback prototype for reporting network change either automatically detected or notified by #linphone_core_set_network_reachable. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param reachable true if network is reachable. */ typedef void (*LinphoneCoreCbsNetworkReachableCb)(LinphoneCore *lc, bool_t reachable); @@ -469,7 +344,7 @@ typedef LinphoneCoreCbsNetworkReachableCb LinphoneCoreNetworkReachableCb; /** * Callback prototype for reporting log collection upload state change. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] state The state of the log collection upload * @param[in] info Additional information: error message in case of error state, URL of uploaded file in case of success. */ @@ -482,7 +357,7 @@ typedef LinphoneCoreCbsLogCollectionUploadStateChangedCb LinphoneCoreLogCollecti /** * Callback prototype for reporting log collection upload progress indication. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object */ typedef void (*LinphoneCoreCbsLogCollectionUploadProgressIndicationCb)(LinphoneCore *lc, size_t offset, size_t total); @@ -493,8 +368,8 @@ typedef LinphoneCoreCbsLogCollectionUploadProgressIndicationCb LinphoneCoreLogCo /** * Callback prototype for reporting when a friend list has been added to the core friends list. - * @param[in] lc LinphoneCore object - * @param[in] list LinphoneFriendList object + * @param[in] lc #LinphoneCore object + * @param[in] list #LinphoneFriendList object */ typedef void (*LinphoneCoreCbsFriendListCreatedCb) (LinphoneCore *lc, LinphoneFriendList *list); @@ -505,8 +380,8 @@ typedef LinphoneCoreCbsFriendListCreatedCb LinphoneCoreFriendListCreatedCb; /** * Callback prototype for reporting when a friend list has been removed from the core friends list. - * @param[in] lc LinphoneCore object - * @param[in] list LinphoneFriendList object + * @param[in] lc #LinphoneCore object + * @param[in] list #LinphoneFriendList object */ typedef void (*LinphoneCoreCbsFriendListRemovedCb) (LinphoneCore *lc, LinphoneFriendList *list); @@ -517,12 +392,26 @@ typedef LinphoneCoreCbsFriendListRemovedCb LinphoneCoreFriendListRemovedCb; /** * Callback prototype for reporting the result of a version update check. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] result The result of the version update check - * @param[in] url The url where to download the new version if the result is LinphoneVersionUpdateCheckNewVersionAvailable + * @param[in] url The url where to download the new version if the result is #LinphoneVersionUpdateCheckNewVersionAvailable */ typedef void (*LinphoneCoreCbsVersionUpdateCheckResultReceivedCb) (LinphoneCore *lc, LinphoneVersionUpdateCheckResult result, const char *version, const char *url); +/** + * Callback prototype telling that a #LinphoneChatRoom state has changed. + * @param[in] lc #LinphoneCore object + * @param[in] cr The #LinphoneChatRoom object for which the state has changed + */ +typedef void (*LinphoneCoreCbsChatRoomStateChangedCb) (LinphoneCore *lc, LinphoneChatRoom *cr, LinphoneChatRoomState state); + +/** + * Callback prototype telling the result of decoded qrcode + * @param[in] lc LinphoneCore object + * @param[in] result The result of the decoded qrcode + */ +typedef void (*LinphoneCoreCbsQrcodeFoundCb)(LinphoneCore *lc, const char *result); + /** * @} **/ @@ -542,6 +431,16 @@ typedef void (*LinphoneCoreCbsNotifyReceivedCb)(LinphoneCore *lc, LinphoneEvent */ typedef LinphoneCoreCbsNotifyReceivedCb LinphoneCoreNotifyReceivedCb; +/** + * Callback prototype for notifying the application about subscription received from the network. +**/ +typedef void (*LinphoneCoreCbsSubscribeReceivedCb)(LinphoneCore *lc, LinphoneEvent *lev, const char *subscribe_event, const LinphoneContent *body); + +/** + * Old name of #LinphoneCoreCbsSubscribeReceivedCb. + */ +typedef LinphoneCoreCbsSubscribeReceivedCb LinphoneCoreSubscribeReceivedCb; + /** * Callback prototype for notifying the application about changes of subscription states, including arrival of new subscriptions. **/ @@ -566,6 +465,21 @@ typedef LinphoneCoreCbsPublishStateChangedCb LinphoneCorePublishStateChangedCb; * @} **/ +/** + * @addtogroup event_api + * @{ + */ + +/** + * Callback used to notify the response to a sent NOTIFY + * @param ev The LinphoneEvent object that has sent the NOTIFY and for which we received a response +**/ +typedef void (*LinphoneEventCbsNotifyResponseCb)(const LinphoneEvent *ev); + +/** + * @} + */ + /** * @addtogroup buddy_list * @{ @@ -573,29 +487,29 @@ typedef LinphoneCoreCbsPublishStateChangedCb LinphoneCorePublishStateChangedCb; /** * Callback used to notify a new contact has been created on the CardDAV server and downloaded locally - * @param list The LinphoneFriendList object the new contact is added to - * @param lf The LinphoneFriend object that has been created + * @param list The #LinphoneFriendList object the new contact is added to + * @param lf The #LinphoneFriend object that has been created **/ typedef void (*LinphoneFriendListCbsContactCreatedCb)(LinphoneFriendList *list, LinphoneFriend *lf); /** * Callback used to notify a contact has been deleted on the CardDAV server - * @param list The LinphoneFriendList object a contact has been removed from - * @param lf The LinphoneFriend object that has been deleted + * @param list The #LinphoneFriendList object a contact has been removed from + * @param lf The #LinphoneFriend object that has been deleted **/ typedef void (*LinphoneFriendListCbsContactDeletedCb)(LinphoneFriendList *list, LinphoneFriend *lf); /** * Callback used to notify a contact has been updated on the CardDAV server - * @param list The LinphoneFriendList object in which a contact has been updated - * @param new_friend The new LinphoneFriend object corresponding to the updated contact - * @param old_friend The old LinphoneFriend object before update + * @param list The #LinphoneFriendList object in which a contact has been updated + * @param new_friend The new #LinphoneFriend object corresponding to the updated contact + * @param old_friend The old #LinphoneFriend object before update **/ typedef void (*LinphoneFriendListCbsContactUpdatedCb)(LinphoneFriendList *list, LinphoneFriend *new_friend, LinphoneFriend *old_friend); /** * Callback used to notify the status of the synchronization has changed - * @param list The LinphoneFriendList object for which the status has changed + * @param list The #LinphoneFriendList object for which the status has changed * @param status The new synchronisation status * @param msg An additional information on the status update **/ @@ -611,44 +525,64 @@ typedef void (*LinphoneFriendListCbsSyncStateChangedCb)(LinphoneFriendList *list */ /** - * Callback to decrypt incoming LinphoneChatMessage + * @brief Function prototype used by #linphone_core_cbs_set_ec_calibrator_result(). + * @param lc The core. + * @param status The state of the calibrator. + * @param delay_ms The measured delay if available. + */ +typedef void (*LinphoneCoreCbsEcCalibrationResultCb)(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms); + +/** + * @brief Function prototype used by #linphone_core_cbs_set_ec_calibrator_audio_init(). + * @param lc The core. + */ +typedef void (*LinphoneCoreCbsEcCalibrationAudioInitCb)(LinphoneCore *lc); + +/** + * @brief Function prototype used by #linphone_core_cbs_set_ec_calibrator_audio_uninit(). + * @param lc The core. + */ +typedef void (*LinphoneCoreCbsEcCalibrationAudioUninitCb)(LinphoneCore *lc); + +/** + * Callback to decrypt incoming #LinphoneChatMessage * @param engine ImEncryptionEngine object - * @param room LinphoneChatRoom object - * @param msg LinphoneChatMessage object + * @param room #LinphoneChatRoom object + * @param msg #LinphoneChatMessage object * @return -1 if nothing to be done, 0 on success or an integer > 0 for error */ typedef int (*LinphoneImEncryptionEngineCbsIncomingMessageCb)(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg); /** - * Callback to encrypt outgoing LinphoneChatMessage - * @param engine LinphoneImEncryptionEngine object - * @param room LinphoneChatRoom object - * @param msg LinphoneChatMessage object + * Callback to encrypt outgoing #LinphoneChatMessage + * @param engine #LinphoneImEncryptionEngine object + * @param room #LinphoneChatRoom object + * @param msg #LinphoneChatMessage object * @return -1 if nothing to be done, 0 on success or an integer > 0 for error */ typedef int (*LinphoneImEncryptionEngineCbsOutgoingMessageCb)(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg); /** * Callback to know whether or not the engine will encrypt files before uploading them - * @param engine LinphoneImEncryptionEngine object - * @param room LinphoneChatRoom object + * @param engine #LinphoneImEncryptionEngine object + * @param room #LinphoneChatRoom object * @return TRUE if files will be encrypted, FALSE otherwise */ typedef bool_t (*LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb)(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room); /** * Callback to generate the key used to encrypt the files before uploading them - * Key can be stored in the LinphoneContent object inside the LinphoneChatMessage using linphone_content_set_key - * @param engine LinphoneImEncryptionEngine object - * @param room LinphoneChatRoom object - * @param msg LinphoneChatMessage object + * Key can be stored in the #LinphoneContent object inside the #LinphoneChatMessage using linphone_content_set_key + * @param engine #LinphoneImEncryptionEngine object + * @param room #LinphoneChatRoom object + * @param msg #LinphoneChatMessage object */ typedef void (*LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb)(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg); /** * Callback to decrypt downloading file - * @param engine LinphoneImEncryptionEngine object - * @param msg LinphoneChatMessage object + * @param engine #LinphoneImEncryptionEngine object + * @param msg #LinphoneChatMessage object * @param offset The current offset of the upload * @param[in] buffer Encrypted data buffer * @param[in] size Size of the encrypted data buffer and maximum size of the decrypted data buffer @@ -659,8 +593,8 @@ typedef int (*LinphoneImEncryptionEngineCbsDownloadingFileCb)(LinphoneImEncrypti /** * Callback to encrypt uploading file - * @param engine LinphoneImEncryptionEngine object - * @param msg LinphoneChatMessage object + * @param engine #LinphoneImEncryptionEngine object + * @param msg #LinphoneChatMessage object * @param offset The current offset of the upload * @param[in] buffer Encrypted data buffer * @param[in,out] size Size of the plain data buffer and the size of the encrypted data buffer once encryption is done @@ -671,7 +605,7 @@ typedef int (*LinphoneImEncryptionEngineCbsUploadingFileCb)(LinphoneImEncryption /** * Callback used to notify the response to an XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object + * @param[in] request #LinphoneXmlRpcRequest object **/ typedef void (*LinphoneXmlRpcRequestCbsResponseCb)(LinphoneXmlRpcRequest *request); @@ -686,7 +620,7 @@ typedef void (*LinphoneXmlRpcRequestCbsResponseCb)(LinphoneXmlRpcRequest *reques /** * Callback for notifying end of play (file). - * @param[in] player The LinphonePlayer object + * @param[in] player The #LinphonePlayer object **/ typedef void (*LinphonePlayerCbsEofReachedCb)(LinphonePlayer *obj); diff --git a/include/linphone/chat.h b/include/linphone/chat.h index b1fc17103..1aec54c01 100644 --- a/include/linphone/chat.h +++ b/include/linphone/chat.h @@ -21,7 +21,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define LINPHONE_CHAT_H_ +#include "linphone/callbacks.h" #include "linphone/types.h" +#include "linphone/api/c-types.h" +#include "linphone/api/c-chat-message.h" +#include "linphone/api/c-chat-message-cbs.h" +#include "linphone/api/c-chat-room.h" +#include "linphone/api/c-chat-room-cbs.h" #ifdef __cplusplus @@ -33,209 +39,6 @@ extern "C" { * @{ */ -/** - * Destroy a LinphoneChatRoom. - * @param cr #LinphoneChatRoom object - * @deprecated Use linphone_chat_room_unref() instead. - * @donotwrap - */ -LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_room_destroy(LinphoneChatRoom *cr); -/** - * Create a message attached to a dedicated chat room; - * @param cr the chat room. - * @param message text message, NULL if absent. - * @return a new #LinphoneChatMessage - */ -LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message(LinphoneChatRoom *cr,const char* message); -/** - * Create a message attached to a dedicated chat room; - * @param cr the chat room. - * @param message text message, NULL if absent. - * @param external_body_url the URL given in external body or NULL. - * @param state the LinphoneChatMessage.State of the message. - * @param time the time_t at which the message has been received/sent. - * @param is_read TRUE if the message should be flagged as read, FALSE otherwise. - * @param is_incoming TRUE if the message has been received, FALSE otherwise. - * @return a new #LinphoneChatMessage - */ -LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_message_2(LinphoneChatRoom *cr, const char* message, const char* external_body_url, LinphoneChatMessageState state, time_t time, bool_t is_read, bool_t is_incoming); -/** - * Create a message attached to a dedicated chat room without converting the message to UTF-8; - * @param cr the chat room. - * @param message text message, NULL if absent. - * @return a new #LinphoneChatMessage - */ -LINPHONE_PUBLIC LinphoneChatMessage *linphone_chat_room_create_message_without_conversion(LinphoneChatRoom *cr, const char *message); - -/** - * Acquire a reference to the chat room. - * @param[in] cr The chat room. - * @return The same chat room. -**/ -LINPHONE_PUBLIC LinphoneChatRoom *linphone_chat_room_ref(LinphoneChatRoom *cr); - -/** - * Release reference to the chat room. - * @param[in] cr The chat room. -**/ -LINPHONE_PUBLIC void linphone_chat_room_unref(LinphoneChatRoom *cr); - -/** - * Retrieve the user pointer associated with the chat room. - * @param[in] cr The chat room. - * @return The user pointer associated with the chat room. -**/ -LINPHONE_PUBLIC void *linphone_chat_room_get_user_data(const LinphoneChatRoom *cr); - -/** - * Assign a user pointer to the chat room. - * @param[in] cr The chat room. - * @param[in] ud The user pointer to associate with the chat room. -**/ -LINPHONE_PUBLIC void linphone_chat_room_set_user_data(LinphoneChatRoom *cr, void *ud); - - /** - * Create a message attached to a dedicated chat room with a particular content. - * Use #linphone_chat_room_send_message to initiate the transfer - * @param cr the chat room. - * @param initial_content #LinphoneContent initial content. #LinphoneCoreVTable.file_transfer_send is invoked later to notify file transfer progress and collect next chunk of the message if LinphoneContent.data is NULL. - * @return a new #LinphoneChatMessage - */ -LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, const LinphoneContent* initial_content); - -/** - * get peer address \link linphone_core_get_chat_room() associated to \endlink this #LinphoneChatRoom - * @param cr #LinphoneChatRoom object - * @return #LinphoneAddress peer address - */ -LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_room_get_peer_address(LinphoneChatRoom *cr); - -/** - * Send a message to peer member of this chat room. - * @deprecated Use linphone_chat_room_send_chat_message() instead. - * @param cr #LinphoneChatRoom object - * @param msg message to be sent - * @donotwrap - */ -LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_room_send_message(LinphoneChatRoom *cr, const char *msg); - -/** - * Send a message to peer member of this chat room. - * @param cr #LinphoneChatRoom object - * @param msg #LinphoneChatMessage message to be sent - * @param status_cb LinphoneChatMessageStateChangeCb status callback invoked when message is delivered or could not be delivered. May be NULL - * @param ud user data for the status cb. - * @deprecated Use linphone_chat_room_send_chat_message() instead. - * @note The LinphoneChatMessage must not be destroyed until the the callback is called. - * The LinphoneChatMessage reference is transfered to the function and thus doesn't need to be unref'd by the application. - * @donotwrap - */ -LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_room_send_message2(LinphoneChatRoom *cr, LinphoneChatMessage* msg,LinphoneChatMessageStateChangedCb status_cb,void* ud); - -/** - * Send a message to peer member of this chat room. - * @param[in] cr LinphoneChatRoom object - * @param[in] msg LinphoneChatMessage object - * The state of the message sending will be notified via the callbacks defined in the LinphoneChatMessageCbs object that can be obtained - * by calling linphone_chat_message_get_callbacks(). - * The LinphoneChatMessage reference is transfered to the function and thus doesn't need to be unref'd by the application. - * @donotwrap - */ -LINPHONE_PUBLIC void linphone_chat_room_send_chat_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); - -/** - * Mark all messages of the conversation as read - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. - */ -LINPHONE_PUBLIC void linphone_chat_room_mark_as_read(LinphoneChatRoom *cr); - -/** - * Delete a message from the chat room history. - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. - * @param[in] msg The #LinphoneChatMessage object to remove. - */ - -LINPHONE_PUBLIC void linphone_chat_room_delete_message(LinphoneChatRoom *cr, LinphoneChatMessage *msg); - -/** - * Delete all messages from the history - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. - */ -LINPHONE_PUBLIC void linphone_chat_room_delete_history(LinphoneChatRoom *cr); - -/** - * Gets the number of messages in a chat room. - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which size has to be computed - * @return the number of messages. - */ -LINPHONE_PUBLIC int linphone_chat_room_get_history_size(LinphoneChatRoom *cr); - -/** - * Gets nb_message most recent messages from cr chat room, sorted from oldest to most recent. - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which messages should be retrieved - * @param[in] nb_message Number of message to retrieve. 0 means everything. - * @return \bctbx_list{LinphoneChatMessage} - */ -LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history(LinphoneChatRoom *cr,int nb_message); - -/** - * Gets the partial list of messages in the given range, sorted from oldest to most recent. - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which messages should be retrieved - * @param[in] begin The first message of the range to be retrieved. History most recent message has index 0. - * @param[in] end The last message of the range to be retrieved. History oldest message has index of history size - 1 (use #linphone_chat_room_get_history_size to retrieve history size) - * @return \bctbx_list{LinphoneChatMessage} - */ -LINPHONE_PUBLIC bctbx_list_t *linphone_chat_room_get_history_range(LinphoneChatRoom *cr, int begin, int end); - -LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_room_find_message(LinphoneChatRoom *cr, const char *message_id); - -/** - * Notifies the destination of the chat message being composed that the user is typing a new message. - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation for which a new message is being typed. - */ -LINPHONE_PUBLIC void linphone_chat_room_compose(LinphoneChatRoom *cr); - -/** - * Tells whether the remote is currently composing a message. - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. - * @return TRUE if the remote is currently composing a message, FALSE otherwise. - */ -LINPHONE_PUBLIC bool_t linphone_chat_room_is_remote_composing(const LinphoneChatRoom *cr); - -/** - * Gets the number of unread messages in the chatroom. - * @param[in] cr The #LinphoneChatRoom object corresponding to the conversation. - * @return the number of unread messages. - */ -LINPHONE_PUBLIC int linphone_chat_room_get_unread_messages_count(LinphoneChatRoom *cr); - -/** - * Returns back pointer to #LinphoneCore object. - * @deprecated use linphone_chat_room_get_core() - * @donotwrap -**/ -LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneCore* linphone_chat_room_get_lc(LinphoneChatRoom *cr); - -/** - * Returns back pointer to #LinphoneCore object. -**/ -LINPHONE_PUBLIC LinphoneCore* linphone_chat_room_get_core(LinphoneChatRoom *cr); - -/** - * When realtime text is enabled #linphone_call_params_realtime_text_enabled, #LinphoneCoreIsComposingReceivedCb is call everytime a char is received from peer. - * At the end of remote typing a regular #LinphoneChatMessage is received with committed data from #LinphoneCoreMessageReceivedCb. - * @param[in] cr #LinphoneChatRoom object - * @returns RFC 4103/T.140 char - */ -LINPHONE_PUBLIC uint32_t linphone_chat_room_get_char(const LinphoneChatRoom *cr); - -/** - * Returns true if lime is available for given peer - * - * @return true if zrtp secrets have already been shared and ready to use - */ -LINPHONE_PUBLIC bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr); - /** * Returns an list of chat rooms * @param[in] lc #LinphoneCore object @@ -243,414 +46,7 @@ LINPHONE_PUBLIC bool_t linphone_chat_room_lime_available(LinphoneChatRoom *cr); **/ LINPHONE_PUBLIC const bctbx_list_t* linphone_core_get_chat_rooms(LinphoneCore *lc); -LINPHONE_PUBLIC unsigned int linphone_chat_message_store(LinphoneChatMessage *msg); -/** - * Get the state of the message - *@param message #LinphoneChatMessage obj - *@return #LinphoneChatMessageState - */ -LINPHONE_PUBLIC LinphoneChatMessageState linphone_chat_message_get_state(const LinphoneChatMessage* message); - -/** - * Duplicate a LinphoneChatMessage -**/ -LINPHONE_PUBLIC LinphoneChatMessage* linphone_chat_message_clone(const LinphoneChatMessage* message); - -/** - * Acquire a reference to the chat message. - * @param msg the chat message - * @return the same chat message -**/ -LINPHONE_PUBLIC LinphoneChatMessage * linphone_chat_message_ref(LinphoneChatMessage *msg); - -/** - * Release reference to the chat message. - * @param msg the chat message. -**/ -LINPHONE_PUBLIC void linphone_chat_message_unref(LinphoneChatMessage *msg); - -/** - * Destroys a LinphoneChatMessage. -**/ -LINPHONE_PUBLIC void linphone_chat_message_destroy(LinphoneChatMessage* msg); - -/** @deprecated Use linphone_chat_message_set_from_address() instead. */ -#define linphone_chat_message_set_from(msg, addr) linphone_chat_message_set_from_address(msg, addr) - -/** - * Set origin of the message - * @param[in] message #LinphoneChatMessage obj - * @param[in] from #LinphoneAddress origin of this message (copied) - */ -LINPHONE_PUBLIC void linphone_chat_message_set_from_address(LinphoneChatMessage* message, const LinphoneAddress* from); - -/** @deprecated Use linphone_chat_message_get_from_address() instead. */ -#define linphone_chat_message_get_from(msg) linphone_chat_message_get_from_address(msg) - -/** - * Get origin of the message - * @param[in] message #LinphoneChatMessage obj - * @return #LinphoneAddress - */ -LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_from_address(const LinphoneChatMessage* message); - -#define linphone_chat_message_set_to(msg, addr) linphone_chat_message_set_to_address(msg, addr) - -/** - * Set destination of the message - * @param[in] message #LinphoneChatMessage obj - * @param[in] addr #LinphoneAddress destination of this message (copied) - */ -LINPHONE_PUBLIC void linphone_chat_message_set_to_address(LinphoneChatMessage* message, const LinphoneAddress* addr); - -/** @deprecated Use linphone_chat_message_get_to_address() instead. */ -#define linphone_chat_message_get_to(msg) linphone_chat_message_get_to_address(msg) - -/** - * Get destination of the message - * @param[in] message #LinphoneChatMessage obj - * @return #LinphoneAddress - */ -LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_to_address(const LinphoneChatMessage* message); - -/** - * Get if the message was encrypted when transfered - * @param[in] message #LinphoneChatMessage obj - * @return whether the message was encrypted when transfered or not - */ -LINPHONE_PUBLIC bool_t linphone_chat_message_is_secured(LinphoneChatMessage *msg); - -/** - * Linphone message can carry external body as defined by rfc2017 - * @param message #LinphoneChatMessage - * @return external body url or NULL if not present. - */ -LINPHONE_PUBLIC const char* linphone_chat_message_get_external_body_url(const LinphoneChatMessage* message); - -/** - * Linphone message can carry external body as defined by rfc2017 - * - * @param message a LinphoneChatMessage - * @param url ex: access-type=URL; URL="http://www.foo.com/file" - */ -LINPHONE_PUBLIC void linphone_chat_message_set_external_body_url(LinphoneChatMessage* message,const char* url); - -/** - * Get the file_transfer_information (used by call backs to recover informations during a rcs file transfer) - * - * @param message #LinphoneChatMessage - * @return a pointer to the LinphoneContent structure or NULL if not present. - */ -LINPHONE_PUBLIC const LinphoneContent* linphone_chat_message_get_file_transfer_information(const LinphoneChatMessage* message); - -/** - * Get the content type of a chat message. - * @param[in] message LinphoneChatMessage object - * @return The content type of the chat message - */ -LINPHONE_PUBLIC const char * linphone_chat_message_get_content_type(const LinphoneChatMessage *message); - -/** - * Set the content type of a chat message. - * This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml. - * @param[in] message LinphoneChatMessage object - * @param[in] content_type The new content type of the chat message - */ -LINPHONE_PUBLIC void linphone_chat_message_set_content_type(LinphoneChatMessage *message, const char *content_type); - -/** - * Return whether or not a chat message is a file tranfer. - * @param[in] message LinphoneChatMessage object - * @return Whether or not the message is a file tranfer - */ -LINPHONE_PUBLIC bool_t linphone_chat_message_is_file_transfer(const LinphoneChatMessage *message); - -/** - * Return whether or not a chat message is a text. - * @param[in] message LinphoneChatMessage object - * @return Whether or not the message is a text - */ -LINPHONE_PUBLIC bool_t linphone_chat_message_is_text(const LinphoneChatMessage *message); - -/** - * Get if a chat message is to be stored. - * @param[in] message LinphoneChatMessage object - * @return Whether or not the message is to be stored - */ -LINPHONE_PUBLIC bool_t linphone_chat_message_get_to_be_stored(const LinphoneChatMessage *message); - -/** - * Set if a chat message is to be stored. - * This content type must match a content that is text representable, such as text/plain, text/html or image/svg+xml. - * @param[in] message LinphoneChatMessage object - * @param[in] to_be_stored Whether or not the chat message is to be stored - */ -LINPHONE_PUBLIC void linphone_chat_message_set_to_be_stored(LinphoneChatMessage *message, bool_t to_be_stored); - -/** - * 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 - * @param ud user data - * @deprecated Use linphone_chat_message_download_file() instead. - * @donotwrap - */ -LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_chat_message_start_file_download(LinphoneChatMessage* message, LinphoneChatMessageStateChangedCb status_cb, void* ud); - -/** - * Start the download of the file referenced in a LinphoneChatMessage from remote server. - * @param[in] message LinphoneChatMessage object. - */ -LINPHONE_PUBLIC LinphoneStatus linphone_chat_message_download_file(LinphoneChatMessage *message); - -/** - * Cancel an ongoing file transfer attached to this message.(upload or download) - * @param msg #LinphoneChatMessage - */ -LINPHONE_PUBLIC void linphone_chat_message_cancel_file_transfer(LinphoneChatMessage* msg); - -/** - * Resend a chat message if it is in the 'not delivered' state for whatever reason. - * @param[in] msg LinphoneChatMessage object - * @donotwrap - */ -LINPHONE_PUBLIC void linphone_chat_message_resend(LinphoneChatMessage *msg); - -/** - * Linphone message has an app-specific field that can store a text. The application might want - * to use it for keeping data over restarts, like thumbnail image path. - * @param message #LinphoneChatMessage - * @return the application-specific data or NULL if none has been stored. - */ -LINPHONE_PUBLIC const char* linphone_chat_message_get_appdata(const LinphoneChatMessage* message); - -/** - * Linphone message has an app-specific field that can store a text. The application might want - * to use it for keeping data over restarts, like thumbnail image path. - * - * Invoking this function will attempt to update the message storage to reflect the changeif it is - * enabled. - * - * @param message #LinphoneChatMessage - * @param data the data to store into the message - */ -LINPHONE_PUBLIC void linphone_chat_message_set_appdata(LinphoneChatMessage* message, const char* data); - -/** - * Get text part of this message - * @return text or NULL if no text. - */ -LINPHONE_PUBLIC const char* linphone_chat_message_get_text(LinphoneChatMessage* message); - -/** - * Get the time the message was sent. - */ -LINPHONE_PUBLIC time_t linphone_chat_message_get_time(const LinphoneChatMessage* message); - -/** - * User pointer get function - */ -LINPHONE_PUBLIC void* linphone_chat_message_get_user_data(const LinphoneChatMessage* message); - -/** - *User pointer set function - */ -LINPHONE_PUBLIC void linphone_chat_message_set_user_data(LinphoneChatMessage* message,void*); - -/** - * Returns the chatroom this message belongs to. -**/ -LINPHONE_PUBLIC LinphoneChatRoom* linphone_chat_message_get_chat_room(LinphoneChatMessage *msg); - -LINPHONE_PUBLIC const LinphoneAddress* linphone_chat_message_get_peer_address(LinphoneChatMessage *msg); - -/** - * Returns the origin address of a message if it was a outgoing message, or the destination address if it was an incoming message. - *@param message #LinphoneChatMessage obj - *@return #LinphoneAddress - */ -LINPHONE_PUBLIC LinphoneAddress *linphone_chat_message_get_local_address(const LinphoneChatMessage* message); - -/** - * Add custom headers to the message. - * @param message the message - * @param header_name name of the header - * @param header_value header value -**/ -LINPHONE_PUBLIC void linphone_chat_message_add_custom_header(LinphoneChatMessage* message, const char *header_name, const char *header_value); - -/** - * Retrieve a custom header value given its name. - * @param message the message - * @param header_name header name searched -**/ -LINPHONE_PUBLIC const char * linphone_chat_message_get_custom_header(LinphoneChatMessage* message, const char *header_name); - -/** - * Removes a custom header from the message. - * @param msg the message - * @param header_name name of the header to remove -**/ -LINPHONE_PUBLIC void linphone_chat_message_remove_custom_header(LinphoneChatMessage *msg, const char *header_name); - -/** - * Returns TRUE if the message has been read, otherwise returns FALSE. - * @param message the message -**/ -LINPHONE_PUBLIC bool_t linphone_chat_message_is_read(LinphoneChatMessage* message); - -/** - * Returns TRUE if the message has been sent, returns FALSE if the message has been received. - * @param message the message -**/ -LINPHONE_PUBLIC bool_t linphone_chat_message_is_outgoing(LinphoneChatMessage* message); - -/** - * Returns the id used to identify this message in the storage database - * @param message the message - * @return the id - */ -LINPHONE_PUBLIC unsigned int linphone_chat_message_get_storage_id(LinphoneChatMessage* message); - -LINPHONE_PUBLIC LinphoneReason linphone_chat_message_get_reason(LinphoneChatMessage* msg); - -/** - * Get full details about delivery error of a chat message. - * @param msg a LinphoneChatMessage - * @return a LinphoneErrorInfo describing the details. -**/ -LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_chat_message_get_error_info(const LinphoneChatMessage *msg); - -/** - * Set the path to the file to read from or write to during the file transfer. - * @param[in] msg LinphoneChatMessage object - * @param[in] filepath The path to the file to use for the file transfer. - */ -LINPHONE_PUBLIC void linphone_chat_message_set_file_transfer_filepath(LinphoneChatMessage *msg, const char *filepath); - -/** - * Get the path to the file to read from or write to during the file transfer. - * @param[in] msg LinphoneChatMessage object - * @return The path to the file to use for the file transfer. - */ -LINPHONE_PUBLIC const char * linphone_chat_message_get_file_transfer_filepath(LinphoneChatMessage *msg); - -/** - * Fulfill a chat message char by char. Message linked to a Real Time Text Call send char in realtime following RFC 4103/T.140 - * To commit a message, use #linphone_chat_room_send_message - * @param[in] msg LinphoneChatMessage - * @param[in] character T.140 char - * @returns 0 if succeed. - */ -LINPHONE_PUBLIC LinphoneStatus linphone_chat_message_put_char(LinphoneChatMessage *msg,uint32_t character); - -/** - * Get the message identifier. - * It is used to identify a message so that it can be notified as delivered and/or displayed. - * @param[in] cm LinphoneChatMessage object - * @return The message identifier. - */ -LINPHONE_PUBLIC const char* linphone_chat_message_get_message_id(const LinphoneChatMessage *cm); - -/** - * get Curent Call associated to this chatroom if any - * To commit a message, use #linphone_chat_room_send_message - * @param[in] room LinphoneChatRomm - * @returns LinphoneCall or NULL. - */ -LINPHONE_PUBLIC LinphoneCall *linphone_chat_room_get_call(const LinphoneChatRoom *room); - -/** - * Get the LinphoneChatMessageCbs object associated with the LinphoneChatMessage. - * @param[in] msg LinphoneChatMessage object - * @return The LinphoneChatMessageCbs object associated with the LinphoneChatMessage. - */ -LINPHONE_PUBLIC LinphoneChatMessageCbs * linphone_chat_message_get_callbacks(const LinphoneChatMessage *msg); - -/** - * Acquire a reference to the LinphoneChatMessageCbs object. - * @param[in] cbs LinphoneChatMessageCbs object. - * @return The same LinphoneChatMessageCbs object. - */ -LINPHONE_PUBLIC LinphoneChatMessageCbs * linphone_chat_message_cbs_ref(LinphoneChatMessageCbs *cbs); - -/** - * Release reference to the LinphoneChatMessageCbs object. - * @param[in] cbs LinphoneChatMessageCbs object. - */ -LINPHONE_PUBLIC void linphone_chat_message_cbs_unref(LinphoneChatMessageCbs *cbs); - -/** - * Retrieve the user pointer associated with the LinphoneChatMessageCbs object. - * @param[in] cbs LinphoneChatMessageCbs object. - * @return The user pointer associated with the LinphoneChatMessageCbs object. - */ -LINPHONE_PUBLIC void *linphone_chat_message_cbs_get_user_data(const LinphoneChatMessageCbs *cbs); - -/** - * Assign a user pointer to the LinphoneChatMessageCbs object. - * @param[in] cbs LinphoneChatMessageCbs object. - * @param[in] ud The user pointer to associate with the LinphoneChatMessageCbs object. - */ -LINPHONE_PUBLIC void linphone_chat_message_cbs_set_user_data(LinphoneChatMessageCbs *cbs, void *ud); - -/** - * Get the message state changed callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @return The current message state changed callback. - */ -LINPHONE_PUBLIC LinphoneChatMessageCbsMsgStateChangedCb linphone_chat_message_cbs_get_msg_state_changed(const LinphoneChatMessageCbs *cbs); - -/** - * Set the message state changed callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @param[in] cb The message state changed callback to be used. - */ -LINPHONE_PUBLIC void linphone_chat_message_cbs_set_msg_state_changed(LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsMsgStateChangedCb cb); - -/** - * Get the file transfer receive callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @return The current file transfer receive callback. - */ -LINPHONE_PUBLIC LinphoneChatMessageCbsFileTransferRecvCb linphone_chat_message_cbs_get_file_transfer_recv(const LinphoneChatMessageCbs *cbs); - -/** - * Set the file transfer receive callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @param[in] cb The file transfer receive callback to be used. - */ -LINPHONE_PUBLIC void linphone_chat_message_cbs_set_file_transfer_recv(LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsFileTransferRecvCb cb); - -/** - * Get the file transfer send callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @return The current file transfer send callback. - */ -LINPHONE_PUBLIC LinphoneChatMessageCbsFileTransferSendCb linphone_chat_message_cbs_get_file_transfer_send(const LinphoneChatMessageCbs *cbs); - -/** - * Set the file transfer send callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @param[in] cb The file transfer send callback to be used. - */ -LINPHONE_PUBLIC void linphone_chat_message_cbs_set_file_transfer_send(LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsFileTransferSendCb cb); - -/** - * Get the file transfer progress indication callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @return The current file transfer progress indication callback. - */ -LINPHONE_PUBLIC LinphoneChatMessageCbsFileTransferProgressIndicationCb linphone_chat_message_cbs_get_file_transfer_progress_indication(const LinphoneChatMessageCbs *cbs); - -/** - * Set the file transfer progress indication callback. - * @param[in] cbs LinphoneChatMessageCbs object. - * @param[in] cb The file transfer progress indication callback to be used. - */ -LINPHONE_PUBLIC void linphone_chat_message_cbs_set_file_transfer_progress_indication(LinphoneChatMessageCbs *cbs, LinphoneChatMessageCbsFileTransferProgressIndicationCb cb); /** * @} diff --git a/include/linphone/conference.h b/include/linphone/conference.h index ea12eac85..d61425437 100644 --- a/include/linphone/conference.h +++ b/include/linphone/conference.h @@ -118,7 +118,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_conference_remove_participant(LinphoneCo LINPHONE_PUBLIC bctbx_list_t *linphone_conference_get_participants(const LinphoneConference *obj); /** - * Invite participants to the conference, by supplying a list of LinphoneAddress + * Invite participants to the conference, by supplying a list of #LinphoneAddress * @param obj The conference. * @param addresses \bctbx_list{LinphoneAddress} * @param params #LinphoneCallParams to use for inviting the participants. diff --git a/include/linphone/content.h b/include/linphone/content.h deleted file mode 100644 index 653d4344a..000000000 --- a/include/linphone/content.h +++ /dev/null @@ -1,226 +0,0 @@ -/* -content.h -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - -#ifndef LINPHONE_CONTENT_H_ -#define LINPHONE_CONTENT_H_ - - -#include "linphone/types.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @addtogroup misc - * @{ - */ - -/** - * Acquire a reference to the content. - * @param[in] content LinphoneContent object. - * @return The same LinphoneContent object. -**/ -LINPHONE_PUBLIC LinphoneContent * linphone_content_ref(LinphoneContent *content); - -/** - * Release reference to the content. - * @param[in] content LinphoneContent object. -**/ -LINPHONE_PUBLIC void linphone_content_unref(LinphoneContent *content); - -/** - * Retrieve the user pointer associated with the content. - * @param[in] content LinphoneContent object. - * @return The user pointer associated with the content. -**/ -LINPHONE_PUBLIC void *linphone_content_get_user_data(const LinphoneContent *content); - -/** - * Assign a user pointer to the content. - * @param[in] content LinphoneContent object. - * @param[in] ud The user pointer to associate with the content. -**/ -LINPHONE_PUBLIC void linphone_content_set_user_data(LinphoneContent *content, void *ud); - -/** - * Get the mime type of the content data. - * @param[in] content LinphoneContent object. - * @return The mime type of the content data, for example "application". - */ -LINPHONE_PUBLIC const char * linphone_content_get_type(const LinphoneContent *content); - -/** - * Set the mime type of the content data. - * @param[in] content LinphoneContent object. - * @param[in] type The mime type of the content data, for example "application". - */ -LINPHONE_PUBLIC void linphone_content_set_type(LinphoneContent *content, const char *type); - -/** - * Get the mime subtype of the content data. - * @param[in] content LinphoneContent object. - * @return The mime subtype of the content data, for example "html". - */ -LINPHONE_PUBLIC const char * linphone_content_get_subtype(const LinphoneContent *content); - -/** - * Set the mime subtype of the content data. - * @param[in] content LinphoneContent object. - * @param[in] subtype The mime subtype of the content data, for example "html". - */ -LINPHONE_PUBLIC void linphone_content_set_subtype(LinphoneContent *content, const char *subtype); - -/** - * Get the content data buffer, usually a string. - * @param[in] content LinphoneContent object. - * @return The content data buffer. - */ -LINPHONE_PUBLIC void * linphone_content_get_buffer(const LinphoneContent *content); - -/** - * Set the content data buffer, usually a string. - * @param[in] content LinphoneContent object. - * @param[in] buffer The content data buffer. - * @param[in] size The size of the content data buffer. - */ -LINPHONE_PUBLIC void linphone_content_set_buffer(LinphoneContent *content, const void *buffer, size_t size); - -/** - * Get the string content data buffer. - * @param[in] content LinphoneContent object - * @return The string content data buffer. - */ -LINPHONE_PUBLIC const char * linphone_content_get_string_buffer(const LinphoneContent *content); - -/** - * Set the string content data buffer. - * @param[in] content LinphoneContent object. - * @param[in] buffer The string content data buffer. - */ -LINPHONE_PUBLIC void linphone_content_set_string_buffer(LinphoneContent *content, const char *buffer); - -/** - * Get the content data buffer size, excluding null character despite null character is always set for convenience. - * @param[in] content LinphoneContent object. - * @return The content data buffer size. - */ -LINPHONE_PUBLIC size_t linphone_content_get_size(const LinphoneContent *content); - -/** - * Set the content data size, excluding null character despite null character is always set for convenience. - * @param[in] content LinphoneContent object - * @param[in] size The content data buffer size. - */ -LINPHONE_PUBLIC void linphone_content_set_size(LinphoneContent *content, size_t size); - -/** - * Get the encoding of the data buffer, for example "gzip". - * @param[in] content LinphoneContent object. - * @return The encoding of the data buffer. - */ -LINPHONE_PUBLIC const char * linphone_content_get_encoding(const LinphoneContent *content); - -/** - * Set the encoding of the data buffer, for example "gzip". - * @param[in] content LinphoneContent object. - * @param[in] encoding The encoding of the data buffer. - */ -LINPHONE_PUBLIC void linphone_content_set_encoding(LinphoneContent *content, const char *encoding); - -/** - * Get the name associated with a RCS file transfer message. It is used to store the original filename of the file to be downloaded from server. - * @param[in] content LinphoneContent object. - * @return The name of the content. - */ -LINPHONE_PUBLIC const char * linphone_content_get_name(const LinphoneContent *content); - -/** - * Set the name associated with a RCS file transfer message. It is used to store the original filename of the file to be downloaded from server. - * @param[in] content LinphoneContent object. - * @param[in] name The name of the content. - */ -LINPHONE_PUBLIC void linphone_content_set_name(LinphoneContent *content, const char *name); - -/** - * Tell whether a content is a multipart content. - * @param[in] content LinphoneContent object. - * @return A boolean value telling whether the content is multipart or not. - */ -LINPHONE_PUBLIC bool_t linphone_content_is_multipart(const LinphoneContent *content); - -/** - * Get a part from a multipart content according to its index. - * @param[in] content LinphoneContent object. - * @param[in] idx The index of the part to get. - * @return A LinphoneContent object holding the part if found, NULL otherwise. - */ -LINPHONE_PUBLIC LinphoneContent * linphone_content_get_part(const LinphoneContent *content, int idx); - -/** - * Find a part from a multipart content looking for a part header with a specified value. - * @param[in] content LinphoneContent object. - * @param[in] header_name The name of the header to look for. - * @param[in] header_value The value of the header to look for. - * @return A LinphoneContent object object the part if found, NULL otherwise. - */ -LINPHONE_PUBLIC LinphoneContent * linphone_content_find_part_by_header(const LinphoneContent *content, const char *header_name, const char *header_value); - -/** - * Get a custom header value of a content. - * @param[in] content LinphoneContent object. - * @param[in] header_name The name of the header to get the value from. - * @return The value of the header if found, NULL otherwise. - */ -LINPHONE_PUBLIC const char * linphone_content_get_custom_header(const LinphoneContent *content, const char *header_name); - -/** - * Get the key associated with a RCS file transfer message if encrypted - * @param[in] content LinphoneContent object. - * @return The key to encrypt/decrypt the file associated to this content. - */ -LINPHONE_PUBLIC const char *linphone_content_get_key(const LinphoneContent *content); - -/** - * Get the size of key associated with a RCS file transfer message if encrypted - * @param[in] content LinphoneContent object. - * @return The key size in bytes - */ -LINPHONE_PUBLIC size_t linphone_content_get_key_size(const LinphoneContent *content); - -/** - * Set the key associated with a RCS file transfer message if encrypted - * @param[in] content LinphoneContent object. - * @param[in] key The key to be used to encrypt/decrypt file associated to this content. - * @param[in] keyLength The lengh of the key. - */ -LINPHONE_PUBLIC void linphone_content_set_key(LinphoneContent *content, const char *key, const size_t keyLength); - -/** - * @} - */ - - -#ifdef __cplusplus -} -#endif - -#endif /* LINPHONE_CONTENT_H_ */ diff --git a/include/linphone/core.h b/include/linphone/core.h index c6b1750a5..9ddb101cc 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -34,7 +34,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/account_creator.h" #include "linphone/account_creator_service.h" -#include "linphone/address.h" #include "linphone/auth_info.h" #include "linphone/buffer.h" #include "linphone/call.h" @@ -43,7 +42,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/call_stats.h" #include "linphone/chat.h" #include "linphone/conference.h" -#include "linphone/content.h" #include "linphone/dictionary.h" #include "linphone/error_info.h" #include "linphone/event.h" @@ -53,6 +51,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/im_encryption_engine.h" #include "linphone/im_notif_policy.h" #include "linphone/info_message.h" +#include "linphone/logging.h" #include "linphone/lpconfig.h" #include "linphone/misc.h" #include "linphone/nat_policy.h" @@ -66,13 +65,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/xmlrpc.h" #include "linphone/headers.h" +// For migration purpose. +#include "linphone/api/c-api.h" #ifdef __cplusplus extern "C" { #endif /** - * Safely down-cast a belle_sip_object_t into LinphoneCore + * Safely down-cast a belle_sip_object_t into #LinphoneCore * @ingroup initializing */ #define LINPHONE_CORE(object) BELLE_SIP_CAST(object, LinphoneCore) @@ -96,9 +97,9 @@ LINPHONE_PUBLIC LinphoneAddress * linphone_core_create_address(LinphoneCore *lc, /** * Create an independent media file player. * This player support WAVE and MATROSKA formats. - * @param lc A LinphoneCore object - * @param sound_card_name Playback sound card. If NULL, the ringer sound card set in LinphoneCore will be used - * @param video_display_name Video display. If NULL, the video display set in LinphoneCore will be used + * @param lc A #LinphoneCore object + * @param sound_card_name Playback sound card. If NULL, the ringer sound card set in #LinphoneCore will be used + * @param video_display_name Video display. If NULL, the video display set in #LinphoneCore will be used * @param window_id Id of the drawing window. Depend of video out * @return A pointer on the new instance. NULL if faild. */ @@ -106,7 +107,7 @@ LINPHONE_PUBLIC LinphonePlayer *linphone_core_create_local_player(LinphoneCore * /** * Creates an empty info message. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @return a new LinphoneInfoMessage. * * The info message can later be filled with information using linphone_info_message_add_header() or linphone_info_message_set_content(), @@ -114,9 +115,17 @@ LINPHONE_PUBLIC LinphonePlayer *linphone_core_create_local_player(LinphoneCore * **/ LINPHONE_PUBLIC LinphoneInfoMessage *linphone_core_create_info_message(LinphoneCore*lc); +/** + * Create a #LinphoneMagicSearch object. + * @param[in] lc #LinphoneCore object + * @return The create #LinphoneMagicSearch object + * @ingroup misc + */ +LINPHONE_PUBLIC LinphoneMagicSearch *linphone_core_create_magic_search(LinphoneCore *lc); + /** * Checks if a new version of the application is available. - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @param current_version The current version of the application */ LINPHONE_PUBLIC void linphone_core_check_for_update(LinphoneCore *lc, const char *current_version); @@ -127,7 +136,7 @@ LINPHONE_PUBLIC void linphone_core_check_for_update(LinphoneCore *lc, const char /** * Get the remote address of the current call. - * @param[in] lc LinphoneCore object. + * @param[in] lc #LinphoneCore object. * @return The remote address of the current call or NULL if there is no current call. * @ingroup call_control */ @@ -139,34 +148,6 @@ LINPHONE_PUBLIC const LinphoneAddress * linphone_core_get_current_call_remote_ad * @{ **/ -/** - * Callback prototype - * @deprecated - * @donotwrap - */ -typedef void (*ShowInterfaceCb)(LinphoneCore *lc); - -/** - * Callback prototype - * @deprecated - * @donotwrap - */ -typedef void (*DisplayStatusCb)(LinphoneCore *lc, const char *message); - -/** - * Callback prototype - * @deprecated - * @donotwrap - */ -typedef void (*DisplayMessageCb)(LinphoneCore *lc, const char *message); - -/** - * Callback prototype - * @deprecated - * @donotwrap - */ -typedef void (*DisplayUrlCb)(LinphoneCore *lc, const char *message, const char *url); - /** * Callback prototype */ @@ -185,7 +166,7 @@ typedef struct _LinphoneCoreVTable{ LinphoneCoreNotifyPresenceReceivedForUriOrTelCb notify_presence_received_for_uri_or_tel; /**< Notify received presence events*/ LinphoneCoreNewSubscriptionRequestedCb new_subscription_requested; /**< Notify about pending presence subscription request */ LINPHONE_DEPRECATED LinphoneCoreAuthInfoRequestedCb auth_info_requested; /** @brief Ask the application some authentication information. - @deprecated Use authentication_requested instead. Deprecated since 2016-09-21 */ + @deprecated Use authentication_requested instead. Deprecated since 2016-09-21 */ LinphoneCoreAuthenticationRequestedCb authentication_requested; /**< Ask the application some authentication information */ LinphoneCoreCallLogUpdatedCb call_log_updated; /**< Notifies that call log list has been updated */ LinphoneCoreMessageReceivedCb message_received; /**< a message is received, can be text or external body*/ @@ -200,23 +181,15 @@ typedef struct _LinphoneCoreVTable{ LinphoneCoreInfoReceivedCb info_received; /**data field of the bctbx_list_t points a PayloadType @@ -1720,10 +1769,10 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const bctbx_list_t *linphone_core_get_audio_ /** * Sets the list of audio codecs. - * @param[in] lc The LinphoneCore object + * @param[in] lc The #LinphoneCore object * @param[in] codecs \bctbx_list{OrtpPayloadType} * @return 0 - * The list is taken by the LinphoneCore thus the application should not free it. + * The list is taken by the #LinphoneCore thus the application should not free it. * This list is made of struct PayloadType describing the codec parameters. * @ingroup media_parameters * @deprecated Use linphone_core_set_audio_payload_types() instead. @@ -1751,7 +1800,7 @@ LINPHONE_PUBLIC void linphone_core_set_video_payload_types(LinphoneCore *lc, con /** * Returns the list of available video codecs. - * @param[in] lc The LinphoneCore object + * @param[in] lc The #LinphoneCore object * @return \bctbx_list{OrtpPayloadType} * * This list is unmodifiable. The ->data field of the bctbx_list_t points a PayloadType @@ -1766,11 +1815,11 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const bctbx_list_t *linphone_core_get_video_ /** * Sets the list of video codecs. - * @param[in] lc The LinphoneCore object + * @param[in] lc The #LinphoneCore object * @param[in] codecs \bctbx_list{OrtpPayloadType} * @return 0 * - * The list is taken by the LinphoneCore thus the application should not free it. + * The list is taken by the #LinphoneCore thus the application should not free it. * This list is made of struct PayloadType describing the codec parameters. * @ingroup media_parameters * @deprecated Use linphone_core_set_video_payload_types() instead. @@ -1798,7 +1847,7 @@ LINPHONE_PUBLIC void linphone_core_set_text_payload_types(LinphoneCore *lc, cons /** * Returns the list of available text codecs. - * @param[in] lc The LinphoneCore object + * @param[in] lc The #LinphoneCore object * @return \bctbx_list{OrtpPayloadType} * * This list is unmodifiable. The ->data field of the bctbx_list_t points a PayloadType @@ -1813,11 +1862,11 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const bctbx_list_t *linphone_core_get_text_c /** * Sets the list of text codecs. - * @param[in] lc The LinphoneCore object + * @param[in] lc The #LinphoneCore object * @param[in] codecs \bctbx_list{LinphonePayloadType} * @return 0 * - * The list is taken by the LinphoneCore thus the application should not free it. + * The list is taken by the #LinphoneCore thus the application should not free it. * This list is made of struct PayloadType describing the codec parameters. * @ingroup media_parameters * @deprecated Use linphone_core_set_text_payload_types() instead. @@ -1828,7 +1877,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_set_text_codecs /** * Enable RFC3389 generic comfort noise algorithm (CN payload type). * It is disabled by default, because this algorithm is only relevant for legacy codecs (PCMU, PCMA, G722). - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] enabled TRUE if enabled, FALSE otherwise. * @deprecated Use linphone_core_enable_generic_comfort_noise() instead */ @@ -1836,7 +1885,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_set_text_codecs /** * Returns enablement of RFC3389 generic comfort noise algorithm. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return TRUE or FALSE. * @deprecated Use linphone_core_generic_comfort_noise_enabled() instead */ @@ -1845,14 +1894,14 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneStatus linphone_core_set_text_codecs /** * Enable RFC3389 generic comfort noise algorithm (CN payload type). * It is disabled by default, because this algorithm is only relevant for legacy codecs (PCMU, PCMA, G722). - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] enabled TRUE if enabled, FALSE otherwise. **/ LINPHONE_PUBLIC void linphone_core_enable_generic_comfort_noise(LinphoneCore *lc, bool_t enabled); /** * Returns enablement of RFC3389 generic comfort noise algorithm. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return TRUE or FALSE. **/ LINPHONE_PUBLIC bool_t linphone_core_generic_comfort_noise_enabled(const LinphoneCore *lc); @@ -1962,7 +2011,7 @@ LINPHONE_PUBLIC LinphonePayloadType *linphone_core_get_payload_type(LinphoneCore LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_get_payload_type_number(LinphoneCore *lc, const OrtpPayloadType *pt); /** - * Force a number for a payload type. The LinphoneCore does payload type number assignment automatically. THis function is to be used mainly for tests, in order + * Force a number for a payload type. The #LinphoneCore does payload type number assignment automatically. THis function is to be used mainly for tests, in order * to override the automatic assignment mechanism. * @ingroup media_parameters * @deprecated Use linphone_payload_type_set_number() instead @@ -2014,14 +2063,14 @@ LINPHONE_PUBLIC void linphone_core_clear_proxy_config(LinphoneCore *lc); /** * Removes a proxy configuration. * - * LinphoneCore will then automatically unregister and place the proxy configuration + * #LinphoneCore will then automatically unregister and place the proxy configuration * on a deleted list. For that reason, a removed proxy does NOT need to be freed. **/ LINPHONE_PUBLIC void linphone_core_remove_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config); /** * Returns an unmodifiable list of entered proxy configurations. - * @param[in] lc The LinphoneCore object + * @param[in] lc The #LinphoneCore object * @return \bctbx_list{LinphoneProxyConfig} **/ LINPHONE_PUBLIC const bctbx_list_t *linphone_core_get_proxy_config_list(const LinphoneCore *lc); @@ -2040,18 +2089,18 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_get_default_proxy(Linphone /** * @return the default proxy configuration, that is the one used to determine the current identity. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The default proxy configuration. **/ -LINPHONE_PUBLIC LinphoneProxyConfig * linphone_core_get_default_proxy_config(LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneProxyConfig * linphone_core_get_default_proxy_config(const LinphoneCore *lc); /** * 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 + * 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] lc #LinphoneCore object * @param[in] config The proxy configuration to use as the default one. **/ LINPHONE_PUBLIC void linphone_core_set_default_proxy_config(LinphoneCore *lc, LinphoneProxyConfig *config); @@ -2093,7 +2142,7 @@ LINPHONE_PUBLIC void linphone_core_remove_auth_info(LinphoneCore *lc, const Linp /** * Returns an unmodifiable list of currently entered #LinphoneAuthInfo. - * @param[in] lc The LinphoneCore object. + * @param[in] lc The #LinphoneCore object. * @return \bctbx_list{LinphoneAuthInfo} * @ingroup authentication */ @@ -2102,7 +2151,7 @@ LINPHONE_PUBLIC const bctbx_list_t *linphone_core_get_auth_info_list(const Linph /** * 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 lc the #LinphoneCore * @param realm the authentication 'realm' (optional) * @param username the SIP username to be authenticated (mandatory) * @param sip_domain the SIP domain name (optional) @@ -2112,7 +2161,7 @@ LINPHONE_PUBLIC const bctbx_list_t *linphone_core_get_auth_info_list(const Linph LINPHONE_PUBLIC const LinphoneAuthInfo *linphone_core_find_auth_info(LinphoneCore *lc, const char *realm, const char *username, const char *sip_domain); /** - * This method is used to abort a user authentication request initiated by LinphoneCore + * This method is used to abort a user authentication request initiated by #LinphoneCore * from the auth_info_requested callback of LinphoneCoreVTable. * @note That function does nothing for now. **/ @@ -2126,15 +2175,15 @@ LINPHONE_PUBLIC void linphone_core_clear_all_auth_info(LinphoneCore *lc); /** * Sets an default account creator service in the core - * @param lc LinphoneCore object - * @param cbs LinphoneAccountCreatorService object + * @param lc #LinphoneCore object + * @param cbs #LinphoneAccountCreatorService object **/ LINPHONE_PUBLIC void linphone_core_set_account_creator_service(LinphoneCore *lc, LinphoneAccountCreatorService *service); /** * Get default account creator service from the core - * @param lc LinphoneCore object - * @return LinphoneAccountCreatorService object + * @param lc #LinphoneCore object + * @return #LinphoneAccountCreatorService object **/ LINPHONE_PUBLIC LinphoneAccountCreatorService * linphone_core_get_account_creator_service(LinphoneCore *lc); @@ -2156,7 +2205,7 @@ LINPHONE_PUBLIC bool_t linphone_core_audio_adaptive_jittcomp_enabled(LinphoneCor /** * Returns the nominal audio jitter buffer size in milliseconds. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The nominal audio jitter buffer size in milliseconds * @ingroup media_parameters **/ @@ -2188,7 +2237,7 @@ LINPHONE_PUBLIC bool_t linphone_core_video_adaptive_jittcomp_enabled(LinphoneCor /** * Returns the nominal video jitter buffer size in milliseconds. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The nominal video jitter buffer size in milliseconds * @ingroup media_parameters **/ @@ -2204,7 +2253,7 @@ LINPHONE_PUBLIC void linphone_core_set_video_jittcomp(LinphoneCore *lc, int mill /** * Gets the UDP port used for audio streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The UDP port used for audio streaming * @ingroup network_parameters **/ @@ -2212,7 +2261,7 @@ LINPHONE_PUBLIC int linphone_core_get_audio_port(const LinphoneCore *lc); /** * Get the audio port range from which is randomly chosen the UDP port used for audio streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[out] min_port The lower bound of the audio port range being used * @param[out] max_port The upper bound of the audio port range being used * @ingroup network_parameters @@ -2222,15 +2271,15 @@ LINPHONE_PUBLIC void linphone_core_get_audio_port_range(const LinphoneCore *lc, /** * Get the audio port range from which is randomly chosen the UDP port used for audio streaming. - * @param[in] lc LinphoneCore object - * @return a LinphoneRange object + * @param[in] lc #LinphoneCore object + * @return a #LinphoneRange object * @ingroup network_parameters */ LINPHONE_PUBLIC LinphoneRange *linphone_core_get_audio_ports_range(const LinphoneCore *lc); /** * Gets the UDP port used for video streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The UDP port used for video streaming * @ingroup network_parameters **/ @@ -2238,7 +2287,7 @@ LINPHONE_PUBLIC int linphone_core_get_video_port(const LinphoneCore *lc); /** * Get the video port range from which is randomly chosen the UDP port used for video streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[out] min_port The lower bound of the video port range being used * @param[out] max_port The upper bound of the video port range being used * @ingroup network_parameters @@ -2248,15 +2297,15 @@ LINPHONE_PUBLIC void linphone_core_get_video_port_range(const LinphoneCore *lc, /** * Get the video port range from which is randomly chosen the UDP port used for video streaming. - * @param[in] lc LinphoneCore object - * @return a LinphoneRange object + * @param[in] lc #LinphoneCore object + * @return a #LinphoneRange object * @ingroup network_parameters */ LINPHONE_PUBLIC LinphoneRange *linphone_core_get_video_ports_range(const LinphoneCore *lc); /** * Gets the UDP port used for text streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The UDP port used for text streaming * @ingroup network_parameters **/ @@ -2264,7 +2313,7 @@ LINPHONE_PUBLIC int linphone_core_get_text_port(const LinphoneCore *lc); /** * Get the video port range from which is randomly chosen the UDP port used for text streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[out] min_port The lower bound of the text port range being used * @param[out] max_port The upper bound of the text port range being used * @ingroup network_parameters @@ -2274,8 +2323,8 @@ LINPHONE_PUBLIC void linphone_core_get_text_port_range(const LinphoneCore *lc, i /** * Get the text port range from which is randomly chosen the UDP port used for text streaming. - * @param[in] lc LinphoneCore object - * @return a LinphoneRange object + * @param[in] lc #LinphoneCore object + * @return a #LinphoneRange object * @ingroup network_parameters */ LINPHONE_PUBLIC LinphoneRange *linphone_core_get_text_ports_range(const LinphoneCore *lc); @@ -2284,10 +2333,10 @@ LINPHONE_PUBLIC LinphoneRange *linphone_core_get_text_ports_range(const Linphone * Gets the value of the no-rtp timeout. * * When no RTP or RTCP packets have been received for a while - * LinphoneCore will consider the call is broken (remote end crashed or + * #LinphoneCore will consider the call is broken (remote end crashed or * disconnected from the network), and thus will terminate the call. * The no-rtp timeout is the duration above which the call is considered broken. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The value of the no-rtp timeout in seconds * @ingroup media_parameters **/ @@ -2297,7 +2346,7 @@ LINPHONE_PUBLIC int linphone_core_get_nortp_timeout(const LinphoneCore *lc); * Sets the UDP port used for audio streaming. * A value of -1 will request the system to allocate the local port randomly. * This is recommended in order to avoid firewall warnings. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] port The UDP port to use for audio streaming * @ingroup network_parameters **/ @@ -2305,7 +2354,7 @@ LINPHONE_PUBLIC void linphone_core_set_audio_port(LinphoneCore *lc, int port); /** * Sets the UDP port range from which to randomly select the port used for audio streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] min_port The lower bound of the audio port range to use * @param[in] max_port The upper bound of the audio port range to use * @ingroup media_parameters @@ -2316,7 +2365,7 @@ LINPHONE_PUBLIC void linphone_core_set_audio_port_range(LinphoneCore *lc, int mi * Sets the UDP port used for video streaming. * A value of -1 will request the system to allocate the local port randomly. * This is recommended in order to avoid firewall warnings. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] port The UDP port to use for video streaming * @ingroup network_parameters **/ @@ -2324,7 +2373,7 @@ LINPHONE_PUBLIC void linphone_core_set_video_port(LinphoneCore *lc, int port); /** * Sets the UDP port range from which to randomly select the port used for video streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] min_port The lower bound of the video port range to use * @param[in] max_port The upper bound of the video port range to use * @ingroup media_parameters @@ -2335,7 +2384,7 @@ LINPHONE_PUBLIC void linphone_core_set_video_port_range(LinphoneCore *lc, int mi * Sets the UDP port used for text streaming. * A value if -1 will request the system to allocate the local port randomly. * This is recommended in order to avoid firewall warnings. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] port The UDP port to use for text streaming * @ingroup network_parameters **/ @@ -2343,7 +2392,7 @@ LINPHONE_PUBLIC void linphone_core_set_text_port(LinphoneCore *lc, int port); /** * Sets the UDP port range from which to randomly select the port used for text streaming. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] min_port The lower bound of the text port range to use * @param[in] max_port The upper bound of the text port range to use * @ingroup media_parameters @@ -2352,7 +2401,7 @@ LINPHONE_PUBLIC void linphone_core_set_text_port_range(LinphoneCore *lc, int min /** * Sets the no-rtp timeout value in seconds. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] seconds The no-rtp timeout value to use in seconds * @ingroup media_parameters * @see linphone_core_get_nortp_timeout() for details. @@ -2361,7 +2410,7 @@ LINPHONE_PUBLIC void linphone_core_set_nortp_timeout(LinphoneCore *lc, int secon /** * Sets whether SIP INFO is to be used to send digits. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] use_info A boolean value telling whether to use SIP INFO to send digits * @ingroup media_parameters **/ @@ -2369,7 +2418,7 @@ LINPHONE_PUBLIC void linphone_core_set_use_info_for_dtmf(LinphoneCore *lc, bool_ /** * Indicates whether SIP INFO is used to send digits. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value telling whether SIP INFO is used to send digits * @ingroup media_parameters **/ @@ -2377,7 +2426,7 @@ LINPHONE_PUBLIC bool_t linphone_core_get_use_info_for_dtmf(LinphoneCore *lc); /** * Sets whether RFC2833 is to be used to send digits. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] use_rfc2833 A boolean value telling whether to use RFC2833 to send digits * @ingroup media_parameters **/ @@ -2385,7 +2434,7 @@ LINPHONE_PUBLIC void linphone_core_set_use_rfc2833_for_dtmf(LinphoneCore *lc,boo /** * Indicates whether RFC2833 is used to send digits. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value telling whether RFC2833 is used to send digits * @ingroup media_parameters **/ @@ -2393,7 +2442,7 @@ LINPHONE_PUBLIC bool_t linphone_core_get_use_rfc2833_for_dtmf(LinphoneCore *lc); /** * Sets the UDP port to be used by SIP. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] port The UDP port to be used by SIP * @ingroup network_parameters * @deprecated use linphone_core_set_sip_transports() instead. @@ -2403,7 +2452,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_sip_port(LinphoneCore /** * Gets the UDP port used by SIP. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The UDP port used by SIP * @ingroup network_parameters * @deprecated use linphone_core_get_sip_transports() instead. @@ -2415,8 +2464,8 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED int linphone_core_get_sip_port(LinphoneCore * Sets the ports to be used for each of transport (UDP or TCP) * A zero value port for a given transport means the transport * is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be choosen randomly by the system. - * @param[in] lc LinphoneCore object - * @param[in] transports A LinphoneSipTransports structure giving the ports to use + * @param[in] lc #LinphoneCore object + * @param[in] transports A #LinphoneSipTransports structure giving the ports to use * @return 0 * @ingroup network_parameters * @deprecated Use linphone_core_set_transports instead @@ -2428,7 +2477,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_sip_transports(LinphoneCore *lc * Retrieves the port configuration used for each transport (udp, tcp, tls). * A zero value port for a given transport means the transport * is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be chosen randomly by the system. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[out] transports A #LinphoneSipTransports structure that will receive the configured ports * @return 0 * @ingroup network_parameters @@ -2441,7 +2490,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_get_sip_transports(LinphoneCore *lc * Retrieves the real port number assigned for each sip transport (udp, tcp, tls). * A zero value means that the transport is not activated. * If LC_SIP_TRANSPORT_RANDOM was passed to linphone_core_set_sip_transports(), the random port choosed by the system is returned. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[out] tr A #LinphoneSipTransports structure that will receive the ports being used * @ingroup network_parameters * @deprecated Use linphone_core_get_transports_used instead @@ -2453,8 +2502,8 @@ LINPHONE_PUBLIC void linphone_core_get_sip_transports_used(LinphoneCore *lc, Lin * Sets the ports to be used for each of transport (UDP or TCP) * A zero value port for a given transport means the transport * is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be choosen randomly by the system. - * @param[in] lc LinphoneCore object - * @param[in] transports A LinphoneSipTransports structure giving the ports to use + * @param[in] lc #LinphoneCore object + * @param[in] transports A #LinphoneSipTransports structure giving the ports to use * @return 0 * @ingroup network_parameters **/ @@ -2464,7 +2513,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_transports(LinphoneCore *lc, co * Retrieves the port configuration used for each transport (udp, tcp, tls). * A zero value port for a given transport means the transport * is not used. A value of LC_SIP_TRANSPORT_RANDOM (-1) means the port is to be chosen randomly by the system. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A #LinphoneTransports structure with the configured ports * @ingroup network_parameters **/ @@ -2474,7 +2523,7 @@ LINPHONE_PUBLIC LinphoneTransports *linphone_core_get_transports(LinphoneCore *l * Retrieves the real port number assigned for each sip transport (udp, tcp, tls). * A zero value means that the transport is not activated. * If LC_SIP_TRANSPORT_RANDOM was passed to linphone_core_set_sip_transports(), the random port choosed by the system is returned. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A #LinphoneTransports structure with the ports being used * @ingroup network_parameters **/ @@ -2482,93 +2531,93 @@ LINPHONE_PUBLIC LinphoneTransports *linphone_core_get_transports_used(LinphoneCo /** * Increment refcount. - * @param[in] transports LinphoneTransports object + * @param[in] transports #LinphoneTransports object * @ingroup network_parameters **/ LINPHONE_PUBLIC LinphoneTransports *linphone_transports_ref(LinphoneTransports *transports); /** * Decrement refcount and possibly free the object. - * @param[in] transports LinphoneTransports object + * @param[in] transports #LinphoneTransports object * @ingroup network_parameters **/ LINPHONE_PUBLIC void linphone_transports_unref(LinphoneTransports *transports); /** - * Gets the user data in the LinphoneTransports object - * @param[in] transports the LinphoneTransports + * Gets the user data in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports * @return the user data * @ingroup network_parameters */ LINPHONE_PUBLIC void *linphone_transports_get_user_data(const LinphoneTransports *transports); /** - * Sets the user data in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Sets the user data in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @param[in] data the user data * @ingroup network_parameters */ LINPHONE_PUBLIC void linphone_transports_set_user_data(LinphoneTransports *transports, void *data); /** - * Gets the UDP port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Gets the UDP port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @return the UDP port * @ingroup network_parameters */ LINPHONE_PUBLIC int linphone_transports_get_udp_port(const LinphoneTransports* transports); /** - * Gets the TCP port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Gets the TCP port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @return the TCP port * @ingroup network_parameters */ LINPHONE_PUBLIC int linphone_transports_get_tcp_port(const LinphoneTransports* transports); /** - * Gets the TLS port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Gets the TLS port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @return the TLS port * @ingroup network_parameters */ LINPHONE_PUBLIC int linphone_transports_get_tls_port(const LinphoneTransports* transports); /** - * Gets the DTLS port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Gets the DTLS port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @return the DTLS port * @ingroup network_parameters */ LINPHONE_PUBLIC int linphone_transports_get_dtls_port(const LinphoneTransports* transports); /** - * Sets the UDP port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Sets the UDP port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @param[in] port the UDP port * @ingroup network_parameters */ LINPHONE_PUBLIC void linphone_transports_set_udp_port(LinphoneTransports *transports, int port); /** - * Sets the TCP port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Sets the TCP port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @param[in] port the TCP port * @ingroup network_parameters */ LINPHONE_PUBLIC void linphone_transports_set_tcp_port(LinphoneTransports *transports, int port); /** - * Sets the TLS port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Sets the TLS port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @param[in] port the TLS port * @ingroup network_parameters */ LINPHONE_PUBLIC void linphone_transports_set_tls_port(LinphoneTransports *transports, int port); /** - * Sets the DTLS port in the LinphoneTransports object - * @param[in] transports the LinphoneTransports object + * Sets the DTLS port in the #LinphoneTransports object + * @param[in] transports the #LinphoneTransports object * @param[in] port the DTLS port * @ingroup network_parameters */ @@ -2576,8 +2625,8 @@ LINPHONE_PUBLIC void linphone_transports_set_dtls_port(LinphoneTransports *trans /** * Tells whether the given transport type is supported by the library. - * @param[in] lc LinphoneCore object - * @param[in] tp LinphoneTranportType to check for support + * @param[in] lc #LinphoneCore object + * @param[in] tp #LinphoneTranportType to check for support * @return A boolean value telling whether the given transport type is supported by the library **/ LINPHONE_PUBLIC bool_t linphone_core_sip_transport_supported(const LinphoneCore *lc, LinphoneTransportType tp); @@ -2596,7 +2645,7 @@ ortp_socket_t linphone_core_get_sip_socket(LinphoneCore *lc); * Set the incoming call timeout in seconds. * If an incoming call isn't answered for this timeout period, it is * automatically declined. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] seconds The new timeout in seconds * @ingroup call_control **/ @@ -2605,7 +2654,7 @@ LINPHONE_PUBLIC void linphone_core_set_inc_timeout(LinphoneCore *lc, int seconds /** * Returns the incoming call timeout * See linphone_core_set_inc_timeout() for details. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current incoming call timeout in seconds * @ingroup call_control **/ @@ -2614,7 +2663,7 @@ LINPHONE_PUBLIC int linphone_core_get_inc_timeout(LinphoneCore *lc); /** * Set the in call timeout in seconds. * After this timeout period, the call is automatically hangup. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] seconds The new timeout in seconds * @ingroup call_control **/ @@ -2623,7 +2672,7 @@ LINPHONE_PUBLIC void linphone_core_set_in_call_timeout(LinphoneCore *lc, int sec /** * Gets the in call timeout * See linphone_core_set_in_call_timeout() for details. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current in call timeout in seconds * @ingroup call_control **/ @@ -2632,7 +2681,7 @@ LINPHONE_PUBLIC int linphone_core_get_in_call_timeout(LinphoneCore *lc); /** * Set the in delayed timeout in seconds. * After this timeout period, a delayed call (internal call initialisation or resolution) is resumed. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] seconds The new delayed timeout * @ingroup call_control **/ @@ -2641,7 +2690,7 @@ LINPHONE_PUBLIC void linphone_core_set_delayed_timeout(LinphoneCore *lc, int sec /** * Gets the delayed timeout * See linphone_core_set_delayed_timeout() for details. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current delayed timeout in seconds * @ingroup call_control **/ @@ -2730,7 +2779,7 @@ LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneFirewallPolicy linphone_core_get_fir * Set the policy to use to pass through NATs/firewalls. * It may be overridden by a NAT policy for a specific proxy config. * @param[in] lc #LinphoneCore object - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @ingroup network_parameters * @see linphone_proxy_config_set_nat_policy() */ @@ -2740,7 +2789,7 @@ LINPHONE_PUBLIC void linphone_core_set_nat_policy(LinphoneCore *lc, LinphoneNatP * Get The policy that is used to pass through NATs/firewalls. * It may be overridden by a NAT policy for a specific proxy config. * @param[in] lc #LinphoneCore object - * @return LinphoneNatPolicy object in use. + * @return #LinphoneNatPolicy object in use. * @ingroup network_parameters * @see linphone_proxy_config_get_nat_policy() */ @@ -2748,12 +2797,22 @@ LINPHONE_PUBLIC LinphoneNatPolicy * linphone_core_get_nat_policy(const LinphoneC /** * Gets the list of the available sound devices. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return An unmodifiable array of strings contanining the names of the available sound devices that is NULL terminated * @ingroup media_parameters + * @donotwrap + * @deprecated use linphone_core_get_sound_devices_list instead **/ LINPHONE_PUBLIC const char** linphone_core_get_sound_devices(LinphoneCore *lc); +/** + * Gets the list of the available sound devices. + * @param[in] lc #LinphoneCore object + * @return \bctbx_list{char *} An unmodifiable array of strings contanining the names of the available sound devices that is NULL terminated + * @ingroup media_parameters +**/ +LINPHONE_PUBLIC bctbx_list_t * linphone_core_get_sound_devices_list(const LinphoneCore *lc); + /** * Use this function when you want to set the default sound devices **/ @@ -2771,7 +2830,7 @@ LINPHONE_PUBLIC void linphone_core_reload_sound_devices(LinphoneCore *lc); /** * Tells whether a specified sound device can capture sound. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] device the device name as returned by linphone_core_get_sound_devices() * @return A boolean value telling whether the specified sound device can capture sound * @ingroup media_parameters @@ -2780,7 +2839,7 @@ LINPHONE_PUBLIC bool_t linphone_core_sound_device_can_capture(LinphoneCore *lc, /** * Tells whether a specified sound device can play sound. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] device the device name as returned by linphone_core_get_sound_devices() * @return A boolean value telling whether the specified sound device can play sound * @ingroup media_parameters @@ -2841,7 +2900,7 @@ LINPHONE_DEPRECATED void linphone_core_set_sound_source(LinphoneCore *lc, char s /** * Allow to control microphone level: gain in db. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] level The new microphone level * @ingroup media_parameters **/ @@ -2849,7 +2908,7 @@ LINPHONE_PUBLIC void linphone_core_set_mic_gain_db(LinphoneCore *lc, float level /** * Get microphone gain in db. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current microphone gain * @ingroup media_parameters **/ @@ -2857,7 +2916,7 @@ LINPHONE_PUBLIC float linphone_core_get_mic_gain_db(LinphoneCore *lc); /** * Allow to control play level before entering sound card: gain in db - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] level The new play level * @ingroup media_parameters **/ @@ -2865,7 +2924,7 @@ LINPHONE_PUBLIC void linphone_core_set_playback_gain_db(LinphoneCore *lc, float /** * Get playback gain in db before entering sound card. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current playback gain * @ingroup media_parameters **/ @@ -2873,7 +2932,7 @@ LINPHONE_PUBLIC float linphone_core_get_playback_gain_db(LinphoneCore *lc); /** * Gets the name of the currently assigned sound device for ringing. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The name of the currently assigned sound device for ringing * @ingroup media_parameters **/ @@ -2881,7 +2940,7 @@ LINPHONE_PUBLIC const char * linphone_core_get_ringer_device(LinphoneCore *lc); /** * Gets the name of the currently assigned sound device for playback. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The name of the currently assigned sound device for playback * @ingroup media_parameters **/ @@ -2889,7 +2948,7 @@ LINPHONE_PUBLIC const char * linphone_core_get_playback_device(LinphoneCore *lc) /** * Gets the name of the currently assigned sound device for capture. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The name of the currently assigned sound device for capture * @ingroup media_parameters **/ @@ -2897,7 +2956,7 @@ LINPHONE_PUBLIC const char * linphone_core_get_capture_device(LinphoneCore *lc); /** * Sets the sound device used for ringing. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] devid The device name as returned by linphone_core_get_sound_devices() * @return 0 * @ingroup media_parameters @@ -2906,7 +2965,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_ringer_device(LinphoneCore *lc, /** * Sets the sound device used for playback. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] devid The device name as returned by linphone_core_get_sound_devices() * @return 0 * @ingroup media_parameters @@ -2915,7 +2974,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_playback_device(LinphoneCore *l /** * Sets the sound device used for capture. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] devid The device name as returned by linphone_core_get_sound_devices() * @return 0 * @ingroup media_parameters @@ -2925,14 +2984,14 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_capture_device(LinphoneCore *lc /** * 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. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @ingroup media_parameters **/ LINPHONE_PUBLIC void linphone_core_stop_ringing(LinphoneCore *lc); /** * Sets the path to a wav file used for ringing. The file must be a wav 16bit linear. Local ring is disabled if null. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] path The path to a wav file to be used for ringing * @ingroup media_parameters **/ @@ -2940,7 +2999,7 @@ LINPHONE_PUBLIC void linphone_core_set_ring(LinphoneCore *lc, const char *path); /** * Returns the path to the wav file used for ringing. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The path to the wav file used for ringing * @ingroup media_parameters **/ @@ -2948,7 +3007,7 @@ LINPHONE_PUBLIC const char *linphone_core_get_ring(const LinphoneCore *lc); /** * Specify whether the tls server certificate must be verified when connecting to a SIP/TLS server. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] yesno A boolean value telling whether the tls server certificate must be verified * @ingroup initializing **/ @@ -2956,7 +3015,7 @@ LINPHONE_PUBLIC void linphone_core_verify_server_certificates(LinphoneCore *lc, /** * Specify whether the tls server certificate common name must be verified when connecting to a SIP/TLS server. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] yesno A boolean value telling whether the tls server certificate common name must be verified * @ingroup initializing **/ @@ -2964,7 +3023,7 @@ LINPHONE_PUBLIC void linphone_core_verify_server_cn(LinphoneCore *lc, bool_t yes /** * Gets the path to a file or folder containing the trusted root CAs (PEM format) - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The path to a file or folder containing the trusted root CAs * @ingroup initializing **/ @@ -2972,7 +3031,7 @@ LINPHONE_PUBLIC const char *linphone_core_get_root_ca(LinphoneCore *lc); /** * Sets the path to a file or folder containing trusted root CAs (PEM format) - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] path The path to a file or folder containing trusted root CAs * @ingroup initializing **/ @@ -2980,7 +3039,7 @@ LINPHONE_PUBLIC void linphone_core_set_root_ca(LinphoneCore *lc, const char *pat /** * Sets the trusted root CAs (PEM format) - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] data The trusted root CAs as a string * @ingroup initializing **/ @@ -3001,7 +3060,7 @@ LINPHONE_PUBLIC void linphone_core_set_ssl_config(LinphoneCore *lc, void *ssl_co * Sets the path to a wav file used for ringing back. * Ringback means the ring that is heard when it's ringing at the remote party. * The file must be a wav 16bit linear. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] path The path to a wav file to be used for ringing back * @ingroup media_parameters **/ @@ -3009,7 +3068,7 @@ LINPHONE_PUBLIC void linphone_core_set_ringback(LinphoneCore *lc, const char *pa /** * Returns the path to the wav file used for ringing back. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The path to the wav file used for ringing back * @ingroup media_parameters **/ @@ -3048,7 +3107,7 @@ LINPHONE_PUBLIC bool_t linphone_core_get_ring_during_incoming_early_media(const LINPHONE_PUBLIC LinphoneStatus linphone_core_preview_ring(LinphoneCore *lc, const char *ring,LinphoneCoreCbFunc func,void * userdata); /** - * Returns the MSFactory (mediastreamer2 factory) used by the LinphoneCore to control mediastreamer2 library. + * Returns the MSFactory (mediastreamer2 factory) used by the #LinphoneCore to control mediastreamer2 library. **/ LINPHONE_PUBLIC MSFactory* linphone_core_get_ms_factory(LinphoneCore* lc); @@ -3056,7 +3115,7 @@ LINPHONE_PUBLIC MSFactory* linphone_core_get_ms_factory(LinphoneCore* lc); * Plays an audio file to the local user. * This function works at any time, during calls, or when no calls are running. * It doesn't request the underlying audio system to support multiple playback streams. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] audiofile The path to an audio file in wav PCM 16 bit format * @return 0 on success, -1 on error * @ingroup misc @@ -3068,7 +3127,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_play_local(LinphoneCore *lc, const * This actually controls software echo cancellation. If hardware echo cancellation is available, * it will be always used and activated for calls, regardless of the value passed to this function. * When hardware echo cancellation is available, the software one is of course not activated. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] val A boolean value telling whether echo cancellation is to be enabled or disabled. * @ingroup media_parameters **/ @@ -3076,7 +3135,7 @@ LINPHONE_PUBLIC void linphone_core_enable_echo_cancellation(LinphoneCore *lc, bo /** * Returns TRUE if echo cancellation is enabled. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value telling whether echo cancellation is enabled or disabled * @ingroup media_parameters **/ @@ -3156,7 +3215,7 @@ LINPHONE_PUBLIC void linphone_core_set_rtp_no_xmit_on_audio_mute(LinphoneCore *l /** * Get the list of call logs (past calls). - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return \bctbx_list{LinphoneCallLog} **/ LINPHONE_PUBLIC const bctbx_list_t * linphone_core_get_call_logs(LinphoneCore *lc); @@ -3164,22 +3223,22 @@ LINPHONE_PUBLIC const bctbx_list_t * linphone_core_get_call_logs(LinphoneCore *l /** * Get the list of call logs (past calls) that matches the given #LinphoneAddress. * At the contrary of linphone_core_get_call_logs, it is your responsibility to unref the logs and free this list once you are done using it. - * @param[in] lc LinphoneCore object - * @param[in] addr LinphoneAddress object + * @param[in] lc #LinphoneCore object + * @param[in] addr #LinphoneAddress object * @return \bctbx_list{LinphoneCallLog} **/ LINPHONE_PUBLIC bctbx_list_t * linphone_core_get_call_history_for_address(LinphoneCore *lc, const LinphoneAddress *addr); /** * Get the latest outgoing call log. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return {LinphoneCallLog} **/ LINPHONE_PUBLIC LinphoneCallLog * linphone_core_get_last_outgoing_call_log(LinphoneCore *lc); /** * Get the call log matching the call id, or NULL if can't be found. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] call_id Call id of the call log to find * @return {LinphoneCallLog} **/ @@ -3187,7 +3246,7 @@ LINPHONE_PUBLIC LinphoneCallLog * linphone_core_find_call_log_from_call_id(Linph /** * Erase the call log. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object **/ LINPHONE_PUBLIC void linphone_core_clear_call_logs(LinphoneCore *lc); @@ -3257,11 +3316,11 @@ LINPHONE_PUBLIC bool_t linphone_core_video_supported(LinphoneCore *lc); /** * Enables video globally. * - * This function does not have any effect during calls. It just indicates LinphoneCore to + * 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. * - * @param lc The LinphoneCore object + * @param lc The #LinphoneCore object * @param vcap_enabled indicates whether video capture is enabled * @param display_enabled indicates whether video display should be shown * @ingroup media_parameters @@ -3337,48 +3396,50 @@ LINPHONE_PUBLIC bool_t linphone_core_video_display_enabled(LinphoneCore *lc); * - video shall be initiated by default for outgoing calls * - video shall be accepter by default for incoming calls * - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] policy The video policy to use * @ingroup media_parameters - * @deprecated + * @deprecated Deprecated since 2017-04-19. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_video_policy(LinphoneCore *lc, const LinphoneVideoPolicy *policy); /** * Get the default policy for video. * See linphone_core_set_video_policy() for more details. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The video policy being used * @ingroup media_parameters - * @deprecated + * @deprecated Deprecated since 2017-04-19. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED const LinphoneVideoPolicy *linphone_core_get_video_policy(const LinphoneCore *lc); /** * Increment refcount. - * @param[in] policy LinphoneVideoActivationPolicy object + * @param[in] policy #LinphoneVideoActivationPolicy object * @ingroup media_parameters **/ LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_video_activation_policy_ref(LinphoneVideoActivationPolicy *policy); /** * Decrement refcount and possibly free the object. - * @param[in] policy LinphoneVideoActivationPolicy object + * @param[in] policy #LinphoneVideoActivationPolicy object * @ingroup media_parameters **/ LINPHONE_PUBLIC void linphone_video_activation_policy_unref(LinphoneVideoActivationPolicy *policy); /** - * Gets the user data in the LinphoneVideoActivationPolicy object - * @param[in] policy the LinphoneVideoActivationPolicy + * Gets the user data in the #LinphoneVideoActivationPolicy object + * @param[in] policy the #LinphoneVideoActivationPolicy * @return the user data * @ingroup media_parameters */ LINPHONE_PUBLIC void *linphone_video_activation_policy_get_user_data(const LinphoneVideoActivationPolicy *policy); /** - * Sets the user data in the LinphoneVideoActivationPolicy object - * @param[in] policy the LinphoneVideoActivationPolicy object + * Sets the user data in the #LinphoneVideoActivationPolicy object + * @param[in] policy the #LinphoneVideoActivationPolicy object * @param[in] data the user data * @ingroup media_parameters */ @@ -3386,7 +3447,7 @@ LINPHONE_PUBLIC void linphone_video_activation_policy_set_user_data(LinphoneVide /** * Gets the value for the automatically accept video policy - * @param[in] policy the LinphoneVideoActivationPolicy object + * @param[in] policy the #LinphoneVideoActivationPolicy object * @return whether or not to automatically accept video requests is enabled * @ingroup media_parameters */ @@ -3394,7 +3455,7 @@ LINPHONE_PUBLIC bool_t linphone_video_activation_policy_get_automatically_accept /** * Gets the value for the automatically initiate video policy - * @param[in] policy the LinphoneVideoActivationPolicy object + * @param[in] policy the #LinphoneVideoActivationPolicy object * @return whether or not to automatically initiate video calls is enabled * @ingroup media_parameters */ @@ -3402,7 +3463,7 @@ LINPHONE_PUBLIC bool_t linphone_video_activation_policy_get_automatically_initia /** * Sets the value for the automatically accept video policy - * @param[in] policy the LinphoneVideoActivationPolicy object + * @param[in] policy the #LinphoneVideoActivationPolicy object * @param[in] enable whether or not to enable automatically accept video requests * @ingroup media_parameters */ @@ -3410,7 +3471,7 @@ LINPHONE_PUBLIC void linphone_video_activation_policy_set_automatically_accept(L /** * Sets the value for the automatically initiate video policy - * @param[in] policy the LinphoneVideoActivationPolicy object + * @param[in] policy the #LinphoneVideoActivationPolicy object * @param[in] enable whether or not to enable automatically initiate video calls * @ingroup media_parameters */ @@ -3421,7 +3482,7 @@ LINPHONE_PUBLIC void linphone_video_activation_policy_set_automatically_initiate * This policy defines whether: * - video shall be initiated by default for outgoing calls * - video shall be accepted by default for incoming calls - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] policy The video policy to use * @ingroup media_parameters **/ @@ -3430,35 +3491,37 @@ LINPHONE_PUBLIC void linphone_core_set_video_activation_policy(LinphoneCore *lc, /** * Get the default policy for video. * See linphone_core_set_video_activation_policy() for more details. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The video policy being used * @ingroup media_parameters **/ LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_core_get_video_activation_policy(const LinphoneCore *lc); /** - * Returns the zero terminated table of supported video resolutions. + * @brief Returns the zero terminated table of supported video resolutions. * @ingroup media_parameters - * @deprecated Use linphone_factory_get_supported_video_definitions() instead + * @deprecated Use #linphone_factory_get_supported_video_definitions() instead. Deprecated since 2017-03-28. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED const MSVideoSizeDef *linphone_core_get_supported_video_sizes(LinphoneCore *lc); /** * Set the preferred video definition for the stream that is captured and sent to the remote party. * All standard video definitions are accepted on the receive path. - * @param[in] lc LinphoneCore object - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] lc #LinphoneCore object + * @param[in] vdef #LinphoneVideoDefinition object * @ingroup media_parameters */ LINPHONE_PUBLIC void linphone_core_set_preferred_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef); /** - * Sets the preferred video size. + * @brief Sets the preferred video size. * * This applies only to the stream that is captured and sent to the remote party, * since we accept all standard video size on the receive path. * @ingroup media_parameters - * @deprecated Use linphone_core_set_preferred_video_definition() instead + * @deprecated Use linphone_core_set_preferred_video_definition() instead. Deprecated since 2017-03-28. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preferred_video_size(LinphoneCore *lc, MSVideoSize vsize); @@ -3467,21 +3530,23 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preferred_video_size( * This method is for advanced usage where a video capture must be set independently of the definition of the stream actually sent through the call. * This allows for example to have the preview window in High Definition even if due to bandwidth constraint the sent video definition is small. * Using this feature increases the CPU consumption, since a rescaling will be done internally. - * @param[in] lc LinphoneCore object - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] lc #LinphoneCore object + * @param[in] vdef #LinphoneVideoDefinition object * @ingroup media_parameters */ LINPHONE_PUBLIC void linphone_core_set_preview_video_definition(LinphoneCore *lc, LinphoneVideoDefinition *vdef); /** - * Sets the video size for the captured (preview) video. + * @brief Sets the video size for the captured (preview) video. + * * This method is for advanced usage where a video capture must be set independently of the size of the stream actually sent through the call. * This allows for example to have the preview window with HD resolution even if due to bandwidth constraint the sent video size is small. * Using this feature increases the CPU consumption, since a rescaling will be done internally. * @ingroup media_parameters * @param lc the linphone core * @param vsize the video resolution choosed for capuring and previewing. It can be (0,0) to not request any specific preview size and let the core optimize the processing. - * @deprecated Use linphone_core_set_preview_video_definition() instead + * @deprecated Use #linphone_core_set_preview_video_definition() instead. Deprecated since 2017-03-28. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_set_preview_video_size(LinphoneCore *lc, MSVideoSize vsize); @@ -3496,56 +3561,60 @@ LINPHONE_PUBLIC void linphone_core_set_preview_video_size_by_name(LinphoneCore * /** * Get the definition of the captured video. - * @param[in] lc LinphoneCore object - * @return The captured LinphoneVideoDefinition if it was previously set by linphone_core_set_preview_video_definition(), otherwise a 0x0 LinphoneVideoDefinition. + * @param[in] lc #LinphoneCore object + * @return The captured #LinphoneVideoDefinition if it was previously set by linphone_core_set_preview_video_definition(), otherwise a 0x0 LinphoneVideoDefinition. * @see linphone_core_set_preview_video_definition() * @ingroup media_parameters */ LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_core_get_preview_video_definition(const LinphoneCore *lc); /** - * Returns video size for the captured video if it was previously set by linphone_core_set_preview_video_size(), otherwise returns a 0,0 size. - * @see linphone_core_set_preview_video_size() + * @brief Returns video size for the captured video if it was previously set by #linphone_core_set_preview_video_size(), otherwise returns a 0,0 size. + * @see #linphone_core_set_preview_video_size() * @ingroup media_parameters * @param lc the core - * @return a MSVideoSize - * @deprecated Use linphone_core_get_preview_video_definition() instead + * @return a #MSVideoSize + * @deprecated Use #linphone_core_get_preview_video_definition() instead. Since 2017-03-28. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_preview_video_size(const LinphoneCore *lc); /** * Get the effective video definition provided by the camera for the captured video. * When preview is disabled or not yet started this function returns a 0x0 video definition. - * @param[in] lc LinphoneCore object - * @return The captured LinphoneVideoDefinition + * @param[in] lc #LinphoneCore object + * @return The captured #LinphoneVideoDefinition * @ingroup media_parameters * @see linphone_core_set_preview_video_definition() */ LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_core_get_current_preview_video_definition(const LinphoneCore *lc); /** - * Returns the effective video size for the captured video as provided by the camera. + * @brief Returns the effective video size for the captured video as provided by the camera. + * * When preview is disabled or not yet started, this function returns a zeroed video size. - * @see linphone_core_set_preview_video_size() + * @see #linphone_core_set_preview_video_size() * @ingroup media_parameters * @param lc the core - * @return a MSVideoSize - * @deprecated Use linphone_core_get_current_preview_video_definition() instead + * @return a #MSVideoSize + * @deprecated Use #linphone_core_get_current_preview_video_definition() instead. Deprecated since 2017-03-28. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_current_preview_video_size(const LinphoneCore *lc); /** * Get the preferred video definition for the stream that is captured and sent to the remote party. - * @param[in] lc LinphoneCore object - * @return The preferred LinphoneVideoDefinition + * @param[in] lc #LinphoneCore object + * @return The preferred #LinphoneVideoDefinition * @ingroup media_parameters */ LINPHONE_PUBLIC const LinphoneVideoDefinition * linphone_core_get_preferred_video_definition(const LinphoneCore *lc); /** - * Returns the current preferred video size for sending. + * @brief Returns the current preferred video size for sending. * @ingroup media_parameters - * @deprecated Use linphone_core_get_preferred_video_definition() instead + * @deprecated Use linphone_core_get_preferred_video_definition() instead. Deprecated since 2017-03-28. + * @donotwrap **/ LINPHONE_PUBLIC LINPHONE_DEPRECATED MSVideoSize linphone_core_get_preferred_video_size(const LinphoneCore *lc); @@ -3573,7 +3642,7 @@ LINPHONE_PUBLIC void linphone_core_set_preferred_video_size_by_name(LinphoneCore * Based on the available bandwidth constraints and network conditions, the video encoder * remains free to lower the framerate. There is no warranty that the preferred frame rate be the actual framerate. * used during a call. Default value is 0, which means "use encoder's default fps value". - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param fps the target frame rate in number of frames per seconds. * @ingroup media_parameters **/ @@ -3596,7 +3665,7 @@ LINPHONE_PUBLIC void linphone_core_preview_ogl_render(const LinphoneCore *lc); /** * Controls video preview enablement. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] val A boolean value telling whether the video preview is to be shown * Video preview refers to the action of displaying the local webcam image * to the user while not in call. @@ -3606,12 +3675,39 @@ LINPHONE_PUBLIC void linphone_core_enable_video_preview(LinphoneCore *lc, bool_t /** * Tells whether video preview is enabled. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value telling whether video preview is enabled * @ingroup media_parameters **/ LINPHONE_PUBLIC bool_t linphone_core_video_preview_enabled(const LinphoneCore *lc); +/** + * Controls QRCode enablement. + * @param[in] lc LinphoneCore object + * @param[in] val A boolean value telling whether the QRCode is enabled in the preview. + * @ingroup media_parameters + **/ +LINPHONE_PUBLIC void linphone_core_enable_qrcode_video_preview(LinphoneCore *lc, bool_t val); + +/** + * Set the rectangle where the decoder will search a QRCode + * @param[in] lc LinphoneCore* object + * @param[in] x axis + * @param[in] y axis + * @param[in] w width + * @param[in] h height + * @ingroup media_parameters + */ +LINPHONE_PUBLIC void linphone_core_set_qrcode_decode_rect(LinphoneCore *lc, const int x, const int y, const int w, const int h); + +/** + * Tells whether QRCode is enabled in the preview. + * @param[in] lc LinphoneCore object + * @return A boolean value telling whether QRCode is enabled in the preview. + * @ingroup media_parameters + **/ +LINPHONE_PUBLIC bool_t linphone_core_qrcode_video_preview_enabled(const LinphoneCore *lc); + /** * Take a photo of currently from capture device and write it into a jpeg file. * Note that the snapshot is asynchronous, an application shall not assume that the file is created when the function returns. @@ -3624,7 +3720,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_take_preview_snapshot(LinphoneCore /** * Enables or disable self view during calls. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] val A boolean value telling whether to enable self view * Self-view refers to having local webcam image inserted in corner * of the video window during calls. @@ -3635,7 +3731,7 @@ LINPHONE_PUBLIC void linphone_core_enable_self_view(LinphoneCore *lc, bool_t val /** * Tells whether video self view during call is enabled or not. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value telling whether self view is enabled * @see linphone_core_enable_self_view() for details. * @ingroup media_parameters @@ -3654,15 +3750,25 @@ LINPHONE_PUBLIC void linphone_core_reload_video_devices(LinphoneCore *lc); /** * Gets the list of the available video capture devices. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return An unmodifiable array of strings contanining the names of the available video capture devices that is NULL terminated * @ingroup media_parameters + * @deprecated use linphone_core_get_video_devices_list instead + * @donotwrap **/ LINPHONE_PUBLIC const char** linphone_core_get_video_devices(const LinphoneCore *lc); +/** + * Gets the list of the available video capture devices. + * @param[in] lc #LinphoneCore object + * @return \bctbx_list{char *} An unmodifiable array of strings contanining the names of the available video capture devices that is NULL terminated + * @ingroup media_parameters +**/ +LINPHONE_PUBLIC bctbx_list_t * linphone_core_get_video_devices_list(const LinphoneCore *lc); + /** * Sets the active video device. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param id The name of the video device to use as returned by linphone_core_get_video_devices() * @ingroup media_parameters **/ @@ -3670,7 +3776,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_video_device(LinphoneCore *lc, /** * Returns the name of the currently active video device. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The name of the currently active video device * @ingroup media_parameters **/ @@ -3710,7 +3816,7 @@ LINPHONE_PUBLIC float linphone_core_get_static_picture_fps(LinphoneCore *lc); /** * Get the native window handle of the video window. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The native window handle of the video window * @ingroup media_parameters **/ @@ -3737,7 +3843,7 @@ LINPHONE_PUBLIC void linphone_core_set_native_video_window_id(LinphoneCore *lc, /** * Get the native window handle of the video preview window. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The native window handle of the video preview window * @ingroup media_parameters **/ @@ -3747,7 +3853,7 @@ LINPHONE_PUBLIC void * linphone_core_get_native_preview_window_id(const Linphone * Set the native window id where the preview video (local camera) is to be displayed. * This has to be used in conjonction with linphone_core_use_preview_window(). * MacOS, Linux, Windows: if not set or zero the core will create its own window, unless the special id -1 is given. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] id The native window id where the preview video is to be displayed * @ingroup media_parameters **/ @@ -3764,7 +3870,7 @@ LINPHONE_PUBLIC void linphone_core_use_preview_window(LinphoneCore *lc, bool_t y /** * Gets the current device orientation. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current device orientation * @ingroup media_parameters * @see linphone_core_set_device_rotation() @@ -3777,7 +3883,7 @@ LINPHONE_PUBLIC int linphone_core_get_device_rotation(LinphoneCore *lc); * oriented images. The exact meaning of the value in rotation if left to each device * specific implementations. * IOS supported values are 0 for UIInterfaceOrientationPortrait and 270 for UIInterfaceOrientationLandscapeRight. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] rotation The orientation to use * @ingroup media_parameters **/ @@ -3805,7 +3911,7 @@ void linphone_core_show_video(LinphoneCore *lc, bool_t show); /** * Ask the core to stream audio from and to files, instead of using the soundcard. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] yesno A boolean value asking to stream audio from and to files or not. * @ingroup media_parameters **/ @@ -3814,7 +3920,7 @@ LINPHONE_PUBLIC void linphone_core_set_use_files(LinphoneCore *lc, bool_t yesno) /** * Gets whether linphone is currently streaming audio from and to files, rather * than using the soundcard. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value representing whether linphone is streaming audio from and to files or not. * @ingroup media_parameters **/ @@ -3825,7 +3931,7 @@ LINPHONE_PUBLIC bool_t linphone_core_get_use_files(LinphoneCore *lc); * or when files are used instead of soundcards (see linphone_core_set_use_files()). * * The file is a 16 bit linear wav file. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The path to the file that is played when putting somebody on hold. * @ingroup media_parameters */ @@ -3836,7 +3942,7 @@ LINPHONE_PUBLIC const char * linphone_core_get_play_file(const LinphoneCore *lc) * or when files are used instead of soundcards (see linphone_core_set_use_files()). * * The file must be a 16 bit linear wav file. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] file The path to the file to be played when putting somebody on hold. * @ingroup media_parameters **/ @@ -3848,7 +3954,7 @@ LINPHONE_PUBLIC void linphone_core_set_play_file(LinphoneCore *lc, const char *f * * This feature is different from call recording (linphone_call_params_set_record_file()) * The file is a 16 bit linear wav file. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The path to the file where incoming stream is recorded. * @ingroup media_parameters **/ @@ -3860,7 +3966,7 @@ LINPHONE_PUBLIC const char * linphone_core_get_record_file(const LinphoneCore *l * * This feature is different from call recording (linphone_call_params_set_record_file()) * The file will be a 16 bit linear wav file. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] file The path to the file where incoming stream is to be recorded. * @ingroup media_parameters **/ @@ -3868,7 +3974,7 @@ LINPHONE_PUBLIC void linphone_core_set_record_file(LinphoneCore *lc, const char /** * Plays a dtmf sound to the local user. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] dtmf DTMF to play ['0'..'16'] | '#' | '#' * @param[in] duration_ms Duration in ms, -1 means play until next further call to #linphone_core_stop_dtmf() * @ingroup media_parameters @@ -3877,7 +3983,7 @@ LINPHONE_PUBLIC void linphone_core_play_dtmf(LinphoneCore *lc, char dtmf, int du /** * Stops playing a dtmf started by linphone_core_play_dtmf(). - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @ingroup media_parameters **/ LINPHONE_PUBLIC void linphone_core_stop_dtmf(LinphoneCore *lc); @@ -3894,7 +4000,7 @@ LINPHONE_PUBLIC int linphone_core_get_mtu(const LinphoneCore *lc); * Sets the maximum transmission unit size in bytes. * This information is useful for sending RTP packets. * Default value is 1500. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] mtu The MTU in bytes * @ingroup media_parameters **/ @@ -3932,7 +4038,7 @@ LINPHONE_PUBLIC void linphone_core_set_media_network_reachable(LinphoneCore* lc, /** * Enables signaling keep alive, small udp packet sent periodically to keep udp NAT association. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] enable A boolean value telling whether signaling keep alive is to be enabled * @ingroup network_parameters */ @@ -3940,7 +4046,7 @@ LINPHONE_PUBLIC void linphone_core_enable_keep_alive(LinphoneCore* lc, bool_t en /** * Is signaling keep alive enabled. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value telling whether signaling keep alive is enabled * @ingroup network_parameters */ @@ -3948,20 +4054,32 @@ LINPHONE_PUBLIC bool_t linphone_core_keep_alive_enabled(LinphoneCore* lc); /** * Retrieves the user pointer that was given to linphone_core_new() - * @param[in] lc LinphoneCore object - * @return The user data associated with the LinphoneCore object + * @param[in] lc #LinphoneCore object + * @return The user data associated with the #LinphoneCore object * @ingroup initializing **/ LINPHONE_PUBLIC void *linphone_core_get_user_data(const LinphoneCore *lc); /** * Associate a user pointer to the linphone core. - * @param[in] lc LinphoneCore object - * @param[in] userdata The user data to associate with the LinphoneCore object + * @param[in] lc #LinphoneCore object + * @param[in] userdata The user data to associate with the #LinphoneCore object * @ingroup initializing **/ LINPHONE_PUBLIC void linphone_core_set_user_data(LinphoneCore *lc, void *userdata); +/** + * This method is called by the application to notify the linphone core library when it enters background mode. + * @ingroup misc + */ +LINPHONE_PUBLIC void linphone_core_enter_background(LinphoneCore *lc); + +/** + * This method is called by the application to notify the linphone core library when it enters foreground mode. + * @ingroup misc + */ +LINPHONE_PUBLIC void linphone_core_enter_foreground(LinphoneCore *lc); + /** * Returns the LpConfig object used to manage the storage (config) file. * @param[in] lc #LinphoneCore object @@ -3969,7 +4087,7 @@ LINPHONE_PUBLIC void linphone_core_set_user_data(LinphoneCore *lc, void *userdat * sections and pairs of key=value in the configuration file. * @ingroup misc **/ -LINPHONE_PUBLIC LinphoneConfig * linphone_core_get_config(LinphoneCore *lc); +LINPHONE_PUBLIC LinphoneConfig * linphone_core_get_config(const LinphoneCore *lc); /** * Create a LpConfig object from a user config file. @@ -4000,8 +4118,8 @@ LINPHONE_PUBLIC void linphone_core_set_waiting_callback(LinphoneCore *lc, Linpho LINPHONE_PUBLIC const bctbx_list_t * linphone_core_get_sip_setups(LinphoneCore *lc); /** - * Destroys a LinphoneCore - * @param[in] lc LinphoneCore object + * Destroys a #LinphoneCore + * @param[in] lc #LinphoneCore object * @ingroup initializing * @deprecated Use linphone_core_unref() instead. * @donotwrap @@ -4026,7 +4144,7 @@ void linphone_core_set_rtp_transport_factories(LinphoneCore* lc, LinphoneRtpTran /** * Retrieve RTP statistics regarding current call. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[out] local RTP statistics computed locally. * @param[out] remote RTP statistics computed by far end (obtained via RTCP feedback). * @return 0 or -1 if no call is running. @@ -4036,7 +4154,7 @@ int linphone_core_get_current_call_stats(LinphoneCore *lc, rtp_stats_t *local, r /** * Get the number of Call - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current number of calls * @ingroup call_control **/ @@ -4045,9 +4163,9 @@ LINPHONE_PUBLIC int linphone_core_get_calls_nb(const LinphoneCore *lc); /** * Gets the current list of calls. * 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. - * To hold references to LinphoneCall object into your program, you must use linphone_call_ref(). - * @param[in] lc The LinphoneCore object + * Similarly the #LinphoneCall objects inside it might be destroyed without prior notice. + * To hold references to #LinphoneCall object into your program, you must use linphone_call_ref(). + * @param[in] lc The #LinphoneCore object * @return \bctbx_list{LinphoneCall} * @ingroup call_control **/ @@ -4114,7 +4232,7 @@ LINPHONE_PUBLIC void linphone_core_reload_ms_plugins(LinphoneCore *lc, const cha * @ingroup call_control * @param lc * @param uri which should match call remote uri - * @return LinphoneCall or NULL is no match is found + * @return #LinphoneCall or NULL is no match is found */ LINPHONE_PUBLIC LinphoneCall* linphone_core_find_call_from_uri(const LinphoneCore *lc, const char *uri); @@ -4248,6 +4366,21 @@ LINPHONE_PUBLIC LinphoneStatus linphone_core_stop_conference_recording(LinphoneC */ LINPHONE_PUBLIC LinphoneConference *linphone_core_get_conference(LinphoneCore *lc); +/** + * Enable the conference server feature. This has the effect to listen of the conference factory uri + * to create new conferences when receiving INVITE messages there. + * @param[in] lc A #LinphoneCore object + * @param[in] enable A boolean value telling whether to enable or disable the conference server feature + */ +LINPHONE_PUBLIC void linphone_core_enable_conference_server (LinphoneCore *lc, bool_t enable); + +/** + * Tells whether the conference server feature is enabled. + * @param[in] lc A #LinphoneCore object + * @return A boolean value telling whether the conference server feature is enabled or not + */ +LINPHONE_PUBLIC bool_t linphone_core_conference_server_enabled (const LinphoneCore *lc); + /** * @} */ @@ -4275,7 +4408,7 @@ LINPHONE_PUBLIC void linphone_core_set_max_calls(LinphoneCore *lc, int max); * In order to prevent this situation, an application can use linphone_core_sound_resources_locked() to know whether * it is possible at a given time to start a new outgoing call. * When the function returns TRUE, an application should not allow the user to start an outgoing call. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return A boolean value telling whether a call will need the sound resources in near future * @ingroup call_control **/ @@ -4284,8 +4417,8 @@ LINPHONE_PUBLIC bool_t linphone_core_sound_resources_locked(LinphoneCore *lc); /** * Check if a media encryption type is supported * @param lc core - * @param menc LinphoneMediaEncryption - * @return whether a media encryption scheme is supported by the LinphoneCore engine + * @param menc #LinphoneMediaEncryption + * @return whether a media encryption scheme is supported by the #LinphoneCore engine * @ingroup initializing **/ LINPHONE_PUBLIC bool_t linphone_core_media_encryption_supported(const LinphoneCore *lc, LinphoneMediaEncryption menc); @@ -4338,14 +4471,14 @@ LINPHONE_PUBLIC bool_t linphone_core_tunnel_available(void); * get tunnel instance if available * @ingroup tunnel * @param lc core object - * @returns LinphoneTunnel or NULL if not available + * @returns #LinphoneTunnel or NULL if not available */ LINPHONE_PUBLIC LinphoneTunnel *linphone_core_get_tunnel(const LinphoneCore *lc); /** * Set the DSCP field for SIP signaling channel. * The DSCP defines the quality of service in IP packets. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] dscp The DSCP value to set * @ingroup network_parameters **/ @@ -4354,7 +4487,7 @@ LINPHONE_PUBLIC void linphone_core_set_sip_dscp(LinphoneCore *lc, int dscp); /** * Get the DSCP field for SIP signaling channel. * The DSCP defines the quality of service in IP packets. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current DSCP value * @ingroup network_parameters **/ @@ -4363,7 +4496,7 @@ LINPHONE_PUBLIC int linphone_core_get_sip_dscp(const LinphoneCore *lc); /** * Set the DSCP field for outgoing audio streams. * The DSCP defines the quality of service in IP packets. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] dscp The DSCP value to set * @ingroup network_parameters **/ @@ -4372,7 +4505,7 @@ LINPHONE_PUBLIC void linphone_core_set_audio_dscp(LinphoneCore *lc, int dscp); /** * Get the DSCP field for outgoing audio streams. * The DSCP defines the quality of service in IP packets. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current DSCP value * @ingroup network_parameters **/ @@ -4381,7 +4514,7 @@ LINPHONE_PUBLIC int linphone_core_get_audio_dscp(const LinphoneCore *lc); /** * Set the DSCP field for outgoing video streams. * The DSCP defines the quality of service in IP packets. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] dscp The DSCP value to set * @ingroup network_parameters **/ @@ -4390,7 +4523,7 @@ LINPHONE_PUBLIC void linphone_core_set_video_dscp(LinphoneCore *lc, int dscp); /** * Get the DSCP field for outgoing video streams. * The DSCP defines the quality of service in IP packets. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current DSCP value * @ingroup network_parameters **/ @@ -4411,7 +4544,7 @@ LINPHONE_PUBLIC void linphone_core_set_video_display_filter(LinphoneCore *lc, co /** * Get the name of the mediastreamer2 filter used for echo cancelling. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The name of the mediastreamer2 filter used for echo cancelling * @ingroup media_parameters */ @@ -4420,7 +4553,7 @@ LINPHONE_PUBLIC const char * linphone_core_get_echo_canceller_filter_name(const /** * Set the name of the mediastreamer2 filter to be used for echo cancelling. * This is for advanced users of the library. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] filtername The name of the mediastreamer2 filter to be used for echo cancelling * @ingroup media_parameters */ @@ -4435,7 +4568,7 @@ typedef void (*ContactSearchCallback)( LinphoneContactSearch* id, bctbx_list_t* * Set URI where to download xml configuration file at startup. * This can also be set from configuration file or factory config file, from [misc] section, item "config-uri". * Calling this function does not load the configuration. It will write the value into configuration so that configuration - * from remote URI will take place at next LinphoneCore start. + * from remote URI will take place at next #LinphoneCore start. * @param lc the linphone core * @param uri the http or https uri to use in order to download the configuration. Passing NULL will disable remote provisioning. * @return -1 if uri could not be parsed, 0 otherwise. Note that this does not check validity of URI endpoint nor scheme and download may still fail. @@ -4525,9 +4658,19 @@ LINPHONE_PUBLIC const char * linphone_core_get_file_transfer_server(LinphoneCore * @param core the core * @return the supported formats, typically 'wav' and 'mkv' * @ingroup media_parameters + * @deprecated use linphone_core_get_supported_file_formats_list instead + * @donotwrap **/ LINPHONE_PUBLIC const char ** linphone_core_get_supported_file_formats(LinphoneCore *core); +/** + * Returns a null terminated table of strings containing the file format extension supported for call recording. + * @param core the core + * @return \bctbx_list{char *} the supported formats, typically 'wav' and 'mkv' + * @ingroup media_parameters +**/ +LINPHONE_PUBLIC bctbx_list_t * linphone_core_get_supported_file_formats_list(LinphoneCore *core); + /** * Returns whether a specific file format is supported. * @see linphone_core_get_supported_file_formats @@ -4540,7 +4683,7 @@ LINPHONE_PUBLIC bool_t linphone_core_file_format_supported(LinphoneCore *lc, con /** * This function controls signaling features supported by the core. * They are typically included in a SIP Supported header. - * @param[in] core LinphoneCore object + * @param[in] core #LinphoneCore object * @param[in] tag The feature tag name * @ingroup initializing **/ @@ -4548,7 +4691,7 @@ LINPHONE_PUBLIC void linphone_core_add_supported_tag(LinphoneCore *core, const c /** * Remove a supported tag. - * @param[in] core LinphoneCore object + * @param[in] core #LinphoneCore object * @param[in] tag The tag to remove * @ingroup initializing * @see linphone_core_add_supported_tag() @@ -4557,10 +4700,10 @@ LINPHONE_PUBLIC void linphone_core_remove_supported_tag(LinphoneCore *core, cons /** * 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(). + * 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[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] mode The AVPF mode to use. * @ingroup media_parameters **/ @@ -4568,7 +4711,7 @@ LINPHONE_PUBLIC void linphone_core_set_avpf_mode(LinphoneCore *lc, LinphoneAVPFM /** * Return AVPF enablement. See linphone_core_set_avpf_mode() . - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current AVPF mode * @ingroup media_parameters **/ @@ -4577,7 +4720,7 @@ LINPHONE_PUBLIC LinphoneAVPFMode linphone_core_get_avpf_mode(const LinphoneCore /** * 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[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] interval The report interval in seconds * @ingroup media_parameters **/ @@ -4585,7 +4728,7 @@ LINPHONE_PUBLIC void linphone_core_set_avpf_rr_interval(LinphoneCore *lc, int in /** * Return the avpf report interval in seconds. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The current AVPF report interval in seconds * @ingroup media_parameters **/ @@ -4696,30 +4839,33 @@ LINPHONE_PUBLIC void linphone_core_enable_video_multicast(LinphoneCore *core, bo LINPHONE_PUBLIC bool_t linphone_core_video_multicast_enabled(const LinphoneCore *core); /** - * Set the network simulator parameters. + * @brief Set the network simulator parameters. + * * Liblinphone has the capabability of simulating the effects of a network (latency, lost packets, jitter, max bandwidth). * Please refer to the oRTP documentation for the meaning of the parameters of the OrtpNetworkSimulatorParams structure. * This function has effect for future calls, but not for currently running calls, though this behavior may be changed in future versions. * @warning Due to design of network simulation in oRTP, simulation is applied independently for audio and video stream. This means for example that a bandwidth * limit of 250kbit/s will have no effect on an audio stream running at 40kbit/s while a videostream targetting 400kbit/s will be highly affected. - * @param lc the LinphoneCore + * @param lc the #LinphoneCore * @param params the parameters used for the network simulation. * @return 0 if successful, -1 otherwise. * @ingroup media_parameters + * @donotwrap **/ LINPHONE_PUBLIC LinphoneStatus linphone_core_set_network_simulator_params(LinphoneCore *lc, const OrtpNetworkSimulatorParams *params); /** - * Get the previously set network simulation parameters. + * @brief Get the previously set network simulation parameters. * @see linphone_core_set_network_simulator_params - * @return a OrtpNetworkSimulatorParams structure. + * @return a #OrtpNetworkSimulatorParams structure. * @ingroup media_parameters + * @donotwrap **/ LINPHONE_PUBLIC const OrtpNetworkSimulatorParams *linphone_core_get_network_simulator_params(const LinphoneCore *lc); /** * Set the video preset to be used for video calls. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] preset The name of the video preset to be used (can be NULL to use the default video preset). * @ingroup media_parameters */ @@ -4727,7 +4873,7 @@ LINPHONE_PUBLIC void linphone_core_set_video_preset(LinphoneCore *lc, const char /** * Get the video preset used for video calls. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return The name of the video preset used for video calls (can be NULL if the default video preset is used). * @ingroup media_parameters */ @@ -4735,15 +4881,17 @@ LINPHONE_PUBLIC const char * linphone_core_get_video_preset(const LinphoneCore * /** * Gets if realtime text is enabled or not - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return true if realtime text is enabled, false otherwise * @ingroup media_parameters */ LINPHONE_PUBLIC bool_t linphone_core_realtime_text_enabled(LinphoneCore *lc); +LINPHONE_PUBLIC void linphone_core_enable_realtime_text(LinphoneCore *lc, bool_t value); + /** * Set http proxy address to be used for signaling during next channel connection. Use #linphone_core_set_network_reachable FASLE/TRUE to force channel restart. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] host Hostname of IP adress of the http proxy (can be NULL to disable). * @ingroup network_parameters */ @@ -4751,7 +4899,7 @@ LINPHONE_PUBLIC void linphone_core_set_http_proxy_host(LinphoneCore *lc, const c /** * Set http proxy port to be used for signaling. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] port of the http proxy. * @ingroup network_parameters */ @@ -4759,7 +4907,7 @@ LINPHONE_PUBLIC void linphone_core_set_http_proxy_port(LinphoneCore *lc, int por /** * Get http proxy address to be used for signaling. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return hostname of IP adress of the http proxy (can be NULL to disable). * @ingroup network_parameters */ @@ -4767,7 +4915,7 @@ LINPHONE_PUBLIC const char *linphone_core_get_http_proxy_host(const LinphoneCore /** * Get http proxy port to be used for signaling. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return port of the http proxy. * @ingroup network_parameters */ @@ -4777,8 +4925,8 @@ LINPHONE_PUBLIC LinphoneRingtonePlayer *linphone_core_get_ringtoneplayer(Linphon /** * Sets a TLS certificate used for TLS authentication - * The certificate won't be stored, you have to set it after each LinphoneCore startup - * @param lc LinphoneCore object + * The certificate won't be stored, you have to set it after each #LinphoneCore startup + * @param lc #LinphoneCore object * @param tls_cert the TLS certificate * @ingroup network_parameters */ @@ -4786,8 +4934,8 @@ LINPHONE_PUBLIC void linphone_core_set_tls_cert(LinphoneCore *lc, const char *tl /** * Sets a TLS key used for TLS authentication - * The key won't be stored, you have to set it after each LinphoneCore startup - * @param lc LinphoneCore object + * The key won't be stored, you have to set it after each #LinphoneCore startup + * @param lc #LinphoneCore object * @param tls_key the TLS key * @ingroup network_parameters */ @@ -4796,7 +4944,7 @@ LINPHONE_PUBLIC void linphone_core_set_tls_key(LinphoneCore *lc, const char *tls /** * Sets a TLS certificate path used for TLS authentication * The path will be stored in the rc file and automatically restored on startup - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @param tls_cert_path path to the TLS certificate * @ingroup network_parameters */ @@ -4805,7 +4953,7 @@ LINPHONE_PUBLIC void linphone_core_set_tls_cert_path(LinphoneCore *lc, const cha /** * Sets a TLS key path used for TLS authentication * The path will be stored in the rc file and automatically restored on startup - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @param tls_key_path path to the TLS key * @ingroup network_parameters */ @@ -4813,7 +4961,7 @@ LINPHONE_PUBLIC void linphone_core_set_tls_key_path(LinphoneCore *lc, const char /** * Gets the TLS certificate - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @return the TLS certificate or NULL if not set yet * @ingroup network_parameters */ @@ -4821,7 +4969,7 @@ LINPHONE_PUBLIC const char *linphone_core_get_tls_cert(const LinphoneCore *lc); /** * Gets the TLS key - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @return the TLS key or NULL if not set yet * @ingroup network_parameters */ @@ -4829,7 +4977,7 @@ LINPHONE_PUBLIC const char *linphone_core_get_tls_key(const LinphoneCore *lc); /** * Gets the path to the TLS certificate file - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @return the TLS certificate path or NULL if not set yet * @ingroup network_parameters */ @@ -4837,7 +4985,7 @@ LINPHONE_PUBLIC const char *linphone_core_get_tls_cert_path(const LinphoneCore * /** * Gets the path to the TLS key file - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @return the TLS key path or NULL if not set yet * @ingroup network_parameters */ @@ -4845,23 +4993,25 @@ LINPHONE_PUBLIC const char *linphone_core_get_tls_key_path(const LinphoneCore *l /** * Sets an IM Encryption Engine in the core - * @param lc LinphoneCore object - * @param imee LinphoneImEncryptionEngine object + * @param lc #LinphoneCore object + * @param imee #LinphoneImEncryptionEngine object * @ingroup chatroom + * @donotwrap */ LINPHONE_PUBLIC void linphone_core_set_im_encryption_engine(LinphoneCore *lc, LinphoneImEncryptionEngine *imee); /** * Gets the IM Encryption Engine in the core if possible - * @param lc LinphoneCore object + * @param lc #LinphoneCore object * @return the IM Encryption Engine in the core or NULL * @ingroup chatroom + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngine * linphone_core_get_im_encryption_engine(const LinphoneCore *lc); /** * Tells whether a content type is supported. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] content_type The content type to check * @return A boolean value telling whether the specified content type is supported or not. */ @@ -4870,11 +5020,27 @@ LINPHONE_PUBLIC bool_t linphone_core_is_content_type_supported(const LinphoneCor /** * Add support for the specified content type. * It is the application responsibility to handle it correctly afterwards. - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @param[in] content_type The content type to add support for */ LINPHONE_PUBLIC void linphone_core_add_content_type_support(LinphoneCore *lc, const char *content_type); +/** + * Get the linphone specs value telling what functionalities the linphone client supports. + * @param[in] core #LinphoneCore object + * @return The linphone specs telling what functionalities the linphone client supports + * @ingroup initializing + */ +LINPHONE_PUBLIC const char *linphone_core_get_linphone_specs (const LinphoneCore *core); + +/** + * Set the linphone specs value telling what functionalities the linphone client supports. + * @param[in] core #LinphoneCore object + * @param[in] specs The linphone specs to set + * @ingroup initializing + */ +LINPHONE_PUBLIC void linphone_core_set_linphone_specs (LinphoneCore *core, const char *specs); + /** * Remove support for the specified content type. * It is the application responsibility to handle it correctly afterwards. @@ -4893,19 +5059,32 @@ LINPHONE_PUBLIC void linphone_core_remove_content_type_support(LinphoneCore *lc, * Set the chat database path. * @param lc the linphone core * @param path the database path + * @deprecated 2018-01-10: Use only for migration purposes */ -LINPHONE_PUBLIC void linphone_core_set_chat_database_path(LinphoneCore *lc, const char *path); +LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_core_set_chat_database_path(LinphoneCore *lc, const char *path); /** * Get path to the database file used for storing chat messages. * @param lc the linphone core * @return file path or NULL if not exist + * @deprecated 2018-01-10 **/ -LINPHONE_PUBLIC const char *linphone_core_get_chat_database_path(const LinphoneCore *lc); +LINPHONE_DEPRECATED LINPHONE_PUBLIC const char *linphone_core_get_chat_database_path(const LinphoneCore *lc); /** - * Get a chat room whose peer is the supplied address. If it does not exist yet, it will be created. - * No reference is transfered to the application. The LinphoneCore keeps a reference on the chat room. + * Create a client-side group chat room. When calling this function the chat room is only created + * at the client-side and is empty. You need to call linphone_chat_room_add_participants() to + * create at the server side and add participants to it. + * @param[in] lc A #LinphoneCore object + * @param[in] subject The subject of the group chat room + * @param[in] fallback Boolean value telling whether we should plan on being able to fallback to a basic chat room if the client-side group chat room creation fails + * @return The newly created client-side group chat room. + */ +LINPHONE_PUBLIC LinphoneChatRoom * linphone_core_create_client_group_chat_room(LinphoneCore *lc, const char *subject, bool_t fallback); + +/** + * Get a basic chat room whose peer is the supplied address. If it does not exist yet, it will be created. + * No reference is transfered to the application. The #LinphoneCore keeps a reference on the chat room. * @param lc the linphone core * @param addr a linphone address. * @return #LinphoneChatRoom where messaging can take place. @@ -4913,14 +5092,42 @@ LINPHONE_PUBLIC const char *linphone_core_get_chat_database_path(const LinphoneC LINPHONE_PUBLIC LinphoneChatRoom *linphone_core_get_chat_room(LinphoneCore *lc, const LinphoneAddress *addr); /** - * 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. - * No reference is transfered to the application. The LinphoneCore keeps a reference on the chat room. + * Get a basic chat room for messaging from a sip uri like sip:joe@sip.linphone.org. If it does not exist yet, it will be created. + * No reference is transfered to the application. The #LinphoneCore keeps a reference on the chat room. * @param lc A #LinphoneCore object * @param to The destination address for messages. * @return #LinphoneChatRoom where messaging can take place. **/ LINPHONE_PUBLIC LinphoneChatRoom *linphone_core_get_chat_room_from_uri(LinphoneCore *lc, const char *to); +/** + * Find a chat room. + * No reference is transfered to the application. The #LinphoneCore keeps a reference on the chat room. + * @param lc the linphone core + * @param peer_addr a linphone address. + * @param local_addr a linphone address. + * @return #LinphoneChatRoom where messaging can take place. +**/ +LINPHONE_PUBLIC LinphoneChatRoom *linphone_core_find_chat_room ( + const LinphoneCore *lc, + const LinphoneAddress *peer_addr, + const LinphoneAddress *local_addr +); + +/** + * Find a one to one chat room. + * No reference is transfered to the application. The #LinphoneCore keeps a reference on the chat room. + * @param lc the linphone core + * @param local_addr a linphone address. + * @param participant_addr a linphone address. + * @return #LinphoneChatRoom where messaging can take place. +**/ +LINPHONE_PUBLIC LinphoneChatRoom *linphone_core_find_one_to_one_chat_room ( + const LinphoneCore *lc, + const LinphoneAddress *local_addr, + const LinphoneAddress *participant_addr +); + /** * Removes a chatroom including all message history from the LinphoneCore. * @param lc A #LinphoneCore object @@ -4949,9 +5156,9 @@ LINPHONE_PUBLIC void linphone_core_enable_chat(LinphoneCore *lc); LINPHONE_PUBLIC bool_t linphone_core_chat_enabled(const LinphoneCore *lc); /** - * Get the LinphoneImNotifPolicy object controlling the instant messaging notifications. - * @param[in] lc LinphoneCore object - * @return A LinphoneImNotifPolicy object. + * Get the #LinphoneImNotifPolicy object controlling the instant messaging notifications. + * @param[in] lc #LinphoneCore object + * @return A #LinphoneImNotifPolicy object. */ LINPHONE_PUBLIC LinphoneImNotifPolicy * linphone_core_get_im_notif_policy(const LinphoneCore *lc); @@ -4961,8 +5168,8 @@ LINPHONE_PUBLIC LinphoneImNotifPolicy * linphone_core_get_im_notif_policy(const /** * Create a content with default values from Linphone core. - * @param[in] lc LinphoneCore object - * @return LinphoneContent object with default values set + * @param[in] lc #LinphoneCore object + * @return #LinphoneContent object with default values set * @ingroup misc */ LINPHONE_PUBLIC LinphoneContent * linphone_core_create_content(LinphoneCore *lc); @@ -4981,7 +5188,7 @@ LINPHONE_PUBLIC LinphoneContent * linphone_core_create_content(LinphoneCore *lc) * @param event the event name * @param expires the whished duration of the subscription * @param body an optional body, may be NULL. - * @return a LinphoneEvent holding the context of the created subcription. + * @return a #LinphoneEvent holding the context of the created subcription. **/ LINPHONE_PUBLIC LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body); @@ -4993,7 +5200,7 @@ LINPHONE_PUBLIC LinphoneEvent *linphone_core_subscribe(LinphoneCore *lc, const L * @param resource the destination resource * @param event the event name * @param expires the whished duration of the subscription - * @return a LinphoneEvent holding the context of the created subcription. + * @return a #LinphoneEvent holding the context of the created subcription. **/ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires); @@ -5004,20 +5211,20 @@ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_subscribe(LinphoneCore *lc, * @param lc the #LinphoneCore * @param resource the destination resource * @param event the event name - * @return a LinphoneEvent holding the context of the notification. + * @return a #LinphoneEvent holding the context of the notification. **/ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_notify(LinphoneCore *lc, const LinphoneAddress *resource, const char *event); /** * Publish an event state. - * This first create a LinphoneEvent with linphone_core_create_publish() and calls linphone_event_send_publish() to actually send it. + * This first create a #LinphoneEvent with linphone_core_create_publish() and calls linphone_event_send_publish() to actually send it. * After expiry, the publication is refreshed unless it is terminated before. * @param lc the #LinphoneCore * @param resource the resource uri for the event * @param event the event name * @param expires the lifetime of event being published, -1 if no associated duration, in which case it will not be refreshed. * @param body the actual published data - * @return the LinphoneEvent holding the context of the publish. + * @return the #LinphoneEvent holding the context of the publish. **/ LINPHONE_PUBLIC LinphoneEvent *linphone_core_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires, const LinphoneContent *body); @@ -5029,19 +5236,19 @@ LINPHONE_PUBLIC LinphoneEvent *linphone_core_publish(LinphoneCore *lc, const Lin * @param resource the resource uri for the event * @param event the event name * @param expires the lifetime of event being published, -1 if no associated duration, in which case it will not be refreshed. - * @return the LinphoneEvent holding the context of the publish. + * @return the #LinphoneEvent holding the context of the publish. **/ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event, int expires); /** * Create a publish context for a one-shot publish. * After being created, the publish must be sent using linphone_event_send_publish(). - * The LinphoneEvent is automatically terminated when the publish transaction is finished, either with success or failure. + * The #LinphoneEvent is automatically terminated when the publish transaction is finished, either with success or failure. * The application must not call linphone_event_terminate() for such one-shot publish. * @param lc the #LinphoneCore * @param resource the resource uri for the event * @param event the event name - * @return the LinphoneEvent holding the context of the publish. + * @return the #LinphoneEvent holding the context of the publish. **/ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_one_shot_publish(LinphoneCore *lc, const LinphoneAddress *resource, const char *event); @@ -5063,9 +5270,9 @@ LINPHONE_PUBLIC LinphoneEvent *linphone_core_create_one_shot_publish(LinphoneCor LINPHONE_PUBLIC LinphoneFriend * linphone_core_create_friend(LinphoneCore *lc); /** - * Create a LinphoneFriend from the given address. + * Create a #LinphoneFriend from the given address. * @param[in] lc #LinphoneCore object - * @param[in] address A string containing the address to create the LinphoneFriend from + * @param[in] address A string containing the address to create the #LinphoneFriend from * @return The created #LinphoneFriend object */ LINPHONE_PUBLIC LinphoneFriend * linphone_core_create_friend_with_address(LinphoneCore *lc, const char *address); @@ -5106,15 +5313,15 @@ LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_get_presence_model(const L /** * Get my consolidated presence - * @param[in] lc LinphoneCore object + * @param[in] lc #LinphoneCore object * @return My consolidated presence */ LINPHONE_PUBLIC LinphoneConsolidatedPresence linphone_core_get_consolidated_presence(const LinphoneCore *lc); /** * Set my consolidated presence - * @param[in] lc LinphoneCore object - * @param[in] presence LinphoneConsolidatedPresence value + * @param[in] lc #LinphoneCore object + * @param[in] presence #LinphoneConsolidatedPresence value */ LINPHONE_PUBLIC void linphone_core_set_consolidated_presence(LinphoneCore *lc, LinphoneConsolidatedPresence presence); @@ -5149,7 +5356,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_core_remove_friend(LinphoneCor LINPHONE_PUBLIC void linphone_core_reject_subscriber(LinphoneCore *lc, LinphoneFriend *lf); /** - * Get Buddy list of LinphoneFriend + * Get Buddy list of #LinphoneFriend * @param[in] lc #LinphoneCore object * @return \bctbx_list{LinphoneFriend} * @deprecated use linphone_core_get_friends_lists() or linphone_friend_list_get_friends() instead. @@ -5165,7 +5372,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED const bctbx_list_t * linphone_core_get_frie LINPHONE_PUBLIC void linphone_core_notify_all_friends(LinphoneCore *lc, LinphonePresenceModel *presence); /** - * Search a LinphoneFriend by its address. + * Search a #LinphoneFriend by its address. * @param[in] lc #LinphoneCore object. * @param[in] addr The address to use to search the friend. * @return The #LinphoneFriend object corresponding to the given address. @@ -5175,7 +5382,7 @@ LINPHONE_PUBLIC void linphone_core_notify_all_friends(LinphoneCore *lc, Linphone LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneFriend *linphone_core_get_friend_by_address(const LinphoneCore *lc, const char *addr); /** - * Search a LinphoneFriend by its address. + * Search a #LinphoneFriend by its address. * @param[in] lc #LinphoneCore object. * @param[in] addr The address to use to search the friend. * @return The #LinphoneFriend object corresponding to the given address. @@ -5183,7 +5390,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneFriend *linphone_core_get_friend_by_ LINPHONE_PUBLIC LinphoneFriend *linphone_core_find_friend(const LinphoneCore *lc, const LinphoneAddress *addr); /** - * Search a LinphoneFriend by its reference key. + * Search a #LinphoneFriend by its reference key. * @param[in] lc #LinphoneCore object. * @param[in] key The reference key to use to search the friend. * @return The #LinphoneFriend object corresponding to the given reference key. @@ -5208,49 +5415,51 @@ LINPHONE_PUBLIC void linphone_core_set_friends_database_path(LinphoneCore *lc, c LINPHONE_PUBLIC const char* linphone_core_get_friends_database_path(LinphoneCore *lc); /** - * Migrates the friends from the linphonerc to the database if not done yet - * @ingroup initializing - * @param lc the linphone core -**/ -LINPHONE_PUBLIC void linphone_core_migrate_friends_from_rc_to_db(LinphoneCore *lc); - -/** - * Create a new empty LinphoneFriendList object. - * @param[in] lc LinphoneCore object. - * @return A new LinphoneFriendList object. + * Create a new empty #LinphoneFriendList object. + * @param[in] lc #LinphoneCore object. + * @return A new #LinphoneFriendList object. **/ LINPHONE_PUBLIC LinphoneFriendList * linphone_core_create_friend_list(LinphoneCore *lc); /** * Add a friend list. - * @param[in] lc LinphoneCore object - * @param[in] list LinphoneFriendList object + * @param[in] lc #LinphoneCore object + * @param[in] list #LinphoneFriendList object */ LINPHONE_PUBLIC void linphone_core_add_friend_list(LinphoneCore *lc, LinphoneFriendList *list); /** * Removes a friend list. - * @param[in] lc LinphoneCore object - * @param[in] list LinphoneFriendList object + * @param[in] lc #LinphoneCore object + * @param[in] list #LinphoneFriendList object */ LINPHONE_PUBLIC void linphone_core_remove_friend_list(LinphoneCore *lc, LinphoneFriendList *list); /** - * Retrieves the list of LinphoneFriendList from the core. - * @param[in] lc LinphoneCore object - * @return \bctbx_list{LinphoneFriendList} a list of LinphoneFriendList + * Retrieves the list of #LinphoneFriendList from the core. + * @param[in] lc #LinphoneCore object + * @return \bctbx_list{LinphoneFriendList} a list of #LinphoneFriendList */ LINPHONE_PUBLIC const bctbx_list_t * linphone_core_get_friends_lists(const LinphoneCore *lc); /** - * Retrieves the first list of LinphoneFriend from the core. - * @param[in] lc LinphoneCore object - * @return the first LinphoneFriendList object or NULL + * Retrieves the first list of #LinphoneFriend from the core. + * @param[in] lc #LinphoneCore object + * @return the first #LinphoneFriendList object or NULL */ LINPHONE_PUBLIC LinphoneFriendList * linphone_core_get_default_friend_list(const LinphoneCore *lc); /** - * Create a LinphonePresenceActivity with the given type and description. + * Retrieves a list of #LinphoneAddress sort and filter + * @param[in] lc #LinphoneCore object + * @param[in] filter Chars used for the filter* + * @param[in] sip_only Only sip address or not + * @return \bctbx_list{LinphoneAddress} a list of filtered #LinphoneAddress + the #LinphoneAddress created with the filter +**/ +LINPHONE_PUBLIC const bctbx_list_t * linphone_core_find_contacts_by_char(LinphoneCore *core, const char *filter, bool_t sip_only); + +/** + * Create a #LinphonePresenceActivity with the given type and description. * @param[in] lc #LinphoneCore object. * @param[in] acttype The #LinphonePresenceActivityType to set for the activity. * @param[in] description An additional description of the activity to set for the activity. Can be NULL if no additional description is to be added. @@ -5266,7 +5475,7 @@ LINPHONE_PUBLIC LinphonePresenceActivity * linphone_core_create_presence_activit LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_create_presence_model(LinphoneCore *lc); /** - * Create a LinphonePresenceModel with the given activity type and activity description. + * Create a #LinphonePresenceModel with the given activity type and activity description. * @param[in] lc #LinphoneCore object. * @param[in] acttype The #LinphonePresenceActivityType to set for the activity of the created model. * @param[in] description An additional description of the activity to set for the activity. Can be NULL if no additional description is to be added. @@ -5275,7 +5484,7 @@ LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_create_presence_model(Linp LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_create_presence_model_with_activity(LinphoneCore *lc, LinphonePresenceActivityType acttype, const char *description); /** - * Create a LinphonePresenceModel with the given activity type, activity description, note content and note language. + * Create a #LinphonePresenceModel with the given activity type, activity description, note content and note language. * @param[in] lc #LinphoneCore object. * @param[in] acttype The #LinphonePresenceActivityType to set for the activity of the created model. * @param[in] description An additional description of the activity to set for the activity. Can be NULL if no additional description is to be added. @@ -5286,7 +5495,7 @@ LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_create_presence_model_with LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_create_presence_model_with_activity_and_note(LinphoneCore *lc, LinphonePresenceActivityType acttype, const char *description, const char *note, const char *lang); /** - * Create a LinphonePresenceNote with the given content and language. + * Create a #LinphonePresenceNote with the given content and language. * @param[in] lc #LinphoneCore object. * @param[in] content The content of the note to be created. * @param[in] lang The language of the note to be created. @@ -5295,7 +5504,7 @@ LINPHONE_PUBLIC LinphonePresenceModel * linphone_core_create_presence_model_with LINPHONE_PUBLIC LinphonePresenceNote * linphone_core_create_presence_note(LinphoneCore *lc, const char *content, const char *lang); /** - * Create a LinphonePresencePerson with the given id. + * Create a #LinphonePresencePerson with the given id. * @param[in] lc #LinphoneCore object * @param[in] id The id of the person to be created. * @return The created #LinphonePresencePerson object. @@ -5303,7 +5512,7 @@ LINPHONE_PUBLIC LinphonePresenceNote * linphone_core_create_presence_note(Linpho LINPHONE_PUBLIC LinphonePresencePerson * linphone_core_create_presence_person(LinphoneCore *lc, const char *id); /** - * Create a LinphonePresenceService with the given id, basic status and contact. + * Create a #LinphonePresenceService with the given id, basic status and contact. * @param[in] lc #LinphoneCore object. * @param[in] id The id of the service to be created. * @param[in] basic_status The basic status of the service to be created. @@ -5342,32 +5551,41 @@ LINPHONE_PUBLIC void linphone_core_notify_notify_presence_received_for_uri_or_te /** - * Create a new LinphoneNatPolicy object with every policies being disabled. - * @param[in] lc LinphoneCore object - * @return A new LinphoneNatPolicy object. + * Create a new #LinphoneNatPolicy object with every policies being disabled. + * @param[in] lc #LinphoneCore object + * @return A new #LinphoneNatPolicy object. * @ingroup network_parameters */ LINPHONE_PUBLIC LinphoneNatPolicy * linphone_core_create_nat_policy(LinphoneCore *lc); /** - * Create a new LinphoneNatPolicy by reading the config of a LinphoneCore according to the passed ref. - * @param[in] lc LinphoneCore object - * @param[in] ref The reference of a NAT policy in the config of the LinphoneCore - * @return A new LinphoneNatPolicy object. + * Create a new #LinphoneNatPolicy by reading the config of a #LinphoneCore according to the passed ref. + * @param[in] lc #LinphoneCore object + * @param[in] ref The reference of a NAT policy in the config of the #LinphoneCore + * @return A new #LinphoneNatPolicy object. * @ingroup network_parameters */ LINPHONE_PUBLIC LinphoneNatPolicy * linphone_core_create_nat_policy_from_config(LinphoneCore *lc, const char *ref); /** - * Create a LinphoneAccountCreator and set Linphone Request callbacks. - * @param[in] core The LinphoneCore used for the XML-RPC communication + * Create a #LinphoneAccountCreator and set Linphone Request callbacks. + * @param[in] core The #LinphoneCore used for the XML-RPC communication * @param[in] xmlrpc_url The URL to the XML-RPC server. Must be NON NULL. - * @return The new LinphoneAccountCreator object. + * @return The new #LinphoneAccountCreator object. * @ingroup account_creator **/ LINPHONE_PUBLIC LinphoneAccountCreator * linphone_core_create_account_creator(LinphoneCore *core, const char *xmlrpc_url); +/** + * Create a #LinphoneXmlRpcSession for a given url. + * @param[in] lc The #LinphoneCore used for the XML-RPC communication + * @param[in] url The URL to the XML-RPC server. Must be NON NULL. + * @return The new #LinphoneXmlRpcSession object. + * @ingroup misc +**/ +LINPHONE_PUBLIC LinphoneXmlRpcSession * linphone_core_create_xml_rpc_session(LinphoneCore *lc, const char *url); + #ifdef __cplusplus } diff --git a/include/linphone/core_utils.h b/include/linphone/core_utils.h index 5f7a97bab..18d0f8807 100644 --- a/include/linphone/core_utils.h +++ b/include/linphone/core_utils.h @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "linphone/types.h" +#include "linphone/callbacks.h" #ifdef __cplusplus @@ -49,26 +50,64 @@ LINPHONE_PUBLIC void linphone_core_use_sound_daemon(LinphoneCore *lc, LinphoneSo LINPHONE_PUBLIC void linphone_sound_daemon_destroy(LinphoneSoundDaemon *obj); -typedef void (*LinphoneEcCalibrationCallback)(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data); -typedef void (*LinphoneEcCalibrationAudioInit)(void *data); -typedef void (*LinphoneEcCalibrationAudioUninit)(void *data); +LINPHONE_DEPRECATED typedef void (*LinphoneEcCalibrationCallback)(LinphoneCore *lc, LinphoneEcCalibratorStatus status, int delay_ms, void *data); +LINPHONE_DEPRECATED typedef void (*LinphoneEcCalibrationAudioInit)(void *data); +LINPHONE_DEPRECATED typedef void (*LinphoneEcCalibrationAudioUninit)(void *data); /** - * - * Start an echo calibration of the sound devices, in order to find adequate settings for the echo canceller automatically. + * @brief Starts an echo calibration of the sound devices, in order to find adequate settings for the echo canceler automatically. + * @deprecated Use #linphone_core_start_echo_canceller_calibration() instead. To set the callbacks create or get an already instantiated + * #LinphoneCoreCbs and call #linphone_core_cbs_set_ec_calibration_result(), #linphone_core_cbs_set_ec_calibration_audio_init() and + * #linphone_core_cbs_set_ec_callibration_audio_uninit(). Deprecated since 2017-10-16. + * @ingroup misc + * @donotwrap **/ -LINPHONE_PUBLIC int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb, +LINPHONE_DEPRECATED LINPHONE_PUBLIC int linphone_core_start_echo_calibration(LinphoneCore *lc, LinphoneEcCalibrationCallback cb, LinphoneEcCalibrationAudioInit audio_init_cb, LinphoneEcCalibrationAudioUninit audio_uninit_cb, void *cb_data); + +/** + * @brief Starts an echo calibration of the sound devices, in order to find adequate settings for the echo canceler automatically. + * @param[in] lc #LinphoneCore object. + * @return #LinphoneStatus whether calibration has started or not. + * @ingroup misc +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_core_start_echo_canceller_calibration(LinphoneCore *lc); + /** * Start the simulation of call to test the latency with an external device * @param lc The core. * @param rate Sound sample rate. + * @ingroup misc **/ LINPHONE_PUBLIC LinphoneStatus linphone_core_start_echo_tester(LinphoneCore *lc, unsigned int rate); + /** * Stop the simulation of call + * @ingroup misc **/ LINPHONE_PUBLIC LinphoneStatus linphone_core_stop_echo_tester(LinphoneCore *lc); + +/** + * Check whether the device is flagged has crappy opengl + * @returns TRUE if crappy opengl flag is set, FALSE otherwise + * @ingroup misc +**/ +LINPHONE_PUBLIC bool_t linphone_core_has_crappy_opengl(LinphoneCore *lc); + +/** + * Check whether the device has a hardware echo canceller + * @returns TRUE if it does, FALSE otherwise + * @ingroup misc +**/ +LINPHONE_PUBLIC bool_t linphone_core_has_builtin_echo_canceller(LinphoneCore *lc); + +/** + * Check whether the device is echo canceller calibration is required + * @returns TRUE if it is required, FALSE otherwise + * @ingroup misc +**/ +LINPHONE_PUBLIC bool_t linphone_core_is_echo_canceller_calibration_required(LinphoneCore *lc); + /** * @ingroup IOS * Special function to warm up dtmf feeback stream. #linphone_core_stop_dtmf_stream must() be called before entering FG mode @@ -83,54 +122,9 @@ LINPHONE_PUBLIC void linphone_core_stop_dtmf_stream(LinphoneCore* lc); typedef bool_t (*LinphoneCoreIterateHook)(void *data); -void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); +LINPHONE_PUBLIC void linphone_core_add_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); -void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); - -typedef struct _LinphoneDialPlan { - const char *country; - const char* iso_country_code; /* ISO 3166-1 alpha-2 code, ex: FR for France*/ - char ccc[8]; /*country calling code*/ - int nnl; /*maximum national number length*/ - const char * icp; /*international call prefix, ex: 00 in europe*/ -} LinphoneDialPlan; - -/** - * @ingroup misc - *Function to get call country code from ISO 3166-1 alpha-2 code, ex: FR returns 33 - *@param iso country code alpha2 - *@return call country code or -1 if not found - */ -LINPHONE_PUBLIC int linphone_dial_plan_lookup_ccc_from_iso(const char* iso); - -/** - * @ingroup misc - *Function to get call country code from an e164 number, ex: +33952650121 will return 33 - *@param e164 phone number - *@return call country code or -1 if not found - */ -LINPHONE_PUBLIC int linphone_dial_plan_lookup_ccc_from_e164(const char* e164); - -/** - * Return NULL-terminated array of all known dial plans -**/ -LINPHONE_PUBLIC const LinphoneDialPlan* linphone_dial_plan_get_all(void); - -/** - * Find best match for given CCC - * @return Return matching dial plan, or a generic one if none found -**/ -LINPHONE_PUBLIC const LinphoneDialPlan* linphone_dial_plan_by_ccc(const char *ccc); -/** - * Find best match for given CCC - * @return Return matching dial plan, or a generic one if none found - **/ -LINPHONE_PUBLIC const LinphoneDialPlan* linphone_dial_plan_by_ccc_as_int(int ccc); - -/** - * Return if given plan is generic -**/ -LINPHONE_PUBLIC bool_t linphone_dial_plan_is_generic(const LinphoneDialPlan *ccc); +LINPHONE_PUBLIC void linphone_core_remove_iterate_hook(LinphoneCore *lc, LinphoneCoreIterateHook hook, void *hook_data); #ifdef __cplusplus } diff --git a/include/linphone/defs.h b/include/linphone/defs.h index fc26222cb..6937ad2bb 100644 --- a/include/linphone/defs.h +++ b/include/linphone/defs.h @@ -1,6 +1,6 @@ /* defs.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 diff --git a/include/linphone/enums/call-enums.h b/include/linphone/enums/call-enums.h new file mode 100644 index 000000000..ff38c00f7 --- /dev/null +++ b/include/linphone/enums/call-enums.h @@ -0,0 +1,74 @@ +/* + * call-enums.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_ENUMS_H_ +#define _L_CALL_ENUMS_H_ + +// ============================================================================= + +#define L_ENUM_VALUES_CALL_SESSION_STATE(F) \ + F(Idle /**< Initial state */) \ + F(IncomingReceived /**< Incoming call received */) \ + F(OutgoingInit /**< Outgoing call initialized */) \ + F(OutgoingProgress /**< Outgoing call in progress */) \ + F(OutgoingRinging /**< Outgoing call ringing */) \ + F(OutgoingEarlyMedia /**< Outgoing call early media */) \ + F(Connected /**< Connected */) \ + F(StreamsRunning /**< Streams running */) \ + F(Pausing /**< Pausing */) \ + F(Paused /**< Paused */) \ + F(Resuming /**< Resuming */) \ + F(Referred /**< Referred */) \ + F(Error /**< Error */) \ + F(End /**< Call end */) \ + F(PausedByRemote /**< Paused by remote */) \ + F(UpdatedByRemote /**< The call's parameters are updated for example when video is asked by remote */) \ + F(IncomingEarlyMedia /**< We are proposing early media to an incoming call */) \ + F(Updating /**< We have initiated a call update */) \ + F(Released /**< The call object is now released */) \ + F(EarlyUpdatedByRemote /**< The call is updated by remote while not yet answered (SIP UPDATE in early dialog received) */) \ + F(EarlyUpdating /**< We are updating the call while not yet answered (SIP UPDATE in early dialog sent) */) + +// ============================================================================= +// DEPRECATED +// ============================================================================= + +#define LinphoneCallIdle LinphoneCallStateIdle +#define LinphoneCallIncomingReceived LinphoneCallStateIncomingReceived +#define LinphoneCallOutgoingInit LinphoneCallStateOutgoingInit +#define LinphoneCallOutgoingProgress LinphoneCallStateOutgoingProgress +#define LinphoneCallOutgoingRinging LinphoneCallStateOutgoingRinging +#define LinphoneCallOutgoingEarlyMedia LinphoneCallStateOutgoingEarlyMedia +#define LinphoneCallConnected LinphoneCallStateConnected +#define LinphoneCallStreamsRunning LinphoneCallStateStreamsRunning +#define LinphoneCallPausing LinphoneCallStatePausing +#define LinphoneCallPaused LinphoneCallStatePaused +#define LinphoneCallResuming LinphoneCallStateResuming +#define LinphoneCallRefered LinphoneCallStateReferred +#define LinphoneCallError LinphoneCallStateError +#define LinphoneCallEnd LinphoneCallStateEnd +#define LinphoneCallPausedByRemote LinphoneCallStatePausedByRemote +#define LinphoneCallUpdatedByRemote LinphoneCallStateUpdatedByRemote +#define LinphoneCallIncomingEarlyMedia LinphoneCallStateIncomingEarlyMedia +#define LinphoneCallUpdating LinphoneCallStateUpdating +#define LinphoneCallReleased LinphoneCallStateReleased +#define LinphoneCallEarlyUpdatedByRemote LinphoneCallStateEarlyUpdatedByRemote +#define LinphoneCallEarlyUpdating LinphoneCallStateEarlyUpdating + +#endif // ifndef _L_CALL_ENUMS_H_ diff --git a/include/linphone/enums/chat-message-enums.h b/include/linphone/enums/chat-message-enums.h new file mode 100644 index 000000000..ba1184073 --- /dev/null +++ b/include/linphone/enums/chat-message-enums.h @@ -0,0 +1,39 @@ +/* + * chat-message-enums.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_MESSAGE_ENUMS_H_ +#define _L_CHAT_MESSAGE_ENUMS_H_ + +// ============================================================================= + +#define L_ENUM_VALUES_CHAT_MESSAGE_STATE(F) \ + F(Idle /**< Initial state */) \ + F(InProgress /**< Delivery in progress */) \ + F(Delivered /**< Message successfully delivered and acknowledged by the server */) \ + F(NotDelivered /**< Message was not delivered */) \ + F(FileTransferError /**< Message was received and acknowledged but cannot get file from server */) \ + F(FileTransferDone /**< File transfer has been completed successfully */) \ + F(DeliveredToUser /**< Message successfully delivered an acknowledged by the remote user */) \ + F(Displayed /**< Message successfully displayed to the remote user */) + +#define L_ENUM_VALUES_CHAT_MESSAGE_DIRECTION(F) \ + F(Incoming /**< Incoming message */) \ + F(Outgoing /**< Outgoing message */) + +#endif // ifndef _L_CHAT_MESSAGE_ENUMS_H_ diff --git a/include/linphone/enums/chat-room-enums.h b/include/linphone/enums/chat-room-enums.h new file mode 100644 index 000000000..32f0c4602 --- /dev/null +++ b/include/linphone/enums/chat-room-enums.h @@ -0,0 +1,44 @@ +/* + * chat-room-enums.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_ROOM_ENUMS_H_ +#define _L_CHAT_ROOM_ENUMS_H_ + +// ============================================================================= + +#define L_ENUM_VALUES_CHAT_ROOM_STATE(F) \ + F(None /**< Initial state */) \ + F(Instantiated /**< Chat room is now instantiated on local */) \ + F(CreationPending /**< One creation request was sent to the server */) \ + F(Created /**< Chat room was created on the server */) \ + F(CreationFailed /**< Chat room creation failed */) \ + F(TerminationPending /**< Wait for chat room termination */) \ + F(Terminated /**< Chat room exists on server but not in local */) \ + F(TerminationFailed /**< The chat room termination failed */) \ + F(Deleted /**< Chat room was deleted on the server */) + +#define L_ENUM_VALUES_CHAT_ROOM_CAPABILITIES(F) \ + F(Basic /**< No server. It's a direct communication */, 1 << 0) \ + F(RealTimeText /**< Supports RTT */, 1 << 1) \ + F(Conference /**< Use server (supports group chat) */, 1 << 2) \ + F(Proxy /**< Special proxy chat room flag */, 1 << 3) \ + F(Migratable /**< Chat room migratable from Basic to Conference */, 1 << 4) \ + F(OneToOne /**< A communication between two participants (can be Basic or Conference) */, 1 << 5) + +#endif // ifndef _L_CHAT_ROOM_ENUMS_H_ diff --git a/include/linphone/enums/event-log-enums.h b/include/linphone/enums/event-log-enums.h new file mode 100644 index 000000000..fd23f7977 --- /dev/null +++ b/include/linphone/enums/event-log-enums.h @@ -0,0 +1,40 @@ +/* + * event-log-enums.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_EVENT_LOG_ENUMS_H_ +#define _L_EVENT_LOG_ENUMS_H_ + +// ============================================================================= + +#define L_ENUM_VALUES_EVENT_LOG_TYPE(F) \ + F(None /**< No defined event */) \ + F(ConferenceCreated /**< Conference (created) event */) \ + F(ConferenceTerminated /**< Conference (terminated) event */) \ + F(ConferenceCallStart /**< Conference call (start) event */) \ + F(ConferenceCallEnd /**< Conference call (end) event */) \ + F(ConferenceChatMessage /**< Conference chat message event */) \ + F(ConferenceParticipantAdded /**< Conference participant (added) event */) \ + F(ConferenceParticipantRemoved /**< Conference participant (removed) event */) \ + F(ConferenceParticipantSetAdmin /**< Conference participant (set admin) event */) \ + F(ConferenceParticipantUnsetAdmin /**< Conference participant (unset admin) event */) \ + F(ConferenceParticipantDeviceAdded /**< Conference participant device (added) event */) \ + F(ConferenceParticipantDeviceRemoved /**< Conference participant device (removed) event */) \ + F(ConferenceSubjectChanged /**< Conference subject event */) \ + +#endif // ifndef _L_EVENT_LOG_ENUMS_H_ diff --git a/include/linphone/error_info.h b/include/linphone/error_info.h index 121983924..23a26c753 100644 --- a/include/linphone/error_info.h +++ b/include/linphone/error_info.h @@ -32,9 +32,9 @@ extern "C" { */ /** - * Create an empty LinphoneErrorInfo object. - * The LinphoneErrorInfo object carries these fields: - * - a LinphoneReason enum member giving overall signification of the error reported. + * Create an empty #LinphoneErrorInfo object. + * The #LinphoneErrorInfo object carries these fields: + * - a #LinphoneReason enum member giving overall signification of the error reported. * - the "protocol" name in which the protocol reason code has meaning, for example SIP or Q.850 * - the "protocol code", an integer referencing the kind of error reported * - the "phrase", a text phrase describing the error @@ -63,10 +63,10 @@ LINPHONE_PUBLIC void linphone_error_info_unref(LinphoneErrorInfo *ei); LINPHONE_PUBLIC LinphoneReason linphone_error_info_get_reason(const LinphoneErrorInfo *ei); /** - * Get pointer to chained LinphoneErrorInfo set in sub_ei. + * Get pointer to chained #LinphoneErrorInfo set in sub_ei. * It corresponds to a Reason header in a received SIP response. * @param ei ErrorInfo object - * @return LinphoneErrorInfo pointer defined in the ei object. + * @return #LinphoneErrorInfo pointer defined in the ei object. */ LINPHONE_PUBLIC LinphoneErrorInfo* linphone_error_info_get_sub_error_info(const LinphoneErrorInfo *ei); @@ -102,10 +102,10 @@ LINPHONE_PUBLIC const char * linphone_error_info_get_warnings(const LinphoneErro LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInfo *ei); /** - * Assign information to a LinphoneErrorInfo object. + * Assign information to a #LinphoneErrorInfo object. * @param[in] ei ErrorInfo object * @param[in] protocol protocol name - * @param[in] reason reason from LinphoneReason enum + * @param[in] reason reason from #LinphoneReason enum * @param[in] code protocol code * @param[in] status_string description of the reason * @param[in] warning warning message @@ -113,44 +113,44 @@ LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInf LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning); /** - * Set the sub_ei in LinphoneErrorInfo to another LinphoneErrorInfo. - * Used when a reason header is to be added in a SIP response. The first level LinphoneErrorInfo defines the SIP response code and phrase, - * the second (sub) LinphoneErroInfo defining the content of the Reason header. - * @param[in] ei LinphoneErrorInfo object to which the other LinphoneErrorInfo will be appended as ei->sub_ei. - * @param[in] appended_ei LinphoneErrorInfo to append + * Set the sub_ei in #LinphoneErrorInfo to another LinphoneErrorInfo. + * Used when a reason header is to be added in a SIP response. The first level #LinphoneErrorInfo defines the SIP response code and phrase, + * the second (sub) #LinphoneErroInfo defining the content of the Reason header. + * @param[in] ei #LinphoneErrorInfo object to which the other #LinphoneErrorInfo will be appended as ei->sub_ei. + * @param[in] appended_ei #LinphoneErrorInfo to append */ LINPHONE_PUBLIC void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei); /** - * Assign reason LinphoneReason to a LinphoneErrorInfo object. + * Assign reason #LinphoneReason to a #LinphoneErrorInfo object. * @param[in] ei ErrorInfo object - * @param[in] reason reason from LinphoneReason enum + * @param[in] reason reason from #LinphoneReason enum */ LINPHONE_PUBLIC void linphone_error_info_set_reason(LinphoneErrorInfo *ei, LinphoneReason reason); /** - * Assign protocol name to a LinphoneErrorInfo object. + * Assign protocol name to a #LinphoneErrorInfo object. * @param[in] ei ErrorInfo object * @param[in] proto the protocol name */ LINPHONE_PUBLIC void linphone_error_info_set_protocol(LinphoneErrorInfo *ei, const char *proto); /** - * Assign protocol code to a LinphoneErrorInfo object. + * Assign protocol code to a #LinphoneErrorInfo object. * @param[in] ei ErrorInfo object * @param[in] code the protocol code */ LINPHONE_PUBLIC void linphone_error_info_set_protocol_code(LinphoneErrorInfo *ei, int code); /** - * Assign phrase to a LinphoneErrorInfo object. + * Assign phrase to a #LinphoneErrorInfo object. * @param[in] ei ErrorInfo object * @param[in] phrase the phrase explaining the error */ LINPHONE_PUBLIC void linphone_error_info_set_phrase(LinphoneErrorInfo *ei, const char *phrase); /** - * Assign warnings to a LinphoneErrorInfo object. + * Assign warnings to a #LinphoneErrorInfo object. * @param[in] ei ErrorInfo object * @param[in] phrase the warnings */ diff --git a/include/linphone/event.h b/include/linphone/event.h index b9b34686f..a2306edbc 100644 --- a/include/linphone/event.h +++ b/include/linphone/event.h @@ -20,6 +20,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef LINPHONE_EVENT_H_ #define LINPHONE_EVENT_H_ +#include "linphone/callbacks.h" #include "linphone/types.h" #ifdef __cplusplus @@ -33,7 +34,7 @@ extern "C" { /** * Send a subscription previously created by linphone_core_create_subscribe(). - * @param ev the LinphoneEvent + * @param ev the #LinphoneEvent * @param body optional content to attach with the subscription. * @return 0 if successful, -1 otherwise. **/ @@ -41,14 +42,14 @@ LINPHONE_PUBLIC LinphoneStatus linphone_event_send_subscribe(LinphoneEvent *ev, /** * Update (refresh) an outgoing subscription, changing the body. - * @param lev a LinphoneEvent + * @param lev a #LinphoneEvent * @param body an optional body to include in the subscription update, may be NULL. **/ LINPHONE_PUBLIC LinphoneStatus linphone_event_update_subscribe(LinphoneEvent *lev, const LinphoneContent *body); /** * Refresh an outgoing subscription keeping the same body. - * @param lev LinphoneEvent object. + * @param lev #LinphoneEvent object. * @return 0 if successful, -1 otherwise. */ LINPHONE_PUBLIC LinphoneStatus linphone_event_refresh_subscribe(LinphoneEvent *lev); @@ -88,7 +89,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_event_update_publish(LinphoneEvent *lev, /** * Refresh an outgoing publish keeping the same body. - * @param lev LinphoneEvent object. + * @param lev #LinphoneEvent object. * @return 0 if successful, -1 otherwise. */ LINPHONE_PUBLIC LinphoneStatus linphone_event_refresh_publish(LinphoneEvent *lev); @@ -140,7 +141,7 @@ LINPHONE_PUBLIC void *linphone_event_get_user_data(const LinphoneEvent *ev); /** * Add a custom header to an outgoing susbscription or publish. - * @param ev the LinphoneEvent + * @param ev the #LinphoneEvent * @param name header's name * @param value the header's value. **/ @@ -148,7 +149,7 @@ LINPHONE_PUBLIC void linphone_event_add_custom_header(LinphoneEvent *ev, const c /** * Obtain the value of a given header for an incoming subscription. - * @param ev the LinphoneEvent + * @param ev the #LinphoneEvent * @param name header's name * @return the header's value or NULL if such header doesn't exist. **/ @@ -156,14 +157,14 @@ LINPHONE_PUBLIC const char *linphone_event_get_custom_header(LinphoneEvent *ev, /** * Terminate an incoming or outgoing subscription that was previously acccepted, or a previous publication. - * The LinphoneEvent shall not be used anymore after this operation, unless the application explicitely took a reference on the object with + * The #LinphoneEvent shall not be used anymore after this operation, unless the application explicitely took a reference on the object with * linphone_event_ref(). **/ LINPHONE_PUBLIC void linphone_event_terminate(LinphoneEvent *lev); /** * Increase reference count of LinphoneEvent. - * By default LinphoneEvents created by the core are owned by the core only. + * By default #LinphoneEvents created by the core are owned by the core only. * An application that wishes to retain a reference to it must call linphone_event_ref(). * When this reference is no longer needed, linphone_event_unref() must be called. * @@ -192,10 +193,66 @@ LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_from(const LinphoneEve LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_resource(const LinphoneEvent *lev); /** - * Returns back pointer to the LinphoneCore that created this LinphoneEvent + * Get the "contact" address of the subscription. + * @param[in] lev #LinphoneEvent object + * @return The "contact" address of the subscription + */ +LINPHONE_PUBLIC const LinphoneAddress *linphone_event_get_remote_contact (const LinphoneEvent *lev); + +/** + * Returns back pointer to the #LinphoneCore that created this #LinphoneEvent **/ LINPHONE_PUBLIC LinphoneCore *linphone_event_get_core(const LinphoneEvent *lev); +/** + * Get the LinphoneEventCbs object associated with a LinphoneEvent. + * @param[in] ev LinphoneEvent object + * @return The LinphoneEventCbs object associated with the LinphoneEvent. +**/ + +LINPHONE_PUBLIC LinphoneEventCbs *linphone_event_get_callbacks(const LinphoneEvent *ev); + +/** + * Acquire a reference to a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. + * @return The same LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC LinphoneEventCbs *linphone_event_cbs_ref(LinphoneEventCbs *cbs); + +/** + * Release a reference to a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC void linphone_event_cbs_unref(LinphoneEventCbs *cbs); + +/** + * Retrieve the user pointer associated with a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. + * @return The user pointer associated with the LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC void *linphone_event_cbs_get_user_data(const LinphoneEventCbs *cbs); + +/** + * Assign a user pointer to a LinphoneEventCbs object. + * @param[in] cbs LinphoneEventCbs object. + * @param[in] ud The user pointer to associate with the LinphoneEventCbs object. +**/ +LINPHONE_PUBLIC void linphone_event_cbs_set_user_data(LinphoneEventCbs *cbs, void *ud); + +/** + * Get the notify response callback. + * @param[in] cbs LinphoneEventCbs object. + * @return The current notify response callback. +**/ +LINPHONE_PUBLIC LinphoneEventCbsNotifyResponseCb linphone_event_cbs_get_notify_response(const LinphoneEventCbs *cbs); + +/** + * Set the notify response callback. + * @param[in] cbs LinphoneEventCbs object. + * @param[in] cb The notify response callback to be used. +**/ +LINPHONE_PUBLIC void linphone_event_cbs_set_notify_response(LinphoneEventCbs *cbs, LinphoneEventCbsNotifyResponseCb cb); + /** * @} **/ diff --git a/include/linphone/factory.h b/include/linphone/factory.h index 8eec1b73c..6a1fbbbf0 100644 --- a/include/linphone/factory.h +++ b/include/linphone/factory.h @@ -47,7 +47,7 @@ LINPHONE_PUBLIC void linphone_factory_clean(void); /** * Instanciate a #LinphoneCore object. * - * The LinphoneCore object is the primary handle for doing all phone actions. + * The #LinphoneCore object is the primary handle for doing all phone actions. * It should be unique within your application. * @param factory The #LinphoneFactory singleton. * @param cbs a #LinphoneCoreCbs object holding your application callbacks. A reference @@ -62,15 +62,19 @@ LINPHONE_PUBLIC void linphone_factory_clean(void); * The settings in this factory file always override the one in the normal config file. * It is OPTIONAL, use NULL if unneeded. * @see linphone_core_new_with_config + * @deprecated 2018-01-10: Use linphone_factory_create_core_3() instead */ -LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, - const char *config_path, const char *factory_config_path); - +LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + const char *config_path, + const char *factory_config_path +); /** * Instanciate a #LinphoneCore object. * - * The LinphoneCore object is the primary handle for doing all phone actions. + * The #LinphoneCore object is the primary handle for doing all phone actions. * It should be unique within your application. * @param factory The #LinphoneFactory singleton. * @param cbs a #LinphoneCoreCbs object holding your application callbacks. A reference @@ -87,40 +91,100 @@ LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core(const LinphoneFactory * @param user_data an application pointer associated with the returned core. * @param system_context a pointer to a system object required by the core to operate. Currently it is required to pass an android Context on android, pass NULL on other platforms. * @see linphone_core_new_with_config + * @deprecated 2018-01-10: Use linphone_factory_create_core_3() instead */ -LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, - const char *config_path, const char *factory_config_path, void *user_data, void *system_context); - +LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_2 ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + const char *config_path, + const char *factory_config_path, + void *user_data, + void *system_context +); /** - * Instantiates a LinphoneCore object with a given LpConfig. + * Instantiate a #LinphoneCore object. + * + * The #LinphoneCore object is the primary handle for doing all phone actions. It should be unique within your + * application. + * The #LinphoneCore object is not started automatically, you need to call linphone_core_start() to that effect. + * @param[in] factory The #LinphoneFactory singleton. + * @param[in] config_path A path to a config file. If it does not exists it will be created. The config file is used to + * store all settings, proxies... so that all these settings become persistent over the life of the #LinphoneCore object. + * It is allowed to set a NULL config file. In that case #LinphoneCore will not store any settings. + * @param[in] factory_config_path A path to a read-only config file that can be used to store hard-coded preferences + * such as proxy settings or internal preferences. The settings in this factory file always override the ones in the + * normal config file. It is optional, use NULL if unneeded. + * @param[in] system_context A pointer to a system object required by the core to operate. Currently it is required to + * pass an android Context on android, pass NULL on other platforms. + * @see linphone_core_new_with_config_3 + */ +LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_3 ( + const LinphoneFactory *factory, + const char *config_path, + const char *factory_config_path, + void *system_context +); + +/** + * Instantiates a #LinphoneCore object with a given LpConfig. * * @param factory The #LinphoneFactory singleton. - * The LinphoneCore object is the primary handle for doing all phone actions. + * The #LinphoneCore object is the primary handle for doing all phone actions. * It should be unique within your application. * @param cbs a #LinphoneCoreCbs object holding your application callbacks. A reference * will be taken on it until the destruciton of the core or the unregistration * with linphone_core_remove_cbs(). - * @param config a pointer to an LpConfig object holding the configuration of the LinphoneCore to be instantiated. + * @param config a pointer to an LpConfig object holding the configuration of the #LinphoneCore to be instantiated. * @see linphone_core_new + * @deprecated 2018-01-10: Use linphone_factory_create_core_with_config_3() instead */ -LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_with_config(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config); +LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_with_config ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + LinphoneConfig *config +); /** - * Instantiates a LinphoneCore object with a given LpConfig. + * Instantiates a #LinphoneCore object with a given LpConfig. * * @param factory The #LinphoneFactory singleton. - * The LinphoneCore object is the primary handle for doing all phone actions. + * The #LinphoneCore object is the primary handle for doing all phone actions. * It should be unique within your application. * @param cbs a #LinphoneCoreCbs object holding your application callbacks. A reference * will be taken on it until the destruciton of the core or the unregistration * with linphone_core_remove_cbs(). - * @param config a pointer to an LpConfig object holding the configuration of the LinphoneCore to be instantiated. + * @param config a pointer to an LpConfig object holding the configuration of the #LinphoneCore to be instantiated. * @param user_data an application pointer associated with the returned core. * @param system_context a pointer to a system object required by the core to operate. Currently it is required to pass an android Context on android, pass NULL on other platforms. * @see linphone_core_new + * @deprecated 2018-01-10: Use linphone_factory_create_core_with_config_3() instead */ -LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_with_config_2(const LinphoneFactory *factory, LinphoneCoreCbs *cbs, LinphoneConfig *config, void *user_data, void *system_context); +LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_with_config_2 ( + const LinphoneFactory *factory, + LinphoneCoreCbs *cbs, + LinphoneConfig *config, + void *user_data, + void *system_context +); + +/** + * Instantiate a #LinphoneCore object with a given LinphoneConfig. + * + * The #LinphoneCore object is the primary handle for doing all phone actions. It should be unique within your + * application. + * The #LinphoneCore object is not started automatically, you need to call linphone_core_start() to that effect. + * @param[in] factory The #LinphoneFactory singleton. + * @param[in] config A #LinphoneConfig object holding the configuration for the #LinphoneCore to be instantiated. + * @param[in] system_context A pointer to a system object required by the core to operate. Currently it is required to + * pass an android Context on android, pass NULL on other platforms. + * @see linphone_factory_create_core_3 + */ +LINPHONE_PUBLIC LinphoneCore *linphone_factory_create_core_with_config_3 ( + const LinphoneFactory *factory, + LinphoneConfig *config, + void *system_context +); /** * Instanciate a #LinphoneCoreCbs object. @@ -148,18 +212,25 @@ LINPHONE_PUBLIC LinphoneAddress *linphone_factory_create_address(const LinphoneF * @param ha1 The ha1-encrypted password if password is not given in clear text. * @param realm The authentication domain (which can be larger than the sip domain. Unfortunately many SIP servers don't use this parameter. * @param domain The SIP domain for which this authentication information is valid, if it has to be restricted for a single SIP domain. - * @return A #LinphoneAuthInfo object. linphone_auth_info_destroy() must be used to destroy it when no longer needed. The LinphoneCore makes a copy of LinphoneAuthInfo + * @return A #LinphoneAuthInfo object. linphone_auth_info_destroy() must be used to destroy it when no longer needed. The #LinphoneCore makes a copy of #LinphoneAuthInfo * passed through linphone_core_add_auth_info(). */ LINPHONE_PUBLIC LinphoneAuthInfo *linphone_factory_create_auth_info(const LinphoneFactory *factory, const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm, const char *domain); /** - * Create a LinphoneCallCbs object that holds callbacks for events happening on a call. - * @param[in] factory LinphoneFactory singletion object - * @return A new LinphoneCallCbs object + * Create a #LinphoneCallCbs object that holds callbacks for events happening on a call. + * @param[in] factory #LinphoneFactory singletion object + * @return A new #LinphoneCallCbs object */ LINPHONE_PUBLIC LinphoneCallCbs * linphone_factory_create_call_cbs(const LinphoneFactory *factory); +/** + * Create a LinphoneChatRoomCbs object that holds callbacks for events happening on a chat room. + * @param[in] factory LinphoneFactory singletion object + * @return A new LinphoneChatRoomCbs object + */ +LINPHONE_PUBLIC LinphoneChatRoomCbs * linphone_factory_create_chat_room_cbs(const LinphoneFactory *factory); + /** * Create an empty #LinphoneVcard. * @return a new #LinphoneVcard. @@ -168,32 +239,32 @@ LINPHONE_PUBLIC LinphoneCallCbs * linphone_factory_create_call_cbs(const Linphon LINPHONE_PUBLIC LinphoneVcard *linphone_factory_create_vcard(LinphoneFactory *factory); /** - * Create a LinphoneVideoDefinition from a given width and height - * @param[in] factory LinphoneFactory singleton object + * Create a #LinphoneVideoDefinition from a given width and height + * @param[in] factory #LinphoneFactory singleton object * @param[in] width The width of the created video definition * @param[in] height The height of the created video definition - * @return A new LinphoneVideoDefinition object + * @return A new #LinphoneVideoDefinition object */ LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_factory_create_video_definition(const LinphoneFactory *factory, unsigned int width, unsigned int height); /** - * Create a LinphoneVideoDefinition from a given standard definition name - * @param[in] factory LinphoneFactory singleton object + * Create a #LinphoneVideoDefinition from a given standard definition name + * @param[in] factory #LinphoneFactory singleton object * @param[in] name The standard definition name of the video definition to create - * @return A new LinphoneVideoDefinition object + * @return A new #LinphoneVideoDefinition object */ LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_factory_create_video_definition_from_name(const LinphoneFactory *factory, const char *name); /** * Get the list of standard video definitions supported by Linphone. - * @param[in] factory LinphoneFactory singleton object + * @param[in] factory #LinphoneFactory singleton object * @return \bctbx_list{LinphoneVideoDefinition} */ LINPHONE_PUBLIC const bctbx_list_t * linphone_factory_get_supported_video_definitions(const LinphoneFactory *factory); /** * Get the top directory where the resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @return The path to the top directory where the resources are located */ LINPHONE_PUBLIC const char * linphone_factory_get_top_resources_dir(const LinphoneFactory *factory); @@ -201,108 +272,207 @@ LINPHONE_PUBLIC const char * linphone_factory_get_top_resources_dir(const Linpho /** * Set the top directory where the resources are located. * If you only define this top directory, the other resources directory will automatically be derived form this one. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @param[in] path The path to the top directory where the resources are located */ LINPHONE_PUBLIC void linphone_factory_set_top_resources_dir(LinphoneFactory *factory, const char *path); /** * Get the directory where the data resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @return The path to the directory where the data resources are located */ LINPHONE_PUBLIC const char * linphone_factory_get_data_resources_dir(LinphoneFactory *factory); /** * Set the directory where the data resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @param[in] path The path where the data resources are located */ LINPHONE_PUBLIC void linphone_factory_set_data_resources_dir(LinphoneFactory *factory, const char *path); /** * Get the directory where the sound resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @return The path to the directory where the sound resources are located */ LINPHONE_PUBLIC const char * linphone_factory_get_sound_resources_dir(LinphoneFactory *factory); /** * Set the directory where the sound resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @param[in] path The path where the sound resources are located */ LINPHONE_PUBLIC void linphone_factory_set_sound_resources_dir(LinphoneFactory *factory, const char *path); /** * Get the directory where the ring resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @return The path to the directory where the ring resources are located */ LINPHONE_PUBLIC const char * linphone_factory_get_ring_resources_dir(LinphoneFactory *factory); /** * Set the directory where the ring resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @param[in] path The path where the ring resources are located */ LINPHONE_PUBLIC void linphone_factory_set_ring_resources_dir(LinphoneFactory *factory, const char *path); /** * Get the directory where the image resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @return The path to the directory where the image resources are located */ LINPHONE_PUBLIC const char * linphone_factory_get_image_resources_dir(LinphoneFactory *factory); /** * Set the directory where the image resources are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @param[in] path The path where the image resources are located */ LINPHONE_PUBLIC void linphone_factory_set_image_resources_dir(LinphoneFactory *factory, const char *path); /** * Get the directory where the mediastreamer2 plugins are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @return The path to the directory where the mediastreamer2 plugins are located, or NULL if it has not been set */ LINPHONE_PUBLIC const char * linphone_factory_get_msplugins_dir(LinphoneFactory *factory); /** * Set the directory where the mediastreamer2 plugins are located. - * @param[in] factory LinphoneFactory object + * @param[in] factory #LinphoneFactory object * @param[in] path The path to the directory where the mediastreamer2 plugins are located */ LINPHONE_PUBLIC void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *path); /** * Creates an object LinphoneErrorInfo. - * @param[in] factory LinphoneFactory object - * @return LinphoneErrorInfo object. + * @param[in] factory #LinphoneFactory object + * @return #LinphoneErrorInfo object. */ LINPHONE_PUBLIC LinphoneErrorInfo *linphone_factory_create_error_info(LinphoneFactory *factory); /** * Creates an object LinphoneRange. - * @param[in] factory LinphoneFactory object - * @return LinphoneRange object. + * @param[in] factory #LinphoneFactory object + * @return #LinphoneRange object. */ LINPHONE_PUBLIC LinphoneRange *linphone_factory_create_range(LinphoneFactory *factory); /** * Creates an object LinphoneTransports. - * @param[in] factory LinphoneFactory object - * @return LinphoneTransports object. + * @param[in] factory #LinphoneFactory object + * @return #LinphoneTransports object. */ LINPHONE_PUBLIC LinphoneTransports *linphone_factory_create_transports(LinphoneFactory *factory); /** * Creates an object LinphoneVideoActivationPolicy. - * @param[in] factory LinphoneFactory object - * @return LinphoneVideoActivationPolicy object. + * @param[in] factory #LinphoneFactory object + * @return #LinphoneVideoActivationPolicy object. */ LINPHONE_PUBLIC LinphoneVideoActivationPolicy *linphone_factory_create_video_activation_policy(LinphoneFactory *factory); + +/** + * Returns a bctbx_list_t of all DialPlans + * @param[in] factory the #LinphoneFactory object + * @return \bctbx_list{LinphoneDialPlan} a list of DialPlan + */ +LINPHONE_PUBLIC const bctbx_list_t * linphone_factory_get_dial_plans(const LinphoneFactory *factory); + +/** + * Creates an object #LinphoneContent + * @param[in] factory the #LinphoneFactory + * @return a #LinphoneContent + */ +LINPHONE_PUBLIC LinphoneContent *linphone_factory_create_content(LinphoneFactory *factory); + +/** + * Creates an object #LinphoneBuffer + * @param[in] factory the #LinphoneFactory + * @return a #LinphoneBuffer + */ +LINPHONE_PUBLIC LinphoneBuffer *linphone_factory_create_buffer(LinphoneFactory *factory); + +/** + * Creates an object #LinphoneBuffer + * @param[in] factory the #LinphoneFactory + * @param[in] data the data to set in the buffer + * @param[in] size the size of the data + * @return a #LinphoneBuffer + */ +LINPHONE_PUBLIC LinphoneBuffer *linphone_factory_create_buffer_from_data(LinphoneFactory *factory, const uint8_t *data, size_t size); + +/** + * Creates an object #LinphoneBuffer + * @param[in] factory the #LinphoneFactory + * @param[in] data the data to set in the buffer + * @return a #LinphoneBuffer + */ +LINPHONE_PUBLIC LinphoneBuffer *linphone_factory_create_buffer_from_string(LinphoneFactory *factory, const char *data); + +/** + * Creates an object #LinphoneConfig + * @param[in] factory the #LinphoneFactory + * @param[in] path the path of the config + * @return a #LinphoneConfig + */ +LINPHONE_PUBLIC LinphoneConfig *linphone_factory_create_config(LinphoneFactory *factory, const char *path); + +/** + * Creates an object #LinphoneConfig + * @param[in] factory the #LinphoneFactory + * @param[in] path the path of the config + * @param[in] path the path of the factory + * @return a #LinphoneConfig + */ +LINPHONE_PUBLIC LinphoneConfig *linphone_factory_create_config_with_factory(LinphoneFactory *factory, const char *path, const char *factory_path); + +/** + * Creates an object #LinphoneConfig + * @param[in] factory the #LinphoneFactory + * @param[in] data the config data + * @return a #LinphoneConfig + */ +LINPHONE_PUBLIC LinphoneConfig *linphone_factory_create_config_from_string(LinphoneFactory *factory, const char *data); + +/** + * Gets the user data in the #LinphoneFactory object + * @param[in] factory the #LinphoneFactory + * @return the user data +*/ +LINPHONE_PUBLIC void *linphone_factory_get_user_data(const LinphoneFactory *factory); + +/** + * Sets the user data in the #LinphoneFactory object + * @param[in] factory the #LinphoneFactory object + * @param[in] data the user data +*/ +LINPHONE_PUBLIC void linphone_factory_set_user_data(LinphoneFactory *factory, void *data); + +/** + * Sets the log collection path + * @param[in] factory the #LinphoneFactory + * @param[in] path the path of the logs + */ +LINPHONE_PUBLIC void linphone_factory_set_log_collection_path(LinphoneFactory *factory, const char *path); + +/** + * Enables or disables log collection + * @param[in] factory the #LinphoneFactory + * @param[in] state the policy for log collection + */ +LINPHONE_PUBLIC void linphone_factory_enable_log_collection(LinphoneFactory *factory, LinphoneLogCollectionState state); + +/** + * Creates an object #LinphoneTunnelConfig + * @param[in] factory the #LinphoneFactory + * @return a #LinphoneTunnelConfig + */ +LINPHONE_PUBLIC LinphoneTunnelConfig *linphone_factory_create_tunnel_config(LinphoneFactory *factory); + /** * @} */ diff --git a/include/linphone/friend.h b/include/linphone/friend.h index b4edf3835..4717ef16f 100644 --- a/include/linphone/friend.h +++ b/include/linphone/friend.h @@ -56,7 +56,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED LinphoneFriend *linphone_friend_new_with_add /** * Destroy a LinphoneFriend. - * @param lf LinphoneFriend object + * @param lf #LinphoneFriend object * @deprecated Use linphone_friend_unref() instead. * @donotwrap */ @@ -77,7 +77,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_friend_set_address(LinphoneFriend *fr, c /** * Get address of this friend. - * @note the LinphoneAddress object returned is hold by the LinphoneFriend, however calling several time this function may return different objects. + * @note the #LinphoneAddress object returned is hold by the LinphoneFriend, however calling several time this function may return different objects. * @param lf #LinphoneFriend object * @return #LinphoneAddress */ @@ -116,7 +116,7 @@ LINPHONE_PUBLIC void linphone_friend_add_phone_number(LinphoneFriend *lf, const * @param lf #LinphoneFriend object * @return \bctbx_list{const char *} */ -LINPHONE_PUBLIC bctbx_list_t* linphone_friend_get_phone_numbers(LinphoneFriend *lf); +LINPHONE_PUBLIC bctbx_list_t* linphone_friend_get_phone_numbers(const LinphoneFriend *lf); /** * Removes a phone number in this friend @@ -215,7 +215,7 @@ LINPHONE_PUBLIC const LinphonePresenceModel * linphone_friend_get_presence_model /** * Get the consolidated presence of a friend. - * @param[in] lf LinphoneFriend object + * @param[in] lf #LinphoneFriend object * @return The consolidated presence of the friend */ LINPHONE_PUBLIC LinphoneConsolidatedPresence linphone_friend_get_consolidated_presence(const LinphoneFriend *lf); @@ -285,39 +285,39 @@ LINPHONE_PUBLIC bool_t linphone_friend_in_list(const LinphoneFriend *lf); /** * Acquire a reference to the linphone friend. - * @param[in] lf LinphoneFriend object - * @return The same LinphoneFriend object + * @param[in] lf #LinphoneFriend object + * @return The same #LinphoneFriend object **/ LINPHONE_PUBLIC LinphoneFriend * linphone_friend_ref(LinphoneFriend *lf); /** * Release a reference to the linphone friend. - * @param[in] lf LinphoneFriend object + * @param[in] lf #LinphoneFriend object **/ LINPHONE_PUBLIC void linphone_friend_unref(LinphoneFriend *lf); /** - * Returns the LinphoneCore object managing this friend, if any. - * @param[in] fr LinphoneFriend object + * Returns the #LinphoneCore object managing this friend, if any. + * @param[in] fr #LinphoneFriend object */ LINPHONE_PUBLIC LinphoneCore *linphone_friend_get_core(const LinphoneFriend *fr); /** * Returns the vCard object associated to this friend, if any - * @param[in] fr LinphoneFriend object + * @param[in] fr #LinphoneFriend object */ -LINPHONE_PUBLIC LinphoneVcard* linphone_friend_get_vcard(LinphoneFriend *fr); +LINPHONE_PUBLIC LinphoneVcard* linphone_friend_get_vcard(const LinphoneFriend *fr); /** * Binds a vCard object to a friend - * @param[in] fr LinphoneFriend object + * @param[in] fr #LinphoneFriend object * @param[in] vcard The vCard object to bind */ LINPHONE_PUBLIC void linphone_friend_set_vcard(LinphoneFriend *fr, LinphoneVcard *vcard); /** * Creates a vCard object associated to this friend if there isn't one yet and if the full name is available, either by the parameter or the one in the friend's SIP URI - * @param[in] fr LinphoneFriend object + * @param[in] fr #LinphoneFriend object * @param[in] name The full name of the friend or NULL to use the one from the friend's SIP URI * @return true if the vCard has been created, false if it wasn't possible (for exemple if name and the friend's SIP URI are null or if the friend's SIP URI doesn't have a display name), or if there is already one vcard */ diff --git a/include/linphone/friendlist.h b/include/linphone/friendlist.h index 1780e8723..b64536717 100644 --- a/include/linphone/friendlist.h +++ b/include/linphone/friendlist.h @@ -36,126 +36,126 @@ extern "C" { /** * Acquire a reference to the friend list. - * @param[in] list LinphoneFriendList object. - * @return The same LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. + * @return The same #LinphoneFriendList object. **/ LINPHONE_PUBLIC LinphoneFriendList * linphone_friend_list_ref(LinphoneFriendList *list); /** * Release reference to the friend list. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. **/ LINPHONE_PUBLIC void linphone_friend_list_unref(LinphoneFriendList *list); /** * Retrieve the user pointer associated with the friend list. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @return The user pointer associated with the friend list. **/ LINPHONE_PUBLIC void * linphone_friend_list_get_user_data(const LinphoneFriendList *list); /** * Assign a user pointer to the friend list. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] ud The user pointer to associate with the friend list. **/ LINPHONE_PUBLIC void linphone_friend_list_set_user_data(LinphoneFriendList *list, void *ud); /** * Get the display name of the friend list. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @return The display name of the friend list. **/ LINPHONE_PUBLIC const char * linphone_friend_list_get_display_name(const LinphoneFriendList *list); /** * Set the display name of the friend list. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] display_name The new display name of the friend list. **/ LINPHONE_PUBLIC void linphone_friend_list_set_display_name(LinphoneFriendList *list, const char *display_name); /** * Get the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @return The RLS URI associated with the friend list. **/ LINPHONE_PUBLIC const char * linphone_friend_list_get_rls_uri(const LinphoneFriendList *list); /** * Set the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] rls_uri The RLS URI to associate with the friend list. **/ LINPHONE_PUBLIC void linphone_friend_list_set_rls_uri(LinphoneFriendList *list, const char *rls_uri); /** * Get the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @return The RLS URI associated with the friend list. **/ LINPHONE_PUBLIC const LinphoneAddress * linphone_friend_list_get_rls_address(const LinphoneFriendList *list); /** * Set the RLS (Resource List Server) URI associated with the friend list to subscribe to these friends presence. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] rls_addr The RLS URI to associate with the friend list. **/ LINPHONE_PUBLIC void linphone_friend_list_set_rls_address(LinphoneFriendList *list, const LinphoneAddress *rls_addr); /** * Add a friend to a friend list. If or when a remote CardDAV server will be attached to the list, the friend will be sent to the server. - * @param[in] list LinphoneFriendList object. - * @param[in] lf LinphoneFriend object to add to the friend list. - * @return LinphoneFriendListOK if successfully added, LinphoneFriendListInvalidFriend if the friend is not valid. + * @param[in] list #LinphoneFriendList object. + * @param[in] lf #LinphoneFriend object to add to the friend list. + * @return #LinphoneFriendListOK if successfully added, #LinphoneFriendListInvalidFriend if the friend is not valid. **/ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_friend(LinphoneFriendList *list, LinphoneFriend *lf); /** * Add a friend to a friend list. The friend will never be sent to a remote CardDAV server. - * Warning! LinphoneFriends added this way will be removed on the next synchronization, and the callback contact_deleted will be called. - * @param[in] list LinphoneFriendList object. - * @param[in] lf LinphoneFriend object to add to the friend list. - * @return LinphoneFriendListOK if successfully added, LinphoneFriendListInvalidFriend if the friend is not valid. + * Warning! #LinphoneFriends added this way will be removed on the next synchronization, and the callback contact_deleted will be called. + * @param[in] list #LinphoneFriendList object. + * @param[in] lf #LinphoneFriend object to add to the friend list. + * @return #LinphoneFriendListOK if successfully added, #LinphoneFriendListInvalidFriend if the friend is not valid. **/ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_add_local_friend(LinphoneFriendList *list, LinphoneFriend *lf); /** * Remove a friend from a friend list. - * @param[in] list LinphoneFriendList object. - * @param[in] lf LinphoneFriend object to remove from the friend list. - * @return LinphoneFriendListOK if removed successfully, LinphoneFriendListNonExistentFriend if the friend is not in the list. + * @param[in] list #LinphoneFriendList object. + * @param[in] lf #LinphoneFriend object to remove from the friend list. + * @return #LinphoneFriendListOK if removed successfully, #LinphoneFriendListNonExistentFriend if the friend is not in the list. **/ LINPHONE_PUBLIC LinphoneFriendListStatus linphone_friend_list_remove_friend(LinphoneFriendList *list, LinphoneFriend *lf); /** - * Retrieves the list of LinphoneFriend from this LinphoneFriendList. - * @param[in] list LinphoneFriendList object - * @return \bctbx_list{LinphoneFriend} a list of LinphoneFriend + * Retrieves the list of #LinphoneFriend from this LinphoneFriendList. + * @param[in] list #LinphoneFriendList object + * @return \bctbx_list{LinphoneFriend} a list of #LinphoneFriend */ LINPHONE_PUBLIC const bctbx_list_t * linphone_friend_list_get_friends(const LinphoneFriendList *list); /** * Find a friend in the friend list using a LinphoneAddress. - * @param[in] list LinphoneFriendList object. - * @param[in] address LinphoneAddress object of the friend we want to search for. - * @return A LinphoneFriend if found, NULL otherwise. + * @param[in] list #LinphoneFriendList object. + * @param[in] address #LinphoneAddress object of the friend we want to search for. + * @return A #LinphoneFriend if found, NULL otherwise. **/ LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_address(const LinphoneFriendList *list, const LinphoneAddress *address); /** * Find a friend in the friend list using an URI string. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] uri A string containing the URI of the friend we want to search for. - * @return A LinphoneFriend if found, NULL otherwise. + * @return A #LinphoneFriend if found, NULL otherwise. **/ LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_uri(const LinphoneFriendList *list, const char *uri); /** * Find a friend in the friend list using a ref key. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] ref_key The ref key string of the friend we want to search for. - * @return A LinphoneFriend if found, NULL otherwise. + * @return A #LinphoneFriend if found, NULL otherwise. **/ LINPHONE_PUBLIC LinphoneFriend * linphone_friend_list_find_friend_by_ref_key(const LinphoneFriendList *list, const char *ref_key); @@ -168,174 +168,174 @@ LINPHONE_PUBLIC void linphone_friend_list_update_subscriptions(LinphoneFriendLis /** * Notify our presence to all the friends in the friend list that have subscribed to our presence directly (not using a RLS). - * @param[in] list LinphoneFriendList object. - * @param[in] presence LinphonePresenceModel object. + * @param[in] list #LinphoneFriendList object. + * @param[in] presence #LinphonePresenceModel object. **/ LINPHONE_PUBLIC void linphone_friend_list_notify_presence(LinphoneFriendList *list, LinphonePresenceModel *presence); /** * Get the URI associated with the friend list. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @return The URI associated with the friend list. **/ LINPHONE_PUBLIC const char * linphone_friend_list_get_uri(const LinphoneFriendList *list); /** * Set the URI associated with the friend list. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] uri The URI to associate with the friend list. **/ LINPHONE_PUBLIC void linphone_friend_list_set_uri(LinphoneFriendList *list, const char *uri); /** * Sets the revision from the last synchronization. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. * @param[in] rev The revision */ LINPHONE_PUBLIC void linphone_friend_list_update_revision(LinphoneFriendList *list, int rev); /** - * Get the LinphoneFriendListCbs object associated with a LinphoneFriendList. - * @param[in] list LinphoneFriendList object - * @return The LinphoneFriendListCbs object associated with the LinphoneFriendList. + * Get the #LinphoneFriendListCbs object associated with a LinphoneFriendList. + * @param[in] list #LinphoneFriendList object + * @return The #LinphoneFriendListCbs object associated with the LinphoneFriendList. **/ LINPHONE_PUBLIC LinphoneFriendListCbs * linphone_friend_list_get_callbacks(const LinphoneFriendList *list); /** - * Acquire a reference to a LinphoneFriendListCbs object. - * @param[in] cbs LinphoneFriendListCbs object. - * @return The same LinphoneFriendListCbs object. + * Acquire a reference to a #LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. + * @return The same #LinphoneFriendListCbs object. **/ LINPHONE_PUBLIC LinphoneFriendListCbs * linphone_friend_list_cbs_ref(LinphoneFriendListCbs *cbs); /** - * Release a reference to a LinphoneFriendListCbs object. - * @param[in] cbs LinphoneFriendListCbs object. + * Release a reference to a #LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. **/ LINPHONE_PUBLIC void linphone_friend_list_cbs_unref(LinphoneFriendListCbs *cbs); /** - * Retrieve the user pointer associated with a LinphoneFriendListCbs object. - * @param[in] cbs LinphoneFriendListCbs object. - * @return The user pointer associated with the LinphoneFriendListCbs object. + * Retrieve the user pointer associated with a #LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. + * @return The user pointer associated with the #LinphoneFriendListCbs object. **/ LINPHONE_PUBLIC void *linphone_friend_list_cbs_get_user_data(const LinphoneFriendListCbs *cbs); /** - * Assign a user pointer to a LinphoneFriendListCbs object. - * @param[in] cbs LinphoneFriendListCbs object. - * @param[in] ud The user pointer to associate with the LinphoneFriendListCbs object. + * Assign a user pointer to a #LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. + * @param[in] ud The user pointer to associate with the #LinphoneFriendListCbs object. **/ LINPHONE_PUBLIC void linphone_friend_list_cbs_set_user_data(LinphoneFriendListCbs *cbs, void *ud); /** * Get the contact created callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @return The current contact created callback. **/ LINPHONE_PUBLIC LinphoneFriendListCbsContactCreatedCb linphone_friend_list_cbs_get_contact_created(const LinphoneFriendListCbs *cbs); /** * Set the contact created callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @param[in] cb The contact created to be used. **/ LINPHONE_PUBLIC void linphone_friend_list_cbs_set_contact_created(LinphoneFriendListCbs *cbs, LinphoneFriendListCbsContactCreatedCb cb); /** * Get the contact deleted callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @return The current contact deleted callback. **/ LINPHONE_PUBLIC LinphoneFriendListCbsContactDeletedCb linphone_friend_list_cbs_get_contact_deleted(const LinphoneFriendListCbs *cbs); /** * Set the contact deleted callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @param[in] cb The contact deleted to be used. **/ LINPHONE_PUBLIC void linphone_friend_list_cbs_set_contact_deleted(LinphoneFriendListCbs *cbs, LinphoneFriendListCbsContactDeletedCb cb); /** * Get the contact updated callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @return The current contact updated callback. **/ LINPHONE_PUBLIC LinphoneFriendListCbsContactUpdatedCb linphone_friend_list_cbs_get_contact_updated(const LinphoneFriendListCbs *cbs); /** * Set the contact updated callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @param[in] cb The contact updated to be used. **/ LINPHONE_PUBLIC void linphone_friend_list_cbs_set_contact_updated(LinphoneFriendListCbs *cbs, LinphoneFriendListCbsContactUpdatedCb cb); /** * Get the sync status changed callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @return The current sync status changedcallback. **/ LINPHONE_PUBLIC LinphoneFriendListCbsSyncStateChangedCb linphone_friend_list_cbs_get_sync_status_changed(const LinphoneFriendListCbs *cbs); /** * Set the contact updated callback. - * @param[in] cbs LinphoneFriendListCbs object. + * @param[in] cbs #LinphoneFriendListCbs object. * @param[in] cb The sync status changed to be used. **/ LINPHONE_PUBLIC void linphone_friend_list_cbs_set_sync_status_changed(LinphoneFriendListCbs *cbs, LinphoneFriendListCbsSyncStateChangedCb cb); /** * Starts a CardDAV synchronization using value set using linphone_friend_list_set_uri. - * @param[in] list LinphoneFriendList object. + * @param[in] list #LinphoneFriendList object. */ LINPHONE_PUBLIC void linphone_friend_list_synchronize_friends_from_server(LinphoneFriendList *list); /** - * Goes through all the LinphoneFriend that are dirty and does a CardDAV PUT to update the server. - * @param[in] list LinphoneFriendList object. + * Goes through all the #LinphoneFriend that are dirty and does a CardDAV PUT to update the server. + * @param[in] list #LinphoneFriendList object. */ LINPHONE_PUBLIC void linphone_friend_list_update_dirty_friends(LinphoneFriendList *list); /** - * Returns the LinphoneCore object attached to this LinphoneFriendList. - * @param[in] list LinphoneFriendList object. - * @return a LinphoneCore object + * Returns the #LinphoneCore object attached to this LinphoneFriendList. + * @param[in] list #LinphoneFriendList object. + * @return a #LinphoneCore object */ LINPHONE_PUBLIC LinphoneCore* linphone_friend_list_get_core(const LinphoneFriendList *list); /** - * Creates and adds LinphoneFriend objects to LinphoneFriendList from a file that contains the vCard(s) to parse - * @param[in] list the LinphoneFriendList object + * Creates and adds #LinphoneFriend objects to #LinphoneFriendList from a file that contains the vCard(s) to parse + * @param[in] list the #LinphoneFriendList object * @param[in] vcard_file the path to a file that contains the vCard(s) to parse * @return the amount of linphone friends created */ LINPHONE_PUBLIC LinphoneStatus linphone_friend_list_import_friends_from_vcard4_file(LinphoneFriendList *list, const char *vcard_file); /** - * Creates and adds LinphoneFriend objects to LinphoneFriendList from a buffer that contains the vCard(s) to parse - * @param[in] list the LinphoneFriendList object + * Creates and adds #LinphoneFriend objects to #LinphoneFriendList from a buffer that contains the vCard(s) to parse + * @param[in] list the #LinphoneFriendList object * @param[in] vcard_buffer the buffer that contains the vCard(s) to parse * @return the amount of linphone friends created */ LINPHONE_PUBLIC LinphoneStatus linphone_friend_list_import_friends_from_vcard4_buffer(LinphoneFriendList *list, const char *vcard_buffer); /** - * Creates and export LinphoneFriend objects from LinphoneFriendList to a file using vCard 4 format - * @param[in] list the LinphoneFriendList object + * Creates and export #LinphoneFriend objects from #LinphoneFriendList to a file using vCard 4 format + * @param[in] list the #LinphoneFriendList object * @param[in] vcard_file the path to a file that will contain the vCards */ LINPHONE_PUBLIC void linphone_friend_list_export_friends_as_vcard4_file(LinphoneFriendList *list, const char *vcard_file); /** * Enable subscription to NOTIFYes of all friends list - * @param[in] list the LinphoneFriendList object + * @param[in] list the #LinphoneFriendList object * @param[in] enabled should subscription be enabled or not */ LINPHONE_PUBLIC void linphone_friend_list_enable_subscriptions(LinphoneFriendList *list, bool_t enabled); /** * Gets whether subscription to NOTIFYes of all friends list are enabled or not - * @param[in] list the LinphoneFriendList object + * @param[in] list the #LinphoneFriendList object * @return Whether subscriptions are enabled or not */ LINPHONE_PUBLIC bool_t linphone_friend_list_subscriptions_enabled(LinphoneFriendList *list); diff --git a/include/linphone/headers.h b/include/linphone/headers.h index 8e9a91f6e..986eb90b7 100644 --- a/include/linphone/headers.h +++ b/include/linphone/headers.h @@ -1,6 +1,6 @@ /* content.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -46,7 +46,7 @@ LINPHONE_PUBLIC void linphone_headers_unref(LinphoneHeaders *obj); /** * Search for a given header name and return its value. - * @param obj the LinphoneHeaders object + * @param obj the #LinphoneHeaders object * @param name the header's name * @return the header's value or NULL if not found. **/ @@ -55,7 +55,7 @@ LINPHONE_PUBLIC const char* linphone_headers_get_value(LinphoneHeaders *obj, con /** * Add given header name and corresponding value. - * @param obj the LinphoneHeaders object + * @param obj the #LinphoneHeaders object * @param name the header's name * @param the header's value **/ @@ -63,7 +63,7 @@ LINPHONE_PUBLIC void linphone_headers_add(LinphoneHeaders *obj, const char *name /** * Add given header name and corresponding value. - * @param obj the LinphoneHeaders object + * @param obj the #LinphoneHeaders object * @param name the header's name * @param the header's value **/ diff --git a/include/linphone/im_encryption_engine.h b/include/linphone/im_encryption_engine.h index d4c15dc3d..8a6bc53b6 100644 --- a/include/linphone/im_encryption_engine.h +++ b/include/linphone/im_encryption_engine.h @@ -33,166 +33,190 @@ extern "C" { /** * Acquire a reference to the LinphoneImEncryptionEngineCbs. - * @param[in] cbs LinphoneImEncryptionEngineCbs object. - * @return The same LinphoneImEncryptionEngineCbs object. + * @param[in] cbs #LinphoneImEncryptionEngineCbs object. + * @return The same #LinphoneImEncryptionEngineCbs object. + * @donotwrap **/ LinphoneImEncryptionEngineCbs * linphone_im_encryption_engine_cbs_ref(LinphoneImEncryptionEngineCbs *cbs); /** * Release reference to the LinphoneImEncryptionEngineCbs. - * @param[in] cbs LinphoneImEncryptionEngineCbs object. + * @param[in] cbs #LinphoneImEncryptionEngineCbs object. + * @donotwrap **/ void linphone_im_encryption_engine_cbs_unref(LinphoneImEncryptionEngineCbs *cbs); /** - * Gets the user data in the LinphoneImEncryptionEngineCbs object - * @param[in] cbs the LinphoneImEncryptionEngineCbs + * Gets the user data in the #LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs * @return the user data + * @donotwrap */ LINPHONE_PUBLIC void *linphone_im_encryption_engine_cbs_get_user_data(const LinphoneImEncryptionEngineCbs *cbs); /** - * Sets the user data in the LinphoneImEncryptionEngineCbs object - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * Sets the user data in the #LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @param[in] data the user data + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_user_data(LinphoneImEncryptionEngineCbs *cbs, void *data); /** * Acquire a reference to the LinphoneImEncryptionEngine. - * @param[in] imee LinphoneImEncryptionEngine object. - * @return The same LinphoneImEncryptionEngine object. + * @param[in] imee #LinphoneImEncryptionEngine object. + * @return The same #LinphoneImEncryptionEngine object. + * @donotwrap **/ LINPHONE_PUBLIC LinphoneImEncryptionEngine * linphone_im_encryption_engine_ref(LinphoneImEncryptionEngine *imee); /** * Release reference to the LinphoneImEncryptionEngine. - * @param[in] imee LinphoneImEncryptionEngine object. + * @param[in] imee #LinphoneImEncryptionEngine object. + * @donotwrap **/ LINPHONE_PUBLIC void linphone_im_encryption_engine_unref(LinphoneImEncryptionEngine *imee); /** - * Gets the user data in the LinphoneImEncryptionEngine object - * @param[in] imee the LinphoneImEncryptionEngine + * Gets the user data in the #LinphoneImEncryptionEngine object + * @param[in] imee the #LinphoneImEncryptionEngine * @return the user data + * @donotwrap */ LINPHONE_PUBLIC void *linphone_im_encryption_engine_get_user_data(const LinphoneImEncryptionEngine *imee); /** - * Sets the user data in the LinphoneImEncryptionEngine object - * @param[in] imee the LinphoneImEncryptionEngine object + * Sets the user data in the #LinphoneImEncryptionEngine object + * @param[in] imee the #LinphoneImEncryptionEngine object * @param[in] data the user data + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_set_user_data(LinphoneImEncryptionEngine *imee, void *data); /** - * Gets the LinphoneCore object that created the IM encryption engine - * @param[in] imee LinphoneImEncryptionEngine object - * @return The LinphoneCore object that created the IM encryption engine + * Gets the #LinphoneCore object that created the IM encryption engine + * @param[in] imee #LinphoneImEncryptionEngine object + * @return The #LinphoneCore object that created the IM encryption engine + * @donotwrap */ LINPHONE_PUBLIC LinphoneCore * linphone_im_encryption_engine_get_core(LinphoneImEncryptionEngine *imee); /** - * Gets the LinphoneImEncryptionEngineCbs object that holds the callbacks - * @param[in] imee the LinphoneImEncryptionEngine object - * @return the LinphoneImEncryptionEngineCbs object + * Gets the #LinphoneImEncryptionEngineCbs object that holds the callbacks + * @param[in] imee the #LinphoneImEncryptionEngine object + * @return the #LinphoneImEncryptionEngineCbs object + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngineCbs* linphone_im_encryption_engine_get_callbacks(const LinphoneImEncryptionEngine *imee); /** * Gets the callback that will decrypt the chat messages upon reception - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @return the callback + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngineCbsIncomingMessageCb linphone_im_encryption_engine_cbs_get_process_incoming_message(LinphoneImEncryptionEngineCbs *cbs); /** * Sets the callback that will decrypt the chat messages upon reception - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @param[in] cb the callback to call + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_incoming_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineCbsIncomingMessageCb cb); /** * Gets the callback that will encrypt the chat messages before sending them - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @return the callback + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngineCbsOutgoingMessageCb linphone_im_encryption_engine_cbs_get_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs); /** * Sets the callback that will encrypt the chat messages before sending them - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @param[in] cb the callback to call + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_outgoing_message(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineCbsOutgoingMessageCb cb); /** * Gets the callback that will decrypt the files while downloading them - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @return the callback + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngineCbsDownloadingFileCb linphone_im_encryption_engine_cbs_get_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs); /** * Sets the callback that will decrypt the files while downloading them - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @param[in] cb the callback to call + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_downloading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineCbsDownloadingFileCb cb); /** * Gets the callback that will will encrypt the files while uploading them - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @return the callback + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngineCbsUploadingFileCb linphone_im_encryption_engine_cbs_get_process_uploading_file(LinphoneImEncryptionEngineCbs *cbs); /** * Sets the callback that will encrypt the files while uploading them - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @param[in] cb the callback to call + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_process_uploading_file(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineCbsUploadingFileCb cb); /** * Gets the callback telling wheter or not to encrypt the files - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @return the callback + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(LinphoneImEncryptionEngineCbs *cbs); /** * Sets the callback telling wheter or not to encrypt the files - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @param[in] cb the callback to call + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_is_encryption_enabled_for_file_transfer(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb cb); /** * Gets the callback that will generate the key to encrypt the file before uploading it - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @return the callback + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(LinphoneImEncryptionEngineCbs *cbs); /** * Sets the callback that will generate the key to encrypt the file before uploading it - * @param[in] cbs the LinphoneImEncryptionEngineCbs object + * @param[in] cbs the #LinphoneImEncryptionEngineCbs object * @param[in] cb the callback to call + * @donotwrap */ LINPHONE_PUBLIC void linphone_im_encryption_engine_cbs_set_generate_file_transfer_key(LinphoneImEncryptionEngineCbs *cbs, LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb cb); /** Set a chat message text to be sent by #linphone_chat_room_send_message - * @param[in] msg LinphoneChatMessage + * @param[in] msg #LinphoneChatMessage * @param[in] text Const char * * @returns 0 if succeed. + * @donotwrap */ LINPHONE_PUBLIC int linphone_chat_message_set_text(LinphoneChatMessage *msg, const char* text); /** * Create the IM encryption engine * @return The created the IM encryption engine + * @donotwrap */ LINPHONE_PUBLIC LinphoneImEncryptionEngine *linphone_im_encryption_engine_new(void); diff --git a/include/linphone/im_notif_policy.h b/include/linphone/im_notif_policy.h index ee2c1a5a3..33aba022d 100644 --- a/include/linphone/im_notif_policy.h +++ b/include/linphone/im_notif_policy.h @@ -35,124 +35,124 @@ extern "C" { */ /** - * Acquire a reference to the LinphoneImNotifPolicy object. - * @param[in] policy LinphoneImNotifPolicy object. - * @return The same LinphoneImNotifPolicy object. + * Acquire a reference to the #LinphoneImNotifPolicy object. + * @param[in] policy #LinphoneImNotifPolicy object. + * @return The same #LinphoneImNotifPolicy object. **/ LINPHONE_PUBLIC LinphoneImNotifPolicy * linphone_im_notif_policy_ref(LinphoneImNotifPolicy *policy); /** - * Release reference to the LinphoneImNotifPolicy object. - * @param[in] policy LinphoneImNotifPolicy object. + * Release reference to the #LinphoneImNotifPolicy object. + * @param[in] policy #LinphoneImNotifPolicy object. **/ LINPHONE_PUBLIC void linphone_im_notif_policy_unref(LinphoneImNotifPolicy *policy); /** - * Retrieve the user pointer associated with the LinphoneImNotifPolicy object. - * @param[in] policy LinphoneImNotifPolicy object. - * @return The user pointer associated with the LinphoneImNotifPolicy object. + * Retrieve the user pointer associated with the #LinphoneImNotifPolicy object. + * @param[in] policy #LinphoneImNotifPolicy object. + * @return The user pointer associated with the #LinphoneImNotifPolicy object. **/ LINPHONE_PUBLIC void *linphone_im_notif_policy_get_user_data(const LinphoneImNotifPolicy *policy); /** - * Assign a user pointer to the LinphoneImNotifPolicy object. - * @param[in] policy LinphoneImNotifPolicy object. - * @param[in] ud The user pointer to associate with the LinphoneImNotifPolicy object. + * Assign a user pointer to the #LinphoneImNotifPolicy object. + * @param[in] policy #LinphoneImNotifPolicy object. + * @param[in] ud The user pointer to associate with the #LinphoneImNotifPolicy object. **/ LINPHONE_PUBLIC void linphone_im_notif_policy_set_user_data(LinphoneImNotifPolicy *policy, void *ud); /** * Clear an IM notif policy (deactivate all receiving and sending of notifications). - * @param[in] policy LinphoneImNotifPolicy object. + * @param[in] policy #LinphoneImNotifPolicy object. */ LINPHONE_PUBLIC void linphone_im_notif_policy_clear(LinphoneImNotifPolicy *policy); /** * Enable all receiving and sending of notifications. - * @param[in] policy LinphoneImNotifPolicy object. + * @param[in] policy #LinphoneImNotifPolicy object. */ LINPHONE_PUBLIC void linphone_im_notif_policy_enable_all(LinphoneImNotifPolicy *policy); /** * Tell whether is_composing notifications are being sent. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @return Boolean value telling whether is_composing notifications are being sent. */ LINPHONE_PUBLIC bool_t linphone_im_notif_policy_get_send_is_composing(const LinphoneImNotifPolicy *policy); /** * Enable is_composing notifications sending. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @param[in] enable Boolean value telling whether to send is_composing notifications. */ LINPHONE_PUBLIC void linphone_im_notif_policy_set_send_is_composing(LinphoneImNotifPolicy *policy, bool_t enable); /** * Tell whether is_composing notifications are being notified when received. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @return Boolean value telling whether is_composing notifications are being notified when received. */ LINPHONE_PUBLIC bool_t linphone_im_notif_policy_get_recv_is_composing(const LinphoneImNotifPolicy *policy); /** * Enable is_composing notifications receiving. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @param[in] enable Boolean value telling whether to notify received is_composing notifications. */ LINPHONE_PUBLIC void linphone_im_notif_policy_set_recv_is_composing(LinphoneImNotifPolicy *policy, bool_t enable); /** * Tell whether imdn delivered notifications are being sent. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @return Boolean value telling whether imdn delivered notifications are being sent. */ LINPHONE_PUBLIC bool_t linphone_im_notif_policy_get_send_imdn_delivered(const LinphoneImNotifPolicy *policy); /** * Enable imdn delivered notifications sending. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @param[in] enable Boolean value telling whether to send imdn delivered notifications. */ LINPHONE_PUBLIC void linphone_im_notif_policy_set_send_imdn_delivered(LinphoneImNotifPolicy *policy, bool_t enable); /** * Tell whether imdn delivered notifications are being notified when received. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @return Boolean value telling whether imdn delivered notifications are being notified when received. */ LINPHONE_PUBLIC bool_t linphone_im_notif_policy_get_recv_imdn_delivered(const LinphoneImNotifPolicy *policy); /** * Enable imdn delivered notifications receiving. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @param[in] enable Boolean value telling whether to notify received imdn delivered notifications. */ LINPHONE_PUBLIC void linphone_im_notif_policy_set_recv_imdn_delivered(LinphoneImNotifPolicy *policy, bool_t enable); /** * Tell whether imdn displayed notifications are being sent. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @return Boolean value telling whether imdn displayed notifications are being sent. */ LINPHONE_PUBLIC bool_t linphone_im_notif_policy_get_send_imdn_displayed(const LinphoneImNotifPolicy *policy); /** * Enable imdn displayed notifications sending. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @param[in] enable Boolean value telling whether to send imdn displayed notifications. */ LINPHONE_PUBLIC void linphone_im_notif_policy_set_send_imdn_displayed(LinphoneImNotifPolicy *policy, bool_t enable); /** * Tell whether imdn displayed notifications are being notified when received. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @return Boolean value telling whether imdn displayed notifications are being notified when received. */ LINPHONE_PUBLIC bool_t linphone_im_notif_policy_get_recv_imdn_displayed(const LinphoneImNotifPolicy *policy); /** * Enable imdn displayed notifications receiving. - * @param[in] policy LinphoneImNotifPolicy object + * @param[in] policy #LinphoneImNotifPolicy object * @param[in] enable Boolean value telling whether to notify received imdn displayed notifications. */ LINPHONE_PUBLIC void linphone_im_notif_policy_set_recv_imdn_displayed(LinphoneImNotifPolicy *policy, bool_t enable); diff --git a/include/linphone/info_message.h b/include/linphone/info_message.h index 06a59ee2a..99804bb14 100644 --- a/include/linphone/info_message.h +++ b/include/linphone/info_message.h @@ -1,6 +1,6 @@ /* info_message.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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,9 +55,9 @@ LINPHONE_PUBLIC const char *linphone_info_message_get_header(const LinphoneInfoM * Assign a content to the info message. * @param im the linphone info message * @param content the content described as a #LinphoneContent structure. - * All fields of the LinphoneContent are copied, thus the application can destroy/modify/recycloe the content object freely ater the function returns. + * All fields of the #LinphoneContent are copied, thus the application can destroy/modify/recycloe the content object freely ater the function returns. **/ -LINPHONE_PUBLIC void linphone_info_message_set_content(LinphoneInfoMessage *im, const LinphoneContent *content); +LINPHONE_PUBLIC void linphone_info_message_set_content(LinphoneInfoMessage *im, const LinphoneContent *content); /** * Returns the info message's content as a #LinphoneContent structure. diff --git a/include/linphone/lpconfig.h b/include/linphone/lpconfig.h index a68292b87..4fa5f681b 100644 --- a/include/linphone/lpconfig.h +++ b/include/linphone/lpconfig.h @@ -33,7 +33,7 @@ */ /** - * Safely downcast a belle_sip_object into LinphoneConfig + * Safely downcast a belle_sip_object into #LinphoneConfig */ #define LINPHONE_CONFIG(obj) BELLE_SIP_CAST(obj, LinphoneConfig); @@ -42,59 +42,59 @@ extern "C" { #endif /** - * Instantiates a LinphoneConfig object from a user config file. + * Instantiates a #LinphoneConfig object from a user config file. * The caller of this constructor owns a reference. linphone_config_unref() must be called when this object is no longer needed. * @ingroup misc - * @param filename the filename of the config file to read to fill the instantiated LinphoneConfig + * @param filename the filename of the config file to read to fill the instantiated #LinphoneConfig * @see linphone_config_new_with_factory */ LINPHONE_PUBLIC LinphoneConfig * linphone_config_new(const char *filename); /** - * Instantiates a LinphoneConfig object from a user provided buffer. + * Instantiates a #LinphoneConfig object from a user provided buffer. * The caller of this constructor owns a reference. linphone_config_unref() must be called when this object is no longer needed. * @ingroup misc - * @param buffer the buffer from which the LinphoneConfig will be retrieved. We expect the buffer to be null-terminated. + * @param buffer the buffer from which the #LinphoneConfig will be retrieved. We expect the buffer to be null-terminated. * @see linphone_config_new_with_factory * @see linphone_config_new */ LINPHONE_PUBLIC LinphoneConfig * linphone_config_new_from_buffer(const char *buffer); /** - * Instantiates a LinphoneConfig object from a user config file and a factory config file. + * Instantiates a #LinphoneConfig object from a user config file and a factory config file. * The caller of this constructor owns a reference. linphone_config_unref() must be called when this object is no longer needed. * @ingroup misc - * @param config_filename the filename of the user config file to read to fill the instantiated LinphoneConfig - * @param factory_config_filename the filename of the factory config file to read to fill the instantiated LinphoneConfig + * @param config_filename the filename of the user config file to read to fill the instantiated #LinphoneConfig + * @param factory_config_filename the filename of the factory config file to read to fill the instantiated #LinphoneConfig * @see linphone_config_new * - * The user config file is read first to fill the LinphoneConfig and then the factory config file is read. + * The user config file is read first to fill the #LinphoneConfig and then the factory config file is read. * Therefore the configuration parameters defined in the user config file will be overwritten by the parameters * defined in the factory config file. */ LINPHONE_PUBLIC LinphoneConfig * linphone_config_new_with_factory(const char *config_filename, const char *factory_config_filename); /** - * Reads a user config file and fill the LinphoneConfig with the read config values. + * Reads a user config file and fill the #LinphoneConfig with the read config values. * @ingroup misc - * @param lpconfig The LinphoneConfig object to fill with the content of the file - * @param filename The filename of the config file to read to fill the LinphoneConfig + * @param lpconfig The #LinphoneConfig object to fill with the content of the file + * @param filename The filename of the config file to read to fill the #LinphoneConfig */ LINPHONE_PUBLIC LinphoneStatus linphone_config_read_file(LinphoneConfig *lpconfig, const char *filename); /** - * Reads a xml config file and fill the LinphoneConfig with the read config dynamic values. + * Reads a xml config file and fill the #LinphoneConfig with the read config dynamic values. * @ingroup misc - * @param lpconfig The LinphoneConfig object to fill with the content of the file - * @param filename The filename of the config file to read to fill the LinphoneConfig + * @param lpconfig The #LinphoneConfig object to fill with the content of the file + * @param filename The filename of the config file to read to fill the #LinphoneConfig */ LINPHONE_PUBLIC const char* linphone_config_load_from_xml_file(LinphoneConfig *lpc, const char *filename); /** - * Reads a xml config string and fill the LinphoneConfig with the read config dynamic values. + * Reads a xml config string and fill the #LinphoneConfig with the read config dynamic values. * @ingroup misc - * @param lpconfig The LinphoneConfig object to fill with the content of the file - * @param buffer The string of the config file to fill the LinphoneConfig + * @param lpconfig The #LinphoneConfig object to fill with the content of the file + * @param buffer The string of the config file to fill the #LinphoneConfig * @return 0 in case of success */ LINPHONE_PUBLIC LinphoneStatus linphone_config_load_from_xml_string(LpConfig *lpc, const char *buffer); @@ -132,6 +132,13 @@ LINPHONE_PUBLIC bool_t linphone_config_get_range(const LinphoneConfig *lpconfig, **/ LINPHONE_PUBLIC int linphone_config_get_int(const LinphoneConfig *lpconfig,const char *section, const char *key, int default_value); +/** + * Retrieves a configuration item as a boolean, given its section, key, and default value. + * + * The default boolean value is returned if the config item isn't found. +**/ +LINPHONE_PUBLIC bool_t linphone_config_get_bool(const LpConfig *lpconfig, const char *section, const char *key, bool_t default_value); + /** * Retrieves a configuration item as a 64 bit integer, given its section, key, and default value. * @@ -170,6 +177,11 @@ LINPHONE_PUBLIC void linphone_config_set_range(LinphoneConfig *lpconfig, const c **/ LINPHONE_PUBLIC void linphone_config_set_int(LinphoneConfig *lpconfig,const char *section, const char *key, int value); +/** + * Sets a boolean config item +**/ +LINPHONE_PUBLIC void linphone_config_set_bool(LinphoneConfig *lpconfig,const char *section, const char *key, bool_t value); + /** * Sets an integer config item, but store it as hexadecimal **/ @@ -202,7 +214,7 @@ LINPHONE_PUBLIC void linphone_config_clean_section(LinphoneConfig *lpconfig, con /** * Returns 1 if a given section with a given key is present in the configuration. - * @param[in] lpconfig The LinphoneConfig object + * @param[in] lpconfig The #LinphoneConfig object * @param[in] section * @param[in] key **/ @@ -210,7 +222,7 @@ LINPHONE_PUBLIC int linphone_config_has_entry(const LinphoneConfig *lpconfig, co /** * Removes entries for key,value in a section. - * @param[in] lpconfig The LinphoneConfig object + * @param[in] lpconfig The #LinphoneConfig object * @param[in] section * @param[in] key **/ @@ -218,18 +230,29 @@ LINPHONE_PUBLIC void linphone_config_clean_entry(LinphoneConfig *lpconfig, const /** * Returns the list of sections' names in the LinphoneConfig. - * @param[in] lpconfig The LinphoneConfig object + * @param[in] lpconfig The #LinphoneConfig object * @return a null terminated static array of strings + * @deprecated use linphone_config_get_sections_names_list instead + * @donotwrap **/ LINPHONE_PUBLIC const char** linphone_config_get_sections_names(LinphoneConfig *lpconfig); /** - * Call a function for each section present in the configuration. + * Returns the list of sections' names in the LinphoneConfig. + * @param[in] lpconfig The #LinphoneConfig object + * @return \bctbx_list{char *} a null terminated static array of strings +**/ +LINPHONE_PUBLIC const bctbx_list_t * linphone_config_get_sections_names_list(LpConfig *lpconfig); + +/** + * @brief Call a function for each section present in the configuration. + * @donotwrap **/ void linphone_config_for_each_section(const LinphoneConfig *lpconfig, void (*callback)(const char *section, void *ctx), void *ctx); /** - * Call a function for each entry present in a section configuration. + * @brief Call a function for each entry present in a section configuration. + * @donotwrap **/ void linphone_config_for_each_entry(const LinphoneConfig *lpconfig, const char *section, void (*callback)(const char *entry, void *ctx), void *ctx); @@ -280,7 +303,7 @@ LINPHONE_PUBLIC void linphone_config_unref(LinphoneConfig *lpconfig); /** * Write a string in a file placed relatively with the Linphone configuration file. - * @param lpconfig LinphoneConfig instance used as a reference + * @param lpconfig #LinphoneConfig 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 */ @@ -288,7 +311,7 @@ LINPHONE_PUBLIC void linphone_config_write_relative_file(const LinphoneConfig *l /** * Read a string from a file placed beside the Linphone configuration file - * @param lpconfig LinphoneConfig instance used as a reference + * @param lpconfig #LinphoneConfig 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 * @param data Buffer where read string will be stored * @param max_length Length of the buffer @@ -303,15 +326,15 @@ LINPHONE_PUBLIC LinphoneStatus linphone_config_read_relative_file(const Linphone LINPHONE_PUBLIC bool_t linphone_config_relative_file_exists(const LinphoneConfig *lpconfig, const char *filename); /** - * Dumps the LinphoneConfig as XML into a buffer - * @param[in] lpconfig The LinphoneConfig object + * Dumps the #LinphoneConfig as XML into a buffer + * @param[in] lpconfig The #LinphoneConfig object * @return The buffer that contains the XML dump **/ LINPHONE_PUBLIC char* linphone_config_dump_as_xml(const LinphoneConfig *lpconfig); /** - * Dumps the LinphoneConfig as INI into a buffer - * @param[in] lpconfig The LinphoneConfig object + * Dumps the #LinphoneConfig as INI into a buffer + * @param[in] lpconfig The #LinphoneConfig object * @return The buffer that contains the config dump **/ LINPHONE_PUBLIC char* linphone_config_dump(const LinphoneConfig *lpconfig); diff --git a/include/linphone/misc.h b/include/linphone/misc.h index 1c05c2dc6..e95ce1252 100644 --- a/include/linphone/misc.h +++ b/include/linphone/misc.h @@ -1,6 +1,6 @@ /* misc.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -102,9 +102,9 @@ LINPHONE_PUBLIC const char *linphone_configuring_state_to_string(LinphoneConfigu LINPHONE_PUBLIC const char* linphone_chat_message_state_to_string(const LinphoneChatMessageState state); /** - * Converts a LinphoneReason enum to a string. + * Converts a #LinphoneReason enum to a string. * @param[in] err A #LinphoneReason - * @return The string representation of the specified LinphoneReason + * @return The string representation of the specified #LinphoneReason * @ingroup misc **/ LINPHONE_PUBLIC const char *linphone_reason_to_string(LinphoneReason err); @@ -118,10 +118,10 @@ LINPHONE_PUBLIC const char *linphone_reason_to_string(LinphoneReason err); LINPHONE_PUBLIC LINPHONE_DEPRECATED const char *linphone_online_status_to_string(LinphoneOnlineStatus ss); /** - * Convert a string into LinphoneTunnelMode enum + * Convert a string into #LinphoneTunnelMode enum * @param string String to convert - * @return An LinphoneTunnelMode enum. If the passed string is NULL or - * does not match with any mode, the LinphoneTunnelModeDisable is returned. + * @return An #LinphoneTunnelMode enum. If the passed string is NULL or + * does not match with any mode, the #LinphoneTunnelModeDisable is returned. */ LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_mode_from_string(const char *string); @@ -139,59 +139,59 @@ LINPHONE_PUBLIC const char *linphone_tunnel_mode_to_string(LinphoneTunnelMode mo LINPHONE_PUBLIC bool_t linphone_local_player_matroska_supported(void); /** - * Converts a LinphoneTransportType enum to a lowercase string. + * Converts a #LinphoneTransportType enum to a lowercase string. * @ingroup misc **/ LINPHONE_PUBLIC const char* linphone_transport_to_string(LinphoneTransportType transport); /** - * Converts a lowercase string to a LinphoneTransportType enum. + * Converts a lowercase string to a #LinphoneTransportType enum. * @ingroup misc - * @return Transport matching input, or LinphoneTransportUdp if nothing is found + * @return Transport matching input, or #LinphoneTransportUdp if nothing is found **/ LINPHONE_PUBLIC LinphoneTransportType linphone_transport_parse(const char* transport); /** * Converts an error code to a LinphoneReason. * @param[in] err An error code - * @return The LinphoneReason corresponding to the specified error code + * @return The #LinphoneReason corresponding to the specified error code * @ingroup misc **/ LINPHONE_PUBLIC LinphoneReason linphone_error_code_to_reason(int err); /** - * Converts a LinphoneReason to an error code. - * @param[in] reason A LinphoneReason - * @return The error code corresponding to the specified LinphoneReason + * Converts a #LinphoneReason to an error code. + * @param[in] reason A #LinphoneReason + * @return The error code corresponding to the specified #LinphoneReason * @ingroup misc */ LINPHONE_PUBLIC int linphone_reason_to_error_code(LinphoneReason reason); /** * Increment refcount. - * @param[in] range LinphoneRange object + * @param[in] range #LinphoneRange object * @ingroup misc **/ LINPHONE_PUBLIC LinphoneRange *linphone_range_ref(LinphoneRange *range); /** * Decrement refcount and possibly free the object. - * @param[in] range LinphoneRange object + * @param[in] range #LinphoneRange object * @ingroup misc **/ LINPHONE_PUBLIC void linphone_range_unref(LinphoneRange *range); /** - * Gets the user data in the LinphoneRange object - * @param[in] range the LinphoneRange + * Gets the user data in the #LinphoneRange object + * @param[in] range the #LinphoneRange * @return the user data * @ingroup misc */ LINPHONE_PUBLIC void *linphone_range_get_user_data(const LinphoneRange *range); /** - * Sets the user data in the LinphoneRange object - * @param[in] range the LinphoneRange object + * Sets the user data in the #LinphoneRange object + * @param[in] range the #LinphoneRange object * @param[in] data the user data * @ingroup misc */ @@ -199,7 +199,7 @@ LINPHONE_PUBLIC void linphone_range_set_user_data(LinphoneRange *range, void *da /** * Gets the lower value of the range - * @param[in] range a LinphoneRange + * @param[in] range a #LinphoneRange * @return The lower value * @ingroup misc */ @@ -207,7 +207,7 @@ LINPHONE_PUBLIC int linphone_range_get_min(const LinphoneRange *range); /** * Gets the higher value of the range - * @param[in] range a LinphoneRange + * @param[in] range a #LinphoneRange * @return The higher value * @ingroup misc */ @@ -215,7 +215,7 @@ LINPHONE_PUBLIC int linphone_range_get_max(const LinphoneRange *range); /** * Sets the lower value of the range - * @param[in] range a LinphoneRange + * @param[in] range a #LinphoneRange * @param[in] min the value to set * @ingroup misc */ @@ -223,7 +223,7 @@ LINPHONE_PUBLIC void linphone_range_set_min(LinphoneRange *range, int min); /** * Sets the higher value of the range - * @param[in] range a LinphoneRange + * @param[in] range a #LinphoneRange * @param[in] max the value to set * @ingroup misc */ diff --git a/include/linphone/nat_policy.h b/include/linphone/nat_policy.h index b409a974f..cf275c65a 100644 --- a/include/linphone/nat_policy.h +++ b/include/linphone/nat_policy.h @@ -35,41 +35,41 @@ extern "C" { */ /** - * Acquire a reference to the LinphoneNatPolicy object. - * @param[in] policy LinphoneNatPolicy object. - * @return The same LinphoneNatPolicy object. + * Acquire a reference to the #LinphoneNatPolicy object. + * @param[in] policy #LinphoneNatPolicy object. + * @return The same #LinphoneNatPolicy object. **/ LINPHONE_PUBLIC LinphoneNatPolicy * linphone_nat_policy_ref(LinphoneNatPolicy *policy); /** - * Release reference to the LinphoneNatPolicy object. - * @param[in] policy LinphoneNatPolicy object. + * Release reference to the #LinphoneNatPolicy object. + * @param[in] policy #LinphoneNatPolicy object. **/ LINPHONE_PUBLIC void linphone_nat_policy_unref(LinphoneNatPolicy *policy); /** - * Retrieve the user pointer associated with the LinphoneNatPolicy object. - * @param[in] policy LinphoneNatPolicy object. - * @return The user pointer associated with the LinphoneNatPolicy object. + * Retrieve the user pointer associated with the #LinphoneNatPolicy object. + * @param[in] policy #LinphoneNatPolicy object. + * @return The user pointer associated with the #LinphoneNatPolicy object. **/ LINPHONE_PUBLIC void *linphone_nat_policy_get_user_data(const LinphoneNatPolicy *policy); /** - * Assign a user pointer to the LinphoneNatPolicy object. - * @param[in] policy LinphoneNatPolicy object. - * @param[in] ud The user pointer to associate with the LinphoneNatPolicy object. + * Assign a user pointer to the #LinphoneNatPolicy object. + * @param[in] policy #LinphoneNatPolicy object. + * @param[in] ud The user pointer to associate with the #LinphoneNatPolicy object. **/ LINPHONE_PUBLIC void linphone_nat_policy_set_user_data(LinphoneNatPolicy *policy, void *ud); /** * Clear a NAT policy (deactivate all protocols and unset the STUN server). - * @param[in] policy LinphoneNatPolicy object. + * @param[in] policy #LinphoneNatPolicy object. */ LINPHONE_PUBLIC void linphone_nat_policy_clear(LinphoneNatPolicy *policy); /** * Tell whether STUN is enabled. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @return Boolean value telling whether STUN is enabled. */ LINPHONE_PUBLIC bool_t linphone_nat_policy_stun_enabled(const LinphoneNatPolicy *policy); @@ -77,14 +77,14 @@ LINPHONE_PUBLIC bool_t linphone_nat_policy_stun_enabled(const LinphoneNatPolicy /** * Enable STUN. * If TURN is also enabled, TURN will be used instead of STUN. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @param[in] enable Boolean value telling whether to enable STUN. */ LINPHONE_PUBLIC void linphone_nat_policy_enable_stun(LinphoneNatPolicy *policy, bool_t enable); /** * Tell whether TURN is enabled. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @return Boolean value telling whether TURN is enabled. */ LINPHONE_PUBLIC bool_t linphone_nat_policy_turn_enabled(const LinphoneNatPolicy *policy); @@ -92,14 +92,14 @@ LINPHONE_PUBLIC bool_t linphone_nat_policy_turn_enabled(const LinphoneNatPolicy /** * Enable TURN. * If STUN is also enabled, it is ignored and TURN is used. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @param[in] enable Boolean value telling whether to enable TURN. */ LINPHONE_PUBLIC void linphone_nat_policy_enable_turn(LinphoneNatPolicy *policy, bool_t enable); /** * Tell whether ICE is enabled. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @return Boolean value telling whether ICE is enabled. */ LINPHONE_PUBLIC bool_t linphone_nat_policy_ice_enabled(const LinphoneNatPolicy *policy); @@ -107,14 +107,14 @@ LINPHONE_PUBLIC bool_t linphone_nat_policy_ice_enabled(const LinphoneNatPolicy * /** * Enable ICE. * ICE can be enabled without STUN/TURN, in which case only the local candidates will be used. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @param[in] enable Boolean value telling whether to enable ICE. */ LINPHONE_PUBLIC void linphone_nat_policy_enable_ice(LinphoneNatPolicy *policy, bool_t enable); /** * Tell whether uPnP is enabled. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @return Boolean value telling whether uPnP is enabled. */ LINPHONE_PUBLIC bool_t linphone_nat_policy_upnp_enabled(const LinphoneNatPolicy *policy); @@ -122,7 +122,7 @@ LINPHONE_PUBLIC bool_t linphone_nat_policy_upnp_enabled(const LinphoneNatPolicy /** * Enable uPnP. * This has the effect to disable every other policies (ICE, STUN and TURN). - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @param[in] enable Boolean value telling whether to enable uPnP. */ LINPHONE_PUBLIC void linphone_nat_policy_enable_upnp(LinphoneNatPolicy *policy, bool_t enable); @@ -130,7 +130,7 @@ LINPHONE_PUBLIC void linphone_nat_policy_enable_upnp(LinphoneNatPolicy *policy, /** * Get the STUN/TURN server to use with this NAT policy. * Used when STUN or TURN are enabled. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @return The STUN server used by this NAT policy. */ LINPHONE_PUBLIC const char * linphone_nat_policy_get_stun_server(const LinphoneNatPolicy *policy); @@ -138,43 +138,50 @@ LINPHONE_PUBLIC const char * linphone_nat_policy_get_stun_server(const LinphoneN /** * Set the STUN/TURN server to use with this NAT policy. * Used when STUN or TURN are enabled. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @param[in] stun_server The STUN server to use with this NAT policy. */ LINPHONE_PUBLIC void linphone_nat_policy_set_stun_server(LinphoneNatPolicy *policy, const char *stun_server); /** * Get the username used to authenticate with the STUN/TURN server. - * The authentication will search for a LinphoneAuthInfo with this username. - * If it is not set the username of the currently used LinphoneProxyConfig is used to search for a LinphoneAuthInfo. - * @param[in] policy LinphoneNatPolicy object + * The authentication will search for a #LinphoneAuthInfo with this username. + * If it is not set the username of the currently used #LinphoneProxyConfig is used to search for a LinphoneAuthInfo. + * @param[in] policy #LinphoneNatPolicy object * @return The username used to authenticate with the STUN/TURN server. */ LINPHONE_PUBLIC const char * linphone_nat_policy_get_stun_server_username(const LinphoneNatPolicy *policy); /** * Set the username used to authenticate with the STUN/TURN server. - * The authentication will search for a LinphoneAuthInfo with this username. - * If it is not set the username of the currently used LinphoneProxyConfig is used to search for a LinphoneAuthInfo. - * @param[in] policy LinphoneNatPolicy object + * The authentication will search for a #LinphoneAuthInfo with this username. + * If it is not set the username of the currently used #LinphoneProxyConfig is used to search for a LinphoneAuthInfo. + * @param[in] policy #LinphoneNatPolicy object * @param[in] username The username used to authenticate with the STUN/TURN server. */ LINPHONE_PUBLIC void linphone_nat_policy_set_stun_server_username(LinphoneNatPolicy *policy, const char *username); /** * Start a STUN server DNS resolution. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object */ LINPHONE_PUBLIC void linphone_nat_policy_resolve_stun_server(LinphoneNatPolicy *policy); /** * Get the addrinfo representation of the STUN server address. * WARNING: This function may block for up to 1 second. - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @return addrinfo representation of the STUN server address. + * @donotwrap */ LINPHONE_PUBLIC const struct addrinfo * linphone_nat_policy_get_stun_server_addrinfo(LinphoneNatPolicy *policy); +/** + * Returns the #LinphoneCore object managing this nat policy, if any. + * @param[in] fr #LinphoneNatPolicy object + */ +LINPHONE_PUBLIC LinphoneCore *linphone_nat_policy_get_core(const LinphoneNatPolicy *policy); + /** * @} */ diff --git a/include/linphone/payload_type.h b/include/linphone/payload_type.h index 8fb848851..a8e420f22 100644 --- a/include/linphone/payload_type.h +++ b/include/linphone/payload_type.h @@ -1,6 +1,6 @@ /* payload_type.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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,7 +114,7 @@ LINPHONE_PUBLIC int linphone_payload_type_get_channels(const LinphonePayloadType LINPHONE_PUBLIC int linphone_payload_type_get_number(const LinphonePayloadType *pt); /** - * Force a number for a payload type. The LinphoneCore does payload type number assignment automatically. + * Force a number for a payload type. The #LinphoneCore does payload type number assignment automatically. * This function is mainly to be used for tests, in order to override the automatic assignment mechanism. * @param[in] pt The payload type. * @param[in] number The number to assign to the payload type. diff --git a/include/linphone/player.h b/include/linphone/player.h index dac160d96..60633f9e6 100644 --- a/include/linphone/player.h +++ b/include/linphone/player.h @@ -1,6 +1,6 @@ /* player.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -37,62 +37,62 @@ extern "C" { /** * Acquire a reference to the player. - * @param[in] player LinphonePlayer object. - * @return The same LinphonePlayer object. + * @param[in] player #LinphonePlayer object. + * @return The same #LinphonePlayer object. **/ LINPHONE_PUBLIC LinphonePlayer * linphone_player_ref(LinphonePlayer *player); /** * Release reference to the player. - * @param[in] player LinphonePlayer object. + * @param[in] player #LinphonePlayer object. **/ LINPHONE_PUBLIC void linphone_player_unref(LinphonePlayer *player); /** * Retrieve the user pointer associated with the player. - * @param[in] player LinphonePlayer object. + * @param[in] player #LinphonePlayer object. * @return The user pointer associated with the player. **/ LINPHONE_PUBLIC void *linphone_player_get_user_data(const LinphonePlayer *player); /** * Assign a user pointer to the player. - * @param[in] player LinphonePlayer object. + * @param[in] player #LinphonePlayer object. * @param[in] ud The user pointer to associate with the player. **/ LINPHONE_PUBLIC void linphone_player_set_user_data(LinphonePlayer *player, void *ud); /** - * Get the LinphonePlayerCbs object associated with the LinphonePlayer. - * @param[in] player LinphonePlayer object - * @return The LinphonePlayerCbs object associated with the LinphonePlayer. + * Get the #LinphonePlayerCbs object associated with the LinphonePlayer. + * @param[in] player #LinphonePlayer object + * @return The #LinphonePlayerCbs object associated with the LinphonePlayer. */ LINPHONE_PUBLIC LinphonePlayerCbs * linphone_player_get_callbacks(const LinphonePlayer *player); /** * Open a file for playing. - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object * @param[in] filename The path to the file to open */ LINPHONE_PUBLIC LinphoneStatus linphone_player_open(LinphonePlayer *obj, const char *filename); /** * Start playing a file that has been opened with linphone_player_open(). - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object * @return 0 on success, a negative value otherwise */ LINPHONE_PUBLIC LinphoneStatus linphone_player_start(LinphonePlayer *obj); /** * Pause the playing of a file. - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object * @return 0 on success, a negative value otherwise */ LINPHONE_PUBLIC LinphoneStatus linphone_player_pause(LinphonePlayer *obj); /** * Seek in an opened file. - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object * @param[in] time_ms The time we want to go to in the file (in milliseconds). * @return 0 on success, a negative value otherwise. */ @@ -100,69 +100,74 @@ LINPHONE_PUBLIC LinphoneStatus linphone_player_seek(LinphonePlayer *obj, int tim /** * Get the current state of a player. - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object * @return The current state of the player. */ LINPHONE_PUBLIC LinphonePlayerState linphone_player_get_state(LinphonePlayer *obj); /** * Get the duration of the opened file. - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object * @return The duration of the opened file */ LINPHONE_PUBLIC int linphone_player_get_duration(LinphonePlayer *obj); /** * Get the current position in the opened file. - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object * @return The current position in the opened file */ LINPHONE_PUBLIC int linphone_player_get_current_position(LinphonePlayer *obj); /** * Close the opened file. - * @param[in] obj LinphonePlayer object + * @param[in] obj #LinphonePlayer object */ LINPHONE_PUBLIC void linphone_player_close(LinphonePlayer *obj); +/** + * Returns the #LinphoneCore object managing this player's call, if any. + * @param[in] fr #LinphonePlayer object + */ +LINPHONE_PUBLIC LinphoneCore *linphone_player_get_core(const LinphonePlayer *player); /** - * Acquire a reference to the LinphonePlayerCbs object. - * @param[in] cbs LinphonePlayerCbs object. - * @return The same LinphonePlayerCbs object. + * Acquire a reference to the #LinphonePlayerCbs object. + * @param[in] cbs #LinphonePlayerCbs object. + * @return The same #LinphonePlayerCbs object. */ LINPHONE_PUBLIC LinphonePlayerCbs * linphone_player_cbs_ref(LinphonePlayerCbs *cbs); /** - * Release reference to the LinphonePlayerCbs object. - * @param[in] cbs LinphonePlayerCbs object. + * Release reference to the #LinphonePlayerCbs object. + * @param[in] cbs #LinphonePlayerCbs object. */ LINPHONE_PUBLIC void linphone_player_cbs_unref(LinphonePlayerCbs *cbs); /** - * Retrieve the user pointer associated with the LinphonePlayerCbs object. - * @param[in] cbs LinphonePlayerCbs object. - * @return The user pointer associated with the LinphonePlayerCbs object. + * Retrieve the user pointer associated with the #LinphonePlayerCbs object. + * @param[in] cbs #LinphonePlayerCbs object. + * @return The user pointer associated with the #LinphonePlayerCbs object. */ LINPHONE_PUBLIC void *linphone_player_cbs_get_user_data(const LinphonePlayerCbs *cbs); /** - * Assign a user pointer to the LinphonePlayerCbs object. - * @param[in] cbs LinphonePlayerCbs object. - * @param[in] ud The user pointer to associate with the LinphonePlayerCbs object. + * Assign a user pointer to the #LinphonePlayerCbs object. + * @param[in] cbs #LinphonePlayerCbs object. + * @param[in] ud The user pointer to associate with the #LinphonePlayerCbs object. */ LINPHONE_PUBLIC void linphone_player_cbs_set_user_data(LinphonePlayerCbs *cbs, void *ud); /** * Get the end-of-file reached callback. - * @param[in] cbs LinphonePlayerCbs object. + * @param[in] cbs #LinphonePlayerCbs object. * @return The current end-of-file reached callback. */ LINPHONE_PUBLIC LinphonePlayerCbsEofReachedCb linphone_player_cbs_get_eof_reached(const LinphonePlayerCbs *cbs); /** * Set the end-of-file reached callback. - * @param[in] cbs LinphonePlayerCbs object. + * @param[in] cbs #LinphonePlayerCbs object. * @param[in] cb The end-of-file reached callback to be used. */ LINPHONE_PUBLIC void linphone_player_cbs_set_eof_reached(LinphonePlayerCbs *cbs, LinphonePlayerCbsEofReachedCb cb); diff --git a/include/linphone/presence.h b/include/linphone/presence.h index 455508d7e..5290fd223 100644 --- a/include/linphone/presence.h +++ b/include/linphone/presence.h @@ -197,8 +197,8 @@ LINPHONE_PUBLIC LinphoneStatus linphone_presence_model_clear_notes(LinphonePrese /** * Get the consolidated presence from a presence model. - * @param[in] model LinphonePresenceModel object - * @return The LinphoneConsolidatedPresence corresponding to the presence model + * @param[in] model #LinphonePresenceModel object + * @return The #LinphoneConsolidatedPresence corresponding to the presence model */ LINPHONE_PUBLIC LinphoneConsolidatedPresence linphone_presence_model_get_consolidated_presence(const LinphonePresenceModel *model); @@ -282,7 +282,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_presence_model_clear_persons(LinphonePre * It is any of theses cases: * - basic status is'open' and no activities * - explicit 'online' tag in the status - * @param[in] model LinphonePresenceModel object + * @param[in] model #LinphonePresenceModel object * @return A boolean value telling whether the presence model is considered online or not. */ LINPHONE_PUBLIC bool_t linphone_presence_model_is_online(const LinphonePresenceModel *model); @@ -294,7 +294,7 @@ LINPHONE_PUBLIC bool_t linphone_presence_model_is_online(const LinphonePresenceM /** * Gets the string representation of a presence basic status. - * @param[in] basic_status A LinphonePresenceBasicStatus for which to get a string representation. + * @param[in] basic_status A #LinphonePresenceBasicStatus for which to get a string representation. * @return A pointer a dynamically allocated string representing the given basic status. * * The returned string is to be freed by calling ms_free(). diff --git a/include/linphone/proxy_config.h b/include/linphone/proxy_config.h index 238cc4b00..1b1d6c54f 100644 --- a/include/linphone/proxy_config.h +++ b/include/linphone/proxy_config.h @@ -99,6 +99,16 @@ LINPHONE_PUBLIC LinphoneStatus linphone_proxy_config_set_identity_address(Linpho **/ LINPHONE_PUBLIC LinphoneStatus linphone_proxy_config_set_route(LinphoneProxyConfig *cfg, const char *route); +/** + * Sets a list of SIP route. + * When a route is set, all outgoing calls will go to the route's destination if this proxy + * is the default one (see linphone_core_set_default_proxy() ). + * @param[in] cfg the #LinphoneProxyConfig + * @param[in] routes A \bctbx_list{const char *} of routes + * @return -1 if routes are invalid, 0 otherwise. +**/ +LINPHONE_PUBLIC LinphoneStatus linphone_proxy_config_set_routes(LinphoneProxyConfig *cfg, const bctbx_list_t *routes); + /** * Sets the registration expiration time in seconds. **/ @@ -107,8 +117,9 @@ LINPHONE_PUBLIC void linphone_proxy_config_set_expires(LinphoneProxyConfig *cfg, #define linphone_proxy_config_expires linphone_proxy_config_set_expires /** - * Indicates either or not, REGISTRATION must be issued for this #LinphoneProxyConfig . - *
In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the linphone_proxy_config_edit() rule. + * @brief Indicates either or not, REGISTRATION must be issued for this #LinphoneProxyConfig . + * + * In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the linphone_proxy_config_edit() rule. * @param[in] cfg #LinphoneProxyConfig object. * @param val if true, registration will be engaged */ @@ -133,11 +144,11 @@ LINPHONE_PUBLIC void linphone_proxy_config_edit(LinphoneProxyConfig *cfg); LINPHONE_PUBLIC LinphoneStatus linphone_proxy_config_done(LinphoneProxyConfig *cfg); /** - * Indicates either or not, PUBLISH must be issued for this #LinphoneProxyConfig . - *
In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the linphone_proxy_config_edit() rule. - * @param[in] cfg #LinphoneProxyConfig object. - * @param val if true, publish will be engaged + * @brief Indicates either or not, PUBLISH must be issued for this #LinphoneProxyConfig. * + * In case this #LinphoneProxyConfig has been added to #LinphoneCore, follows the #linphone_proxy_config_edit() rule. + * @param[in] cfg #LinphoneProxyConfig object. + * @param val if TRUE, publish will be engaged */ LINPHONE_PUBLIC void linphone_proxy_config_enable_publish(LinphoneProxyConfig *cfg, bool_t val); @@ -257,9 +268,17 @@ LINPHONE_PUBLIC void linphone_proxy_config_set_realm(LinphoneProxyConfig *cfg, c /** * @return the route set for this proxy configuration. + * @deprecated Use linphone_proxy_config_get_routes() instead. **/ LINPHONE_PUBLIC const char *linphone_proxy_config_get_route(const LinphoneProxyConfig *cfg); +/** + * Gets the list of the routes set for this proxy config. + * @param[in] cfg #LinphoneProxyConfig object. + * @return \bctbx_list{const char *} the list of routes. + */ +LINPHONE_PUBLIC const bctbx_list_t* linphone_proxy_config_get_routes(const LinphoneProxyConfig *cfg); + /** * @return the SIP identity that belongs to this proxy configuration. **/ @@ -309,6 +328,11 @@ LINPHONE_PUBLIC void linphone_proxy_config_refresh_register(LinphoneProxyConfig **/ LINPHONE_PUBLIC void linphone_proxy_config_pause_register(LinphoneProxyConfig *cfg); +/** + * Return the contact address of the proxy config. + * @param[in] cfg #LinphoneProxyConfig object. + * @return a #LinphoneAddress correspong to the contact address of the proxy config. +**/ LINPHONE_PUBLIC const LinphoneAddress* linphone_proxy_config_get_contact(const LinphoneProxyConfig *cfg); /** @@ -383,7 +407,7 @@ LINPHONE_PUBLIC const char* linphone_proxy_config_get_transport(const LinphonePr /** * Destroys a proxy config. - * @note: LinphoneProxyConfig that have been removed from LinphoneCore with + * @note: #LinphoneProxyConfig that have been removed from #LinphoneCore with * linphone_core_remove_proxy_config() must not be freed. * @deprecated * @donotwrap @@ -444,7 +468,7 @@ LINPHONE_PUBLIC LinphoneAddress* linphone_proxy_config_normalize_sip_uri(Linphon /** * Set default privacy policy for all calls routed through this proxy. * @param[in] cfg #LinphoneProxyConfig object. - * @param privacy LinphonePrivacy to configure privacy + * @param privacy #LinphonePrivacy to configure privacy * */ LINPHONE_PUBLIC void linphone_proxy_config_set_privacy(LinphoneProxyConfig *cfg, LinphonePrivacyMask privacy); @@ -506,14 +530,14 @@ LINPHONE_PUBLIC uint8_t linphone_proxy_config_get_avpf_rr_interval(const Linphon /** * Get enablement status of RTCP feedback (also known as AVPF profile). * @param[in] cfg #LinphoneProxyConfig object. - * @return the enablement mode, which can be LinphoneAVPFDefault (use LinphoneCore's mode), LinphoneAVPFEnabled (avpf is enabled), or LinphoneAVPFDisabled (disabled). + * @return the enablement mode, which can be #LinphoneAVPFDefault (use LinphoneCore's mode), #LinphoneAVPFEnabled (avpf is enabled), or #LinphoneAVPFDisabled (disabled). **/ LINPHONE_PUBLIC LinphoneAVPFMode linphone_proxy_config_get_avpf_mode(const LinphoneProxyConfig *cfg); /** * Enable the use of RTCP feedback (also known as AVPF profile). * @param[in] cfg #LinphoneProxyConfig object. - * @param[in] mode the enablement mode, which can be LinphoneAVPFDefault (use LinphoneCore's mode), LinphoneAVPFEnabled (avpf is enabled), or LinphoneAVPFDisabled (disabled). + * @param[in] mode the enablement mode, which can be #LinphoneAVPFDefault (use LinphoneCore's mode), #LinphoneAVPFEnabled (avpf is enabled), or #LinphoneAVPFDisabled (disabled). **/ LINPHONE_PUBLIC void linphone_proxy_config_set_avpf_mode(LinphoneProxyConfig *cfg, LinphoneAVPFMode mode); @@ -566,7 +590,7 @@ LINPHONE_PUBLIC void linphone_proxy_config_set_ref_key(LinphoneProxyConfig *cfg, * Get The policy that is used to pass through NATs/firewalls when using this proxy config. * If it is set to NULL, the default NAT policy from the core will be used instead. * @param[in] cfg #LinphoneProxyConfig object - * @return LinphoneNatPolicy object in use. + * @return #LinphoneNatPolicy object in use. * @see linphone_core_get_nat_policy() */ LINPHONE_PUBLIC LinphoneNatPolicy * linphone_proxy_config_get_nat_policy(const LinphoneProxyConfig *cfg); @@ -575,11 +599,39 @@ LINPHONE_PUBLIC LinphoneNatPolicy * linphone_proxy_config_get_nat_policy(const L * Set the policy to use to pass through NATs/firewalls when using this proxy config. * If it is set to NULL, the default NAT policy from the core will be used instead. * @param[in] cfg #LinphoneProxyConfig object - * @param[in] policy LinphoneNatPolicy object + * @param[in] policy #LinphoneNatPolicy object * @see linphone_core_set_nat_policy() */ LINPHONE_PUBLIC void linphone_proxy_config_set_nat_policy(LinphoneProxyConfig *cfg, LinphoneNatPolicy *policy); +/** + * Set the conference factory uri. + * @param[in] cfg A #LinphoneProxyConfig object + * @param[in] uri The uri of the conference factory + */ +LINPHONE_PUBLIC void linphone_proxy_config_set_conference_factory_uri(LinphoneProxyConfig *cfg, const char *uri); + +/** + * Get the conference factory uri. + * @param[in] cfg A #LinphoneProxyConfig object + * @return The uri of the conference factory + */ +LINPHONE_PUBLIC const char * linphone_proxy_config_get_conference_factory_uri(const LinphoneProxyConfig *cfg); + +/** + * Indicates whether to add to the contact parameters the push notification information. + * @param[in] cfg #LinphoneProxyConfig object. + * @param[in] allow True to allow push notification information, false otherwise. + */ +LINPHONE_PUBLIC void linphone_proxy_config_set_push_notification_allowed(LinphoneProxyConfig *cfg, bool_t allow); + +/** + * Indicates whether to add to the contact parameters the push notification information. + * @param[in] cfg #LinphoneProxyConfig object. + * @return True if push notification informations should be added, false otherwise. + */ +LINPHONE_PUBLIC bool_t linphone_proxy_config_is_push_notification_allowed(const LinphoneProxyConfig *cfg); + /** * @} */ diff --git a/include/linphone/ringtoneplayer.h b/include/linphone/ringtoneplayer.h index 81dc5f45d..fce0dd739 100644 --- a/include/linphone/ringtoneplayer.h +++ b/include/linphone/ringtoneplayer.h @@ -35,7 +35,7 @@ LINPHONE_PUBLIC LinphoneStatus linphone_ringtoneplayer_start(MSFactory *factory, /** * Start a ringtone player * @param factory A MSFactory object - * @param rp LinphoneRingtonePlayer object + * @param rp #LinphoneRingtonePlayer object * @param card unused argument * @param ringtone path to the ringtone to play * @param loop_pause_ms pause interval in milliseconds to be observed between end of play and resuming at start. A value of -1 disables loop mode diff --git a/include/linphone/tunnel.h b/include/linphone/tunnel.h index 3fbfa9c4b..fbd174a0f 100644 --- a/include/linphone/tunnel.h +++ b/include/linphone/tunnel.h @@ -37,13 +37,13 @@ /** * Linphone tunnel aims is to bypass IP traffic blocking due to aggressive firewalls which typically only authorize TCP traffic with destination port 443. *
Its principle is tunneling all SIP and/or RTP traffic through a single secure https connection up to a detunnelizer server. - *
This set of methods enhance LinphoneCore functionalities in order to provide an easy to use API to + *
This set of methods enhance #LinphoneCore functionalities in order to provide an easy to use API to * \li provision tunnel servers IP addresses and ports. This functionality is an option not implemented under GPL. Availability can be check at runtime using function #linphone_core_tunnel_available * \li start/stop the tunneling service * \li 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. + * No other action on #LinphoneCore is required to enable full operation in tunnel mode. * *
Provision is done using object #LinphoneTunnelConfig created by function #linphone_tunnel_config_new(). Functions #linphone_tunnel_config_set_host * and #linphone_tunnel_config_set_port allow to point to tunnel server IP/port. Once set, use function #linphone_tunnel_add_server to provision a tunnel server. @@ -108,56 +108,56 @@ LINPHONE_PUBLIC void linphone_tunnel_unref(LinphoneTunnel *tunnel); /** * Set the IP address or hostname of the tunnel server. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @param host The tunnel server IP address or hostname */ LINPHONE_PUBLIC void linphone_tunnel_config_set_host(LinphoneTunnelConfig *tunnel, const char *host); /** * Get the IP address or hostname of the tunnel server. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @return The tunnel server IP address or hostname */ LINPHONE_PUBLIC const char *linphone_tunnel_config_get_host(const LinphoneTunnelConfig *tunnel); /** * Set tls port of server. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @param port The tunnel server TLS port, recommended value is 443 */ LINPHONE_PUBLIC void linphone_tunnel_config_set_port(LinphoneTunnelConfig *tunnel, int port); /** * Get the TLS port of the tunnel server. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @return The TLS port of the tunnel server */ LINPHONE_PUBLIC int linphone_tunnel_config_get_port(const LinphoneTunnelConfig *tunnel); /** * Set the IP address or hostname of the second tunnel server when using dual tunnel client. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @param host The tunnel server IP address or hostname */ LINPHONE_PUBLIC void linphone_tunnel_config_set_host2(LinphoneTunnelConfig *tunnel, const char *host); /** * Get the IP address or hostname of the second tunnel server when using dual tunnel client. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @return The tunnel server IP address or hostname */ LINPHONE_PUBLIC const char *linphone_tunnel_config_get_host2(const LinphoneTunnelConfig *tunnel); /** * Set tls port of the second server when using dual tunnel client. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @param port The tunnel server TLS port, recommended value is 443 */ LINPHONE_PUBLIC void linphone_tunnel_config_set_port2(LinphoneTunnelConfig *tunnel, int port); /** * Get the TLS port of the second tunnel server when using dual tunnel client. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @return The TLS port of the tunnel server */ LINPHONE_PUBLIC int linphone_tunnel_config_get_port2(const LinphoneTunnelConfig *tunnel); @@ -165,7 +165,7 @@ LINPHONE_PUBLIC int linphone_tunnel_config_get_port2(const LinphoneTunnelConfig /** * Set the remote port on the tunnel server side used to test UDP reachability. * This is used when the mode is set auto, to detect whether the tunnel has to be enabled or not. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @param remote_udp_mirror_port The remote port on the tunnel server side used to test UDP reachability, set to -1 to disable the feature */ LINPHONE_PUBLIC void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneTunnelConfig *tunnel, int remote_udp_mirror_port); @@ -173,40 +173,40 @@ LINPHONE_PUBLIC void linphone_tunnel_config_set_remote_udp_mirror_port(LinphoneT /** * Get the remote port on the tunnel server side used to test UDP reachability. * This is used when the mode is set auto, to detect whether the tunnel has to be enabled or not. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @return The remote port on the tunnel server side used to test UDP reachability */ LINPHONE_PUBLIC int linphone_tunnel_config_get_remote_udp_mirror_port(const LinphoneTunnelConfig *tunnel); /** * Set the UDP packet round trip delay in ms for a tunnel configuration. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @param delay The UDP packet round trip delay in ms considered as acceptable (recommended value is 1000 ms). */ LINPHONE_PUBLIC void linphone_tunnel_config_set_delay(LinphoneTunnelConfig *tunnel, int delay); /** * Get the UDP packet round trip delay in ms for a tunnel configuration. - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @return The UDP packet round trip delay in ms. */ LINPHONE_PUBLIC int linphone_tunnel_config_get_delay(const LinphoneTunnelConfig *tunnel); /** - * Increment the refcount of LinphoneTunnelConfig object. - * @param cfg the LinphoneTunnelConfig object. + * Increment the refcount of #LinphoneTunnelConfig object. + * @param cfg the #LinphoneTunnelConfig object. * @return the same cfg object. **/ LINPHONE_PUBLIC LinphoneTunnelConfig * linphone_tunnel_config_ref(LinphoneTunnelConfig *cfg); /** - * Decrement the refcount of LinphoneTunnelConfig object. - * @param cfg the LinphoneTunnelConfig object. + * Decrement the refcount of #LinphoneTunnelConfig object. + * @param cfg the #LinphoneTunnelConfig object. **/ LINPHONE_PUBLIC void linphone_tunnel_config_unref(LinphoneTunnelConfig *cfg); /** * Destroy a tunnel configuration - * @param tunnel LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnelConfig object * @deprecated use linphone_tunnel_config_unref(). * @donotwrap */ @@ -228,28 +228,28 @@ LINPHONE_PUBLIC void *linphone_tunnel_config_get_user_data(LinphoneTunnelConfig /** * Add a tunnel server configuration. - * @param tunnel LinphoneTunnel object - * @param tunnel_config LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnel object + * @param tunnel_config #LinphoneTunnelConfig object */ LINPHONE_PUBLIC void linphone_tunnel_add_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); /** * Remove a tunnel server configuration. - * @param tunnel LinphoneTunnel object - * @param tunnel_config LinphoneTunnelConfig object + * @param tunnel #LinphoneTunnel object + * @param tunnel_config #LinphoneTunnelConfig object */ LINPHONE_PUBLIC void linphone_tunnel_remove_server(LinphoneTunnel *tunnel, LinphoneTunnelConfig *tunnel_config); /** * Get added servers - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @return \bctbx_list{LinphoneTunnelConfig} */ LINPHONE_PUBLIC const bctbx_list_t *linphone_tunnel_get_servers(const LinphoneTunnel *tunnel); /** * Remove all tunnel server addresses previously entered with linphone_tunnel_add_server() - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object **/ LINPHONE_PUBLIC void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel); @@ -259,15 +259,15 @@ LINPHONE_PUBLIC void linphone_tunnel_clean_servers(LinphoneTunnel *tunnel); * 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 LinphoneTunnel object - * @param mode The desired LinphoneTunnelMode + * @param tunnel #LinphoneTunnel object + * @param mode The desired #LinphoneTunnelMode **/ LINPHONE_PUBLIC void linphone_tunnel_set_mode(LinphoneTunnel *tunnel, LinphoneTunnelMode mode); /** * Get the tunnel mode - * @param tunnel LinphoneTunnel object - * @return The current LinphoneTunnelMode + * @param tunnel #LinphoneTunnel object + * @return The current #LinphoneTunnelMode **/ LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel *tunnel); @@ -275,14 +275,14 @@ LINPHONE_PUBLIC LinphoneTunnelMode linphone_tunnel_get_mode(const LinphoneTunnel * Sets whether or not to use the dual tunnel client mode. * By default this feature is disabled. * After enabling it, add a server with 2 hosts and 2 ports for the feature to work. - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @param dual_mode_enabled TRUE to enable it, FALSE to disable it */ LINPHONE_PUBLIC void linphone_tunnel_enable_dual_mode(LinphoneTunnel *tunnel, bool_t dual_mode_enabled); /** * Get the dual tunnel client mode - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @return TRUE if dual tunnel client mode is enabled, FALSE otherwise **/ LINPHONE_PUBLIC bool_t linphone_tunnel_dual_mode_enabled(const LinphoneTunnel *tunnel); @@ -298,7 +298,7 @@ LINPHONE_PUBLIC bool_t linphone_tunnel_get_activated(const LinphoneTunnel *tunne /** * Check whether the tunnel is connected - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @return A boolean value telling if the tunnel is connected **/ LINPHONE_PUBLIC bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel); @@ -308,27 +308,27 @@ LINPHONE_PUBLIC bool_t linphone_tunnel_connected(const LinphoneTunnel *tunnel); * This method is useful when the device switches from wifi to Edge/3G or vice versa. In most cases the tunnel client socket * won't be notified promptly that its connection is now zombie, so it is recommended to call this method that will cause * the lost connection to be closed and new connection to be issued. - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object **/ LINPHONE_PUBLIC void linphone_tunnel_reconnect(LinphoneTunnel *tunnel); /** * Set whether SIP packets must be directly sent to a UA or pass through the tunnel - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @param enable If true, SIP packets shall pass through the tunnel */ LINPHONE_PUBLIC void linphone_tunnel_enable_sip(LinphoneTunnel *tunnel, bool_t enable); /** * Check whether tunnel is set to transport SIP packets - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @return A boolean value telling whether SIP packets shall pass through the 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. - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @param host http proxy host * @param port http proxy port * @param username Optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed. @@ -338,7 +338,7 @@ LINPHONE_PUBLIC void linphone_tunnel_set_http_proxy(LinphoneTunnel *tunnel, cons /** * Retrieve optional http proxy configuration previously set with linphone_tunnel_set_http_proxy(). - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @param host http proxy host * @param port http proxy port * @param username Optional http proxy username if the proxy request authentication. Currently only basic authentication is supported. Use NULL if not needed. @@ -349,7 +349,7 @@ LINPHONE_PUBLIC void linphone_tunnel_get_http_proxy(LinphoneTunnel*tunnel,const /** * Set authentication info for the http proxy - * @param tunnel LinphoneTunnel object + * @param tunnel #LinphoneTunnel object * @param username User name * @param passwd Password */ @@ -387,7 +387,7 @@ LINPHONE_PUBLIC LINPHONE_DEPRECATED void linphone_tunnel_auto_detect(LinphoneTun /** * Tell whether tunnel auto detection is enabled. - * @param[in] tunnel LinphoneTunnel object. + * @param[in] tunnel #LinphoneTunnel object. * @return TRUE if auto detection is enabled, FALSE otherwise. * @deprecated Replaced by linphone_tunnel_get_mode() * @donotwrap diff --git a/include/linphone/types.h b/include/linphone/types.h index 058ab6231..340b34342 100644 --- a/include/linphone/types.h +++ b/include/linphone/types.h @@ -1,6 +1,6 @@ /* types.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -26,22 +26,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "mediastreamer2/msvideo.h" #include "linphone/defs.h" +// For migration purpose. +#include "linphone/api/c-types.h" /** - * The LinphoneAccountCreator object used to configure an account on a server via XML-RPC. + * The #LinphoneAccountCreator object used to configure an account on a server via XML-RPC. * @ingroup account_creator **/ typedef struct _LinphoneAccountCreator LinphoneAccountCreator; /** - * An object to define a LinphoneAccountCreator service. + * An object to define a #LinphoneAccountCreator service. * @ingroup account_creator * @donotwrap **/ typedef struct _LinphoneAccountCreatorService LinphoneAccountCreatorService; /** - * An object to handle the responses callbacks for handling the LinphoneAccountCreator operations. + * An object to handle the responses callbacks for handling the #LinphoneAccountCreator operations. * @ingroup account_creator **/ typedef struct _LinphoneAccountCreatorCbs LinphoneAccountCreatorCbs; @@ -169,22 +171,6 @@ typedef enum _LinphoneAccountCreatorStatus { LinphoneAccountCreatorStatusServerError /**< Error server */ } LinphoneAccountCreatorStatus; -struct SalAddress; - -/** - * Object that represents a SIP address. - * - * The LinphoneAddress is an opaque object to represents SIP addresses, ie - * the content of SIP's 'from' and 'to' headers. - * A SIP address is made of display name, username, domain name, port, and various - * uri headers (such as tags). It looks like 'Alice '. - * The LinphoneAddress has methods to extract and manipulate all parts of the address. - * When some part of the address (for example the username) is empty, the accessor methods - * return NULL. - * @ingroup linphone_address - */ -typedef struct SalAddress LinphoneAddress; - /** * Enum describing Ip family. * @ingroup initializing @@ -207,24 +193,24 @@ typedef enum _LinphoneAudioRoute { /** * Object holding authentication information. * + * @note The object's fields should not be accessed directly. Prefer using + * the accessor methods. + * * In most case, authentication information consists of a username and password. * Sometimes, a userid is required by proxy, and realm can be useful to discriminate * different SIP domains. * - * Once created and filled, a LinphoneAuthInfo must be added to the LinphoneCore in + * Once created and filled, a #LinphoneAuthInfo must be added to the #LinphoneCore in * order to become known and used automatically when needed. * Use linphone_core_add_auth_info() for that purpose. * - * The LinphoneCore object can take the initiative to request authentication information + * The #LinphoneCore object can take the initiative to request authentication information * when needed to the application through the auth_info_requested callback of the - * LinphoneCoreVTable structure. + * #LinphoneCoreVTable structure. * * The application can respond to this information request later using * linphone_core_add_auth_info(). This will unblock all pending authentication * transactions and retry them with authentication headers. - * - * @note The object's fields should not be accessed directly. Prefer using - * the accessor methods. * * @ingroup authentication **/ @@ -250,27 +236,11 @@ typedef enum _LinphoneAVPFMode { } LinphoneAVPFMode; /** - * The LinphoneContent object representing a data buffer. + * The #LinphoneContent object representing a data buffer. * @ingroup misc **/ typedef struct _LinphoneBuffer LinphoneBuffer; -/** - * The LinphoneCall object represents a call issued or received by the LinphoneCore - * @ingroup call_control -**/ -typedef struct _LinphoneCall LinphoneCall; - -/** - * That class holds all the callbacks which are called by LinphoneCall objects. - * - * Use linphone_factory_create_call_cbs() to create an instance. Then, call the - * callback setters on the events you need to monitor and pass the object to - * a LinphoneCall instance through linphone_call_add_callbacks(). - * @ingroup call_control - */ -typedef struct _LinphoneCallCbs LinphoneCallCbs; - /** * Enum representing the direction of a call. * @ingroup call_logs @@ -287,7 +257,7 @@ typedef enum _LinphoneCallDir { typedef struct _LinphoneCallLog LinphoneCallLog; /** - * The LinphoneCallParams is an object containing various call related parameters. + * 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. * @ingroup call_control @@ -295,39 +265,10 @@ typedef struct _LinphoneCallLog LinphoneCallLog; typedef struct _LinphoneCallParams LinphoneCallParams; /** - * LinphoneCallState enum represents the different state a call can reach into. - * The application is notified of state changes through the LinphoneCoreVTable::call_state_changed callback. - * @ingroup call_control -**/ -typedef enum _LinphoneCallState{ - LinphoneCallIdle, /**< Initial call state */ - LinphoneCallIncomingReceived, /**< This is a new incoming call */ - LinphoneCallOutgoingInit, /**< An outgoing call is started */ - LinphoneCallOutgoingProgress, /**< An outgoing call is in progress */ - LinphoneCallOutgoingRinging, /**< An outgoing call is ringing at remote end */ - LinphoneCallOutgoingEarlyMedia, /**< An outgoing call is proposed early media */ - LinphoneCallConnected, /**< Connected, the call is answered */ - LinphoneCallStreamsRunning, /**< The media streams are established and running */ - LinphoneCallPausing, /**< The call is pausing at the initiative of local end */ - LinphoneCallPaused, /**< The call is paused, remote end has accepted the pause */ - LinphoneCallResuming, /**< The call is being resumed by local end */ - LinphoneCallRefered, /**< The call is being transfered to another party, resulting in a new outgoing call to follow immediately */ - LinphoneCallError, /**< The call encountered an error */ - LinphoneCallEnd, /**< The call ended normally */ - LinphoneCallPausedByRemote, /**< The call is paused by remote end */ - LinphoneCallUpdatedByRemote, /**< The call's parameters change is requested by remote end, used for example when video is added by remote */ - LinphoneCallIncomingEarlyMedia, /**< We are proposing early media to an incoming call */ - LinphoneCallUpdating, /**< A call update has been initiated by us */ - LinphoneCallReleased, /**< The call object is no more retained by the core */ - LinphoneCallEarlyUpdatedByRemote, /**< The call is updated by remote while not yet answered (early dialog SIP UPDATE received) */ - LinphoneCallEarlyUpdating /**< We are updating the call while not yet answered (early dialog SIP UPDATE sent) */ -} LinphoneCallState; - -/** - * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. + * The #LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. * - * To receive these informations periodically and as soon as they are computed, the application is invited to place a #LinphoneCoreCallStatsUpdatedCb callback in the LinphoneCoreVTable structure - * it passes for instanciating the LinphoneCore object (see linphone_core_new() ). + * To receive these informations periodically and as soon as they are computed, the application is invited to place a #LinphoneCoreCallStatsUpdatedCb callback in the #LinphoneCoreVTable structure + * it passes for instanciating the #LinphoneCore object (see linphone_core_new() ). * * At any time, the application can access last computed statistics using linphone_call_get_audio_stats() or linphone_call_get_video_stats(). * @ingroup call_misc @@ -349,42 +290,7 @@ typedef enum _LinphoneCallStatus { } LinphoneCallStatus; /** - * A chat room message to hold content to be sent. - * Can be created by linphone_chat_room_create_message(). - * @ingroup chatroom - */ -typedef struct _LinphoneChatMessage LinphoneChatMessage; - -/** - * An object to handle the callbacks for the handling a LinphoneChatMessage objects. - * @ingroup chatroom - */ -typedef struct _LinphoneChatMessageCbs LinphoneChatMessageCbs; - -/** - * LinphoneChatMessageState is used to notify if messages have been succesfully delivered or not. - * @ingroup chatroom - */ -typedef enum _LinphoneChatMessageState { - LinphoneChatMessageStateIdle, /**< Initial state */ - LinphoneChatMessageStateInProgress, /**< Delivery in progress */ - LinphoneChatMessageStateDelivered, /**< Message successfully delivered and acknowledged by server */ - LinphoneChatMessageStateNotDelivered, /**< Message was not delivered */ - LinphoneChatMessageStateFileTransferError, /**< Message was received(and acknowledged) but cannot get file from server */ - LinphoneChatMessageStateFileTransferDone, /**< File transfer has been completed successfully */ - LinphoneChatMessageStateDeliveredToUser, /**< Message successfully delivered and acknowledged to destination */ - LinphoneChatMessageStateDisplayed /**< Message displayed to the remote user */ -} LinphoneChatMessageState; - -/** - * A chat room is the place where text messages are exchanged. - * Can be created by linphone_core_create_chat_room(). - * @ingroup chatroom - */ -typedef struct _LinphoneChatRoom LinphoneChatRoom; - -/** - * LinphoneConference class + * #LinphoneConference class * The _LinphoneConference struct does not exists, it's the Conference C++ class that is used behind * @ingroup call_control */ @@ -398,7 +304,7 @@ typedef struct _LinphoneConference LinphoneConference; typedef struct _LinphoneConferenceParams LinphoneConferenceParams; /** - * The LinphoneConfig object is used to manipulate a configuration file. + * The #LinphoneConfig object is used to manipulate a configuration file. * * The format of the configuration file is a .ini like format: * - sections are defined in [] @@ -424,7 +330,7 @@ typedef struct _LpConfig LinphoneConfig; #define LpConfig LinphoneConfig /** - * LinphoneGlobalState describes the global state of the LinphoneCore object. + * #LinphoneGlobalState describes the global state of the #LinphoneCore object. * It is notified via the LinphoneCoreVTable::global_state_changed * @ingroup initializing **/ @@ -455,18 +361,12 @@ typedef struct _LinphoneContactSearch LinphoneContactSearch; typedef unsigned int LinphoneContactSearchID; /** - * Old name of LinphoneContactSearchID + * Old name of #LinphoneContactSearchID * @deprecated * @donotwrap */ LINPHONE_DEPRECATED typedef LinphoneContactSearchID ContactSearchID; -/** - * The LinphoneContent object holds data that can be embedded in a signaling message. - * @ingroup misc -**/ -typedef struct _LinphoneContent LinphoneContent; - /** * Linphone core main object created by function linphone_core_new() . * @ingroup initializing @@ -500,7 +400,7 @@ typedef enum _LinphoneEcCalibratorStatus { /** * Object representing full details about a signaling error or status. - * All LinphoneErrorInfo object returned by the liblinphone API are readonly and transcients. For safety they must be used immediately + * All #LinphoneErrorInfo object returned by the liblinphone API are readonly and transcients. For safety they must be used immediately * after obtaining them. Any other function call to the liblinphone may change their content or invalidate the pointer. * @ingroup misc **/ @@ -514,6 +414,12 @@ typedef struct _LinphoneErrorInfo LinphoneErrorInfo; **/ typedef struct _LinphoneEvent LinphoneEvent; +/** + * An object to handle the callbacks for handling the LinphoneEvent operations. + * @ingroup event_api +**/ +typedef struct _LinphoneEventCbs LinphoneEventCbs; + /** * #LinphoneFactory is a singleton object devoted to the creation of all the object * of Liblinphone that cannot be created by #LinphoneCore itself. @@ -542,13 +448,13 @@ typedef enum _LinphoneFirewallPolicy { typedef struct _LinphoneFriend LinphoneFriend; /** - * The LinphoneFriendList object representing a list of friends. + * The #LinphoneFriendList object representing a list of friends. * @ingroup buddy_list **/ typedef struct _LinphoneFriendList LinphoneFriendList; /** - * An object to handle the callbacks for LinphoneFriend synchronization. + * An object to handle the callbacks for #LinphoneFriend synchronization. * @ingroup buddy_list **/ typedef struct _LinphoneFriendListCbs LinphoneFriendListCbs; @@ -574,7 +480,7 @@ typedef enum _LinphoneFriendListSyncStatus { } LinphoneFriendListSyncStatus; /** - * LinphoneGlobalState describes the global state of the LinphoneCore object. + * #LinphoneGlobalState describes the global state of the #LinphoneCore object. * It is notified via the LinphoneCoreVTable::global_state_changed * @ingroup initializing **/ @@ -602,12 +508,14 @@ typedef enum _LinphoneIceState { /** * IM encryption engine. * @ingroup misc + * @donotwrap */ typedef struct _LinphoneImEncryptionEngine LinphoneImEncryptionEngine; /** - * An object to handle the callbacks for the handling a LinphoneImEncryptionEngine object. + * An object to handle the callbacks for the handling a #LinphoneImEncryptionEngine object. * @ingroup misc + * @donotwrap */ typedef struct _LinphoneImEncryptionEngineCbs LinphoneImEncryptionEngineCbs; @@ -619,7 +527,7 @@ typedef struct _LinphoneImEncryptionEngineCbs LinphoneImEncryptionEngineCbs; typedef struct _LinphoneImNotifPolicy LinphoneImNotifPolicy; /** - * The LinphoneInfoMessage is an object representing an informational message sent or received by the core. + * The #LinphoneInfoMessage is an object representing an informational message sent or received by the core. * @ingroup misc **/ typedef struct _LinphoneInfoMessage LinphoneInfoMessage; @@ -647,7 +555,7 @@ typedef enum _LinphoneLogCollectionState { } LinphoneLogCollectionState; /** - * LinphoneCoreLogCollectionUploadState is used to notify if log collection upload have been succesfully delivered or not. + * #LinphoneCoreLogCollectionUploadState is used to notify if log collection upload have been succesfully delivered or not. * @ingroup initializing */ typedef enum _LinphoneCoreLogCollectionUploadState { @@ -714,7 +622,7 @@ typedef enum _LinphoneOnlineStatus{ typedef struct _LinphonePlayer LinphonePlayer; /** - * An object to handle the callbacks for the handling a LinphonePlayer objects. + * An object to handle the callbacks for the handling a #LinphonePlayer objects. * @ingroup call_control */ typedef struct _LinphonePlayerCbs LinphonePlayerCbs; @@ -924,11 +832,11 @@ typedef enum _LinphonePrivacy { typedef unsigned int LinphonePrivacyMask; /** - * The LinphoneProxyConfig object represents a proxy configuration to be used - * by the LinphoneCore object. + * 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 linphone_core_add_proxy_config(). + * Once created and filled properly the #LinphoneProxyConfig can be given to + * #LinphoneCore with linphone_core_add_proxy_config(). * This will automatically triggers the registration, if enabled. * * The proxy configuration are persistent to restarts because they are saved @@ -992,7 +900,7 @@ typedef enum _LinphoneReason{ #define LinphoneReasonMedia LinphoneReasonUnsupportedContent /** - * LinphoneRegistrationState describes proxy registration states. + * #LinphoneRegistrationState describes proxy registration states. * @ingroup proxies **/ typedef enum _LinphoneRegistrationState { @@ -1028,7 +936,7 @@ typedef struct _LinphoneSipTransports { typedef struct _LinphoneTransports LinphoneTransports; /** - * Old name of LinphoneSipTransports + * Old name of #LinphoneSipTransports * @deprecated * @donotwrap */ @@ -1074,7 +982,7 @@ typedef enum _LinphoneSubscriptionDir{ /** * Enum for subscription states. - * LinphoneSubscriptionTerminated and LinphoneSubscriptionError are final states. + * #LinphoneSubscriptionTerminated and #LinphoneSubscriptionError are final states. * @ingroup event_api **/ typedef enum _LinphoneSubscriptionState{ @@ -1119,7 +1027,7 @@ typedef enum _LinphoneTransportType { typedef struct _LinphoneTunnel LinphoneTunnel; /** - * @brief Class to store tunnel settings. + * @brief Tunnel settings. * @ingroup tunnel */ typedef struct _LinphoneTunnelConfig LinphoneTunnelConfig; @@ -1150,7 +1058,7 @@ typedef enum _LinphoneUpnpState { } LinphoneUpnpState; /** - * The LinphoneVcard object. + * The #LinphoneVcard object. * @ingroup carddav_vcard */ typedef struct _LinphoneVcard LinphoneVcard; @@ -1166,7 +1074,7 @@ typedef enum _LinphoneVersionUpdateCheckResult { } LinphoneVersionUpdateCheckResult; /** - * The LinphoneVideoDefinition object represents a video definition, eg. its width and its height. + * The #LinphoneVideoDefinition object represents a video definition, eg. its width and its height. * @ingroup media_parameters */ typedef struct _LinphoneVideoDefinition LinphoneVideoDefinition; @@ -1195,7 +1103,7 @@ typedef struct LinphoneVideoSizeDef { } LinphoneVideoSizeDef; /** - * Old name of LinphoneVideoSizeDef + * Old name of #LinphoneVideoSizeDef * @deprecated */ typedef LinphoneVideoSizeDef MSVideoSizeDef; @@ -1217,19 +1125,19 @@ typedef enum _LinphoneXmlRpcArgType { } LinphoneXmlRpcArgType; /** - * The LinphoneXmlRpcRequest object representing a XML-RPC request to be sent. + * The #LinphoneXmlRpcRequest object representing a XML-RPC request to be sent. * @ingroup misc **/ typedef struct _LinphoneXmlRpcRequest LinphoneXmlRpcRequest; /** - * An object to handle the callbacks for handling the LinphoneXmlRpcRequest operations. + * An object to handle the callbacks for handling the #LinphoneXmlRpcRequest operations. * @ingroup misc **/ typedef struct _LinphoneXmlRpcRequestCbs LinphoneXmlRpcRequestCbs; /** - * The LinphoneXmlRpcSession object used to send XML-RPC requests and handle their responses. + * The #LinphoneXmlRpcSession object used to send XML-RPC requests and handle their responses. * @ingroup misc **/ typedef struct _LinphoneXmlRpcSession LinphoneXmlRpcSession; diff --git a/include/linphone/utils/algorithm.h b/include/linphone/utils/algorithm.h new file mode 100644 index 000000000..2a31d6cb1 --- /dev/null +++ b/include/linphone/utils/algorithm.h @@ -0,0 +1,70 @@ +/* + * algorithm.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ALGORITHM_H_ +#define _L_ALGORITHM_H_ + +#include + +#include "general.h" + +// ============================================================================= + +// NOTE: Maybe use https://github.com/ericniebler/range-v3 one day? + +LINPHONE_BEGIN_NAMESPACE + +template +typename T::const_iterator find (const T &container, const Value &value) { + return std::find(container.cbegin(), container.cend(), value); +} + +template +typename T::iterator find (T &container, const Value &value) { + return std::find(container.begin(), container.end(), value); +} + +template +typename T::const_iterator findIf (const T &container, Predicate predicate) { + return std::find_if(container.cbegin(), container.cend(), predicate); +} + +template +typename T::iterator findIf (T &container, Predicate predicate) { + return std::find_if(container.begin(), container.end(), predicate); +} + +template +bool removeFirst (T &container, const Value &value) { + auto it = find(container, value); + if (it != container.end()) { + container.erase(it); + return true; + } + return false; +} + +template +void removeIf (T &container, Predicate predicate) { + std::remove_if(container.begin(), container.end(), predicate); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ALGORITHM_H_ diff --git a/include/linphone/utils/enum-generator.h b/include/linphone/utils/enum-generator.h new file mode 100644 index 000000000..ebdca6c61 --- /dev/null +++ b/include/linphone/utils/enum-generator.h @@ -0,0 +1,113 @@ +/* + * enum-generator.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ENUM_GENERATOR_H_ +#define _L_ENUM_GENERATOR_H_ + +#include "linphone/utils/magic-macros.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- +// Low-level, do not call. +// ----------------------------------------------------------------------------- + +// Declare one enum value. `value` is optional, it can be generated. +// It's useful to force value in the case of mask. +#define L_DECLARE_ENUM_VALUE_1_ARG(NAME) NAME, +#define L_DECLARE_ENUM_VALUE_2_ARGS(NAME, VALUE) NAME = VALUE, + +// Call the right macro. (With or without value.) +#define L_DECLARE_ENUM_MACRO_CHOOSER(...) \ + L_EXPAND(L_GET_ARG_3(__VA_ARGS__, L_DECLARE_ENUM_VALUE_2_ARGS, L_DECLARE_ENUM_VALUE_1_ARG)) + +// Enum value declaration. +#define L_DECLARE_ENUM_VALUE(...) \ + L_EXPAND(L_DECLARE_ENUM_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)) + +#ifdef __cplusplus + +// `getEnumValue` helper. +#define L_DECLARE_ENUM_VALUE_STR_CASE(ENUM_NAME, VALUE_NAME, ...) \ + case ENUM_NAME::VALUE_NAME: return #ENUM_NAME "::" #VALUE_NAME; + +// Helper to get enum name. +#define L_DECLARE_ENUM_NAME(NAME, ...) NAME, + +// Get names as string from enum values. +#define L_GET_ENUM_VALUE_NAMES(VALUES) L_GET_HEAP(VALUES(L_DECLARE_ENUM_NAME)) + +#endif + +// ----------------------------------------------------------------------------- +// Public API. +// ----------------------------------------------------------------------------- + +#ifdef __cplusplus + +#define L_DECLARE_ENUM(NAME, VALUES) \ + enum class NAME { \ + VALUES(L_DECLARE_ENUM_VALUE) \ + }; \ + friend constexpr const char *getEnumNameAsString (NAME) { \ + return #NAME; \ + } \ + friend const char *getEnumValueAsString (const NAME &value) { \ + switch (value) { \ + L_APPLY_WITHOUT_COMMA(L_DECLARE_ENUM_VALUE_STR_CASE, NAME, L_GET_ENUM_VALUE_NAMES(VALUES)) \ + } \ + return ""; \ + } + +template +inline char getEnumValueAsString (const T &) { return 0; } + +template +struct IsDefinedEnum { + enum { value = sizeof(getEnumValueAsString(std::declval())) == sizeof(const char *) }; +}; + +#endif + +#define L_C_ENUM_PREFIX Linphone + +// TODO: This macro should be used but it is triggering a bug in doxygen that +// has been fixed in the 1.8.8 version. See https://bugzilla.gnome.org/show_bug.cgi?id=731985 +// Meanwhile use 2 different macros. +#if 0 +#define L_DECLARE_C_ENUM(NAME, VALUES) \ + typedef enum L_CONCAT(_, L_CONCAT(L_C_ENUM_PREFIX, NAME)) { \ + L_APPLY(L_CONCAT, L_CONCAT(L_C_ENUM_PREFIX, NAME), L_GET_HEAP(VALUES(L_DECLARE_ENUM_VALUE))) \ + } L_CONCAT(L_C_ENUM_PREFIX, NAME) +#else +#define L_DECLARE_C_ENUM(NAME, VALUES) \ + typedef enum L_CONCAT(_, L_CONCAT(L_C_ENUM_PREFIX, NAME)) { \ + L_APPLY(L_CONCAT, L_CONCAT(L_C_ENUM_PREFIX, NAME), L_GET_HEAP(VALUES(L_DECLARE_ENUM_VALUE_1_ARG))) \ + } L_CONCAT(L_C_ENUM_PREFIX, NAME) +#define L_DECLARE_C_ENUM_FIXED_VALUES(NAME, VALUES) \ + typedef enum L_CONCAT(_, L_CONCAT(L_C_ENUM_PREFIX, NAME)) { \ + L_APPLY(L_CONCAT, L_CONCAT(L_C_ENUM_PREFIX, NAME), L_GET_HEAP(VALUES(L_DECLARE_ENUM_VALUE_2_ARGS))) \ + } L_CONCAT(L_C_ENUM_PREFIX, NAME) +#endif + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ENUM_GENERATOR_H_ diff --git a/include/linphone/utils/enum-mask.h b/include/linphone/utils/enum-mask.h new file mode 100644 index 000000000..53eac2c5f --- /dev/null +++ b/include/linphone/utils/enum-mask.h @@ -0,0 +1,163 @@ +/* + * enum-mask.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ENUM_MASK_H_ +#define _L_ENUM_MASK_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +template +class EnumMask { + static_assert(std::is_enum::value, "EnumMask must be used with enum type. Logic no?"); + static_assert(sizeof(T) <= sizeof(int), "EnumMask supports only int, short or char values."); + +public: + // EnumMask's type. Can be int or unsigned int. + // See: http://en.cppreference.com/w/cpp/types/underlying_type + typedef typename std::conditional< + std::is_signed::type>::value, int, unsigned int + >::type StorageType; + + constexpr EnumMask (int mask = 0) : mMask(mask) {} + constexpr EnumMask (T value) : mMask(StorageType(value)) {} + constexpr EnumMask (std::initializer_list mask) : mMask(init(mask.begin(), mask.end())) {} + + constexpr operator StorageType () const { + return mMask; + } + + constexpr bool isSet (T value) const { + return isSet(StorageType(value)); + } + + inline EnumMask &set (T value) { + *this |= value; + return *this; + } + + inline EnumMask &unset (T value) { + *this &= ~value; + return *this; + } + + constexpr bool operator! () const { + return !mMask; + } + + inline EnumMask &operator&= (int mask) { + mMask &= mask; + return *this; + } + + inline EnumMask &operator&= (unsigned int mask) { + mMask &= mask; + return *this; + } + + inline EnumMask &operator&= (T mask) { + mMask &= StorageType(mask); + return *this; + } + + inline EnumMask &operator|= (EnumMask mask) { + mMask |= mask.mMask; + return *this; + } + + inline EnumMask &operator|= (T mask) { + mMask |= StorageType(mask); + return *this; + } + + inline EnumMask &operator^= (EnumMask mask) { + mMask ^= mask.mMask; + return *this; + } + + inline EnumMask &operator^= (T mask) { + mMask ^= StorageType(mask); + return *this; + } + + constexpr EnumMask operator& (int mask) const { + return mMask & mask; + } + + constexpr EnumMask operator& (unsigned int mask) const { + return mMask & mask; + } + + constexpr EnumMask operator& (T mask) const { + return mMask & StorageType(mask); + } + + constexpr EnumMask operator| (EnumMask mask) const { + return mMask | mask.mMask; + } + + constexpr EnumMask operator| (T mask) const { + return mMask | StorageType(mask); + } + + constexpr EnumMask operator^ (EnumMask mask) const { + return mMask ^ mask.mMask; + } + + constexpr EnumMask operator^ (T mask) const { + return mMask ^ StorageType(mask); + } + + constexpr EnumMask operator~ () const { + return ~mMask; + } + +private: + constexpr bool isSet (StorageType value) const { + return (mMask & value) == value && (value || mMask == 0); + } + +// On CentOs 7 GCC 4.8.5 have issue with array-bounds. +#if __GNUC__ == 4 && __GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ == 5 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" +#endif + + static constexpr StorageType init ( + typename std::initializer_list::const_iterator begin, + typename std::initializer_list::const_iterator end + ) { + return begin != end ? (StorageType(*begin) | init(begin + 1, end)) : StorageType(0); + } + +#if __GNUC__ == 4 && __GNUC_MINOR__ == 8 && __GNUC_PATCHLEVEL__ == 5 + #pragma GCC diagnostic pop +#endif + + StorageType mMask; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ENUM_MASK_H_ diff --git a/include/linphone/utils/fs.h b/include/linphone/utils/fs.h new file mode 100644 index 000000000..4332c4532 --- /dev/null +++ b/include/linphone/utils/fs.h @@ -0,0 +1,38 @@ +/* + * fs.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_FS_H_ +#define _L_FS_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +namespace Fs { + // Copy one file to other destination. Return true on success. + LINPHONE_PUBLIC bool copy (const std::string &srcPath, const std::string &destPath); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_FS_H_ diff --git a/include/linphone/utils/general.h b/include/linphone/utils/general.h new file mode 100644 index 000000000..87f4a4808 --- /dev/null +++ b/include/linphone/utils/general.h @@ -0,0 +1,330 @@ +/* + * general.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_GENERAL_H_ +#define _L_GENERAL_H_ + +#ifdef __cplusplus + #include + #include +#endif + +// ============================================================================= + +// ----------------------------------------------------------------------------- +// Namespace. +// ----------------------------------------------------------------------------- + +#ifdef __cplusplus + #define LINPHONE_BEGIN_NAMESPACE namespace LinphonePrivate { + #define LINPHONE_END_NAMESPACE } +#else + #define LINPHONE_BEGIN_NAMESPACE + #define LINPHONE_END_NAMESPACE +#endif + +// ----------------------------------------------------------------------------- + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- +// Export. +// ----------------------------------------------------------------------------- + +#ifndef LINPHONE_PUBLIC + #if defined(_MSC_VER) + #ifdef LINPHONE_STATIC + #define LINPHONE_PUBLIC + #else + #ifdef LINPHONE_EXPORTS + #define LINPHONE_PUBLIC __declspec(dllexport) + #else + #define LINPHONE_PUBLIC __declspec(dllimport) + #endif + #endif + #else + #define LINPHONE_PUBLIC + #endif +#endif + +#ifndef LINPHONE_DEPRECATED + #if defined(_MSC_VER) + #define LINPHONE_DEPRECATED __declspec(deprecated) + #else + #define LINPHONE_DEPRECATED __attribute__((deprecated)) + #endif +#endif + +// ----------------------------------------------------------------------------- + +#ifdef __cplusplus + +// ----------------------------------------------------------------------------- +// Debug. +// ----------------------------------------------------------------------------- + +void lAssert (const char *condition, const char *file, int line); + +#ifdef DEBUG + #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast(0) : LinphonePrivate::lAssert(#CONDITION, __FILE__, __LINE__)) +#else + #define L_ASSERT(CONDITION) static_cast(false && (CONDITION)) +#endif + +// ----------------------------------------------------------------------------- +// Optimization. +// ----------------------------------------------------------------------------- + +#ifndef _MSC_VER + #define L_LIKELY(EXPRESSION) __builtin_expect(static_cast(EXPRESSION), true) + #define L_UNLIKELY(EXPRESSION) __builtin_expect(static_cast(EXPRESSION), false) +#else + #define L_LIKELY(EXPRESSION) EXPRESSION + #define L_UNLIKELY(EXPRESSION) EXPRESSION +#endif + +// ----------------------------------------------------------------------------- +// Misc. +// ----------------------------------------------------------------------------- + +// Define an integer version like: 0xXXYYZZ, XX=MAJOR, YY=MINOR, and ZZ=PATCH. +constexpr unsigned int makeVersion (unsigned int major, unsigned int minor, unsigned int patch) { + return ((major << 16) | (minor << 8) | patch); +} + +// Not available in C++11... +template +std::unique_ptr makeUnique(Args && ...args) { + return std::unique_ptr(new T(std::forward(args)...)); +} + +#define L_AUTO_RETURN(VALUE) -> decltype(VALUE) { return VALUE; } + +// ----------------------------------------------------------------------------- +// Class tools. +// ----------------------------------------------------------------------------- + +#define L_DISABLE_COPY(CLASS) \ + CLASS (const CLASS &) = delete; \ + CLASS &operator= (const CLASS &) = delete; + +// ----------------------------------------------------------------------------- +// PImpl tools. +// ----------------------------------------------------------------------------- + +class BaseObject; +class BaseObjectPrivate; +class ClonableObject; +class ClonableObjectPrivate; +class Object; +class ObjectPrivate; + +namespace Private { + template + using BetterPrivateAncestor = typename std::conditional< + std::is_base_of::value, + BaseObject, + typename std::conditional< + std::is_base_of::value, + ClonableObject, + T + >::type + >::type; + + // Generic public helper. + template< + typename R, + typename P, + typename C + > + constexpr R *getPublicHelper (P *object, const C *) { + return static_cast(object); + } + + // Generic public helper. Deal with shared data. + template< + typename R, + typename P, + typename C + > + inline R *getPublicHelper (const P &objectSet, const C *) { + auto it = objectSet.cbegin(); + L_ASSERT(it != objectSet.cend()); + return static_cast(*it); + } + + template + struct AddConstMirror { + typedef U type; + }; + + template + struct AddConstMirror { + typedef typename std::add_const::type type; + }; +} + +#define L_INTERNAL_CHECK_OBJECT_INHERITANCE(CLASS) \ + static_assert( \ + !(std::is_base_of::value && std::is_base_of::value), \ + "Multiple inheritance between BaseObject and ClonableObject is not allowed." \ + ); + +#define L_INTERNAL_DECLARE_PRIVATE(CLASS) \ + inline CLASS ## Private *getPrivate () { \ + L_INTERNAL_CHECK_OBJECT_INHERITANCE(CLASS); \ + using TypeAncestor = LinphonePrivate::Private::BetterPrivateAncestor; \ + return reinterpret_cast(TypeAncestor::mPrivate); \ + } \ + inline const CLASS ## Private *getPrivate () const { \ + L_INTERNAL_CHECK_OBJECT_INHERITANCE(CLASS); \ + using TypeAncestor = LinphonePrivate::Private::BetterPrivateAncestor; \ + return reinterpret_cast(TypeAncestor::mPrivate); \ + } \ + friend class CLASS ## Private; \ + friend class Wrapper; + +// Allows access to private internal data. +// Gives a control to C Wrapper. +#ifndef LINPHONE_TESTER + #define L_DECLARE_PRIVATE(CLASS) L_INTERNAL_DECLARE_PRIVATE(CLASS) +#else + #define L_DECLARE_PRIVATE(CLASS) \ + L_INTERNAL_DECLARE_PRIVATE(CLASS) \ + friend class Tester; +#endif + +#define L_DECLARE_PUBLIC(CLASS) \ + CLASS *getPublic () { \ + return LinphonePrivate::Private::getPublicHelper(mPublic, this); \ + } \ + const CLASS *getPublic () const { \ + return LinphonePrivate::Private::getPublicHelper(mPublic, this); \ + } \ + friend class CLASS; + +// Get Private data. +#define L_D() decltype(getPrivate()) const d = getPrivate(); + +// Get Public data. +#define L_Q() decltype(getPublic()) const q = getPublic(); + +// Get Private data of class in a multiple inheritance case. +#define L_D_T(CLASS, NAME) \ + auto const NAME = static_cast< \ + LinphonePrivate::Private::AddConstMirror< \ + std::remove_reference::type, \ + CLASS ## Private \ + >::type * \ + >(CLASS::mPrivate); + +// Get Private data of class in a multiple inheritance case. +#define L_Q_T(CLASS, NAME) \ + auto const NAME = static_cast< \ + LinphonePrivate::Private::AddConstMirror< \ + std::remove_reference::type, \ + CLASS \ + >::type * \ + >(getPublic()); + +// ----------------------------------------------------------------------------- +// Overload. +// ----------------------------------------------------------------------------- + +#define L_OVERRIDE_SHARED_FROM_THIS(CLASS) \ + inline std::shared_ptr getSharedFromThis () { \ + return std::static_pointer_cast(Object::getSharedFromThis()); \ + } \ + inline std::shared_ptr getSharedFromThis () const { \ + return std::static_pointer_cast(Object::getSharedFromThis()); \ + } + +namespace Private { + template + struct ResolveMemberFunctionOverload { + template + constexpr auto operator() (Ret (Obj::*func)(Args...)) const L_AUTO_RETURN(func); + }; + + template + struct ResolveConstMemberFunctionOverload { + template + constexpr auto operator() (Ret (Obj::*func)(Args...) const) const L_AUTO_RETURN(func); + }; + + template + struct ResolveOverload : ResolveMemberFunctionOverload, ResolveConstMemberFunctionOverload { + using ResolveMemberFunctionOverload::operator(); + using ResolveConstMemberFunctionOverload::operator(); + + template + constexpr auto operator() (Ret (*func)(Args...)) const L_AUTO_RETURN(func); + }; +} + +// Useful to select a specific overloaded function. (Avoid usage of static_cast.) +template +using resolveOverload = Private::ResolveOverload; + +// ----------------------------------------------------------------------------- +// Math. +// ----------------------------------------------------------------------------- + +// Get the length of one integer. +constexpr int getIntLength (int n) { + return n < 0 ? 1 + getIntLength(-n) : (n < 10 ? 1 : 1 + getIntLength(n / 10)); +} + +namespace Private { + constexpr int pow10Impl (int n, int acc) { + return n == 0 ? acc : pow10Impl(n - 1, acc * 10); + } +} + +template +constexpr T abs (const T &value) { + return value < 0 ? -value : value; +} + +constexpr int pow10 (int n) { + return (n < 0 ? -1 : +1) * Private::pow10Impl(abs(n), 1); +} + +// Returns the sum of n elements. +constexpr int sums () { + return 0; +} + +template +constexpr int sums (T i, Args... args) { + return i + sums(args...); +} + +// ----------------------------------------------------------------------------- +// Wrapper public. +// ----------------------------------------------------------------------------- + +#define L_DECL_C_STRUCT(STRUCT) typedef struct _ ## STRUCT STRUCT; +#define L_DECL_C_STRUCT_PREFIX_LESS(STRUCT) typedef struct STRUCT STRUCT; + +#endif // ifdef __cplusplus + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_GENERAL_H_ diff --git a/include/linphone/utils/magic-macros.h b/include/linphone/utils/magic-macros.h new file mode 100644 index 000000000..c1ba0b946 --- /dev/null +++ b/include/linphone/utils/magic-macros.h @@ -0,0 +1,290 @@ +/* + * magic-macros.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAGIC_MACROS_H_ +#define _L_MAGIC_MACROS_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +// Concat in depth context. +#define L_CONCAT__(A, B) A ## B +#define L_CONCAT_(A, B) L_CONCAT__(A, B) +#define L_CONCAT(A, B) L_CONCAT_(A, B) + +// Get argument numbers from variadic. +#define L_ARG_N( \ + A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, \ + A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, N, ... \ +) N + +#define L_EXPAND(X) X + +// Useful in depth context. +#define L_STRINGIFY(X) #X + +#define L_GET_N_ARGS(...) L_EXPAND(L_ARG_N( \ + __VA_ARGS__, \ + 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 \ +)) + +// Get argument numbers - 1 from variadic. +#define L_GET_N_ARGS_SUB(X, ...) L_GET_N_ARGS(__VA_ARGS__) + +// Get argument from variadic macro. +#define L_GET_ARG_1(A1, ...) A1 +#define L_GET_ARG_2(A1, A2, ...) A2 +#define L_GET_ARG_3(A1, A2, A3, ...) A3 +#define L_GET_ARG_4(A1, A2, A3, A4, ...) A4 +#define L_GET_ARG_5(A1, A2, A3, A4, A5, ...) A5 +#define L_GET_ARG_6(A1, A2, A3, A4, A5, A6, ...) A6 +#define L_GET_ARG_7(A1, A2, A3, A4, A5, A6, A7, ...) A7 +#define L_GET_ARG_8(A1, A2, A3, A4, A5, A6, A7, A8, ...) A8 +#define L_GET_ARG_9(A1, A2, A3, A4, A5, A6, A7, A8, A9, ...) A9 +#define L_GET_ARG_10(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, ...) A10 +#define L_GET_ARG_11(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, ...) A11 +#define L_GET_ARG_12(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, ...) A12 +#define L_GET_ARG_13(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, ...) A13 +#define L_GET_ARG_14(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, ...) A14 +#define L_GET_ARG_15(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, ...) A15 +#define L_GET_ARG_16(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, ...) A16 +#define L_GET_ARG_17(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, ...) A17 +#define L_GET_ARG_18(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, ...) A18 +#define L_GET_ARG_19(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, ...) A19 +#define L_GET_ARG_20(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, ...) A20 +#define L_GET_ARG_21(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, ...) A21 + +// Get left part of variadic. +#define L_GET_HEAP_1(A1, ...) A1 +#define L_GET_HEAP_2(A1, A2, ...) A1, A2 +#define L_GET_HEAP_3(A1, A2, A3, ...) A1, A2, A3 +#define L_GET_HEAP_4(A1, A2, A3, A4, ...) A1, A2, A3, A4 +#define L_GET_HEAP_5(A1, A2, A3, A4, A5, ...) A1, A2, A3, A4, A5 +#define L_GET_HEAP_6(A1, A2, A3, A4, A5, A6, ...) A1, A2, A3, A4, A5, A6 +#define L_GET_HEAP_7(A1, A2, A3, A4, A5, A6, A7, ...) A1, A2, A3, A4, A5, A6, A7 +#define L_GET_HEAP_8(A1, A2, A3, A4, A5, A6, A7, A8, ...) A1, A2, A3, A4, A5, A6, A7, A8 +#define L_GET_HEAP_9(A1, A2, A3, A4, A5, A6, A7, A8, A9, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9 +#define L_GET_HEAP_10(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10 +#define L_GET_HEAP_11(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11 +#define L_GET_HEAP_12(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12 +#define L_GET_HEAP_13(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13 +#define L_GET_HEAP_14(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14 +#define L_GET_HEAP_15(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15 +#define L_GET_HEAP_16(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16 +#define L_GET_HEAP_17(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17 +#define L_GET_HEAP_18(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18 +#define L_GET_HEAP_19(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19 +#define L_GET_HEAP_20(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20 +#define L_GET_HEAP_21(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, ...) A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21 + +#define L_GET_HEAP(...) L_EXPAND( \ + L_CONCAT(L_GET_HEAP_, L_GET_N_ARGS_SUB(__VA_ARGS__)) (__VA_ARGS__) \ +) + +// Call a macro on args. +#define L_CALL(MACRO, ARGS) MACRO ARGS +#define L_CALL_HELPER(MACRO, ARGS) MACRO ARGS + +// Map each variadic args. +#define L_APPLY_1(MACRONAME, DATA, A1) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) + +#define L_APPLY_2(MACRONAME, DATA, A1, A2) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_1(MACRONAME, DATA, A2) + +#define L_APPLY_3(MACRONAME, DATA, A1, A2, A3) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_2(MACRONAME, DATA, A2, A3) + +#define L_APPLY_4(MACRONAME, DATA, A1, A2, A3, A4) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_3(MACRONAME, DATA, A2, A3, A4) + +#define L_APPLY_5(MACRONAME, DATA, A1, A2, A3, A4, A5) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_4(MACRONAME, DATA, A2, A3, A4, A5) + +#define L_APPLY_6(MACRONAME, DATA, A1, A2, A3, A4, A5, A6) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_5(MACRONAME, DATA, A2, A3, A4, A5, A6) + +#define L_APPLY_7(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_6(MACRONAME, DATA, A2, A3, A4, A5, A6, A7) + +#define L_APPLY_8(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_7(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8) + +#define L_APPLY_9(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_8(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9) + +#define L_APPLY_10(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_9(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10) + +#define L_APPLY_11(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_10(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) + +#define L_APPLY_12(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_11(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) + +#define L_APPLY_13(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_12(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) + +#define L_APPLY_14(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_13(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) + +#define L_APPLY_15(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_14(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) + +#define L_APPLY_16(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_15(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) + +#define L_APPLY_17(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_16(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) + +#define L_APPLY_18(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_17(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18) + +#define L_APPLY_19(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_18(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19) + +#define L_APPLY_20(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_19(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20) + +#define L_APPLY_21(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)), \ + L_APPLY_20(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21) + +#define L_APPLY(MACRONAME, DATA, ...) \ + L_CALL( \ + L_CONCAT(L_APPLY_, L_GET_N_ARGS(__VA_ARGS__)), \ + (MACRONAME, DATA, __VA_ARGS__) \ + ) + +// Map each variadic args without comma separator. +#define L_APPLY_WITHOUT_COMMA_1(MACRONAME, DATA, A1) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) + +#define L_APPLY_WITHOUT_COMMA_2(MACRONAME, DATA, A1, A2) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_1(MACRONAME, DATA, A2) + +#define L_APPLY_WITHOUT_COMMA_3(MACRONAME, DATA, A1, A2, A3) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_2(MACRONAME, DATA, A2, A3) + +#define L_APPLY_WITHOUT_COMMA_4(MACRONAME, DATA, A1, A2, A3, A4) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_3(MACRONAME, DATA, A2, A3, A4) + +#define L_APPLY_WITHOUT_COMMA_5(MACRONAME, DATA, A1, A2, A3, A4, A5) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_4(MACRONAME, DATA, A2, A3, A4, A5) + +#define L_APPLY_WITHOUT_COMMA_6(MACRONAME, DATA, A1, A2, A3, A4, A5, A6) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_5(MACRONAME, DATA, A2, A3, A4, A5, A6) + +#define L_APPLY_WITHOUT_COMMA_7(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_6(MACRONAME, DATA, A2, A3, A4, A5, A6, A7) + +#define L_APPLY_WITHOUT_COMMA_8(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_7(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8) + +#define L_APPLY_WITHOUT_COMMA_9(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_8(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9) + +#define L_APPLY_WITHOUT_COMMA_10(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_9(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10) + +#define L_APPLY_WITHOUT_COMMA_11(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_10(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) + +#define L_APPLY_WITHOUT_COMMA_12(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_11(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) + +#define L_APPLY_WITHOUT_COMMA_13(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_12(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) + +#define L_APPLY_WITHOUT_COMMA_14(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_13(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) + +#define L_APPLY_WITHOUT_COMMA_15(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_14(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) + +#define L_APPLY_WITHOUT_COMMA_16(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_15(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) + +#define L_APPLY_WITHOUT_COMMA_17(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_16(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) + +#define L_APPLY_WITHOUT_COMMA_18(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_17(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18) + +#define L_APPLY_WITHOUT_COMMA_19(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_18(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19) + +#define L_APPLY_WITHOUT_COMMA_20(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_19(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20) + +#define L_APPLY_WITHOUT_COMMA_21(MACRONAME, DATA, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21) \ + L_CALL_HELPER(MACRONAME, (DATA, A1)) \ + L_APPLY_WITHOUT_COMMA_20(MACRONAME, DATA, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21) + +#define L_APPLY_WITHOUT_COMMA(MACRONAME, DATA, ...) \ + L_CALL( \ + L_CONCAT(L_APPLY_WITHOUT_COMMA_, L_GET_N_ARGS(__VA_ARGS__)), \ + (MACRONAME, DATA, __VA_ARGS__) \ + ) + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MAGIC_MACROS_H_ diff --git a/include/linphone/utils/static-string.h b/include/linphone/utils/static-string.h new file mode 100644 index 000000000..44f31a847 --- /dev/null +++ b/include/linphone/utils/static-string.h @@ -0,0 +1,170 @@ +/* + * static-string.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_STATIC_STRING_H_ +#define _L_STATIC_STRING_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= +// Compile time strings. Useful to build const char * at compilation. +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +template +struct IndexSequence { + using Type = IndexSequence; +}; + +namespace Private { + template + struct ConcatIndexSequenceImpl; + + template + struct ConcatIndexSequenceImpl, IndexSequence> : + IndexSequence {}; + + template + struct MakeIndexSequenceImpl : ConcatIndexSequenceImpl< + typename MakeIndexSequenceImpl::Type, + typename MakeIndexSequenceImpl::Type + > {}; + + template<> + struct MakeIndexSequenceImpl<0> : IndexSequence<> {}; + + template<> + struct MakeIndexSequenceImpl<1> : IndexSequence<0> {}; +} + +template +using MakeIndexSequence = typename Private::MakeIndexSequenceImpl::Type; + +// ============================================================================= + +// See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4121.pdf +template +using RawStaticString = const char [N]; + +namespace Private { + template> + struct StaticString; + + template + struct StaticString> { + constexpr StaticString (const RawStaticString &inRaw) : raw{ (inRaw[Index])... } {} + + constexpr char operator[] (std::size_t i) const { + return raw[i]; + } + + constexpr operator const char * () const { + return raw; + } + + RawStaticString raw; + }; + + template + class StaticStringConcatHelper { + public: + template + constexpr StaticStringConcatHelper( + const Private::StaticString &s1, + const Private::StaticString &s2 + ) : StaticStringConcatHelper(s1, s2, MakeIndexSequence{}, MakeIndexSequence{}) {} + + RawStaticString raw; + + private: + template + constexpr StaticStringConcatHelper( + const Private::StaticString &s1, + const Private::StaticString &s2, + IndexSequence, + IndexSequence + ) : raw{ s1[Index1]..., s2[Index2]... } {} + }; + + template + class StaticIntStringHelper { + public: + constexpr StaticIntStringHelper () : StaticIntStringHelper(MakeIndexSequence= 0 ? N - 1 : N - 2>{}) {} + + RawStaticString raw; + + private: + // Workaround for MSVC 2015. + // See: https://stackoverflow.com/questions/41593649/why-wont-visual-studio-let-me-use-a-templatized-constexpr-function-in-enable-i/41597153 + struct IsNeg { static const bool value = Value < 0; }; + + template::type* = nullptr> + constexpr StaticIntStringHelper (const IndexSequence &) : + raw{ char('0' + Value / pow10(N - Index - 2) % 10)..., '\0' } {} + + template::type* = nullptr> + constexpr StaticIntStringHelper (const IndexSequence &) : + raw{ '-', char('0' + abs(Value) / pow10(N - Index - 3) % 10)..., '\0' } {} + }; +}; + +// ----------------------------------------------------------------------------- + +template +constexpr Private::StaticString StaticString (const RawStaticString &raw) { + return Private::StaticString(raw); +} + +template +constexpr Private::StaticString operator+ ( + const Private::StaticString &s1, + const Private::StaticString &s2 +) { + return StaticString(Private::StaticStringConcatHelper(s1, s2).raw); +} + +template +constexpr Private::StaticString operator+ ( + const Private::StaticString &s1, + const RawStaticString &s2 +) { + return StaticString(Private::StaticStringConcatHelper(s1, StaticString(s2)).raw); +} + +template +constexpr Private::StaticString operator+ ( + const RawStaticString &s1, + const Private::StaticString &s2 +) { + return StaticString(Private::StaticStringConcatHelper(StaticString(s1), s2).raw); +} + +// ----------------------------------------------------------------------------- + +template +constexpr Private::StaticString StaticIntString () { + return StaticString(Private::StaticIntStringHelper().raw); +} + +// ----------------------------------------------------------------------------- + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_STATIC_STRING_H_ diff --git a/include/linphone/utils/traits.h b/include/linphone/utils/traits.h new file mode 100644 index 000000000..db1c0ab77 --- /dev/null +++ b/include/linphone/utils/traits.h @@ -0,0 +1,57 @@ +/* + * traits.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_TRAITS_H_ +#define _L_TRAITS_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +namespace Private { + // See: http://en.cppreference.com/w/cpp/types/void_t + template struct MakeVoid { + typedef void type; + }; + template + using void_t = typename MakeVoid::type; + + template + struct IsMapContainerImpl : std::false_type {}; + + template + struct IsMapContainerImpl< + T, + void_t< + typename T::key_type, + typename T::mapped_type, + decltype(std::declval()[std::declval()]) + > + > : std::true_type {}; +}; + +// Check if a type is a std container like map, unordered_map... +template +struct IsMapContainer : Private::IsMapContainerImpl::type {}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_TRAITS_H_ diff --git a/include/linphone/utils/utils.h b/include/linphone/utils/utils.h new file mode 100644 index 000000000..b4675af0c --- /dev/null +++ b/include/linphone/utils/utils.h @@ -0,0 +1,137 @@ +/* + * utils.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_UTILS_H_ +#define _L_UTILS_H_ + +#include +#include +#include +#include +#include +#include + +#include "linphone/utils/enum-generator.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +namespace Utils { + template + constexpr T *getPtr (std::shared_ptr &object) { + return object.get(); + } + + template + constexpr T *getPtr (const std::shared_ptr &object) { + return object.get(); + } + + template + constexpr T *getPtr (std::unique_ptr &object) { + return object.get(); + } + + template + constexpr T *getPtr (const std::unique_ptr &object) { + return object.get(); + } + + template + constexpr T *getPtr (T *object) { + return object; + } + + template + constexpr T *getPtr (T &object) { + return &object; + } + + LINPHONE_PUBLIC bool iequals (const std::string &a, const std::string &b); + + LINPHONE_PUBLIC std::vector split (const std::string &str, const std::string &delimiter); + + LINPHONE_PUBLIC inline std::vector split (const std::string &str, char delimiter) { + return split(str, std::string(1, delimiter)); + } + + LINPHONE_PUBLIC std::string toString (int val); + LINPHONE_PUBLIC std::string toString (long val); + LINPHONE_PUBLIC std::string toString (long long val); + LINPHONE_PUBLIC std::string toString (unsigned val); + LINPHONE_PUBLIC std::string toString (unsigned long val); + LINPHONE_PUBLIC std::string toString (unsigned long long val); + LINPHONE_PUBLIC std::string toString (float val); + LINPHONE_PUBLIC std::string toString (double val); + LINPHONE_PUBLIC std::string toString (long double val); + LINPHONE_PUBLIC std::string toString (const void *val); + + template::value, T>::type> + LINPHONE_PUBLIC inline std::string toString (const T &val) { return getEnumValueAsString(val); } + + LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC long long stoll (const std::string &str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC unsigned long long stoull (const std::string &str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC double stod (const std::string &str, size_t *idx = 0); + LINPHONE_PUBLIC float stof (const std::string &str, size_t *idx = 0); + LINPHONE_PUBLIC bool stob (const std::string &str); + + LINPHONE_PUBLIC int stoi (const char *str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC long long stoll (const char *str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC unsigned long long stoull (const char *str, size_t *idx = 0, int base = 10); + LINPHONE_PUBLIC double stod (const char *str, size_t *idx = 0); + LINPHONE_PUBLIC float stof (const char *str, size_t *idx = 0); + + LINPHONE_PUBLIC std::string stringToLower (const std::string &str); + + LINPHONE_PUBLIC char *utf8ToChar (uint32_t ic); + + LINPHONE_PUBLIC inline std::string cStringToCppString (const char *str) { + return str ? str : ""; + } + + template + inline std::string join (const std::vector& elems, const S& delim) { + std::stringstream ss; + auto e = elems.begin(); + ss << *e++; + for (; e != elems.end(); ++e) + ss << delim << *e; + return ss.str(); + } + LINPHONE_PUBLIC std::string trim (const std::string &str); + + template + inline const T &getEmptyConstRefObject () { + static const T object{}; + return object; + } + + LINPHONE_PUBLIC std::tm getTimeTAsTm (time_t time); + LINPHONE_PUBLIC time_t getTmAsTimeT (const std::tm &time); + + LINPHONE_PUBLIC std::string localeToUtf8 (const std::string &str); + LINPHONE_PUBLIC std::string utf8ToLocale (const std::string &str); + LINPHONE_PUBLIC std::string convertAnyToUtf8 (const std::string &str, const std::string &encoding); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_UTILS_H_ diff --git a/include/linphone/vcard.h b/include/linphone/vcard.h index fd12db4fb..9f7527f08 100644 --- a/include/linphone/vcard.h +++ b/include/linphone/vcard.h @@ -38,16 +38,16 @@ extern "C" #define LINPHONE_VCARD BELLE_SIP_CAST(object, LinphoneVcard) /** - * Creates a LinphoneVcard object that has a pointer to an empty vCard - * @return a new LinphoneVcard object + * Creates a #LinphoneVcard object that has a pointer to an empty vCard + * @return a new #LinphoneVcard object * @deprecated Use linphone_factory_create_vcard() instead. * @donotwrap */ LINPHONE_DEPRECATED LINPHONE_PUBLIC LinphoneVcard* linphone_vcard_new(void); /** - * Deletes a LinphoneVcard object properly - * @param[in] vCard the LinphoneVcard to destroy + * Deletes a #LinphoneVcard object properly + * @param[in] vCard the #LinphoneVcard to destroy * @deprecated Use linphone_vcard_unref() or belle_sip_object_unref() instead. * @donotwrap */ @@ -55,145 +55,145 @@ LINPHONE_DEPRECATED LINPHONE_PUBLIC void linphone_vcard_free(LinphoneVcard *vCar /** * Take a ref on a #LinphoneVcard. - * @param[in] vCard LinphoneVcard object + * @param[in] vCard #LinphoneVcard object */ LINPHONE_PUBLIC LinphoneVcard *linphone_vcard_ref(LinphoneVcard *vCard); /** * Release a #LinphoneVcard. - * @param[in] vCard LinphoneVcard object + * @param[in] vCard #LinphoneVcard object */ LINPHONE_PUBLIC void linphone_vcard_unref(LinphoneVcard *vCard); /** * Clone a #LinphoneVcard. - * @param[in] vCard LinphoneVcard object - * @return a new LinphoneVcard object + * @param[in] vCard #LinphoneVcard object + * @return a new #LinphoneVcard object */ LINPHONE_PUBLIC LinphoneVcard *linphone_vcard_clone(const LinphoneVcard *vCard); /** * Returns the vCard4 representation of the LinphoneVcard. - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return a const char * that represents the vCard */ LINPHONE_PUBLIC const char* linphone_vcard_as_vcard4_string(LinphoneVcard *vCard); /** * Sets the FN attribute of the vCard (which is mandatory). - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] name the display name to set for the vCard */ LINPHONE_PUBLIC void linphone_vcard_set_full_name(LinphoneVcard *vCard, const char *name); /** * Returns the FN attribute of the vCard, or NULL if it isn't set yet. - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the display name of the vCard, or NULL */ LINPHONE_PUBLIC const char* linphone_vcard_get_full_name(const LinphoneVcard *vCard); /** * Sets the skipFieldValidation property of the vcard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] skip skipFieldValidation property of the vcard */ LINPHONE_PUBLIC void linphone_vcard_set_skip_validation(LinphoneVcard *vCard, bool_t skip); /** * Returns the skipFieldValidation property of the vcard. - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the skipFieldValidation property of the vcard */ LINPHONE_PUBLIC bool_t linphone_vcard_get_skip_validation(const LinphoneVcard *vCard); /** * Sets the family name in the N attribute of the vCard. - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] name the family name to set for the vCard */ LINPHONE_PUBLIC void linphone_vcard_set_family_name(LinphoneVcard *vCard, const char *name); /** * Returns the family name in the N attribute of the vCard, or NULL if it isn't set yet. - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the family name of the vCard, or NULL */ LINPHONE_PUBLIC const char* linphone_vcard_get_family_name(const LinphoneVcard *vCard); /** * Sets the given name in the N attribute of the vCard. - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] name the given name to set for the vCard */ LINPHONE_PUBLIC void linphone_vcard_set_given_name(LinphoneVcard *vCard, const char *name); /** * Returns the given name in the N attribute of the vCard, or NULL if it isn't set yet. - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the given name of the vCard, or NULL */ LINPHONE_PUBLIC const char* linphone_vcard_get_given_name(const LinphoneVcard *vCard); /** * Adds a SIP address in the vCard, using the IMPP property - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] sip_address the SIP address to add */ LINPHONE_PUBLIC void linphone_vcard_add_sip_address(LinphoneVcard *vCard, const char *sip_address); /** * Removes a SIP address in the vCard (if it exists), using the IMPP property - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] sip_address the SIP address to remove */ LINPHONE_PUBLIC void linphone_vcard_remove_sip_address(LinphoneVcard *vCard, const char *sip_address); /** * Edits the preferred SIP address in the vCard (or the first one), using the IMPP property - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] sip_address the new SIP address */ LINPHONE_PUBLIC void linphone_vcard_edit_main_sip_address(LinphoneVcard *vCard, const char *sip_address); /** * Returns the list of SIP addresses (as LinphoneAddress) in the vCard (all the IMPP attributes that has an URI value starting by "sip:") or NULL - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return \bctbx_list{LinphoneAddress} */ LINPHONE_PUBLIC const bctbx_list_t* linphone_vcard_get_sip_addresses(LinphoneVcard *vCard); /** * Adds a phone number in the vCard, using the TEL property - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] phone the phone number to add */ LINPHONE_PUBLIC void linphone_vcard_add_phone_number(LinphoneVcard *vCard, const char *phone); /** * Removes a phone number in the vCard (if it exists), using the TEL property - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] phone the phone number to remove */ LINPHONE_PUBLIC void linphone_vcard_remove_phone_number(LinphoneVcard *vCard, const char *phone); /** * Returns the list of phone numbers (as string) in the vCard (all the TEL attributes) or NULL - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return \bctbx_list{const char *} */ LINPHONE_PUBLIC bctbx_list_t* linphone_vcard_get_phone_numbers(const LinphoneVcard *vCard); /** * Fills the Organization field of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] organization the Organization */ LINPHONE_PUBLIC void linphone_vcard_set_organization(LinphoneVcard *vCard, const char *organization); /** * Gets the Organization of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the Organization of the vCard or NULL */ LINPHONE_PUBLIC const char* linphone_vcard_get_organization(const LinphoneVcard *vCard); @@ -201,49 +201,49 @@ LINPHONE_PUBLIC const char* linphone_vcard_get_organization(const LinphoneVcard /** * Generates a random unique id for the vCard. * If is required to be able to synchronize the vCard with a CardDAV server - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return TRUE if operation is successful, otherwise FALSE (for example if it already has an unique ID) */ LINPHONE_PUBLIC bool_t linphone_vcard_generate_unique_id(LinphoneVcard *vCard); /** * Sets the unique ID of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] uid the unique id */ LINPHONE_PUBLIC void linphone_vcard_set_uid(LinphoneVcard *vCard, const char *uid); /** * Gets the UID of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the UID of the vCard, otherwise NULL */ LINPHONE_PUBLIC const char* linphone_vcard_get_uid(const LinphoneVcard *vCard); /** * Sets the eTAG of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] etag the eTAG */ LINPHONE_PUBLIC void linphone_vcard_set_etag(LinphoneVcard *vCard, const char * etag); /** * Gets the eTag of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the eTag of the vCard in the CardDAV server, otherwise NULL */ LINPHONE_PUBLIC const char* linphone_vcard_get_etag(const LinphoneVcard *vCard); /** * Sets the URL of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @param[in] url the URL */ LINPHONE_PUBLIC void linphone_vcard_set_url(LinphoneVcard *vCard, const char *url); /** * Gets the URL of the vCard - * @param[in] vCard the LinphoneVcard + * @param[in] vCard the #LinphoneVcard * @return the URL of the vCard in the CardDAV server, otherwise NULL */ LINPHONE_PUBLIC const char* linphone_vcard_get_url(const LinphoneVcard *vCard); diff --git a/include/linphone/video_definition.h b/include/linphone/video_definition.h index f33973778..4b38e020f 100644 --- a/include/linphone/video_definition.h +++ b/include/linphone/video_definition.h @@ -1,6 +1,6 @@ /* video_definition.h -Copyright (C) 2010-2017 Belledonne Communications SARL +Copyright (C) 2010-2018 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 @@ -36,69 +36,69 @@ extern "C" { /** * Acquire a reference to the video definition. - * @param[in] vdef LinphoneVideoDefinition object. - * @return The same LinphoneVideoDefinition object. + * @param[in] vdef #LinphoneVideoDefinition object. + * @return The same #LinphoneVideoDefinition object. **/ LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_video_definition_ref(LinphoneVideoDefinition *vdef); /** * Release reference to the video definition. - * @param[in] vdef LinphoneVideoDefinition object. + * @param[in] vdef #LinphoneVideoDefinition object. **/ LINPHONE_PUBLIC void linphone_video_definition_unref(LinphoneVideoDefinition *vdef); /** * Retrieve the user pointer associated with the video definition. - * @param[in] vdef LinphoneVideoDefinition object. + * @param[in] vdef #LinphoneVideoDefinition object. * @return The user pointer associated with the video definition. **/ LINPHONE_PUBLIC void *linphone_video_definition_get_user_data(const LinphoneVideoDefinition *vdef); /** * Assign a user pointer to the video definition. - * @param[in] vdef LinphoneVideoDefinition object. + * @param[in] vdef #LinphoneVideoDefinition object. * @param[in] ud The user pointer to associate with the video definition. **/ LINPHONE_PUBLIC void linphone_video_definition_set_user_data(LinphoneVideoDefinition *vdef, void *ud); /** * Clone a video definition. - * @param[in] vdef LinphoneVideoDefinition object to be cloned + * @param[in] vdef #LinphoneVideoDefinition object to be cloned * @return The new clone of the video definition */ LINPHONE_PUBLIC LinphoneVideoDefinition * linphone_video_definition_clone(const LinphoneVideoDefinition *vdef); /** * Get the width of the video definition. - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] vdef #LinphoneVideoDefinition object * @return The width of the video definition */ LINPHONE_PUBLIC unsigned int linphone_video_definition_get_width(const LinphoneVideoDefinition *vdef); /** * Set the width of the video definition. - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] vdef #LinphoneVideoDefinition object * @param[in] width The width of the video definition */ LINPHONE_PUBLIC void linphone_video_definition_set_width(LinphoneVideoDefinition *vdef, unsigned int width); /** * Get the height of the video definition. - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] vdef #LinphoneVideoDefinition object * @return The height of the video definition */ LINPHONE_PUBLIC unsigned int linphone_video_definition_get_height(const LinphoneVideoDefinition *vdef); /** * Set the height of the video definition. - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] vdef #LinphoneVideoDefinition object * @param[in] height The height of the video definition */ LINPHONE_PUBLIC void linphone_video_definition_set_height(LinphoneVideoDefinition *vdef, unsigned int height); /** * Set the width and the height of the video definition. - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] vdef #LinphoneVideoDefinition object * @param[in] width The width of the video definition * @param[in] height The height of the video definition */ @@ -106,38 +106,38 @@ LINPHONE_PUBLIC void linphone_video_definition_set_definition(LinphoneVideoDefin /** * Get the name of the video definition. - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] vdef #LinphoneVideoDefinition object * @return The name of the video definition */ LINPHONE_PUBLIC const char * linphone_video_definition_get_name(const LinphoneVideoDefinition *vdef); /** * Set the name of the video definition. - * @param[in] vdef LinphoneVideoDefinition object + * @param[in] vdef #LinphoneVideoDefinition object * @param[in] name The name of the video definition */ LINPHONE_PUBLIC void linphone_video_definition_set_name(LinphoneVideoDefinition *vdef, const char *name); /** - * Tells whether two LinphoneVideoDefinition objects are equal (the widths and the heights are the same but can be switched). - * @param[in] vdef1 LinphoneVideoDefinition object - * @param[in] vdef2 LinphoneVideoDefinition object - * @return A boolean value telling whether the two LinphoneVideoDefinition objects are equal. + * Tells whether two #LinphoneVideoDefinition objects are equal (the widths and the heights are the same but can be switched). + * @param[in] vdef1 #LinphoneVideoDefinition object + * @param[in] vdef2 #LinphoneVideoDefinition object + * @return A boolean value telling whether the two #LinphoneVideoDefinition objects are equal. */ LINPHONE_PUBLIC bool_t linphone_video_definition_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2); /** - * Tells whether two LinphoneVideoDefinition objects are strictly equal (the widths are the same and the heights are the same). - * @param[in] vdef1 LinphoneVideoDefinition object - * @param[in] vdef2 LinphoneVideoDefinition object - * @return A boolean value telling whether the two LinphoneVideoDefinition objects are strictly equal. + * Tells whether two #LinphoneVideoDefinition objects are strictly equal (the widths are the same and the heights are the same). + * @param[in] vdef1 #LinphoneVideoDefinition object + * @param[in] vdef2 #LinphoneVideoDefinition object + * @return A boolean value telling whether the two #LinphoneVideoDefinition objects are strictly equal. */ LINPHONE_PUBLIC bool_t linphone_video_definition_strict_equals(const LinphoneVideoDefinition *vdef1, const LinphoneVideoDefinition *vdef2); /** - * Tells whether a LinphoneVideoDefinition is undefined. - * @param[in] vdef LinphoneVideoDefinition object - * @return A boolean value telling whether the LinphoneVideoDefinition is undefined. + * Tells whether a #LinphoneVideoDefinition is undefined. + * @param[in] vdef #LinphoneVideoDefinition object + * @return A boolean value telling whether the #LinphoneVideoDefinition is undefined. */ LINPHONE_PUBLIC bool_t linphone_video_definition_is_undefined(const LinphoneVideoDefinition *vdef); diff --git a/include/linphone/wrapper_utils.h b/include/linphone/wrapper_utils.h index d9990aa50..686f8f16f 100644 --- a/include/linphone/wrapper_utils.h +++ b/include/linphone/wrapper_utils.h @@ -25,6 +25,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef _WRAPPER_UTILS_H #define _WRAPPER_UTILS_H +#include +#include "linphone/defs.h" #include "linphone/types.h" #ifdef __cplusplus @@ -36,6 +38,37 @@ extern "C" { * @{ */ +/** + * @brief Gets the list of listener in the core. + * @param lc The #LinphoneCore. + * @return The list of #LinphoneCoreCbs. + * @donotwrap + */ +LINPHONE_PUBLIC bctbx_list_t *linphone_core_get_callbacks_list(const LinphoneCore *lc); + +/** + * @brief Gets the list of listener in the call. + * @param[in] call #LinphoneCall object. + * @return The list of #LinphoneCallCbs. + * @donotwrap + */ +LINPHONE_PUBLIC const bctbx_list_t *linphone_call_get_callbacks_list(const LinphoneCall *call); + +/** + * @brief Gets the list of listener in the chat room. + * @param[in] cr #LinphoneChatRoom object. + * @return The list of #LinphoneChatRoomCbs. + * @donotwrap + */ +LINPHONE_PUBLIC const bctbx_list_t *linphone_chat_room_get_callbacks_list(const LinphoneChatRoom *cr); + +/** + * Sets the current LinphoneChatRoomCbs. + * @param[in] cr LinphoneChatRoom object + * @param[in] cbs LinphoneChatRoomCbs object + */ +LINPHONE_PUBLIC void linphone_chat_room_set_current_callbacks(LinphoneChatRoom *cr, LinphoneChatRoomCbs *cbs); + /** * Send a message to peer member of this chat room. * @@ -56,7 +89,7 @@ LINPHONE_PUBLIC void linphone_chat_room_send_chat_message_2(LinphoneChatRoom *cr * instead of totaly takes ownership on it. Thus, the #LinphoneChatMessage object must be released by the API user after calling * that function. * - * @param[in] msg LinphoneChatMessage object + * @param[in] msg #LinphoneChatMessage object */ LINPHONE_PUBLIC void linphone_chat_message_resend_2(LinphoneChatMessage *msg); @@ -65,6 +98,16 @@ LINPHONE_PUBLIC void linphone_chat_message_resend_2(LinphoneChatMessage *msg); */ LINPHONE_PUBLIC void *linphone_vcard_get_belcard(LinphoneVcard *vcard); +/** + * @brief Increases the reference counter of #LinphoneDialPlan objects. + */ +LINPHONE_PUBLIC LinphoneDialPlan *linphone_dial_plan_ref(LinphoneDialPlan *dp); + +/** + * @brief Decreases the reference counter of #LinphoneDialPaln objects. + */ +LINPHONE_PUBLIC void linphone_dial_plan_unref(LinphoneDialPlan *dp); + /** * @} */ diff --git a/include/linphone/xmlrpc.h b/include/linphone/xmlrpc.h index 36283bd15..ce3cecfc6 100644 --- a/include/linphone/xmlrpc.h +++ b/include/linphone/xmlrpc.h @@ -35,78 +35,78 @@ extern "C" { */ /** - * Create a new LinphoneXmlRpcRequest object. + * Create a new #LinphoneXmlRpcRequest object. * @param[in] return_type The expected XML-RPC response type. * @param[in] method The XML-RPC method to call. - * @return A new LinphoneXmlRpcRequest object. + * @return A new #LinphoneXmlRpcRequest object. **/ LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_request_new(LinphoneXmlRpcArgType return_type, const char *method); /** * Acquire a reference to the XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. - * @return The same LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. + * @return The same #LinphoneXmlRpcRequest object. **/ LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_request_ref(LinphoneXmlRpcRequest *request); /** * Release reference to the XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. **/ LINPHONE_PUBLIC void linphone_xml_rpc_request_unref(LinphoneXmlRpcRequest *request); /** * Retrieve the user pointer associated with the XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. * @return The user pointer associated with the XML-RPC request. **/ LINPHONE_PUBLIC void *linphone_xml_rpc_request_get_user_data(const LinphoneXmlRpcRequest *request); /** * Assign a user pointer to the XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. * @param[in] ud The user pointer to associate with the XML-RPC request. **/ LINPHONE_PUBLIC void linphone_xml_rpc_request_set_user_data(LinphoneXmlRpcRequest *request, void *ud); /** * Add an integer argument to an XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. * @param[in] value The integer value of the added argument. **/ LINPHONE_PUBLIC void linphone_xml_rpc_request_add_int_arg(LinphoneXmlRpcRequest *request, int value); /** * Add a string argument to an XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. * @param[in] value The string value of the added argument. **/ LINPHONE_PUBLIC void linphone_xml_rpc_request_add_string_arg(LinphoneXmlRpcRequest *request, const char *value); /** - * Get the LinphoneXmlRpcRequestCbs object associated with a LinphoneXmlRpcRequest. - * @param[in] request LinphoneXmlRpcRequest object - * @return The LinphoneXmlRpcRequestCbs object associated with the LinphoneXmlRpcRequest. + * Get the #LinphoneXmlRpcRequestCbs object associated with a LinphoneXmlRpcRequest. + * @param[in] request #LinphoneXmlRpcRequest object + * @return The #LinphoneXmlRpcRequestCbs object associated with the LinphoneXmlRpcRequest. **/ LINPHONE_PUBLIC LinphoneXmlRpcRequestCbs * linphone_xml_rpc_request_get_callbacks(const LinphoneXmlRpcRequest *request); /** * Get the content of the XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. * @return The string representation of the content of the XML-RPC request. */ LINPHONE_PUBLIC const char * linphone_xml_rpc_request_get_content(const LinphoneXmlRpcRequest *request); /** * Get the status of the XML-RPC request. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. * @return The status of the XML-RPC request. **/ LINPHONE_PUBLIC LinphoneXmlRpcStatus linphone_xml_rpc_request_get_status(const LinphoneXmlRpcRequest *request); /** * Get the response to an XML-RPC request sent with linphone_xml_rpc_session_send_request() and returning an integer response. - * @param[in] request LinphoneXmlRpcRequest object. + * @param[in] request #LinphoneXmlRpcRequest object. * @return The integer response to the XML-RPC request. **/ LINPHONE_PUBLIC int linphone_xml_rpc_request_get_int_response(const LinphoneXmlRpcRequest *request); @@ -119,95 +119,104 @@ LINPHONE_PUBLIC int linphone_xml_rpc_request_get_int_response(const LinphoneXmlR LINPHONE_PUBLIC const char * linphone_xml_rpc_request_get_string_response(const LinphoneXmlRpcRequest *request); /** - * Create a new LinphoneXmlRpcSession object. - * @param[in] core The LinphoneCore object used to send the XML-RPC requests. + * Create a new #LinphoneXmlRpcSession object. + * @param[in] core The #LinphoneCore object used to send the XML-RPC requests. * @param[in] url The URL of the XML-RPC server to send the XML-RPC requests to. - * @return A new LinphoneXmlRpcSession object. + * @return A new #LinphoneXmlRpcSession object. */ LINPHONE_PUBLIC LinphoneXmlRpcSession * linphone_xml_rpc_session_new(LinphoneCore *core, const char *url); /** * Acquire a reference to the XML-RPC session. - * @param[in] session LinphoneXmlRpcSession object. - * @return The same LinphoneXmlRpcSession object. + * @param[in] session #LinphoneXmlRpcSession object. + * @return The same #LinphoneXmlRpcSession object. **/ LINPHONE_PUBLIC LinphoneXmlRpcSession * linphone_xml_rpc_session_ref(LinphoneXmlRpcSession *session); /** * Release reference to the XML-RPC session. - * @param[in] session LinphoneXmlRpcSession object. + * @param[in] session #LinphoneXmlRpcSession object. * @warning This will not stop pending xml-rpc requests. Use linphone_xml_rpc_session_release() instead if this is intended. **/ LINPHONE_PUBLIC void linphone_xml_rpc_session_unref(LinphoneXmlRpcSession *session); /** * Retrieve the user pointer associated with the XML-RPC session. - * @param[in] session LinphoneXmlRpcSession object. + * @param[in] session #LinphoneXmlRpcSession object. * @return The user pointer associated with the XML-RPC session. **/ LINPHONE_PUBLIC void *linphone_xml_rpc_session_get_user_data(const LinphoneXmlRpcSession *session); /** * Assign a user pointer to the XML-RPC session. - * @param[in] session LinphoneXmlRpcSession object. + * @param[in] session #LinphoneXmlRpcSession object. * @param[in] ud The user pointer to associate with the XML-RPC session. **/ LINPHONE_PUBLIC void linphone_xml_rpc_session_set_user_data(LinphoneXmlRpcSession *session, void *ud); /** * Send an XML-RPC request. - * @param[in] session LinphoneXmlRpcSession object. - * @param[in] request The LinphoneXmlRpcRequest to be sent. + * @param[in] session #LinphoneXmlRpcSession object. + * @param[in] request The #LinphoneXmlRpcRequest to be sent. **/ LINPHONE_PUBLIC void linphone_xml_rpc_session_send_request(LinphoneXmlRpcSession *session, LinphoneXmlRpcRequest *request); /** * Stop and unref an XML rpc session. Pending requests will be aborted. - * @param[in] session LinphoneXmlRpcSession object. + * @param[in] session #LinphoneXmlRpcSession object. **/ LINPHONE_PUBLIC void linphone_xml_rpc_session_release(LinphoneXmlRpcSession *session); /** - * Acquire a reference to a LinphoneXmlRpcRequestCbs object. - * @param[in] cbs LinphoneXmlRpcRequestCbs object. - * @return The same LinphoneXmlRpcRequestCbs object. + * Acquire a reference to a #LinphoneXmlRpcRequestCbs object. + * @param[in] cbs #LinphoneXmlRpcRequestCbs object. + * @return The same #LinphoneXmlRpcRequestCbs object. **/ LINPHONE_PUBLIC LinphoneXmlRpcRequestCbs * linphone_xml_rpc_request_cbs_ref(LinphoneXmlRpcRequestCbs *cbs); /** - * Release a reference to a LinphoneXmlRpcRequestCbs object. - * @param[in] cbs LinphoneXmlRpcRequestCbs object. + * Release a reference to a #LinphoneXmlRpcRequestCbs object. + * @param[in] cbs #LinphoneXmlRpcRequestCbs object. **/ LINPHONE_PUBLIC void linphone_xml_rpc_request_cbs_unref(LinphoneXmlRpcRequestCbs *cbs); /** - * Retrieve the user pointer associated with a LinphoneXmlRpcRequestCbs object. - * @param[in] cbs LinphoneXmlRpcRequestCbs object. - * @return The user pointer associated with the LinphoneXmlRpcRequestCbs object. + * Retrieve the user pointer associated with a #LinphoneXmlRpcRequestCbs object. + * @param[in] cbs #LinphoneXmlRpcRequestCbs object. + * @return The user pointer associated with the #LinphoneXmlRpcRequestCbs object. **/ LINPHONE_PUBLIC void *linphone_xml_rpc_request_cbs_get_user_data(const LinphoneXmlRpcRequestCbs *cbs); /** - * Assign a user pointer to a LinphoneXmlRpcRequestCbs object. - * @param[in] cbs LinphoneXmlRpcRequestCbs object. - * @param[in] ud The user pointer to associate with the LinphoneXmlRpcRequestCbs object. + * Assign a user pointer to a #LinphoneXmlRpcRequestCbs object. + * @param[in] cbs #LinphoneXmlRpcRequestCbs object. + * @param[in] ud The user pointer to associate with the #LinphoneXmlRpcRequestCbs object. **/ LINPHONE_PUBLIC void linphone_xml_rpc_request_cbs_set_user_data(LinphoneXmlRpcRequestCbs *cbs, void *ud); /** * Get the response callback. - * @param[in] cbs LinphoneXmlRpcRequestCbs object. + * @param[in] cbs #LinphoneXmlRpcRequestCbs object. * @return The current response callback. **/ LINPHONE_PUBLIC LinphoneXmlRpcRequestCbsResponseCb linphone_xml_rpc_request_cbs_get_response(const LinphoneXmlRpcRequestCbs *cbs); /** * Set the response callback. - * @param[in] cbs LinphoneXmlRpcRequestCbs object. + * @param[in] cbs #LinphoneXmlRpcRequestCbs object. * @param[in] cb The response callback to be used. **/ LINPHONE_PUBLIC void linphone_xml_rpc_request_cbs_set_response(LinphoneXmlRpcRequestCbs *cbs, LinphoneXmlRpcRequestCbsResponseCb cb); +/** + * Creates a #LinphoneXmlRpcRequest from a #LinphoneXmlRpcSession + * @param[in] session the #LinphoneXmlRpcSession + * @param[in] return_type the return type of the request as a #LinphoneXmlRpcArgType + * @param[in] method the function name to call + * @return a #LinphoneXmlRpcRequest object + */ +LINPHONE_PUBLIC LinphoneXmlRpcRequest * linphone_xml_rpc_session_create_request(LinphoneXmlRpcSession *session, LinphoneXmlRpcArgType return_type, const char *method); + /** * @} */ diff --git a/intl/ChangeLog b/intl/ChangeLog deleted file mode 100644 index 65ec50f78..000000000 --- a/intl/ChangeLog +++ /dev/null @@ -1,4 +0,0 @@ -2002-08-06 GNU - - * Version 0.11.5 released. - diff --git a/intl/Makefile.in b/intl/Makefile.in deleted file mode 100644 index 0486dc93a..000000000 --- a/intl/Makefile.in +++ /dev/null @@ -1,337 +0,0 @@ -# Makefile for directory with message catalog handling in GNU NLS Utilities. -# Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Library General Public License as published -# by the Free Software Foundation; either version 2, 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 -# Library General Public License for more details. -# -# You should have received a copy of the GNU Library 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. - -PACKAGE = @PACKAGE@ -VERSION = @VERSION@ - -SHELL = /bin/sh - -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -top_builddir = .. -VPATH = @srcdir@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -transform = @program_transform_name@ -libdir = @libdir@ -includedir = @includedir@ -datadir = @datadir@ -localedir = $(datadir)/locale -gettextsrcdir = $(datadir)/gettext/intl -aliaspath = $(localedir) -subdir = intl - -INSTALL = @INSTALL@ -INSTALL_DATA = @INSTALL_DATA@ -MKINSTALLDIRS = @MKINSTALLDIRS@ -mkinstalldirs = $(SHELL) `case "$(MKINSTALLDIRS)" in /*) echo "$(MKINSTALLDIRS)" ;; *) echo "$(top_builddir)/$(MKINSTALLDIRS)" ;; esac` - -l = @INTL_LIBTOOL_SUFFIX_PREFIX@ - -AR = ar -CC = @CC@ -LIBTOOL = @LIBTOOL@ -RANLIB = @RANLIB@ -YACC = @INTLBISON@ -y -d -YFLAGS = --name-prefix=__gettext - -DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \ --DLIBDIR=\"$(libdir)\" -DIN_LIBINTL @DEFS@ -CPPFLAGS = @CPPFLAGS@ -CFLAGS = @CFLAGS@ -LDFLAGS = @LDFLAGS@ - -COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) - -HEADERS = $(COMHDRS) libgnuintl.h loadinfo.h -COMHDRS = gmo.h gettextP.h hash-string.h plural-exp.h eval-plural.h os2compat.h -SOURCES = $(COMSRCS) intl-compat.c -COMSRCS = bindtextdom.c dcgettext.c dgettext.c gettext.c \ -finddomain.c loadmsgcat.c localealias.c textdomain.c l10nflist.c \ -explodename.c dcigettext.c dcngettext.c dngettext.c ngettext.c plural.y \ -plural-exp.c localcharset.c localename.c osdep.c os2compat.c -OBJECTS = @INTLOBJS@ bindtextdom.$lo dcgettext.$lo dgettext.$lo gettext.$lo \ -finddomain.$lo loadmsgcat.$lo localealias.$lo textdomain.$lo l10nflist.$lo \ -explodename.$lo dcigettext.$lo dcngettext.$lo dngettext.$lo ngettext.$lo \ -plural.$lo plural-exp.$lo localcharset.$lo localename.$lo osdep.$lo -GETTOBJS = intl-compat.$lo -DISTFILES.common = Makefile.in \ -config.charset locale.alias ref-add.sin ref-del.sin $(HEADERS) $(SOURCES) -DISTFILES.generated = plural.c -DISTFILES.normal = VERSION -DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc -DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \ -COPYING.LIB-2 gettext.h libgettext.h plural-eval.c - -# Libtool's library version information for libintl. -# Before making a gettext release, the gettext maintainer must change this -# according to the libtool documentation, section "Library interface versions". -# Maintainers of other packages that include the intl directory must *not* -# change these values. -LTV_CURRENT=4 -LTV_REVISION=0 -LTV_AGE=2 - -.SUFFIXES: -.SUFFIXES: .c .y .o .lo .sin .sed -.c.o: - $(COMPILE) $< -.c.lo: - $(LIBTOOL) --mode=compile $(COMPILE) $< - -.y.c: - $(YACC) $(YFLAGS) --output $@ $< - rm -f $*.h - -.sin.sed: - sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $< > t-$@ - mv t-$@ $@ - -INCLUDES = -I.. -I. -I$(top_srcdir)/intl - -all: all-@USE_INCLUDED_LIBINTL@ -all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed -all-no: all-no-@BUILD_INCLUDED_LIBINTL@ -all-no-yes: libgnuintl.$la -all-no-no: - -libintl.a libgnuintl.a: $(OBJECTS) - rm -f $@ - $(AR) cru $@ $(OBJECTS) - $(RANLIB) $@ - -libintl.la libgnuintl.la: $(OBJECTS) - $(LIBTOOL) --mode=link \ - $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \ - $(OBJECTS) @LTLIBICONV@ -lc \ - -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \ - -rpath $(libdir) \ - -no-undefined - -libintl.h: libgnuintl.h - cp $(srcdir)/libgnuintl.h libintl.h - -charset.alias: config.charset - $(SHELL) $(srcdir)/config.charset '@host@' > t-$@ - mv t-$@ $@ - -check: all - -# This installation goal is only used in GNU gettext. Packages which -# only use the library should use install instead. - -# We must not install the libintl.h/libintl.a files if we are on a -# system which has the GNU gettext() function in its C library or in a -# separate library. -# If you want to use the one which comes with this version of the -# package, you have to use `configure --with-included-gettext'. -install: install-exec install-data -install-exec: all - if test "$(PACKAGE)" = "gettext" \ - && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ - $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ - $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \ - $(LIBTOOL) --mode=install \ - $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \ - else \ - : ; \ - fi - if test '@USE_INCLUDED_LIBINTL@' = yes; then \ - test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \ - temp=$(DESTDIR)$(libdir)/t-charset.alias; \ - dest=$(DESTDIR)$(libdir)/charset.alias; \ - if test -f $(DESTDIR)$(libdir)/charset.alias; then \ - orig=$(DESTDIR)$(libdir)/charset.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - else \ - if test @GLIBC21@ = no; then \ - orig=charset.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - fi; \ - fi; \ - $(mkinstalldirs) $(DESTDIR)$(localedir); \ - test -f $(DESTDIR)$(localedir)/locale.alias \ - && orig=$(DESTDIR)$(localedir)/locale.alias \ - || orig=$(srcdir)/locale.alias; \ - temp=$(DESTDIR)$(localedir)/t-locale.alias; \ - dest=$(DESTDIR)$(localedir)/locale.alias; \ - sed -f ref-add.sed $$orig > $$temp; \ - $(INSTALL_DATA) $$temp $$dest; \ - rm -f $$temp; \ - else \ - : ; \ - fi -install-data: all - if test "$(PACKAGE)" = "gettext"; then \ - $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ - $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \ - $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \ - dists="COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common)"; \ - for file in $$dists; do \ - $(INSTALL_DATA) $(srcdir)/$$file \ - $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \ - dists="$(DISTFILES.generated)"; \ - for file in $$dists; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - $(INSTALL_DATA) $$dir/$$file \ - $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - dists="$(DISTFILES.obsolete)"; \ - for file in $$dists; do \ - rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - else \ - : ; \ - fi - -install-strip: install - -installdirs: - if test "$(PACKAGE)" = "gettext" \ - && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ - $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \ - else \ - : ; \ - fi - if test '@USE_INCLUDED_LIBINTL@' = yes; then \ - test @GLIBC21@ != no || $(mkinstalldirs) $(DESTDIR)$(libdir); \ - $(mkinstalldirs) $(DESTDIR)$(localedir); \ - else \ - : ; \ - fi - if test "$(PACKAGE)" = "gettext"; then \ - $(mkinstalldirs) $(DESTDIR)$(gettextsrcdir); \ - else \ - : ; \ - fi - -# Define this as empty until I found a useful application. -installcheck: - -uninstall: - if test "$(PACKAGE)" = "gettext" \ - && test '@INTLOBJS@' = '$(GETTOBJS)'; then \ - rm -f $(DESTDIR)$(includedir)/libintl.h; \ - $(LIBTOOL) --mode=uninstall \ - rm -f $(DESTDIR)$(libdir)/libintl.$la; \ - else \ - : ; \ - fi - if test '@USE_INCLUDED_LIBINTL@' = yes; then \ - if test -f $(DESTDIR)$(libdir)/charset.alias; then \ - temp=$(DESTDIR)$(libdir)/t-charset.alias; \ - dest=$(DESTDIR)$(libdir)/charset.alias; \ - sed -f ref-del.sed $$dest > $$temp; \ - if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ - rm -f $$dest; \ - else \ - $(INSTALL_DATA) $$temp $$dest; \ - fi; \ - rm -f $$temp; \ - fi; \ - if test -f $(DESTDIR)$(localedir)/locale.alias; then \ - temp=$(DESTDIR)$(localedir)/t-locale.alias; \ - dest=$(DESTDIR)$(localedir)/locale.alias; \ - sed -f ref-del.sed $$dest > $$temp; \ - if grep '^# Packages using this file: $$' $$temp > /dev/null; then \ - rm -f $$dest; \ - else \ - $(INSTALL_DATA) $$temp $$dest; \ - fi; \ - rm -f $$temp; \ - fi; \ - else \ - : ; \ - fi - if test "$(PACKAGE)" = "gettext"; then \ - for file in VERSION ChangeLog COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \ - rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \ - done; \ - else \ - : ; \ - fi - -info dvi: - -$(OBJECTS): ../config.h libgnuintl.h -bindtextdom.$lo dcgettext.$lo dcigettext.$lo dcngettext.$lo dgettext.$lo dngettext.$lo finddomain.$lo gettext.$lo intl-compat.$lo loadmsgcat.$lo localealias.$lo ngettext.$lo textdomain.$lo: gettextP.h gmo.h loadinfo.h -dcigettext.$lo: hash-string.h -explodename.$lo l10nflist.$lo: loadinfo.h -dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: plural-exp.h -dcigettext.$lo: eval-plural.h - -tags: TAGS - -TAGS: $(HEADERS) $(SOURCES) - here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES) - -id: ID - -ID: $(HEADERS) $(SOURCES) - here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES) - - -mostlyclean: - rm -f *.a *.la *.o *.lo core core.* - rm -f libintl.h charset.alias ref-add.sed ref-del.sed - rm -f -r .libs _libs - -clean: mostlyclean - -distclean: clean - rm -f Makefile ID TAGS - if test "$(PACKAGE)" = gettext; then \ - rm -f ChangeLog.inst $(DISTFILES.normal); \ - else \ - : ; \ - fi - -maintainer-clean: distclean - @echo "This command is intended for maintainers to use;" - @echo "it deletes files that may require special tools to rebuild." - - -# GNU gettext needs not contain the file `VERSION' but contains some -# other files which should not be distributed in other packages. -distdir = ../$(PACKAGE)-$(VERSION)/$(subdir) -dist distdir: Makefile - if test "$(PACKAGE)" = gettext; then \ - additional="$(DISTFILES.gettext)"; \ - else \ - additional="$(DISTFILES.normal)"; \ - fi; \ - $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \ - for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \ - if test -f $$file; then dir=.; else dir=$(srcdir); fi; \ - cp -p $$dir/$$file $(distdir); \ - done - -Makefile: Makefile.in ../config.status - cd .. \ - && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status - -# Tell versions [3.59,3.63) of GNU make not to export all variables. -# Otherwise a system limit (for SysV at least) may be exceeded. -.NOEXPORT: diff --git a/intl/VERSION b/intl/VERSION deleted file mode 100644 index acc8052f3..000000000 --- a/intl/VERSION +++ /dev/null @@ -1 +0,0 @@ -GNU gettext library from gettext-0.11.5 diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c deleted file mode 100644 index d582ce11d..000000000 --- a/intl/bindtextdom.c +++ /dev/null @@ -1,369 +0,0 @@ -/* Implementation of the bindtextdomain(3) function - Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "gettextP.h" - -#ifdef _LIBC -/* We have to handle multi-threaded applications. */ -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_rwlock_define(CLASS, NAME) -# define __libc_rwlock_wrlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_dirname libintl_nl_default_dirname -# define _nl_domain_bindings libintl_nl_domain_bindings -#endif - -/* Some compilers, like SunOS4 cc, don't have offsetof in . */ -#ifndef offsetof -# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) -#endif - -/* @@ end of prolog @@ */ - -/* Contains the default location of the message catalogs. */ -extern const char _nl_default_dirname[]; - -/* List with bindings of specific domains. */ -extern struct binding *_nl_domain_bindings; - -/* Lock variable to protect the global data in the gettext implementation. */ -__libc_rwlock_define (extern, _nl_state_lock attribute_hidden) - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define BINDTEXTDOMAIN __bindtextdomain -# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset -# ifndef strdup -# define strdup(str) __strdup (str) -# endif -#else -# define BINDTEXTDOMAIN libintl_bindtextdomain -# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset -#endif - -/* Prototypes for local functions. */ -static void set_binding_values PARAMS ((const char *domainname, - const char **dirnamep, - const char **codesetp)); - -/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP - to be used for the DOMAINNAME message catalog. - If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not - modified, only the current value is returned. - If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither - modified nor returned. */ -static void -set_binding_values (domainname, dirnamep, codesetp) - const char *domainname; - const char **dirnamep; - const char **codesetp; -{ - struct binding *binding; - int modified; - - /* Some sanity checks. */ - if (domainname == NULL || domainname[0] == '\0') - { - if (dirnamep) - *dirnamep = NULL; - if (codesetp) - *codesetp = NULL; - return; - } - - __libc_rwlock_wrlock (_nl_state_lock); - - modified = 0; - - for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) - { - int compare = strcmp (domainname, binding->domainname); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It is not in the list. */ - binding = NULL; - break; - } - } - - if (binding != NULL) - { - if (dirnamep) - { - const char *dirname = *dirnamep; - - if (dirname == NULL) - /* The current binding has be to returned. */ - *dirnamep = binding->dirname; - else - { - /* The domain is already bound. If the new value and the old - one are equal we simply do nothing. Otherwise replace the - old binding. */ - char *result = binding->dirname; - if (strcmp (dirname, result) != 0) - { - if (strcmp (dirname, _nl_default_dirname) == 0) - result = (char *) _nl_default_dirname; - else - { -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (dirname); -#else - size_t len = strlen (dirname) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result != NULL, 1)) - memcpy (result, dirname, len); -#endif - } - - if (__builtin_expect (result != NULL, 1)) - { - if (binding->dirname != _nl_default_dirname) - free (binding->dirname); - - binding->dirname = result; - modified = 1; - } - } - *dirnamep = result; - } - } - - if (codesetp) - { - const char *codeset = *codesetp; - - if (codeset == NULL) - /* The current binding has be to returned. */ - *codesetp = binding->codeset; - else - { - /* The domain is already bound. If the new value and the old - one are equal we simply do nothing. Otherwise replace the - old binding. */ - char *result = binding->codeset; - if (result == NULL || strcmp (codeset, result) != 0) - { -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (codeset); -#else - size_t len = strlen (codeset) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result != NULL, 1)) - memcpy (result, codeset, len); -#endif - - if (__builtin_expect (result != NULL, 1)) - { - if (binding->codeset != NULL) - free (binding->codeset); - - binding->codeset = result; - binding->codeset_cntr++; - modified = 1; - } - } - *codesetp = result; - } - } - } - else if ((dirnamep == NULL || *dirnamep == NULL) - && (codesetp == NULL || *codesetp == NULL)) - { - /* Simply return the default values. */ - if (dirnamep) - *dirnamep = _nl_default_dirname; - if (codesetp) - *codesetp = NULL; - } - else - { - /* We have to create a new binding. */ - size_t len = strlen (domainname) + 1; - struct binding *new_binding = - (struct binding *) malloc (offsetof (struct binding, domainname) + len); - - if (__builtin_expect (new_binding == NULL, 0)) - goto failed; - - memcpy (new_binding->domainname, domainname, len); - - if (dirnamep) - { - const char *dirname = *dirnamep; - - if (dirname == NULL) - /* The default value. */ - dirname = _nl_default_dirname; - else - { - if (strcmp (dirname, _nl_default_dirname) == 0) - dirname = _nl_default_dirname; - else - { - char *result; -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (dirname); - if (__builtin_expect (result == NULL, 0)) - goto failed_dirname; -#else - size_t len = strlen (dirname) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result == NULL, 0)) - goto failed_dirname; - memcpy (result, dirname, len); -#endif - dirname = result; - } - } - *dirnamep = dirname; - new_binding->dirname = (char *) dirname; - } - else - /* The default value. */ - new_binding->dirname = (char *) _nl_default_dirname; - - new_binding->codeset_cntr = 0; - - if (codesetp) - { - const char *codeset = *codesetp; - - if (codeset != NULL) - { - char *result; - -#if defined _LIBC || defined HAVE_STRDUP - result = strdup (codeset); - if (__builtin_expect (result == NULL, 0)) - goto failed_codeset; -#else - size_t len = strlen (codeset) + 1; - result = (char *) malloc (len); - if (__builtin_expect (result == NULL, 0)) - goto failed_codeset; - memcpy (result, codeset, len); -#endif - codeset = result; - new_binding->codeset_cntr++; - } - *codesetp = codeset; - new_binding->codeset = (char *) codeset; - } - else - new_binding->codeset = NULL; - - /* Now enqueue it. */ - if (_nl_domain_bindings == NULL - || strcmp (domainname, _nl_domain_bindings->domainname) < 0) - { - new_binding->next = _nl_domain_bindings; - _nl_domain_bindings = new_binding; - } - else - { - binding = _nl_domain_bindings; - while (binding->next != NULL - && strcmp (domainname, binding->next->domainname) > 0) - binding = binding->next; - - new_binding->next = binding->next; - binding->next = new_binding; - } - - modified = 1; - - /* Here we deal with memory allocation failures. */ - if (0) - { - failed_codeset: - if (new_binding->dirname != _nl_default_dirname) - free (new_binding->dirname); - failed_dirname: - free (new_binding); - failed: - if (dirnamep) - *dirnamep = NULL; - if (codesetp) - *codesetp = NULL; - } - } - - /* If we modified any binding, we flush the caches. */ - if (modified) - ++_nl_msg_cat_cntr; - - __libc_rwlock_unlock (_nl_state_lock); -} - -/* Specify that the DOMAINNAME message catalog will be found - in DIRNAME rather than in the system locale data base. */ -char * -BINDTEXTDOMAIN (domainname, dirname) - const char *domainname; - const char *dirname; -{ - set_binding_values (domainname, &dirname, NULL); - return (char *) dirname; -} - -/* Specify the character encoding in which the messages from the - DOMAINNAME message catalog will be returned. */ -char * -BIND_TEXTDOMAIN_CODESET (domainname, codeset) - const char *domainname; - const char *codeset; -{ - set_binding_values (domainname, NULL, &codeset); - return (char *) codeset; -} - -#ifdef _LIBC -/* Aliases for function names in GNU C Library. */ -weak_alias (__bindtextdomain, bindtextdomain); -weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset); -#endif diff --git a/intl/cat-compat.c b/intl/cat-compat.c deleted file mode 100644 index 867d901b8..000000000 --- a/intl/cat-compat.c +++ /dev/null @@ -1,262 +0,0 @@ -/* Compatibility code for gettext-using-catgets interface. - Copyright (C) 1995, 1997 Free Software Foundation, Inc. - - 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, 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#ifdef STDC_HEADERS -# include -# include -#else -char *getenv (); -# ifdef HAVE_MALLOC_H -# include -# endif -#endif - -#ifdef HAVE_NL_TYPES_H -# include -#endif - -#include "libgettext.h" - -/* @@ end of prolog @@ */ - -/* XPG3 defines the result of `setlocale (category, NULL)' as: - ``Directs `setlocale()' to query `category' and return the current - setting of `local'.'' - However it does not specify the exact format. And even worse: POSIX - defines this not at all. So we can use this feature only on selected - system (e.g. those using GNU C Library). */ -#ifdef _LIBC -# define HAVE_LOCALE_NULL -#endif - -/* The catalog descriptor. */ -static nl_catd catalog = (nl_catd) -1; - -/* Name of the default catalog. */ -static const char default_catalog_name[] = "messages"; - -/* Name of currently used catalog. */ -static const char *catalog_name = default_catalog_name; - -/* Get ID for given string. If not found return -1. */ -static int msg_to_cat_id PARAMS ((const char *msg)); - -/* Substitution for systems lacking this function in their C library. */ -#if !_LIBC && !HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); -#endif - - -/* Set currently used domain/catalog. */ -char * -textdomain (domainname) - const char *domainname; -{ - nl_catd new_catalog; - char *new_name; - size_t new_name_len; - char *lang; - -#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES \ - && defined HAVE_LOCALE_NULL - lang = setlocale (LC_MESSAGES, NULL); -#else - lang = getenv ("LC_ALL"); - if (lang == NULL || lang[0] == '\0') - { - lang = getenv ("LC_MESSAGES"); - if (lang == NULL || lang[0] == '\0') - lang = getenv ("LANG"); - } -#endif - if (lang == NULL || lang[0] == '\0') - lang = "C"; - - /* See whether name of currently used domain is asked. */ - if (domainname == NULL) - return (char *) catalog_name; - - if (domainname[0] == '\0') - domainname = default_catalog_name; - - /* Compute length of added path element. */ - new_name_len = sizeof (LOCALEDIR) - 1 + 1 + strlen (lang) - + sizeof ("/LC_MESSAGES/") - 1 + sizeof (PACKAGE) - 1 - + sizeof (".cat"); - - new_name = (char *) malloc (new_name_len); - if (new_name == NULL) - return NULL; - - strcpy (new_name, PACKAGE); - new_catalog = catopen (new_name, 0); - - if (new_catalog == (nl_catd) -1) - { - /* NLSPATH search didn't work, try absolute path */ - sprintf (new_name, "%s/%s/LC_MESSAGES/%s.cat", LOCALEDIR, lang, - PACKAGE); - new_catalog = catopen (new_name, 0); - - if (new_catalog == (nl_catd) -1) - { - free (new_name); - return (char *) catalog_name; - } - } - - /* Close old catalog. */ - if (catalog != (nl_catd) -1) - catclose (catalog); - if (catalog_name != default_catalog_name) - free ((char *) catalog_name); - - catalog = new_catalog; - catalog_name = new_name; - - return (char *) catalog_name; -} - -char * -bindtextdomain (domainname, dirname) - const char *domainname; - const char *dirname; -{ -#if HAVE_SETENV || HAVE_PUTENV - char *old_val, *new_val, *cp; - size_t new_val_len; - - /* This does not make much sense here but to be compatible do it. */ - if (domainname == NULL) - return NULL; - - /* Compute length of added path element. If we use setenv we don't need - the first byts for NLSPATH=, but why complicate the code for this - peanuts. */ - new_val_len = sizeof ("NLSPATH=") - 1 + strlen (dirname) - + sizeof ("/%L/LC_MESSAGES/%N.cat"); - - old_val = getenv ("NLSPATH"); - if (old_val == NULL || old_val[0] == '\0') - { - old_val = NULL; - new_val_len += 1 + sizeof (LOCALEDIR) - 1 - + sizeof ("/%L/LC_MESSAGES/%N.cat"); - } - else - new_val_len += strlen (old_val); - - new_val = (char *) malloc (new_val_len); - if (new_val == NULL) - return NULL; - -# if HAVE_SETENV - cp = new_val; -# else - cp = stpcpy (new_val, "NLSPATH="); -# endif - - cp = stpcpy (cp, dirname); - cp = stpcpy (cp, "/%L/LC_MESSAGES/%N.cat:"); - - if (old_val == NULL) - { -# if __STDC__ - stpcpy (cp, LOCALEDIR "/%L/LC_MESSAGES/%N.cat"); -# else - - cp = stpcpy (cp, LOCALEDIR); - stpcpy (cp, "/%L/LC_MESSAGES/%N.cat"); -# endif - } - else - stpcpy (cp, old_val); - -# if HAVE_SETENV - setenv ("NLSPATH", new_val, 1); - free (new_val); -# else - putenv (new_val); - /* Do *not* free the environment entry we just entered. It is used - from now on. */ -# endif - -#endif - - return (char *) domainname; -} - -#undef gettext -char * -gettext (msg) - const char *msg; -{ - int msgid; - - if (msg == NULL || catalog == (nl_catd) -1) - return (char *) msg; - - /* Get the message from the catalog. We always use set number 1. - The message ID is computed by the function `msg_to_cat_id' - which works on the table generated by `po-to-tbl'. */ - msgid = msg_to_cat_id (msg); - if (msgid == -1) - return (char *) msg; - - return catgets (catalog, 1, msgid, (char *) msg); -} - -/* Look through the table `_msg_tbl' which has `_msg_tbl_length' entries - for the one equal to msg. If it is found return the ID. In case when - the string is not found return -1. */ -static int -msg_to_cat_id (msg) - const char *msg; -{ - int cnt; - - for (cnt = 0; cnt < _msg_tbl_length; ++cnt) - if (strcmp (msg, _msg_tbl[cnt]._msg) == 0) - return _msg_tbl[cnt]._msg_number; - - return -1; -} - - -/* @@ begin of epilog @@ */ - -/* We don't want libintl.a to depend on any other library. So we - avoid the non-standard function stpcpy. In GNU C Library this - function is available, though. Also allow the symbol HAVE_STPCPY - to be defined. */ -#if !_LIBC && !HAVE_STPCPY -static char * -stpcpy (dest, src) - char *dest; - const char *src; -{ - while ((*dest++ = *src++) != '\0') - /* Do nothing. */ ; - return dest - 1; -} -#endif diff --git a/intl/dcgettext.c b/intl/dcgettext.c deleted file mode 100644 index ca6a1c82d..000000000 --- a/intl/dcgettext.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Implementation of the dcgettext(3) function. - Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DCGETTEXT __dcgettext -# define DCIGETTEXT __dcigettext -#else -# define DCGETTEXT libintl_dcgettext -# define DCIGETTEXT libintl_dcigettext -#endif - -/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY - locale. */ -char * -DCGETTEXT (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; -{ - return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -INTDEF(__dcgettext) -weak_alias (__dcgettext, dcgettext); -#endif diff --git a/intl/dgettext.c b/intl/dgettext.c deleted file mode 100644 index cf5b4037f..000000000 --- a/intl/dgettext.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Implementation of the dgettext(3) function. - Copyright (C) 1995-1997, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define DGETTEXT __dgettext -# define DCGETTEXT INTUSE(__dcgettext) -#else -# define DGETTEXT libintl_dgettext -# define DCGETTEXT libintl_dcgettext -#endif - -/* Look up MSGID in the DOMAINNAME message catalog of the current - LC_MESSAGES locale. */ -char * -DGETTEXT (domainname, msgid) - const char *domainname; - const char *msgid; -{ - return DCGETTEXT (domainname, msgid, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__dgettext, dgettext); -#endif diff --git a/intl/explodename.c b/intl/explodename.c deleted file mode 100644 index 2985064c9..000000000 --- a/intl/explodename.c +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - Contributed by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include - -#include "loadinfo.h" - -/* On some strange systems still no definition of NULL is found. Sigh! */ -#ifndef NULL -# if defined __STDC__ && __STDC__ -# define NULL ((void *) 0) -# else -# define NULL 0 -# endif -#endif - -/* @@ end of prolog @@ */ - -char * -_nl_find_language (name) - const char *name; -{ - while (name[0] != '\0' && name[0] != '_' && name[0] != '@' - && name[0] != '+' && name[0] != ',') - ++name; - - return (char *) name; -} - - -int -_nl_explode_name (name, language, modifier, territory, codeset, - normalized_codeset, special, sponsor, revision) - char *name; - const char **language; - const char **modifier; - const char **territory; - const char **codeset; - const char **normalized_codeset; - const char **special; - const char **sponsor; - const char **revision; -{ - enum { undecided, xpg, cen } syntax; - char *cp; - int mask; - - *modifier = NULL; - *territory = NULL; - *codeset = NULL; - *normalized_codeset = NULL; - *special = NULL; - *sponsor = NULL; - *revision = NULL; - - /* Now we determine the single parts of the locale name. First - look for the language. Termination symbols are `_' and `@' if - we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ - mask = 0; - syntax = undecided; - *language = cp = name; - cp = _nl_find_language (*language); - - if (*language == cp) - /* This does not make sense: language has to be specified. Use - this entry as it is without exploding. Perhaps it is an alias. */ - cp = strchr (*language, '\0'); - else if (cp[0] == '_') - { - /* Next is the territory. */ - cp[0] = '\0'; - *territory = ++cp; - - while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@' - && cp[0] != '+' && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= TERRITORY; - - if (cp[0] == '.') - { - /* Next is the codeset. */ - syntax = xpg; - cp[0] = '\0'; - *codeset = ++cp; - - while (cp[0] != '\0' && cp[0] != '@') - ++cp; - - mask |= XPG_CODESET; - - if (*codeset != cp && (*codeset)[0] != '\0') - { - *normalized_codeset = _nl_normalize_codeset (*codeset, - cp - *codeset); - if (strcmp (*codeset, *normalized_codeset) == 0) - free ((char *) *normalized_codeset); - else - mask |= XPG_NORM_CODESET; - } - } - } - - if (cp[0] == '@' || (syntax != xpg && cp[0] == '+')) - { - /* Next is the modifier. */ - syntax = cp[0] == '@' ? xpg : cen; - cp[0] = '\0'; - *modifier = ++cp; - - while (syntax == cen && cp[0] != '\0' && cp[0] != '+' - && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= XPG_MODIFIER | CEN_AUDIENCE; - } - - if (syntax != xpg && (cp[0] == '+' || cp[0] == ',' || cp[0] == '_')) - { - syntax = cen; - - if (cp[0] == '+') - { - /* Next is special application (CEN syntax). */ - cp[0] = '\0'; - *special = ++cp; - - while (cp[0] != '\0' && cp[0] != ',' && cp[0] != '_') - ++cp; - - mask |= CEN_SPECIAL; - } - - if (cp[0] == ',') - { - /* Next is sponsor (CEN syntax). */ - cp[0] = '\0'; - *sponsor = ++cp; - - while (cp[0] != '\0' && cp[0] != '_') - ++cp; - - mask |= CEN_SPONSOR; - } - - if (cp[0] == '_') - { - /* Next is revision (CEN syntax). */ - cp[0] = '\0'; - *revision = ++cp; - - mask |= CEN_REVISION; - } - } - - /* For CEN syntax values it might be important to have the - separator character in the file name, not for XPG syntax. */ - if (syntax == xpg) - { - if (*territory != NULL && (*territory)[0] == '\0') - mask &= ~TERRITORY; - - if (*codeset != NULL && (*codeset)[0] == '\0') - mask &= ~XPG_CODESET; - - if (*modifier != NULL && (*modifier)[0] == '\0') - mask &= ~XPG_MODIFIER; - } - - return mask; -} diff --git a/intl/finddomain.c b/intl/finddomain.c deleted file mode 100644 index 2f103d556..000000000 --- a/intl/finddomain.c +++ /dev/null @@ -1,198 +0,0 @@ -/* Handle list of needed message catalogs - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - Written by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ -/* List of already loaded domains. */ -static struct loaded_l10nfile *_nl_loaded_domains; - - -/* Return a data structure describing the message catalog described by - the DOMAINNAME and CATEGORY parameters with respect to the currently - established bindings. */ -struct loaded_l10nfile * -internal_function -_nl_find_domain (dirname, locale, domainname, domainbinding) - const char *dirname; - char *locale; - const char *domainname; - struct binding *domainbinding; -{ - struct loaded_l10nfile *retval; - const char *language; - const char *modifier; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *special; - const char *sponsor; - const char *revision; - const char *alias_value; - int mask; - - /* LOCALE can consist of up to four recognized parts for the XPG syntax: - - language[_territory[.codeset]][@modifier] - - and six parts for the CEN syntax: - - language[_territory][+audience][+special][,[sponsor][_revision]] - - Beside the first part all of them are allowed to be missing. If - the full specified locale is not found, the less specific one are - looked for. The various parts will be stripped off according to - the following order: - (1) revision - (2) sponsor - (3) special - (4) codeset - (5) normalized codeset - (6) territory - (7) audience/modifier - */ - - /* If we have already tested for this locale entry there has to - be one data set in the list of loaded domains. */ - retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, - strlen (dirname) + 1, 0, locale, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, domainname, 0); - if (retval != NULL) - { - /* We know something about this locale. */ - int cnt; - - if (retval->decided == 0) - _nl_load_domain (retval, domainbinding); - - if (retval->data != NULL) - return retval; - - for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) - { - if (retval->successor[cnt]->decided == 0) - _nl_load_domain (retval->successor[cnt], domainbinding); - - if (retval->successor[cnt]->data != NULL) - break; - } - return cnt >= 0 ? retval : NULL; - /* NOTREACHED */ - } - - /* See whether the locale value is an alias. If yes its value - *overwrites* the alias name. No test for the original value is - done. */ - alias_value = _nl_expand_alias (locale); - if (alias_value != NULL) - { -#if defined _LIBC || defined HAVE_STRDUP - locale = strdup (alias_value); - if (locale == NULL) - return NULL; -#else - size_t len = strlen (alias_value) + 1; - locale = (char *) malloc (len); - if (locale == NULL) - return NULL; - - memcpy (locale, alias_value, len); -#endif - } - - /* Now we determine the single parts of the locale name. First - look for the language. Termination symbols are `_' and `@' if - we use XPG4 style, and `_', `+', and `,' if we use CEN syntax. */ - mask = _nl_explode_name (locale, &language, &modifier, &territory, - &codeset, &normalized_codeset, &special, - &sponsor, &revision); - - /* Create all possible locale entries which might be interested in - generalization. */ - retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname, - strlen (dirname) + 1, mask, language, territory, - codeset, normalized_codeset, modifier, special, - sponsor, revision, domainname, 1); - if (retval == NULL) - /* This means we are out of core. */ - return NULL; - - if (retval->decided == 0) - _nl_load_domain (retval, domainbinding); - if (retval->data == NULL) - { - int cnt; - for (cnt = 0; retval->successor[cnt] != NULL; ++cnt) - { - if (retval->successor[cnt]->decided == 0) - _nl_load_domain (retval->successor[cnt], domainbinding); - if (retval->successor[cnt]->data != NULL) - break; - } - } - - /* The room for an alias was dynamically allocated. Free it now. */ - if (alias_value != NULL) - free (locale); - - /* The space for normalized_codeset is dynamically allocated. Free it. */ - if (mask & XPG_NORM_CODESET) - free ((void *) normalized_codeset); - - return retval; -} - - -#ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) -{ - struct loaded_l10nfile *runp = _nl_loaded_domains; - - while (runp != NULL) - { - struct loaded_l10nfile *here = runp; - if (runp->data != NULL) - _nl_unload_domain ((struct loaded_domain *) runp->data); - runp = runp->next; - free ((char *) here->filename); - free (here); - } -} - -text_set_element (__libc_subfreeres, free_mem); -#endif diff --git a/intl/gettext.c b/intl/gettext.c deleted file mode 100644 index 43d689f55..000000000 --- a/intl/gettext.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Implementation of gettext(3) function. - Copyright (C) 1995, 1997, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#ifdef _LIBC -# define __need_NULL -# include -#else -# include /* Just for NULL. */ -#endif - -#include "gettextP.h" -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif - -/* @@ end of prolog @@ */ - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define GETTEXT __gettext -# define DCGETTEXT INTUSE(__dcgettext) -#else -# define GETTEXT libintl_gettext -# define DCGETTEXT libintl_dcgettext -#endif - -/* Look up MSGID in the current default message catalog for the current - LC_MESSAGES locale. If not found, returns MSGID itself (the default - text). */ -char * -GETTEXT (msgid) - const char *msgid; -{ - return DCGETTEXT (NULL, msgid, LC_MESSAGES); -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__gettext, gettext); -#endif diff --git a/intl/gettext.h b/intl/gettext.h deleted file mode 100644 index 6f5d76055..000000000 --- a/intl/gettext.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Description of GNU message catalog format: general file layout. - Copyright (C) 1995, 1997, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _GETTEXT_H -#define _GETTEXT_H 1 - -#if HAVE_LIMITS_H || _LIBC -# include -#endif - -/* @@ end of prolog @@ */ - -/* The magic number of the GNU message catalog format. */ -#define _MAGIC 0x950412de -#define _MAGIC_SWAPPED 0xde120495 - -/* Revision number of the currently used .mo (binary) file format. */ -#define MO_REVISION_NUMBER 0 - -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work - when cross-compiling. */ - -#if __STDC__ -# define UINT_MAX_32_BITS 4294967295U -#else -# define UINT_MAX_32_BITS 0xFFFFFFFF -#endif - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -#ifndef UINT_MAX -# define UINT_MAX UINT_MAX_32_BITS -#endif - -#if UINT_MAX == UINT_MAX_32_BITS -typedef unsigned nls_uint32; -#else -# if USHRT_MAX == UINT_MAX_32_BITS -typedef unsigned short nls_uint32; -# else -# if ULONG_MAX == UINT_MAX_32_BITS -typedef unsigned long nls_uint32; -# else - /* The following line is intended to throw an error. Using #error is - not portable enough. */ - "Cannot determine unsigned 32-bit data type." -# endif -# endif -#endif - - -/* Header for binary .mo file format. */ -struct mo_file_header -{ - /* The magic number. */ - nls_uint32 magic; - /* The revision number of the file format. */ - nls_uint32 revision; - /* The number of strings pairs. */ - nls_uint32 nstrings; - /* Offset of table with start offsets of original strings. */ - nls_uint32 orig_tab_offset; - /* Offset of table with start offsets of translation strings. */ - nls_uint32 trans_tab_offset; - /* Size of hashing table. */ - nls_uint32 hash_tab_size; - /* Offset of first hashing entry. */ - nls_uint32 hash_tab_offset; -}; - -struct string_desc -{ - /* Length of addressed string. */ - nls_uint32 length; - /* Offset of string in file. */ - nls_uint32 offset; -}; - -/* @@ begin of epilog @@ */ - -#endif /* gettext.h */ diff --git a/intl/gettextP.h b/intl/gettextP.h deleted file mode 100644 index f085c59bb..000000000 --- a/intl/gettextP.h +++ /dev/null @@ -1,242 +0,0 @@ -/* Header describing internals of libintl library. - Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc. - Written by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _GETTEXTP_H -#define _GETTEXTP_H - -#include /* Get size_t. */ - -#ifdef _LIBC -# include "../iconv/gconv_int.h" -#else -# if HAVE_ICONV -# include -# endif -#endif - -#include "loadinfo.h" - -#include "gmo.h" /* Get nls_uint32. */ - -/* @@ end of prolog @@ */ - -#ifndef PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - -#ifndef internal_function -# define internal_function -#endif - -#ifndef attribute_hidden -# define attribute_hidden -#endif - -/* Tell the compiler when a conditional or integer expression is - almost always true or almost always false. */ -#ifndef HAVE_BUILTIN_EXPECT -# define __builtin_expect(expr, val) (expr) -#endif - -#ifndef W -# define W(flag, data) ((flag) ? SWAP (data) : (data)) -#endif - - -#ifdef _LIBC -# include -# define SWAP(i) bswap_32 (i) -#else -static inline nls_uint32 -SWAP (i) - nls_uint32 i; -{ - return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24); -} -#endif - - -/* In-memory representation of system dependent string. */ -struct sysdep_string_desc -{ - /* Length of addressed string, including the trailing NUL. */ - size_t length; - /* Pointer to addressed string. */ - const char *pointer; -}; - -/* The representation of an opened message catalog. */ -struct loaded_domain -{ - /* Pointer to memory containing the .mo file. */ - const char *data; - /* 1 if the memory is mmap()ed, 0 if the memory is malloc()ed. */ - int use_mmap; - /* Size of mmap()ed memory. */ - size_t mmap_size; - /* 1 if the .mo file uses a different endianness than this machine. */ - int must_swap; - /* Pointer to additional malloc()ed memory. */ - void *malloced; - - /* Number of static strings pairs. */ - nls_uint32 nstrings; - /* Pointer to descriptors of original strings in the file. */ - const struct string_desc *orig_tab; - /* Pointer to descriptors of translated strings in the file. */ - const struct string_desc *trans_tab; - - /* Number of system dependent strings pairs. */ - nls_uint32 n_sysdep_strings; - /* Pointer to descriptors of original sysdep strings. */ - const struct sysdep_string_desc *orig_sysdep_tab; - /* Pointer to descriptors of translated sysdep strings. */ - const struct sysdep_string_desc *trans_sysdep_tab; - - /* Size of hash table. */ - nls_uint32 hash_size; - /* Pointer to hash table. */ - const nls_uint32 *hash_tab; - /* 1 if the hash table uses a different endianness than this machine. */ - int must_swap_hash_tab; - - int codeset_cntr; -#ifdef _LIBC - __gconv_t conv; -#else -# if HAVE_ICONV - iconv_t conv; -# endif -#endif - char **conv_tab; - - struct expression *plural; - unsigned long int nplurals; -}; - -/* We want to allocate a string at the end of the struct. But ISO C - doesn't allow zero sized arrays. */ -#ifdef __GNUC__ -# define ZERO 0 -#else -# define ZERO 1 -#endif - -/* A set of settings bound to a message domain. Used to store settings - from bindtextdomain() and bind_textdomain_codeset(). */ -struct binding -{ - struct binding *next; - char *dirname; - int codeset_cntr; /* Incremented each time codeset changes. */ - char *codeset; - char domainname[ZERO]; -}; - -/* A counter which is incremented each time some previous translations - become invalid. - This variable is part of the external ABI of the GNU libintl. */ -extern int _nl_msg_cat_cntr; - -#ifndef _LIBC -const char *_nl_locale_name PARAMS ((int category, const char *categoryname)); -#endif - -struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname, - char *__locale, - const char *__domainname, - struct binding *__domainbinding)) - internal_function; -void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain, - struct binding *__domainbinding)) - internal_function; -void _nl_unload_domain PARAMS ((struct loaded_domain *__domain)) - internal_function; -const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file, - struct loaded_domain *__domain, - struct binding *__domainbinding)) - internal_function; -void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain)) - internal_function; - -char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file, - struct binding *domainbinding, - const char *msgid, size_t *lengthp)) - internal_function; - -#ifdef _LIBC -extern char *__gettext PARAMS ((const char *__msgid)); -extern char *__dgettext PARAMS ((const char *__domainname, - const char *__msgid)); -extern char *__dcgettext PARAMS ((const char *__domainname, - const char *__msgid, int __category)); -extern char *__ngettext PARAMS ((const char *__msgid1, const char *__msgid2, - unsigned long int __n)); -extern char *__dngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int n)); -extern char *__dcngettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - unsigned long int __n, int __category)); -extern char *__dcigettext PARAMS ((const char *__domainname, - const char *__msgid1, const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); -extern char *__textdomain PARAMS ((const char *__domainname)); -extern char *__bindtextdomain PARAMS ((const char *__domainname, - const char *__dirname)); -extern char *__bind_textdomain_codeset PARAMS ((const char *__domainname, - const char *__codeset)); -#else -extern char *libintl_gettext PARAMS ((const char *__msgid)); -extern char *libintl_dgettext PARAMS ((const char *__domainname, - const char *__msgid)); -extern char *libintl_dcgettext PARAMS ((const char *__domainname, - const char *__msgid, int __category)); -extern char *libintl_ngettext PARAMS ((const char *__msgid1, - const char *__msgid2, - unsigned long int __n)); -extern char *libintl_dngettext PARAMS ((const char *__domainname, - const char *__msgid1, - const char *__msgid2, - unsigned long int __n)); -extern char *libintl_dcngettext PARAMS ((const char *__domainname, - const char *__msgid1, - const char *__msgid2, - unsigned long int __n, - int __category)); -extern char *libintl_dcigettext PARAMS ((const char *__domainname, - const char *__msgid1, - const char *__msgid2, - int __plural, unsigned long int __n, - int __category)); -extern char *libintl_textdomain PARAMS ((const char *__domainname)); -extern char *libintl_bindtextdomain PARAMS ((const char *__domainname, - const char *__dirname)); -extern char *libintl_bind_textdomain_codeset PARAMS ((const char *__domainname, - const char *__codeset)); -#endif - -/* @@ begin of epilog @@ */ - -#endif /* gettextP.h */ diff --git a/intl/hash-string.h b/intl/hash-string.h deleted file mode 100644 index b267a8778..000000000 --- a/intl/hash-string.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Description of GNU message catalog format: string hashing function. - Copyright (C) 1995, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* @@ end of prolog @@ */ - -#ifndef PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define PARAMS(Args) Args -# else -# define PARAMS(Args) () -# endif -#endif - -/* We assume to have `unsigned long int' value with at least 32 bits. */ -#define HASHWORDBITS 32 - - -/* Defines the so called `hashpjw' function by P.J. Weinberger - [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools, - 1986, 1987 Bell Telephone Laboratories, Inc.] */ -static unsigned long int hash_string PARAMS ((const char *__str_param)); - -static inline unsigned long int -hash_string (str_param) - const char *str_param; -{ - unsigned long int hval, g; - const char *str = str_param; - - /* Compute the hash value for the given string. */ - hval = 0; - while (*str != '\0') - { - hval <<= 4; - hval += (unsigned long int) *str++; - g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4)); - if (g != 0) - { - hval ^= g >> (HASHWORDBITS - 8); - hval ^= g; - } - } - return hval; -} diff --git a/intl/intl-compat.c b/intl/intl-compat.c deleted file mode 100644 index da890159f..000000000 --- a/intl/intl-compat.c +++ /dev/null @@ -1,131 +0,0 @@ -/* intl-compat.c - Stub functions to call gettext functions from GNU gettext - Library. - Copyright (C) 1995, 2000-2002 Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#define _INTL_REDIRECT_MACROS -#include "libgnuintl.h" -#include "gettextP.h" - -/* @@ end of prolog @@ */ - -/* This file redirects the gettext functions (without prefix) to those - defined in the included GNU libintl library (with "libintl_" prefix). - It is compiled into libintl in order to make the AM_GNU_GETTEXT test - of gettext <= 0.11.2 work with the libintl library >= 0.11.3 which - has the redirections primarily in the include file. */ - - -#undef gettext -#undef dgettext -#undef dcgettext -#undef ngettext -#undef dngettext -#undef dcngettext -#undef textdomain -#undef bindtextdomain -#undef bind_textdomain_codeset - - -char * -gettext (msgid) - const char *msgid; -{ - return libintl_gettext (msgid); -} - - -char * -dgettext (domainname, msgid) - const char *domainname; - const char *msgid; -{ - return libintl_dgettext (domainname, msgid); -} - - -char * -dcgettext (domainname, msgid, category) - const char *domainname; - const char *msgid; - int category; -{ - return libintl_dcgettext (domainname, msgid, category); -} - - -char * -ngettext (msgid1, msgid2, n) - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return libintl_ngettext (msgid1, msgid2, n); -} - - -char * -dngettext (domainname, msgid1, msgid2, n) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; -{ - return libintl_dngettext (domainname, msgid1, msgid2, n); -} - - -char * -dcngettext (domainname, msgid1, msgid2, n, category) - const char *domainname; - const char *msgid1; - const char *msgid2; - unsigned long int n; - int category; -{ - return libintl_dcngettext (domainname, msgid1, msgid2, n, category); -} - - -char * -textdomain (domainname) - const char *domainname; -{ - return libintl_textdomain (domainname); -} - - -char * -bindtextdomain (domainname, dirname) - const char *domainname; - const char *dirname; -{ - return libintl_bindtextdomain (domainname, dirname); -} - - -char * -bind_textdomain_codeset (domainname, codeset) - const char *domainname; - const char *codeset; -{ - return libintl_bind_textdomain_codeset (domainname, codeset); -} diff --git a/intl/l10nflist.c b/intl/l10nflist.c deleted file mode 100644 index ec8713f8e..000000000 --- a/intl/l10nflist.c +++ /dev/null @@ -1,453 +0,0 @@ -/* Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc. - Contributed by Ulrich Drepper , 1995. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for stpcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#if defined _LIBC || defined HAVE_ARGZ_H -# include -#endif -#include -#include -#include - -#include "loadinfo.h" - -/* On some strange systems still no definition of NULL is found. Sigh! */ -#ifndef NULL -# if defined __STDC__ && __STDC__ -# define NULL ((void *) 0) -# else -# define NULL 0 -# endif -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# ifndef stpcpy -# define stpcpy(dest, src) __stpcpy(dest, src) -# endif -#else -# ifndef HAVE_STPCPY -static char *stpcpy PARAMS ((char *dest, const char *src)); -# endif -#endif - -/* Pathname support. - ISSLASH(C) tests whether C is a directory separator character. - IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, - it may be concatenated to a directory pathname. - */ -#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ - /* Win32, OS/2, DOS */ -# define ISSLASH(C) ((C) == '/' || (C) == '\\') -# define HAS_DEVICE(P) \ - ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ - && (P)[1] == ':') -# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) -#else - /* Unix */ -# define ISSLASH(C) ((C) == '/') -# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) -#endif - -/* Define function which are usually not available. */ - -#if !defined _LIBC && !defined HAVE___ARGZ_COUNT -/* Returns the number of strings in ARGZ. */ -static size_t argz_count__ PARAMS ((const char *argz, size_t len)); - -static size_t -argz_count__ (argz, len) - const char *argz; - size_t len; -{ - size_t count = 0; - while (len > 0) - { - size_t part_len = strlen (argz); - argz += part_len + 1; - len -= part_len + 1; - count++; - } - return count; -} -# undef __argz_count -# define __argz_count(argz, len) argz_count__ (argz, len) -#else -# ifdef _LIBC -# define __argz_count(argz, len) INTUSE(__argz_count) (argz, len) -# endif -#endif /* !_LIBC && !HAVE___ARGZ_COUNT */ - -#if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY -/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's - except the last into the character SEP. */ -static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep)); - -static void -argz_stringify__ (argz, len, sep) - char *argz; - size_t len; - int sep; -{ - while (len > 0) - { - size_t part_len = strlen (argz); - argz += part_len; - len -= part_len + 1; - if (len > 0) - *argz++ = sep; - } -} -# undef __argz_stringify -# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep) -#else -# ifdef _LIBC -# define __argz_stringify(argz, len, sep) \ - INTUSE(__argz_stringify) (argz, len, sep) -# endif -#endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */ - -#if !defined _LIBC && !defined HAVE___ARGZ_NEXT -static char *argz_next__ PARAMS ((char *argz, size_t argz_len, - const char *entry)); - -static char * -argz_next__ (argz, argz_len, entry) - char *argz; - size_t argz_len; - const char *entry; -{ - if (entry) - { - if (entry < argz + argz_len) - entry = strchr (entry, '\0') + 1; - - return entry >= argz + argz_len ? NULL : (char *) entry; - } - else - if (argz_len > 0) - return argz; - else - return 0; -} -# undef __argz_next -# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry) -#endif /* !_LIBC && !HAVE___ARGZ_NEXT */ - - -/* Return number of bits set in X. */ -static int pop PARAMS ((int x)); - -static inline int -pop (x) - int x; -{ - /* We assume that no more than 16 bits are used. */ - x = ((x & ~0x5555) >> 1) + (x & 0x5555); - x = ((x & ~0x3333) >> 2) + (x & 0x3333); - x = ((x >> 4) + x) & 0x0f0f; - x = ((x >> 8) + x) & 0xff; - - return x; -} - - -struct loaded_l10nfile * -_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language, - territory, codeset, normalized_codeset, modifier, special, - sponsor, revision, filename, do_allocate) - struct loaded_l10nfile **l10nfile_list; - const char *dirlist; - size_t dirlist_len; - int mask; - const char *language; - const char *territory; - const char *codeset; - const char *normalized_codeset; - const char *modifier; - const char *special; - const char *sponsor; - const char *revision; - const char *filename; - int do_allocate; -{ - char *abs_filename; - struct loaded_l10nfile **lastp; - struct loaded_l10nfile *retval; - char *cp; - size_t dirlist_count; - size_t entries; - int cnt; - - /* If LANGUAGE contains an absolute directory specification, we ignore - DIRLIST. */ - if (IS_ABSOLUTE_PATH (language)) - dirlist_len = 0; - - /* Allocate room for the full file name. */ - abs_filename = (char *) malloc (dirlist_len - + strlen (language) - + ((mask & TERRITORY) != 0 - ? strlen (territory) + 1 : 0) - + ((mask & XPG_CODESET) != 0 - ? strlen (codeset) + 1 : 0) - + ((mask & XPG_NORM_CODESET) != 0 - ? strlen (normalized_codeset) + 1 : 0) - + (((mask & XPG_MODIFIER) != 0 - || (mask & CEN_AUDIENCE) != 0) - ? strlen (modifier) + 1 : 0) - + ((mask & CEN_SPECIAL) != 0 - ? strlen (special) + 1 : 0) - + (((mask & CEN_SPONSOR) != 0 - || (mask & CEN_REVISION) != 0) - ? (1 + ((mask & CEN_SPONSOR) != 0 - ? strlen (sponsor) : 0) - + ((mask & CEN_REVISION) != 0 - ? strlen (revision) + 1 : 0)) : 0) - + 1 + strlen (filename) + 1); - - if (abs_filename == NULL) - return NULL; - - /* Construct file name. */ - cp = abs_filename; - if (dirlist_len > 0) - { - memcpy (cp, dirlist, dirlist_len); - __argz_stringify (cp, dirlist_len, PATH_SEPARATOR); - cp += dirlist_len; - cp[-1] = '/'; - } - - cp = stpcpy (cp, language); - - if ((mask & TERRITORY) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, territory); - } - if ((mask & XPG_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, codeset); - } - if ((mask & XPG_NORM_CODESET) != 0) - { - *cp++ = '.'; - cp = stpcpy (cp, normalized_codeset); - } - if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0) - { - /* This component can be part of both syntaces but has different - leading characters. For CEN we use `+', else `@'. */ - *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@'; - cp = stpcpy (cp, modifier); - } - if ((mask & CEN_SPECIAL) != 0) - { - *cp++ = '+'; - cp = stpcpy (cp, special); - } - if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0) - { - *cp++ = ','; - if ((mask & CEN_SPONSOR) != 0) - cp = stpcpy (cp, sponsor); - if ((mask & CEN_REVISION) != 0) - { - *cp++ = '_'; - cp = stpcpy (cp, revision); - } - } - - *cp++ = '/'; - stpcpy (cp, filename); - - /* Look in list of already loaded domains whether it is already - available. */ - lastp = l10nfile_list; - for (retval = *l10nfile_list; retval != NULL; retval = retval->next) - if (retval->filename != NULL) - { - int compare = strcmp (retval->filename, abs_filename); - if (compare == 0) - /* We found it! */ - break; - if (compare < 0) - { - /* It's not in the list. */ - retval = NULL; - break; - } - - lastp = &retval->next; - } - - if (retval != NULL || do_allocate == 0) - { - free (abs_filename); - return retval; - } - - dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1); - - /* Allocate a new loaded_l10nfile. */ - retval = - (struct loaded_l10nfile *) - malloc (sizeof (*retval) - + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0)) - * sizeof (struct loaded_l10nfile *))); - if (retval == NULL) - return NULL; - - retval->filename = abs_filename; - - /* We set retval->data to NULL here; it is filled in later. - Setting retval->decided to 1 here means that retval does not - correspond to a real file (dirlist_count > 1) or is not worth - looking up (if an unnormalized codeset was specified). */ - retval->decided = (dirlist_count > 1 - || ((mask & XPG_CODESET) != 0 - && (mask & XPG_NORM_CODESET) != 0)); - retval->data = NULL; - - retval->next = *lastp; - *lastp = retval; - - entries = 0; - /* Recurse to fill the inheritance list of RETVAL. - If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL - entry does not correspond to a real file; retval->filename contains - colons. In this case we loop across all elements of DIRLIST and - across all bit patterns dominated by MASK. - If the DIRLIST is a single directory or entirely redundant (i.e. - DIRLIST_COUNT == 1), we loop across all bit patterns dominated by - MASK, excluding MASK itself. - In either case, we loop down from MASK to 0. This has the effect - that the extra bits in the locale name are dropped in this order: - first the modifier, then the territory, then the codeset, then the - normalized_codeset. */ - for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt) - if ((cnt & ~mask) == 0 - && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0) - && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0)) - { - if (dirlist_count > 1) - { - /* Iterate over all elements of the DIRLIST. */ - char *dir = NULL; - - while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir)) - != NULL) - retval->successor[entries++] - = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, - cnt, language, territory, codeset, - normalized_codeset, modifier, special, - sponsor, revision, filename, 1); - } - else - retval->successor[entries++] - = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, - cnt, language, territory, codeset, - normalized_codeset, modifier, special, - sponsor, revision, filename, 1); - } - retval->successor[entries] = NULL; - - return retval; -} - -/* Normalize codeset name. There is no standard for the codeset - names. Normalization allows the user to use any of the common - names. The return value is dynamically allocated and has to be - freed by the caller. */ -const char * -_nl_normalize_codeset (codeset, name_len) - const char *codeset; - size_t name_len; -{ - int len = 0; - int only_digit = 1; - char *retval; - char *wp; - size_t cnt; - - for (cnt = 0; cnt < name_len; ++cnt) - if (isalnum ((unsigned char) codeset[cnt])) - { - ++len; - - if (isalpha ((unsigned char) codeset[cnt])) - only_digit = 0; - } - - retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1); - - if (retval != NULL) - { - if (only_digit) - wp = stpcpy (retval, "iso"); - else - wp = retval; - - for (cnt = 0; cnt < name_len; ++cnt) - if (isalpha ((unsigned char) codeset[cnt])) - *wp++ = tolower ((unsigned char) codeset[cnt]); - else if (isdigit ((unsigned char) codeset[cnt])) - *wp++ = codeset[cnt]; - - *wp = '\0'; - } - - return (const char *) retval; -} - - -/* @@ begin of epilog @@ */ - -/* We don't want libintl.a to depend on any other library. So we - avoid the non-standard function stpcpy. In GNU C Library this - function is available, though. Also allow the symbol HAVE_STPCPY - to be defined. */ -#if !_LIBC && !HAVE_STPCPY -static char * -stpcpy (dest, src) - char *dest; - const char *src; -{ - while ((*dest++ = *src++) != '\0') - /* Do nothing. */ ; - return dest - 1; -} -#endif diff --git a/intl/libgettext.h b/intl/libgettext.h deleted file mode 100644 index c5be54a80..000000000 --- a/intl/libgettext.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -#else - -# define gettext(Msgid) (Msgid) -# define dgettext(Domainname, Msgid) (Msgid) -# define dcgettext(Domainname, Msgid, Category) (Msgid) -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((N) == 1 ? (char *) (Msgid1) : (char *) (Msgid2)) -# define textdomain(Domainname) ((char *) (Domainname)) -# define bindtextdomain(Domainname, Dirname) ((char *) (Dirname)) -# define bind_textdomain_codeset(Domainname, Codeset) ((char *) (Codeset)) - -#endif - -/* For automatical extraction of messages sometimes no real - translation is needed. Instead the string itself is the result. */ -#define gettext_noop(Str) (Str) - -#endif /* _LIBGETTEXT_H */ diff --git a/intl/linux-msg.sed b/intl/linux-msg.sed deleted file mode 100644 index 5918e720a..000000000 --- a/intl/linux-msg.sed +++ /dev/null @@ -1,100 +0,0 @@ -# po2msg.sed - Convert Uniforum style .po file to Linux style .msg file -# Copyright (C) 1995 Free Software Foundation, Inc. -# Ulrich Drepper , 1995. -# -# 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, 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. -# -# -# The first directive in the .msg should be the definition of the -# message set number. We use always set number 1. -# -1 { - i\ -$set 1 # Automatically created by po2msg.sed - h - s/.*/0/ - x -} -# -# Mitch's old catalog format does not allow comments. -# -# We copy the original message as a comment into the .msg file. -# -/^msgid/ { - s/msgid[ ]*"// -# -# This does not work now with the new format. -# /"$/! { -# s/\\$// -# s/$/ ... (more lines following)"/ -# } - x -# The following nice solution is by -# Bruno - td -# Increment a decimal number in pattern space. -# First hide trailing `9' digits. - :d - s/9\(_*\)$/_\1/ - td -# Assure at least one digit is available. - s/^\(_*\)$/0\1/ -# Increment the last digit. - s/8\(_*\)$/9\1/ - s/7\(_*\)$/8\1/ - s/6\(_*\)$/7\1/ - s/5\(_*\)$/6\1/ - s/4\(_*\)$/5\1/ - s/3\(_*\)$/4\1/ - s/2\(_*\)$/3\1/ - s/1\(_*\)$/2\1/ - s/0\(_*\)$/1\1/ -# Convert the hidden `9' digits to `0's. - s/_/0/g - x - G - s/\(.*\)"\n\([0-9]*\)/$ #\2 Original Message:(\1)/p -} -# -# The .msg file contains, other then the .po file, only the translations -# but each given a unique ID. Starting from 1 and incrementing by 1 for -# each message we assign them to the messages. -# It is important that the .po file used to generate the cat-id-tbl.c file -# (with po-to-tbl) is the same as the one used here. (At least the order -# of declarations must not be changed.) -# -/^msgstr/ { - s/msgstr[ ]*"\(.*\)"/# \1/ -# Clear substitution flag. - tb -# Append the next line. - :b - N -# Look whether second part is continuation line. - s/\(.*\n\)"\(.*\)"/\1\2/ -# Yes, then branch. - ta - P - D -# Note that D includes a jump to the start!! -# We found a continuation line. But before printing insert '\'. - :a - s/\(.*\)\(\n.*\)/\1\\\2/ - P -# We cannot use D here. - s/.*\n\(.*\)/\1/ - tb -} -d diff --git a/intl/loadinfo.h b/intl/loadinfo.h deleted file mode 100644 index 1d3ba6162..000000000 --- a/intl/loadinfo.h +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 1996-1999, 2000-2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 1996. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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 _LOADINFO_H -#define _LOADINFO_H 1 - -/* Declarations of locale dependent catalog lookup functions. - Implemented in - - localealias.c Possibly replace a locale name by another. - explodename.c Split a locale name into its various fields. - l10nflist.c Generate a list of filenames of possible message catalogs. - finddomain.c Find and open the relevant message catalogs. - - The main function _nl_find_domain() in finddomain.c is declared - in gettextP.h. - */ - -#ifndef PARAMS -# if __STDC__ || defined __GNUC__ || defined __SUNPRO_C || defined __cplusplus || __PROTOTYPES -# define PARAMS(args) args -# else -# define PARAMS(args) () -# endif -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* Tell the compiler when a conditional or integer expression is - almost always true or almost always false. */ -#ifndef HAVE_BUILTIN_EXPECT -# define __builtin_expect(expr, val) (expr) -#endif - -/* Separator in PATH like lists of pathnames. */ -#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ - /* Win32, OS/2, DOS */ -# define PATH_SEPARATOR ';' -#else - /* Unix */ -# define PATH_SEPARATOR ':' -#endif - -/* Encoding of locale name parts. */ -#define CEN_REVISION 1 -#define CEN_SPONSOR 2 -#define CEN_SPECIAL 4 -#define XPG_NORM_CODESET 8 -#define XPG_CODESET 16 -#define TERRITORY 32 -#define CEN_AUDIENCE 64 -#define XPG_MODIFIER 128 - -#define CEN_SPECIFIC (CEN_REVISION|CEN_SPONSOR|CEN_SPECIAL|CEN_AUDIENCE) -#define XPG_SPECIFIC (XPG_CODESET|XPG_NORM_CODESET|XPG_MODIFIER) - - -struct loaded_l10nfile -{ - const char *filename; - int decided; - - const void *data; - - struct loaded_l10nfile *next; - struct loaded_l10nfile *successor[1]; -}; - - -/* Normalize codeset name. There is no standard for the codeset - names. Normalization allows the user to use any of the common - names. The return value is dynamically allocated and has to be - freed by the caller. */ -extern const char *_nl_normalize_codeset PARAMS ((const char *codeset, - size_t name_len)); - -/* Lookup a locale dependent file. - *L10NFILE_LIST denotes a pool of lookup results of locale dependent - files of the same kind, sorted in decreasing order of ->filename. - DIRLIST and DIRLIST_LEN are an argz list of directories in which to - look, containing at least one directory (i.e. DIRLIST_LEN > 0). - MASK, LANGUAGE, TERRITORY, CODESET, NORMALIZED_CODESET, MODIFIER, - SPECIAL, SPONSOR, REVISION are the pieces of the locale name, as - produced by _nl_explode_name(). FILENAME is the filename suffix. - The return value is the lookup result, either found in *L10NFILE_LIST, - or - if DO_ALLOCATE is nonzero - freshly allocated, or possibly NULL. - If the return value is non-NULL, it is added to *L10NFILE_LIST, and - its ->next field denotes the chaining inside *L10NFILE_LIST, and - furthermore its ->successor[] field contains a list of other lookup - results from which this lookup result inherits. */ -extern struct loaded_l10nfile * -_nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list, - const char *dirlist, size_t dirlist_len, int mask, - const char *language, const char *territory, - const char *codeset, - const char *normalized_codeset, - const char *modifier, const char *special, - const char *sponsor, const char *revision, - const char *filename, int do_allocate)); - -/* Lookup the real locale name for a locale alias NAME, or NULL if - NAME is not a locale alias (but possibly a real locale name). - The return value is statically allocated and must not be freed. */ -extern const char *_nl_expand_alias PARAMS ((const char *name)); - -/* Split a locale name NAME into its pieces: language, modifier, - territory, codeset, special, sponsor, revision. - NAME gets destructively modified: NUL bytes are inserted here and - there. *LANGUAGE gets assigned NAME. Each of *MODIFIER, *TERRITORY, - *CODESET, *SPECIAL, *SPONSOR, *REVISION gets assigned either a - pointer into the old NAME string, or NULL. *NORMALIZED_CODESET - gets assigned the expanded *CODESET, if it is different from *CODESET; - this one is dynamically allocated and has to be freed by the caller. - The return value is a bitmask, where each bit corresponds to one - filled-in value: - XPG_MODIFIER, CEN_AUDIENCE for *MODIFIER, - TERRITORY for *TERRITORY, - XPG_CODESET for *CODESET, - XPG_NORM_CODESET for *NORMALIZED_CODESET, - CEN_SPECIAL for *SPECIAL, - CEN_SPONSOR for *SPONSOR, - CEN_REVISION for *REVISION. - */ -extern int _nl_explode_name PARAMS ((char *name, const char **language, - const char **modifier, - const char **territory, - const char **codeset, - const char **normalized_codeset, - const char **special, - const char **sponsor, - const char **revision)); - -/* Split a locale name NAME into a leading language part and all the - rest. Return a pointer to the first character after the language, - i.e. to the first byte of the rest. */ -extern char *_nl_find_language PARAMS ((const char *name)); - -#endif /* loadinfo.h */ diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c deleted file mode 100644 index 516f5211b..000000000 --- a/intl/loadmsgcat.c +++ /dev/null @@ -1,1316 +0,0 @@ -/* Load needed message catalogs. - Copyright (C) 1995-1999, 2000-2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include -#include - -#if defined HAVE_UNISTD_H || defined _LIBC -# include -#endif - -#ifdef _LIBC -# include -# include -#endif - -#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ - || (defined _LIBC && defined _POSIX_MAPPED_FILES) -# include -# undef HAVE_MMAP -# define HAVE_MMAP 1 -#else -# undef HAVE_MMAP -#endif - -#if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC -# include -#endif -#if defined HAVE_INTTYPES_H || defined _LIBC -# include -#endif - -#include "gmo.h" -#include "gettextP.h" -#include "hash-string.h" -#include "plural-exp.h" - -#ifdef _LIBC -# include "../locale/localeinfo.h" -#endif - -/* Provide fallback values for macros that ought to be defined in . - Note that our fallback values need not be literal strings, because we don't - use them with preprocessor string concatenation. */ -#if !defined PRId8 || PRI_MACROS_BROKEN -# undef PRId8 -# define PRId8 "d" -#endif -#if !defined PRIi8 || PRI_MACROS_BROKEN -# undef PRIi8 -# define PRIi8 "i" -#endif -#if !defined PRIo8 || PRI_MACROS_BROKEN -# undef PRIo8 -# define PRIo8 "o" -#endif -#if !defined PRIu8 || PRI_MACROS_BROKEN -# undef PRIu8 -# define PRIu8 "u" -#endif -#if !defined PRIx8 || PRI_MACROS_BROKEN -# undef PRIx8 -# define PRIx8 "x" -#endif -#if !defined PRIX8 || PRI_MACROS_BROKEN -# undef PRIX8 -# define PRIX8 "X" -#endif -#if !defined PRId16 || PRI_MACROS_BROKEN -# undef PRId16 -# define PRId16 "d" -#endif -#if !defined PRIi16 || PRI_MACROS_BROKEN -# undef PRIi16 -# define PRIi16 "i" -#endif -#if !defined PRIo16 || PRI_MACROS_BROKEN -# undef PRIo16 -# define PRIo16 "o" -#endif -#if !defined PRIu16 || PRI_MACROS_BROKEN -# undef PRIu16 -# define PRIu16 "u" -#endif -#if !defined PRIx16 || PRI_MACROS_BROKEN -# undef PRIx16 -# define PRIx16 "x" -#endif -#if !defined PRIX16 || PRI_MACROS_BROKEN -# undef PRIX16 -# define PRIX16 "X" -#endif -#if !defined PRId32 || PRI_MACROS_BROKEN -# undef PRId32 -# define PRId32 "d" -#endif -#if !defined PRIi32 || PRI_MACROS_BROKEN -# undef PRIi32 -# define PRIi32 "i" -#endif -#if !defined PRIo32 || PRI_MACROS_BROKEN -# undef PRIo32 -# define PRIo32 "o" -#endif -#if !defined PRIu32 || PRI_MACROS_BROKEN -# undef PRIu32 -# define PRIu32 "u" -#endif -#if !defined PRIx32 || PRI_MACROS_BROKEN -# undef PRIx32 -# define PRIx32 "x" -#endif -#if !defined PRIX32 || PRI_MACROS_BROKEN -# undef PRIX32 -# define PRIX32 "X" -#endif -#if !defined PRId64 || PRI_MACROS_BROKEN -# undef PRId64 -# define PRId64 (sizeof (long) == 8 ? "ld" : "lld") -#endif -#if !defined PRIi64 || PRI_MACROS_BROKEN -# undef PRIi64 -# define PRIi64 (sizeof (long) == 8 ? "li" : "lli") -#endif -#if !defined PRIo64 || PRI_MACROS_BROKEN -# undef PRIo64 -# define PRIo64 (sizeof (long) == 8 ? "lo" : "llo") -#endif -#if !defined PRIu64 || PRI_MACROS_BROKEN -# undef PRIu64 -# define PRIu64 (sizeof (long) == 8 ? "lu" : "llu") -#endif -#if !defined PRIx64 || PRI_MACROS_BROKEN -# undef PRIx64 -# define PRIx64 (sizeof (long) == 8 ? "lx" : "llx") -#endif -#if !defined PRIX64 || PRI_MACROS_BROKEN -# undef PRIX64 -# define PRIX64 (sizeof (long) == 8 ? "lX" : "llX") -#endif -#if !defined PRIdLEAST8 || PRI_MACROS_BROKEN -# undef PRIdLEAST8 -# define PRIdLEAST8 "d" -#endif -#if !defined PRIiLEAST8 || PRI_MACROS_BROKEN -# undef PRIiLEAST8 -# define PRIiLEAST8 "i" -#endif -#if !defined PRIoLEAST8 || PRI_MACROS_BROKEN -# undef PRIoLEAST8 -# define PRIoLEAST8 "o" -#endif -#if !defined PRIuLEAST8 || PRI_MACROS_BROKEN -# undef PRIuLEAST8 -# define PRIuLEAST8 "u" -#endif -#if !defined PRIxLEAST8 || PRI_MACROS_BROKEN -# undef PRIxLEAST8 -# define PRIxLEAST8 "x" -#endif -#if !defined PRIXLEAST8 || PRI_MACROS_BROKEN -# undef PRIXLEAST8 -# define PRIXLEAST8 "X" -#endif -#if !defined PRIdLEAST16 || PRI_MACROS_BROKEN -# undef PRIdLEAST16 -# define PRIdLEAST16 "d" -#endif -#if !defined PRIiLEAST16 || PRI_MACROS_BROKEN -# undef PRIiLEAST16 -# define PRIiLEAST16 "i" -#endif -#if !defined PRIoLEAST16 || PRI_MACROS_BROKEN -# undef PRIoLEAST16 -# define PRIoLEAST16 "o" -#endif -#if !defined PRIuLEAST16 || PRI_MACROS_BROKEN -# undef PRIuLEAST16 -# define PRIuLEAST16 "u" -#endif -#if !defined PRIxLEAST16 || PRI_MACROS_BROKEN -# undef PRIxLEAST16 -# define PRIxLEAST16 "x" -#endif -#if !defined PRIXLEAST16 || PRI_MACROS_BROKEN -# undef PRIXLEAST16 -# define PRIXLEAST16 "X" -#endif -#if !defined PRIdLEAST32 || PRI_MACROS_BROKEN -# undef PRIdLEAST32 -# define PRIdLEAST32 "d" -#endif -#if !defined PRIiLEAST32 || PRI_MACROS_BROKEN -# undef PRIiLEAST32 -# define PRIiLEAST32 "i" -#endif -#if !defined PRIoLEAST32 || PRI_MACROS_BROKEN -# undef PRIoLEAST32 -# define PRIoLEAST32 "o" -#endif -#if !defined PRIuLEAST32 || PRI_MACROS_BROKEN -# undef PRIuLEAST32 -# define PRIuLEAST32 "u" -#endif -#if !defined PRIxLEAST32 || PRI_MACROS_BROKEN -# undef PRIxLEAST32 -# define PRIxLEAST32 "x" -#endif -#if !defined PRIXLEAST32 || PRI_MACROS_BROKEN -# undef PRIXLEAST32 -# define PRIXLEAST32 "X" -#endif -#if !defined PRIdLEAST64 || PRI_MACROS_BROKEN -# undef PRIdLEAST64 -# define PRIdLEAST64 PRId64 -#endif -#if !defined PRIiLEAST64 || PRI_MACROS_BROKEN -# undef PRIiLEAST64 -# define PRIiLEAST64 PRIi64 -#endif -#if !defined PRIoLEAST64 || PRI_MACROS_BROKEN -# undef PRIoLEAST64 -# define PRIoLEAST64 PRIo64 -#endif -#if !defined PRIuLEAST64 || PRI_MACROS_BROKEN -# undef PRIuLEAST64 -# define PRIuLEAST64 PRIu64 -#endif -#if !defined PRIxLEAST64 || PRI_MACROS_BROKEN -# undef PRIxLEAST64 -# define PRIxLEAST64 PRIx64 -#endif -#if !defined PRIXLEAST64 || PRI_MACROS_BROKEN -# undef PRIXLEAST64 -# define PRIXLEAST64 PRIX64 -#endif -#if !defined PRIdFAST8 || PRI_MACROS_BROKEN -# undef PRIdFAST8 -# define PRIdFAST8 "d" -#endif -#if !defined PRIiFAST8 || PRI_MACROS_BROKEN -# undef PRIiFAST8 -# define PRIiFAST8 "i" -#endif -#if !defined PRIoFAST8 || PRI_MACROS_BROKEN -# undef PRIoFAST8 -# define PRIoFAST8 "o" -#endif -#if !defined PRIuFAST8 || PRI_MACROS_BROKEN -# undef PRIuFAST8 -# define PRIuFAST8 "u" -#endif -#if !defined PRIxFAST8 || PRI_MACROS_BROKEN -# undef PRIxFAST8 -# define PRIxFAST8 "x" -#endif -#if !defined PRIXFAST8 || PRI_MACROS_BROKEN -# undef PRIXFAST8 -# define PRIXFAST8 "X" -#endif -#if !defined PRIdFAST16 || PRI_MACROS_BROKEN -# undef PRIdFAST16 -# define PRIdFAST16 "d" -#endif -#if !defined PRIiFAST16 || PRI_MACROS_BROKEN -# undef PRIiFAST16 -# define PRIiFAST16 "i" -#endif -#if !defined PRIoFAST16 || PRI_MACROS_BROKEN -# undef PRIoFAST16 -# define PRIoFAST16 "o" -#endif -#if !defined PRIuFAST16 || PRI_MACROS_BROKEN -# undef PRIuFAST16 -# define PRIuFAST16 "u" -#endif -#if !defined PRIxFAST16 || PRI_MACROS_BROKEN -# undef PRIxFAST16 -# define PRIxFAST16 "x" -#endif -#if !defined PRIXFAST16 || PRI_MACROS_BROKEN -# undef PRIXFAST16 -# define PRIXFAST16 "X" -#endif -#if !defined PRIdFAST32 || PRI_MACROS_BROKEN -# undef PRIdFAST32 -# define PRIdFAST32 "d" -#endif -#if !defined PRIiFAST32 || PRI_MACROS_BROKEN -# undef PRIiFAST32 -# define PRIiFAST32 "i" -#endif -#if !defined PRIoFAST32 || PRI_MACROS_BROKEN -# undef PRIoFAST32 -# define PRIoFAST32 "o" -#endif -#if !defined PRIuFAST32 || PRI_MACROS_BROKEN -# undef PRIuFAST32 -# define PRIuFAST32 "u" -#endif -#if !defined PRIxFAST32 || PRI_MACROS_BROKEN -# undef PRIxFAST32 -# define PRIxFAST32 "x" -#endif -#if !defined PRIXFAST32 || PRI_MACROS_BROKEN -# undef PRIXFAST32 -# define PRIXFAST32 "X" -#endif -#if !defined PRIdFAST64 || PRI_MACROS_BROKEN -# undef PRIdFAST64 -# define PRIdFAST64 PRId64 -#endif -#if !defined PRIiFAST64 || PRI_MACROS_BROKEN -# undef PRIiFAST64 -# define PRIiFAST64 PRIi64 -#endif -#if !defined PRIoFAST64 || PRI_MACROS_BROKEN -# undef PRIoFAST64 -# define PRIoFAST64 PRIo64 -#endif -#if !defined PRIuFAST64 || PRI_MACROS_BROKEN -# undef PRIuFAST64 -# define PRIuFAST64 PRIu64 -#endif -#if !defined PRIxFAST64 || PRI_MACROS_BROKEN -# undef PRIxFAST64 -# define PRIxFAST64 PRIx64 -#endif -#if !defined PRIXFAST64 || PRI_MACROS_BROKEN -# undef PRIXFAST64 -# define PRIXFAST64 PRIX64 -#endif -#if !defined PRIdMAX || PRI_MACROS_BROKEN -# undef PRIdMAX -# define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld") -#endif -#if !defined PRIiMAX || PRI_MACROS_BROKEN -# undef PRIiMAX -# define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli") -#endif -#if !defined PRIoMAX || PRI_MACROS_BROKEN -# undef PRIoMAX -# define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo") -#endif -#if !defined PRIuMAX || PRI_MACROS_BROKEN -# undef PRIuMAX -# define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu") -#endif -#if !defined PRIxMAX || PRI_MACROS_BROKEN -# undef PRIxMAX -# define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx") -#endif -#if !defined PRIXMAX || PRI_MACROS_BROKEN -# undef PRIXMAX -# define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX") -#endif -#if !defined PRIdPTR || PRI_MACROS_BROKEN -# undef PRIdPTR -# define PRIdPTR \ - (sizeof (void *) == sizeof (long) ? "ld" : \ - sizeof (void *) == sizeof (int) ? "d" : \ - "lld") -#endif -#if !defined PRIiPTR || PRI_MACROS_BROKEN -# undef PRIiPTR -# define PRIiPTR \ - (sizeof (void *) == sizeof (long) ? "li" : \ - sizeof (void *) == sizeof (int) ? "i" : \ - "lli") -#endif -#if !defined PRIoPTR || PRI_MACROS_BROKEN -# undef PRIoPTR -# define PRIoPTR \ - (sizeof (void *) == sizeof (long) ? "lo" : \ - sizeof (void *) == sizeof (int) ? "o" : \ - "llo") -#endif -#if !defined PRIuPTR || PRI_MACROS_BROKEN -# undef PRIuPTR -# define PRIuPTR \ - (sizeof (void *) == sizeof (long) ? "lu" : \ - sizeof (void *) == sizeof (int) ? "u" : \ - "llu") -#endif -#if !defined PRIxPTR || PRI_MACROS_BROKEN -# undef PRIxPTR -# define PRIxPTR \ - (sizeof (void *) == sizeof (long) ? "lx" : \ - sizeof (void *) == sizeof (int) ? "x" : \ - "llx") -#endif -#if !defined PRIXPTR || PRI_MACROS_BROKEN -# undef PRIXPTR -# define PRIXPTR \ - (sizeof (void *) == sizeof (long) ? "lX" : \ - sizeof (void *) == sizeof (int) ? "X" : \ - "llX") -#endif - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ISO C functions. This is required by the standard - because some ISO C functions will require linking with this object - file and the name space must not be polluted. */ -# define open __open -# define close __close -# define read __read -# define mmap __mmap -# define munmap __munmap -#endif - -/* For those losing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -# define freea(p) /* nothing */ -#else -# define alloca(n) malloc (n) -# define freea(p) free (p) -#endif - -/* For systems that distinguish between text and binary I/O. - O_BINARY is usually declared in . */ -#if !defined O_BINARY && defined _O_BINARY - /* For MSC-compatible compilers. */ -# define O_BINARY _O_BINARY -# define O_TEXT _O_TEXT -#endif -#ifdef __BEOS__ - /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ -# undef O_BINARY -# undef O_TEXT -#endif -/* On reasonable systems, binary I/O is the default. */ -#ifndef O_BINARY -# define O_BINARY 0 -#endif - - -/* Prototypes for local functions. Needed to ensure compiler checking of - function argument counts despite of K&R C function definition syntax. */ -static const char *get_sysdep_segment_value PARAMS ((const char *name)); - - -/* We need a sign, whether a new catalog was loaded, which can be associated - with all translations. This is important if the translations are - cached by one of GCC's features. */ -int _nl_msg_cat_cntr; - - -/* Expand a system dependent string segment. Return NULL if unsupported. */ -static const char * -get_sysdep_segment_value (name) - const char *name; -{ - /* Test for an ISO C 99 section 7.8.1 format string directive. - Syntax: - P R I { d | i | o | u | x | X } - { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */ - /* We don't use a table of 14 times 6 'const char *' strings here, because - data relocations cost startup time. */ - if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I') - { - if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u' - || name[3] == 'x' || name[3] == 'X') - { - if (name[4] == '8' && name[5] == '\0') - { - if (name[3] == 'd') - return PRId8; - if (name[3] == 'i') - return PRIi8; - if (name[3] == 'o') - return PRIo8; - if (name[3] == 'u') - return PRIu8; - if (name[3] == 'x') - return PRIx8; - if (name[3] == 'X') - return PRIX8; - abort (); - } - if (name[4] == '1' && name[5] == '6' && name[6] == '\0') - { - if (name[3] == 'd') - return PRId16; - if (name[3] == 'i') - return PRIi16; - if (name[3] == 'o') - return PRIo16; - if (name[3] == 'u') - return PRIu16; - if (name[3] == 'x') - return PRIx16; - if (name[3] == 'X') - return PRIX16; - abort (); - } - if (name[4] == '3' && name[5] == '2' && name[6] == '\0') - { - if (name[3] == 'd') - return PRId32; - if (name[3] == 'i') - return PRIi32; - if (name[3] == 'o') - return PRIo32; - if (name[3] == 'u') - return PRIu32; - if (name[3] == 'x') - return PRIx32; - if (name[3] == 'X') - return PRIX32; - abort (); - } - if (name[4] == '6' && name[5] == '4' && name[6] == '\0') - { - if (name[3] == 'd') - return PRId64; - if (name[3] == 'i') - return PRIi64; - if (name[3] == 'o') - return PRIo64; - if (name[3] == 'u') - return PRIu64; - if (name[3] == 'x') - return PRIx64; - if (name[3] == 'X') - return PRIX64; - abort (); - } - if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A' - && name[7] == 'S' && name[8] == 'T') - { - if (name[9] == '8' && name[10] == '\0') - { - if (name[3] == 'd') - return PRIdLEAST8; - if (name[3] == 'i') - return PRIiLEAST8; - if (name[3] == 'o') - return PRIoLEAST8; - if (name[3] == 'u') - return PRIuLEAST8; - if (name[3] == 'x') - return PRIxLEAST8; - if (name[3] == 'X') - return PRIXLEAST8; - abort (); - } - if (name[9] == '1' && name[10] == '6' && name[11] == '\0') - { - if (name[3] == 'd') - return PRIdLEAST16; - if (name[3] == 'i') - return PRIiLEAST16; - if (name[3] == 'o') - return PRIoLEAST16; - if (name[3] == 'u') - return PRIuLEAST16; - if (name[3] == 'x') - return PRIxLEAST16; - if (name[3] == 'X') - return PRIXLEAST16; - abort (); - } - if (name[9] == '3' && name[10] == '2' && name[11] == '\0') - { - if (name[3] == 'd') - return PRIdLEAST32; - if (name[3] == 'i') - return PRIiLEAST32; - if (name[3] == 'o') - return PRIoLEAST32; - if (name[3] == 'u') - return PRIuLEAST32; - if (name[3] == 'x') - return PRIxLEAST32; - if (name[3] == 'X') - return PRIXLEAST32; - abort (); - } - if (name[9] == '6' && name[10] == '4' && name[11] == '\0') - { - if (name[3] == 'd') - return PRIdLEAST64; - if (name[3] == 'i') - return PRIiLEAST64; - if (name[3] == 'o') - return PRIoLEAST64; - if (name[3] == 'u') - return PRIuLEAST64; - if (name[3] == 'x') - return PRIxLEAST64; - if (name[3] == 'X') - return PRIXLEAST64; - abort (); - } - } - if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S' - && name[7] == 'T') - { - if (name[8] == '8' && name[9] == '\0') - { - if (name[3] == 'd') - return PRIdFAST8; - if (name[3] == 'i') - return PRIiFAST8; - if (name[3] == 'o') - return PRIoFAST8; - if (name[3] == 'u') - return PRIuFAST8; - if (name[3] == 'x') - return PRIxFAST8; - if (name[3] == 'X') - return PRIXFAST8; - abort (); - } - if (name[8] == '1' && name[9] == '6' && name[10] == '\0') - { - if (name[3] == 'd') - return PRIdFAST16; - if (name[3] == 'i') - return PRIiFAST16; - if (name[3] == 'o') - return PRIoFAST16; - if (name[3] == 'u') - return PRIuFAST16; - if (name[3] == 'x') - return PRIxFAST16; - if (name[3] == 'X') - return PRIXFAST16; - abort (); - } - if (name[8] == '3' && name[9] == '2' && name[10] == '\0') - { - if (name[3] == 'd') - return PRIdFAST32; - if (name[3] == 'i') - return PRIiFAST32; - if (name[3] == 'o') - return PRIoFAST32; - if (name[3] == 'u') - return PRIuFAST32; - if (name[3] == 'x') - return PRIxFAST32; - if (name[3] == 'X') - return PRIXFAST32; - abort (); - } - if (name[8] == '6' && name[9] == '4' && name[10] == '\0') - { - if (name[3] == 'd') - return PRIdFAST64; - if (name[3] == 'i') - return PRIiFAST64; - if (name[3] == 'o') - return PRIoFAST64; - if (name[3] == 'u') - return PRIuFAST64; - if (name[3] == 'x') - return PRIxFAST64; - if (name[3] == 'X') - return PRIXFAST64; - abort (); - } - } - if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X' - && name[7] == '\0') - { - if (name[3] == 'd') - return PRIdMAX; - if (name[3] == 'i') - return PRIiMAX; - if (name[3] == 'o') - return PRIoMAX; - if (name[3] == 'u') - return PRIuMAX; - if (name[3] == 'x') - return PRIxMAX; - if (name[3] == 'X') - return PRIXMAX; - abort (); - } - if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R' - && name[7] == '\0') - { - if (name[3] == 'd') - return PRIdPTR; - if (name[3] == 'i') - return PRIiPTR; - if (name[3] == 'o') - return PRIoPTR; - if (name[3] == 'u') - return PRIuPTR; - if (name[3] == 'x') - return PRIxPTR; - if (name[3] == 'X') - return PRIXPTR; - abort (); - } - } - } - /* Other system dependent strings are not valid. */ - return NULL; -} - -/* Initialize the codeset dependent parts of an opened message catalog. - Return the header entry. */ -const char * -internal_function -_nl_init_domain_conv (domain_file, domain, domainbinding) - struct loaded_l10nfile *domain_file; - struct loaded_domain *domain; - struct binding *domainbinding; -{ - /* Find out about the character set the file is encoded with. - This can be found (in textual form) in the entry "". If this - entry does not exist or if this does not contain the `charset=' - information, we will assume the charset matches the one the - current locale and we don't have to perform any conversion. */ - char *nullentry; - size_t nullentrylen; - - /* Preinitialize fields, to avoid recursion during _nl_find_msg. */ - domain->codeset_cntr = - (domainbinding != NULL ? domainbinding->codeset_cntr : 0); -#ifdef _LIBC - domain->conv = (__gconv_t) -1; -#else -# if HAVE_ICONV - domain->conv = (iconv_t) -1; -# endif -#endif - domain->conv_tab = NULL; - - /* Get the header entry. */ - nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen); - - if (nullentry != NULL) - { -#if defined _LIBC || HAVE_ICONV - const char *charsetstr; - - charsetstr = strstr (nullentry, "charset="); - if (charsetstr != NULL) - { - size_t len; - char *charset; - const char *outcharset; - - charsetstr += strlen ("charset="); - len = strcspn (charsetstr, " \t\n"); - - charset = (char *) alloca (len + 1); -# if defined _LIBC || HAVE_MEMPCPY - *((char *) mempcpy (charset, charsetstr, len)) = '\0'; -# else - memcpy (charset, charsetstr, len); - charset[len] = '\0'; -# endif - - /* The output charset should normally be determined by the - locale. But sometimes the locale is not used or not correctly - set up, so we provide a possibility for the user to override - this. Moreover, the value specified through - bind_textdomain_codeset overrides both. */ - if (domainbinding != NULL && domainbinding->codeset != NULL) - outcharset = domainbinding->codeset; - else - { - outcharset = getenv ("OUTPUT_CHARSET"); - if (outcharset == NULL || outcharset[0] == '\0') - { -# ifdef _LIBC - outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string; -# else -# if HAVE_ICONV - extern const char *locale_charset PARAMS ((void)); - outcharset = locale_charset (); -# endif -# endif - } - } - -# ifdef _LIBC - /* We always want to use transliteration. */ - outcharset = norm_add_slashes (outcharset, "TRANSLIT"); - charset = norm_add_slashes (charset, NULL); - if (__gconv_open (outcharset, charset, &domain->conv, - GCONV_AVOID_NOCONV) - != __GCONV_OK) - domain->conv = (__gconv_t) -1; -# else -# if HAVE_ICONV - /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, - we want to use transliteration. */ -# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ - || _LIBICONV_VERSION >= 0x0105 - if (strchr (outcharset, '/') == NULL) - { - char *tmp; - - len = strlen (outcharset); - tmp = (char *) alloca (len + 10 + 1); - memcpy (tmp, outcharset, len); - memcpy (tmp + len, "//TRANSLIT", 10 + 1); - outcharset = tmp; - - domain->conv = iconv_open (outcharset, charset); - - freea (outcharset); - } - else -# endif - domain->conv = iconv_open (outcharset, charset); -# endif -# endif - - freea (charset); - } -#endif /* _LIBC || HAVE_ICONV */ - } - - return nullentry; -} - -/* Frees the codeset dependent parts of an opened message catalog. */ -void -internal_function -_nl_free_domain_conv (domain) - struct loaded_domain *domain; -{ - if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) - free (domain->conv_tab); - -#ifdef _LIBC - if (domain->conv != (__gconv_t) -1) - __gconv_close (domain->conv); -#else -# if HAVE_ICONV - if (domain->conv != (iconv_t) -1) - iconv_close (domain->conv); -# endif -#endif -} - -/* Load the message catalogs specified by FILENAME. If it is no valid - message catalog do nothing. */ -void -internal_function -_nl_load_domain (domain_file, domainbinding) - struct loaded_l10nfile *domain_file; - struct binding *domainbinding; -{ - int fd; - size_t size; -#ifdef _LIBC - struct stat64 st; -#else - struct stat st; -#endif - struct mo_file_header *data = (struct mo_file_header *) -1; - int use_mmap = 0; - struct loaded_domain *domain; - int revision; - const char *nullentry; - - domain_file->decided = 1; - domain_file->data = NULL; - - /* Note that it would be useless to store domainbinding in domain_file - because domainbinding might be == NULL now but != NULL later (after - a call to bind_textdomain_codeset). */ - - /* If the record does not represent a valid locale the FILENAME - might be NULL. This can happen when according to the given - specification the locale file name is different for XPG and CEN - syntax. */ - if (domain_file->filename == NULL) - return; - - /* Try to open the addressed file. */ - fd = open (domain_file->filename, O_RDONLY | O_BINARY); - if (fd == -1) - return; - - /* We must know about the size of the file. */ - if ( -#ifdef _LIBC - __builtin_expect (fstat64 (fd, &st) != 0, 0) -#else - __builtin_expect (fstat (fd, &st) != 0, 0) -#endif - || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0) - || __builtin_expect (size < sizeof (struct mo_file_header), 0)) - { - /* Something went wrong. */ - close (fd); - return; - } - -#ifdef HAVE_MMAP - /* Now we are ready to load the file. If mmap() is available we try - this first. If not available or it failed we try to load it. */ - data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, - MAP_PRIVATE, fd, 0); - - if (__builtin_expect (data != (struct mo_file_header *) -1, 1)) - { - /* mmap() call was successful. */ - close (fd); - use_mmap = 1; - } -#endif - - /* If the data is not yet available (i.e. mmap'ed) we try to load - it manually. */ - if (data == (struct mo_file_header *) -1) - { - size_t to_read; - char *read_ptr; - - data = (struct mo_file_header *) malloc (size); - if (data == NULL) - return; - - to_read = size; - read_ptr = (char *) data; - do - { - long int nb = (long int) read (fd, read_ptr, to_read); - if (nb <= 0) - { -#ifdef EINTR - if (nb == -1 && errno == EINTR) - continue; -#endif - close (fd); - return; - } - read_ptr += nb; - to_read -= nb; - } - while (to_read > 0); - - close (fd); - } - - /* Using the magic number we can test whether it really is a message - catalog file. */ - if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED, - 0)) - { - /* The magic number is wrong: not a message catalog file. */ -#ifdef HAVE_MMAP - if (use_mmap) - munmap ((caddr_t) data, size); - else -#endif - free (data); - return; - } - - domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); - if (domain == NULL) - return; - domain_file->data = domain; - - domain->data = (char *) data; - domain->use_mmap = use_mmap; - domain->mmap_size = size; - domain->must_swap = data->magic != _MAGIC; - domain->malloced = NULL; - - /* Fill in the information about the available tables. */ - revision = W (domain->must_swap, data->revision); - /* We support only the major revision 0. */ - switch (revision >> 16) - { - case 0: - domain->nstrings = W (domain->must_swap, data->nstrings); - domain->orig_tab = (const struct string_desc *) - ((char *) data + W (domain->must_swap, data->orig_tab_offset)); - domain->trans_tab = (const struct string_desc *) - ((char *) data + W (domain->must_swap, data->trans_tab_offset)); - domain->hash_size = W (domain->must_swap, data->hash_tab_size); - domain->hash_tab = - (domain->hash_size > 2 - ? (const nls_uint32 *) - ((char *) data + W (domain->must_swap, data->hash_tab_offset)) - : NULL); - domain->must_swap_hash_tab = domain->must_swap; - - /* Now dispatch on the minor revision. */ - switch (revision & 0xffff) - { - case 0: - domain->n_sysdep_strings = 0; - domain->orig_sysdep_tab = NULL; - domain->trans_sysdep_tab = NULL; - break; - case 1: - default: - { - nls_uint32 n_sysdep_strings; - - if (domain->hash_tab == NULL) - /* This is invalid. These minor revisions need a hash table. */ - goto invalid; - - n_sysdep_strings = - W (domain->must_swap, data->n_sysdep_strings); - if (n_sysdep_strings > 0) - { - nls_uint32 n_sysdep_segments; - const struct sysdep_segment *sysdep_segments; - const char **sysdep_segment_values; - const nls_uint32 *orig_sysdep_tab; - const nls_uint32 *trans_sysdep_tab; - size_t memneed; - char *mem; - struct sysdep_string_desc *inmem_orig_sysdep_tab; - struct sysdep_string_desc *inmem_trans_sysdep_tab; - nls_uint32 *inmem_hash_tab; - unsigned int i; - - /* Get the values of the system dependent segments. */ - n_sysdep_segments = - W (domain->must_swap, data->n_sysdep_segments); - sysdep_segments = (const struct sysdep_segment *) - ((char *) data - + W (domain->must_swap, data->sysdep_segments_offset)); - sysdep_segment_values = - alloca (n_sysdep_segments * sizeof (const char *)); - for (i = 0; i < n_sysdep_segments; i++) - { - const char *name = - (char *) data - + W (domain->must_swap, sysdep_segments[i].offset); - nls_uint32 namelen = - W (domain->must_swap, sysdep_segments[i].length); - - if (!(namelen > 0 && name[namelen - 1] == '\0')) - { - freea (sysdep_segment_values); - goto invalid; - } - - sysdep_segment_values[i] = get_sysdep_segment_value (name); - } - - orig_sysdep_tab = (const nls_uint32 *) - ((char *) data - + W (domain->must_swap, data->orig_sysdep_tab_offset)); - trans_sysdep_tab = (const nls_uint32 *) - ((char *) data - + W (domain->must_swap, data->trans_sysdep_tab_offset)); - - /* Compute the amount of additional memory needed for the - system dependent strings and the augmented hash table. */ - memneed = 2 * n_sysdep_strings - * sizeof (struct sysdep_string_desc) - + domain->hash_size * sizeof (nls_uint32); - for (i = 0; i < 2 * n_sysdep_strings; i++) - { - const struct sysdep_string *sysdep_string = - (const struct sysdep_string *) - ((char *) data - + W (domain->must_swap, - i < n_sysdep_strings - ? orig_sysdep_tab[i] - : trans_sysdep_tab[i - n_sysdep_strings])); - size_t need = 0; - const struct segment_pair *p = sysdep_string->segments; - - if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END) - for (p = sysdep_string->segments;; p++) - { - nls_uint32 sysdepref; - - need += W (domain->must_swap, p->segsize); - - sysdepref = W (domain->must_swap, p->sysdepref); - if (sysdepref == SEGMENTS_END) - break; - - if (sysdepref >= n_sysdep_segments) - { - /* Invalid. */ - freea (sysdep_segment_values); - goto invalid; - } - - need += strlen (sysdep_segment_values[sysdepref]); - } - - memneed += need; - } - - /* Allocate additional memory. */ - mem = (char *) malloc (memneed); - if (mem == NULL) - goto invalid; - - domain->malloced = mem; - inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem; - mem += n_sysdep_strings * sizeof (struct sysdep_string_desc); - inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem; - mem += n_sysdep_strings * sizeof (struct sysdep_string_desc); - inmem_hash_tab = (nls_uint32 *) mem; - mem += domain->hash_size * sizeof (nls_uint32); - - /* Compute the system dependent strings. */ - for (i = 0; i < 2 * n_sysdep_strings; i++) - { - const struct sysdep_string *sysdep_string = - (const struct sysdep_string *) - ((char *) data - + W (domain->must_swap, - i < n_sysdep_strings - ? orig_sysdep_tab[i] - : trans_sysdep_tab[i - n_sysdep_strings])); - const char *static_segments = - (char *) data - + W (domain->must_swap, sysdep_string->offset); - const struct segment_pair *p = sysdep_string->segments; - - /* Concatenate the segments, and fill - inmem_orig_sysdep_tab[i] (for i < n_sysdep_strings) and - inmem_trans_sysdep_tab[i-n_sysdep_strings] (for - i >= n_sysdep_strings). */ - - if (W (domain->must_swap, p->sysdepref) == SEGMENTS_END) - { - /* Only one static segment. */ - inmem_orig_sysdep_tab[i].length = - W (domain->must_swap, p->segsize); - inmem_orig_sysdep_tab[i].pointer = static_segments; - } - else - { - inmem_orig_sysdep_tab[i].pointer = mem; - - for (p = sysdep_string->segments;; p++) - { - nls_uint32 segsize = - W (domain->must_swap, p->segsize); - nls_uint32 sysdepref = - W (domain->must_swap, p->sysdepref); - size_t n; - - if (segsize > 0) - { - memcpy (mem, static_segments, segsize); - mem += segsize; - static_segments += segsize; - } - - if (sysdepref == SEGMENTS_END) - break; - - n = strlen (sysdep_segment_values[sysdepref]); - memcpy (mem, sysdep_segment_values[sysdepref], n); - mem += n; - } - - inmem_orig_sysdep_tab[i].length = - mem - inmem_orig_sysdep_tab[i].pointer; - } - } - - /* Compute the augmented hash table. */ - for (i = 0; i < domain->hash_size; i++) - inmem_hash_tab[i] = - W (domain->must_swap_hash_tab, domain->hash_tab[i]); - for (i = 0; i < n_sysdep_strings; i++) - { - const char *msgid = inmem_orig_sysdep_tab[i].pointer; - nls_uint32 hash_val = hash_string (msgid); - nls_uint32 idx = hash_val % domain->hash_size; - nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); - - for (;;) - { - if (inmem_hash_tab[idx] == 0) - { - /* Hash table entry is empty. Use it. */ - inmem_hash_tab[idx] = 1 + domain->nstrings + i; - break; - } - - if (idx >= domain->hash_size - incr) - idx -= domain->hash_size - incr; - else - idx += incr; - } - } - - freea (sysdep_segment_values); - - domain->n_sysdep_strings = n_sysdep_strings; - domain->orig_sysdep_tab = inmem_orig_sysdep_tab; - domain->trans_sysdep_tab = inmem_trans_sysdep_tab; - - domain->hash_tab = inmem_hash_tab; - domain->must_swap_hash_tab = 0; - } - else - { - domain->n_sysdep_strings = 0; - domain->orig_sysdep_tab = NULL; - domain->trans_sysdep_tab = NULL; - } - } - break; - } - break; - default: - /* This is an invalid revision. */ - invalid: - /* This is an invalid .mo file. */ - if (domain->malloced) - free (domain->malloced); -#ifdef HAVE_MMAP - if (use_mmap) - munmap ((caddr_t) data, size); - else -#endif - free (data); - free (domain); - domain_file->data = NULL; - return; - } - - /* Now initialize the character set converter from the character set - the file is encoded with (found in the header entry) to the domain's - specified character set or the locale's character set. */ - nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); - - /* Also look for a plural specification. */ - EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); -} - - -#ifdef _LIBC -void -internal_function -_nl_unload_domain (domain) - struct loaded_domain *domain; -{ - if (domain->plural != &__gettext_germanic_plural) - __gettext_free_exp (domain->plural); - - _nl_free_domain_conv (domain); - - if (domain->malloced) - free (domain->malloced); - -# ifdef _POSIX_MAPPED_FILES - if (domain->use_mmap) - munmap ((caddr_t) domain->data, domain->mmap_size); - else -# endif /* _POSIX_MAPPED_FILES */ - free ((void *) domain->data); - - free (domain); -} -#endif diff --git a/intl/localealias.c b/intl/localealias.c deleted file mode 100644 index 456e41e37..000000000 --- a/intl/localealias.c +++ /dev/null @@ -1,419 +0,0 @@ -/* Handle aliases for locale names. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -/* Tell glibc's to provide a prototype for mempcpy(). - This must come before because may include - , and once has been included, it's too late. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#if defined _LIBC || defined HAVE___FSETLOCKING -# include -#endif -#include - -#ifdef __GNUC__ -# define alloca __builtin_alloca -# define HAVE_ALLOCA 1 -#else -# if defined HAVE_ALLOCA_H || defined _LIBC -# include -# else -# ifdef _AIX - #pragma alloca -# else -# ifndef alloca -char *alloca (); -# endif -# endif -# endif -#endif - -#include -#include - -#include "gettextP.h" - -/* @@ end of prolog @@ */ - -#ifdef _LIBC -/* Rename the non ANSI C functions. This is required by the standard - because some ANSI C functions will require linking with this object - file and the name space must not be polluted. */ -# define strcasecmp __strcasecmp - -# ifndef mempcpy -# define mempcpy __mempcpy -# endif -# define HAVE_MEMPCPY 1 -# define HAVE___FSETLOCKING 1 - -/* We need locking here since we can be called from different places. */ -# include - -__libc_lock_define_initialized (static, lock); -#endif - -#ifndef internal_function -# define internal_function -#endif - -/* Some optimizations for glibc. */ -#ifdef _LIBC -# define FEOF(fp) feof_unlocked (fp) -# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp) -#else -# define FEOF(fp) feof (fp) -# define FGETS(buf, n, fp) fgets (buf, n, fp) -#endif - -/* For those losing systems which don't have `alloca' we have to add - some additional code emulating it. */ -#ifdef HAVE_ALLOCA -# define freea(p) /* nothing */ -#else -# define alloca(n) malloc (n) -# define freea(p) free (p) -#endif - -#if defined _LIBC_REENTRANT || defined HAVE_FGETS_UNLOCKED -# undef fgets -# define fgets(buf, len, s) fgets_unlocked (buf, len, s) -#endif -#if defined _LIBC_REENTRANT || defined HAVE_FEOF_UNLOCKED -# undef feof -# define feof(s) feof_unlocked (s) -#endif - - -struct alias_map -{ - const char *alias; - const char *value; -}; - - -static char *string_space; -static size_t string_space_act; -static size_t string_space_max; -static struct alias_map *map; -static size_t nmap; -static size_t maxmap; - - -/* Prototypes for local functions. */ -static size_t read_alias_file PARAMS ((const char *fname, int fname_len)) - internal_function; -static int extend_alias_table PARAMS ((void)); -static int alias_compare PARAMS ((const struct alias_map *map1, - const struct alias_map *map2)); - - -const char * -_nl_expand_alias (name) - const char *name; -{ - static const char *locale_alias_path; - struct alias_map *retval; - const char *result = NULL; - size_t added; - -#ifdef _LIBC - __libc_lock_lock (lock); -#endif - - if (locale_alias_path == NULL) - locale_alias_path = LOCALE_ALIAS_PATH; - - do - { - struct alias_map item; - - item.alias = name; - - if (nmap > 0) - retval = (struct alias_map *) bsearch (&item, map, nmap, - sizeof (struct alias_map), - (int (*) PARAMS ((const void *, - const void *)) - ) alias_compare); - else - retval = NULL; - - /* We really found an alias. Return the value. */ - if (retval != NULL) - { - result = retval->value; - break; - } - - /* Perhaps we can find another alias file. */ - added = 0; - while (added == 0 && locale_alias_path[0] != '\0') - { - const char *start; - - while (locale_alias_path[0] == PATH_SEPARATOR) - ++locale_alias_path; - start = locale_alias_path; - - while (locale_alias_path[0] != '\0' - && locale_alias_path[0] != PATH_SEPARATOR) - ++locale_alias_path; - - if (start < locale_alias_path) - added = read_alias_file (start, locale_alias_path - start); - } - } - while (added != 0); - -#ifdef _LIBC - __libc_lock_unlock (lock); -#endif - - return result; -} - - -static size_t -internal_function -read_alias_file (fname, fname_len) - const char *fname; - int fname_len; -{ - FILE *fp; - char *full_fname; - size_t added; - static const char aliasfile[] = "/locale.alias"; - - full_fname = (char *) alloca (fname_len + sizeof aliasfile); -#ifdef HAVE_MEMPCPY - mempcpy (mempcpy (full_fname, fname, fname_len), - aliasfile, sizeof aliasfile); -#else - memcpy (full_fname, fname, fname_len); - memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile); -#endif - - fp = fopen (full_fname, "r"); - freea (full_fname); - if (fp == NULL) - return 0; - -#ifdef HAVE___FSETLOCKING - /* No threads present. */ - __fsetlocking (fp, FSETLOCKING_BYCALLER); -#endif - - added = 0; - while (!FEOF (fp)) - { - /* It is a reasonable approach to use a fix buffer here because - a) we are only interested in the first two fields - b) these fields must be usable as file names and so must not - be that long - */ - char buf[BUFSIZ]; - char *alias; - char *value; - char *cp; - - if (FGETS (buf, sizeof buf, fp) == NULL) - /* EOF reached. */ - break; - - /* Possibly not the whole line fits into the buffer. Ignore - the rest of the line. */ - if (strchr (buf, '\n') == NULL) - { - char altbuf[BUFSIZ]; - do - if (FGETS (altbuf, sizeof altbuf, fp) == NULL) - /* Make sure the inner loop will be left. The outer loop - will exit at the `feof' test. */ - break; - while (strchr (altbuf, '\n') == NULL); - } - - cp = buf; - /* Ignore leading white space. */ - while (isspace ((unsigned char) cp[0])) - ++cp; - - /* A leading '#' signals a comment line. */ - if (cp[0] != '\0' && cp[0] != '#') - { - alias = cp++; - while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) - ++cp; - /* Terminate alias name. */ - if (cp[0] != '\0') - *cp++ = '\0'; - - /* Now look for the beginning of the value. */ - while (isspace ((unsigned char) cp[0])) - ++cp; - - if (cp[0] != '\0') - { - size_t alias_len; - size_t value_len; - - value = cp++; - while (cp[0] != '\0' && !isspace ((unsigned char) cp[0])) - ++cp; - /* Terminate value. */ - if (cp[0] == '\n') - { - /* This has to be done to make the following test - for the end of line possible. We are looking for - the terminating '\n' which do not overwrite here. */ - *cp++ = '\0'; - *cp = '\n'; - } - else if (cp[0] != '\0') - *cp++ = '\0'; - - if (nmap >= maxmap) - if (__builtin_expect (extend_alias_table (), 0)) - return added; - - alias_len = strlen (alias) + 1; - value_len = strlen (value) + 1; - - if (string_space_act + alias_len + value_len > string_space_max) - { - /* Increase size of memory pool. */ - size_t new_size = (string_space_max - + (alias_len + value_len > 1024 - ? alias_len + value_len : 1024)); - char *new_pool = (char *) realloc (string_space, new_size); - if (new_pool == NULL) - return added; - - if (__builtin_expect (string_space != new_pool, 0)) - { - size_t i; - - for (i = 0; i < nmap; i++) - { - map[i].alias += new_pool - string_space; - map[i].value += new_pool - string_space; - } - } - - string_space = new_pool; - string_space_max = new_size; - } - - map[nmap].alias = memcpy (&string_space[string_space_act], - alias, alias_len); - string_space_act += alias_len; - - map[nmap].value = memcpy (&string_space[string_space_act], - value, value_len); - string_space_act += value_len; - - ++nmap; - ++added; - } - } - } - - /* Should we test for ferror()? I think we have to silently ignore - errors. --drepper */ - fclose (fp); - - if (added > 0) - qsort (map, nmap, sizeof (struct alias_map), - (int (*) PARAMS ((const void *, const void *))) alias_compare); - - return added; -} - - -static int -extend_alias_table () -{ - size_t new_size; - struct alias_map *new_map; - - new_size = maxmap == 0 ? 100 : 2 * maxmap; - new_map = (struct alias_map *) realloc (map, (new_size - * sizeof (struct alias_map))); - if (new_map == NULL) - /* Simply don't extend: we don't have any more core. */ - return -1; - - map = new_map; - maxmap = new_size; - return 0; -} - - -#ifdef _LIBC -static void __attribute__ ((unused)) -free_mem (void) -{ - if (string_space != NULL) - free (string_space); - if (map != NULL) - free (map); -} -text_set_element (__libc_subfreeres, free_mem); -#endif - - -static int -alias_compare (map1, map2) - const struct alias_map *map1; - const struct alias_map *map2; -{ -#if defined _LIBC || defined HAVE_STRCASECMP - return strcasecmp (map1->alias, map2->alias); -#else - const unsigned char *p1 = (const unsigned char *) map1->alias; - const unsigned char *p2 = (const unsigned char *) map2->alias; - unsigned char c1, c2; - - if (p1 == p2) - return 0; - - do - { - /* I know this seems to be odd but the tolower() function in - some systems libc cannot handle nonalpha characters. */ - c1 = isupper (*p1) ? tolower (*p1) : *p1; - c2 = isupper (*p2) ? tolower (*p2) : *p2; - if (c1 == '\0') - break; - ++p1; - ++p2; - } - while (c1 == c2); - - return c1 - c2; -#endif -} diff --git a/intl/po2tbl.sed.in b/intl/po2tbl.sed.in deleted file mode 100644 index b3bcca4d7..000000000 --- a/intl/po2tbl.sed.in +++ /dev/null @@ -1,102 +0,0 @@ -# po2tbl.sed - Convert Uniforum style .po file to lookup table for catgets -# Copyright (C) 1995 Free Software Foundation, Inc. -# Ulrich Drepper , 1995. -# -# 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, 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. -# -1 { - i\ -/* Automatically generated by po2tbl.sed from @PACKAGE NAME@.pot. */\ -\ -#if HAVE_CONFIG_H\ -# include \ -#endif\ -\ -#include "libgettext.h"\ -\ -const struct _msg_ent _msg_tbl[] = { - h - s/.*/0/ - x -} -# -# Write msgid entries in C array form. -# -/^msgid/ { - s/msgid[ ]*\(".*"\)/ {\1/ - tb -# Append the next line - :b - N -# Look whether second part is continuation line. - s/\(.*\)"\(\n\)"\(.*"\)/\1\2\3/ -# Yes, then branch. - ta -# Because we assume that the input file correctly formed the line -# just read cannot be again be a msgid line. So it's safe to ignore -# it. - s/\(.*\)\n.*/\1/ - bc -# We found a continuation line. But before printing insert '\'. - :a - s/\(.*\)\(\n.*\)/\1\\\2/ - P -# We cannot use D here. - s/.*\n\(.*\)/\1/ -# Some buggy seds do not clear the `successful substitution since last ``t''' -# flag on `N', so we do a `t' here to clear it. - tb -# Not reached - :c - x -# The following nice solution is by -# Bruno - td -# Increment a decimal number in pattern space. -# First hide trailing `9' digits. - :d - s/9\(_*\)$/_\1/ - td -# Assure at least one digit is available. - s/^\(_*\)$/0\1/ -# Increment the last digit. - s/8\(_*\)$/9\1/ - s/7\(_*\)$/8\1/ - s/6\(_*\)$/7\1/ - s/5\(_*\)$/6\1/ - s/4\(_*\)$/5\1/ - s/3\(_*\)$/4\1/ - s/2\(_*\)$/3\1/ - s/1\(_*\)$/2\1/ - s/0\(_*\)$/1\1/ -# Convert the hidden `9' digits to `0's. - s/_/0/g - x - G - s/\(.*\)\n\([0-9]*\)/\1, \2},/ - s/\(.*\)"$/\1/ - p -} -# -# Last line. -# -$ { - i\ -};\ - - g - s/0*\(.*\)/int _msg_tbl_length = \1;/p -} -d diff --git a/intl/textdomain.c b/intl/textdomain.c deleted file mode 100644 index f259c696d..000000000 --- a/intl/textdomain.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Implementation of the textdomain(3) function. - Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published - by the Free Software Foundation; either version 2, 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library 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. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#ifdef _LIBC -# include -#else -# include "libgnuintl.h" -#endif -#include "gettextP.h" - -#ifdef _LIBC -/* We have to handle multi-threaded applications. */ -# include -#else -/* Provide dummy implementation if this is outside glibc. */ -# define __libc_rwlock_define(CLASS, NAME) -# define __libc_rwlock_wrlock(NAME) -# define __libc_rwlock_unlock(NAME) -#endif - -/* The internal variables in the standalone libintl.a must have different - names than the internal variables in GNU libc, otherwise programs - using libintl.a cannot be linked statically. */ -#if !defined _LIBC -# define _nl_default_default_domain libintl_nl_default_default_domain -# define _nl_current_default_domain libintl_nl_current_default_domain -#endif - -/* @@ end of prolog @@ */ - -/* Name of the default text domain. */ -extern const char _nl_default_default_domain[] attribute_hidden; - -/* Default text domain in which entries for gettext(3) are to be found. */ -extern const char *_nl_current_default_domain attribute_hidden; - - -/* Names for the libintl functions are a problem. They must not clash - with existing names and they should follow ANSI C. But this source - code is also used in GNU C Library where the names have a __ - prefix. So we have to make a difference here. */ -#ifdef _LIBC -# define TEXTDOMAIN __textdomain -# ifndef strdup -# define strdup(str) __strdup (str) -# endif -#else -# define TEXTDOMAIN libintl_textdomain -#endif - -/* Lock variable to protect the global data in the gettext implementation. */ -__libc_rwlock_define (extern, _nl_state_lock attribute_hidden) - -/* Set the current default message catalog to DOMAINNAME. - If DOMAINNAME is null, return the current default. - If DOMAINNAME is "", reset to the default of "messages". */ -char * -TEXTDOMAIN (domainname) - const char *domainname; -{ - char *new_domain; - char *old_domain; - - /* A NULL pointer requests the current setting. */ - if (domainname == NULL) - return (char *) _nl_current_default_domain; - - __libc_rwlock_wrlock (_nl_state_lock); - - old_domain = (char *) _nl_current_default_domain; - - /* If domain name is the null string set to default domain "messages". */ - if (domainname[0] == '\0' - || strcmp (domainname, _nl_default_default_domain) == 0) - { - _nl_current_default_domain = _nl_default_default_domain; - new_domain = (char *) _nl_current_default_domain; - } - else if (strcmp (domainname, old_domain) == 0) - /* This can happen and people will use it to signal that some - environment variable changed. */ - new_domain = old_domain; - else - { - /* If the following malloc fails `_nl_current_default_domain' - will be NULL. This value will be returned and so signals we - are out of core. */ -#if defined _LIBC || defined HAVE_STRDUP - new_domain = strdup (domainname); -#else - size_t len = strlen (domainname) + 1; - new_domain = (char *) malloc (len); - if (new_domain != NULL) - memcpy (new_domain, domainname, len); -#endif - - if (new_domain != NULL) - _nl_current_default_domain = new_domain; - } - - /* We use this possibility to signal a change of the loaded catalogs - since this is most likely the case and there is no other easy we - to do it. Do it only when the call was successful. */ - if (new_domain != NULL) - { - ++_nl_msg_cat_cntr; - - if (old_domain != new_domain && old_domain != _nl_default_default_domain) - free (old_domain); - } - - __libc_rwlock_unlock (_nl_state_lock); - - return new_domain; -} - -#ifdef _LIBC -/* Alias for function name in GNU C Library. */ -weak_alias (__textdomain, textdomain); -#endif diff --git a/intl/xopen-msg.sed b/intl/xopen-msg.sed deleted file mode 100644 index b19c0bbd0..000000000 --- a/intl/xopen-msg.sed +++ /dev/null @@ -1,104 +0,0 @@ -# po2msg.sed - Convert Uniforum style .po file to X/Open style .msg file -# Copyright (C) 1995 Free Software Foundation, Inc. -# Ulrich Drepper , 1995. -# -# 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, 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. -# -# -# The first directive in the .msg should be the definition of the -# message set number. We use always set number 1. -# -1 { - i\ -$set 1 # Automatically created by po2msg.sed - h - s/.*/0/ - x -} -# -# We copy all comments into the .msg file. Perhaps they can help. -# -/^#/ s/^#[ ]*/$ /p -# -# We copy the original message as a comment into the .msg file. -# -/^msgid/ { -# Does not work now -# /"$/! { -# s/\\$// -# s/$/ ... (more lines following)"/ -# } - s/^msgid[ ]*"\(.*\)"$/$ Original Message: \1/ - p -} -# -# The .msg file contains, other then the .po file, only the translations -# but each given a unique ID. Starting from 1 and incrementing by 1 for -# each message we assign them to the messages. -# It is important that the .po file used to generate the cat-id-tbl.c file -# (with po-to-tbl) is the same as the one used here. (At least the order -# of declarations must not be changed.) -# -/^msgstr/ { - s/msgstr[ ]*"\(.*\)"/\1/ - x -# The following nice solution is by -# Bruno - td -# Increment a decimal number in pattern space. -# First hide trailing `9' digits. - :d - s/9\(_*\)$/_\1/ - td -# Assure at least one digit is available. - s/^\(_*\)$/0\1/ -# Increment the last digit. - s/8\(_*\)$/9\1/ - s/7\(_*\)$/8\1/ - s/6\(_*\)$/7\1/ - s/5\(_*\)$/6\1/ - s/4\(_*\)$/5\1/ - s/3\(_*\)$/4\1/ - s/2\(_*\)$/3\1/ - s/1\(_*\)$/2\1/ - s/0\(_*\)$/1\1/ -# Convert the hidden `9' digits to `0's. - s/_/0/g - x -# Bring the line in the format ` ' - G - s/^[^\n]*$/& / - s/\(.*\)\n\([0-9]*\)/\2 \1/ -# Clear flag from last substitution. - tb -# Append the next line. - :b - N -# Look whether second part is a continuation line. - s/\(.*\n\)"\(.*\)"/\1\2/ -# Yes, then branch. - ta - P - D -# Note that `D' includes a jump to the start!! -# We found a continuation line. But before printing insert '\'. - :a - s/\(.*\)\(\n.*\)/\1\\\2/ - P -# We cannot use the sed command `D' here - s/.*\n\(.*\)/\1/ - tb -} -d diff --git a/java/common/org/linphone/core/LinphoneChatMessage.java b/java/common/org/linphone/core/LinphoneChatMessage.java index aeec09645..0efe5a94d 100644 --- a/java/common/org/linphone/core/LinphoneChatMessage.java +++ b/java/common/org/linphone/core/LinphoneChatMessage.java @@ -225,7 +225,7 @@ public interface LinphoneChatMessage { /** * Start the download of the file referenced in a LinphoneChatMessage from remote server. */ - int downloadFile(); + boolean downloadFile(); /** * Set the callbacks associated with the LinphoneChatMessage. diff --git a/java/common/org/linphone/core/LinphoneCore.java b/java/common/org/linphone/core/LinphoneCore.java index c388aec1c..f92ee8dee 100644 --- a/java/common/org/linphone/core/LinphoneCore.java +++ b/java/common/org/linphone/core/LinphoneCore.java @@ -1107,6 +1107,14 @@ public interface LinphoneCore { */ LinphoneFriendList[] getFriendLists(); + /** + * Get filtered list by filter + * @param filter + * @param sipOnly get only sip address + * @return LinphoneAddress list + */ + LinphoneAddress[] findContactsByChar(String filter, boolean sipOnly); + /** * Set my presence status * @param minutes_away how long in away diff --git a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java index 9ca40a269..a7771766f 100644 --- a/java/impl/org/linphone/core/LinphoneChatMessageImpl.java +++ b/java/impl/org/linphone/core/LinphoneChatMessageImpl.java @@ -16,7 +16,7 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage { private native void store(long ptr); private native int getStorageId(long ptr); private native void setFileTransferFilepath(long ptr, String path); - private native int downloadFile(long ptr); + private native boolean downloadFile(long ptr); private native void setListener(long ptr, LinphoneChatMessageListener listener); private native void unref(long ptr); @@ -146,7 +146,7 @@ public class LinphoneChatMessageImpl implements LinphoneChatMessage { } @Override - public int downloadFile() { + public boolean downloadFile() { return downloadFile(nativePtr); } diff --git a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java index 3023b3305..653d31061 100644 --- a/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreFactoryImpl.java @@ -43,7 +43,7 @@ public class LinphoneCoreFactoryImpl extends LinphoneCoreFactory { } static { - System.loadLibrary("gnustl_shared"); + System.loadLibrary("c++_shared"); loadOptionalLibrary("ffmpeg-linphone"); System.loadLibrary("bctoolbox"); System.loadLibrary("ortp"); diff --git a/java/impl/org/linphone/core/LinphoneCoreImpl.java b/java/impl/org/linphone/core/LinphoneCoreImpl.java index 162663ed1..a980ab7ee 100644 --- a/java/impl/org/linphone/core/LinphoneCoreImpl.java +++ b/java/impl/org/linphone/core/LinphoneCoreImpl.java @@ -196,7 +196,6 @@ class LinphoneCoreImpl implements LinphoneCore { private native Object createFriend(long nativePtr); private native Object createFriendWithAddress(long nativePtr, String address); private native int getIncomingTimeout(long nativePtr); - LinphoneCoreImpl(LinphoneCoreListener listener, File userConfig, File factoryConfig, Object userdata, Object context) throws IOException { mListener = listener; String user = userConfig == null ? null : userConfig.getCanonicalPath(); @@ -500,6 +499,11 @@ class LinphoneCoreImpl implements LinphoneCore { return getFriendLists(nativePtr); } + private native LinphoneAddress[] findContactsByChar(long nativePtr, String filter, boolean sipOnly); + public synchronized LinphoneAddress[] findContactsByChar(String filter, boolean sipOnly) { + return findContactsByChar(nativePtr, filter, sipOnly); + } + @SuppressWarnings("deprecation") public synchronized void setPresenceInfo(int minutes_away, String alternative_contact, OnlineStatus status) { setPresenceInfo(nativePtr, minutes_away, alternative_contact, status.mValue); diff --git a/java/impl/org/linphone/core/util/AndroidPlatformHelper.java b/java/impl/org/linphone/core/util/AndroidPlatformHelper.java deleted file mode 100644 index d5fe34f68..000000000 --- a/java/impl/org/linphone/core/util/AndroidPlatformHelper.java +++ /dev/null @@ -1,114 +0,0 @@ -/* -AndroidPlatformHelper.java -Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ - - -package org.linphone.core.util; - -import org.linphone.mediastream.Log; - -import android.net.wifi.WifiManager; -import android.net.wifi.WifiManager.MulticastLock; -import android.net.wifi.WifiManager.WifiLock; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkInfo; -import android.os.PowerManager; -import android.os.PowerManager.WakeLock; - -import java.net.InetAddress; -import java.util.List; -import android.os.Build; - -/** - * This class is instanciated directly by the linphone library in order to access specific features only accessible in java. -**/ - -public class AndroidPlatformHelper{ - private WifiManager.WifiLock mWifiLock; - private WifiManager.MulticastLock mMcastLock; - private ConnectivityManager mConnectivityManager; - private PowerManager mPowerManager; - private WakeLock mWakeLock; - - public AndroidPlatformHelper(Object ctx_obj){ - Context ctx = (Context) ctx_obj; - WifiManager wifiMgr = (WifiManager)ctx.getSystemService(Context.WIFI_SERVICE); - mPowerManager = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE); - mConnectivityManager = (ConnectivityManager) ctx.getSystemService(Context.CONNECTIVITY_SERVICE); - - mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidPlatformHelper"); - mWakeLock.setReferenceCounted(true); - mMcastLock = wifiMgr.createMulticastLock("AndroidPlatformHelper"); - mMcastLock.setReferenceCounted(true); - mWifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "AndroidPlatformHelper"); - mWifiLock.setReferenceCounted(true); - } - - public Object getPowerManager(){ - return mPowerManager; - } - - public String[] getDnsServers() { - if (mConnectivityManager == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.M) - return null; - - if (mConnectivityManager.getActiveNetwork() == null - || mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()) == null) - return null; - - int i = 0; - List inetServers = null; - inetServers = mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()).getDnsServers(); - - String[] servers = new String[inetServers.size()]; - - for (InetAddress address : inetServers) { - servers[i++] = address.getHostAddress(); - } - Log.i("getDnsServers() returning"); - return servers; - } - public void acquireWifiLock(){ - Log.i("acquireWifiLock()"); - mWifiLock.acquire(); - } - public void releaseWifiLock(){ - Log.i("releaseWifiLock()"); - mWifiLock.release(); - } - public void acquireMcastLock(){ - Log.i("acquireMcastLock()"); - mMcastLock.acquire(); - } - public void releaseMcastLock(){ - Log.i("releaseMcastLock()"); - mMcastLock.release(); - } - public void acquireCpuLock(){ - Log.i("acquireCpuLock()"); - mWakeLock.acquire(); - } - public void releaseCpuLock(){ - Log.i("releaseCpuLock()"); - mWakeLock.release(); - } -}; - - diff --git a/linphone-deps.filelist b/linphone-deps.filelist deleted file mode 100755 index 8a77ad29b..000000000 --- a/linphone-deps.filelist +++ /dev/null @@ -1,19 +0,0 @@ -./bin/avcodec-53.dll -./bin/libspeex-1.dll -./bin/libspeexdsp-1.dll -./bin/avutil-51.dll -./bin/libpolarssl-0.dll -./bin/libbellesip-0.dll -./bin/libantlr3c.dll -./bin/libogg-0.dll -./bin/libtheora-0.dll -./bin/libxml2-2.dll -./bin/swscale-2.dll -./bin/libsoup-2.4-1.dll -./bin/libgcrypt-11.dll -./bin/libgpg-error-0.dll -./bin/libgnutls-26.dll -./bin/libtasn1-3.dll -./bin/libsqlite3-0.dll -./bin/libopus-0.dll -./bin/libbzrtp-0.dll diff --git a/pixmaps/.gitignore b/pixmaps/.gitignore deleted file mode 100644 index 282522db0..000000000 --- a/pixmaps/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -Makefile -Makefile.in diff --git a/pixmaps/CMakeLists.txt b/pixmaps/CMakeLists.txt deleted file mode 100644 index 68a33b22e..000000000 --- a/pixmaps/CMakeLists.txt +++ /dev/null @@ -1,140 +0,0 @@ -############################################################################ -# 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -############################################################################ - -set(ICONS_INSTALL_DIR ${PACKAGE_DATA_DIR}/icons/hicolor) - -install(FILES "linphone.icns" "linphone-banner.png" - DESTINATION ${PACKAGE_DATA_DIR}/pixmaps/linphone - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ -) - -install(FILES - svg/linphone-micro-muted.svg - svg/linphone-speaker-muted.svg - svg/linphone-micro-enabled.svg - svg/linphone-speaker-enabled.svg - svg/linphone-status-online.svg - svg/linphone-status-away.svg - svg/linphone-status-donotdisturb.svg - svg/linphone-status-offline.svg - svg/linphone-call-status-incoming.svg - svg/linphone-call-status-missed.svg - svg/linphone-call-status-outgoing.svg - svg/linphone-chat-new-message-and-writing.svg - svg/linphone-chat-new-message.svg - svg/linphone-chat-nothing.svg - svg/linphone-chat-writing.svg - svg/linphone-ok.svg - svg/linphone-inprogress.svg - svg/linphone-failed.svg - svg/linphone-camera-enabled.svg - svg/linphone-camera-disabled.svg - svg/linphone-security-ok.svg - svg/linphone-security-pending.svg - svg/linphone-media-play.svg - svg/linphone-media-pause.svg - svg/linphone-warning.svg - DESTINATION ${ICONS_INSTALL_DIR}/scalable/status - PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ -) - -install(FILES - svg/linphone-start-call.svg - svg/linphone-add-call.svg - svg/linphone-hold-off.svg - svg/linphone-hold-on.svg - svg/linphone-start-call2.svg - svg/linphone-start-chat.svg - svg/linphone-history.svg - svg/linphone-edit.svg - svg/linphone-delete.svg - svg/linphone-contact-add.svg - svg/linphone-conference-start.svg - svg/linphone-call-transfer.svg - svg/linphone-record.svg - svg/linphone-chat-send.svg - DESTINATION ${ICONS_INSTALL_DIR}/scalable/actions - PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ -) - -install(FILES - linphone-micro-muted.png - linphone-speaker-muted.png - linphone-micro-enabled.png - linphone-speaker-enabled.png - linphone-status-online.png - linphone-status-away.png - linphone-status-donotdisturb.png - linphone-status-offline.png - linphone-chat-nothing.png - linphone-chat-new-message.png - linphone-chat-writing.png - linphone-chat-new-message-and-writing.png - linphone-call-status-incoming.png - linphone-call-status-outgoing.png - linphone-call-status-missed.png - linphone-ok.png - linphone-inprogress.png - linphone-failed.png - linphone-camera-enabled.png - linphone-camera-disabled.png - linphone-security-ok.png - linphone-security-pending.png - linphone-media-play.png - linphone-media-pause.png - linphone-warning.png - DESTINATION ${ICONS_INSTALL_DIR}/48x48/status - PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ -) - -install(FILES - linphone-start-call2.png - linphone-add-call.png - linphone-start-call.png - linphone-start-chat.png - linphone-stop-call.png - linphone-hold-on.png - linphone-hold-off.png - linphone-history.png - linphone-edit.png - linphone-delete.png - linphone-contact-add.png - linphone-conference-start.png - linphone-call-transfer.png - linphone-record.png - linphone-chat-send.png - linphone-take-screenshot.png - DESTINATION ${ICONS_INSTALL_DIR}/48x48/actions - PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ -) - -install(FILES linphone.png - DESTINATION ${ICONS_INSTALL_DIR}/48x48/apps - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ -) - -if(WIN32) - install(FILES index.theme - DESTINATION ${ICONS_INSTALL_DIR} - PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ - ) -endif() diff --git a/pixmaps/Makefile.am b/pixmaps/Makefile.am deleted file mode 100644 index 18dab92fa..000000000 --- a/pixmaps/Makefile.am +++ /dev/null @@ -1,104 +0,0 @@ -pixmapdir=$(datadir)/pixmaps/linphone -dist_pixmap_DATA= \ - linphone-banner.png \ - linphone.icns - -iconsdir=$(datadir)/icons/hicolor -if BUILD_WIN32 - dist_icons_DATA=index.theme -endif - -appiconsdir=$(iconsdir)/48x48/apps -dist_appicons_DATA= linphone.png - -status48iconsdir=$(iconsdir)/48x48/status -dist_status48icons_DATA= \ - linphone-micro-muted.png \ - linphone-speaker-muted.png \ - linphone-micro-enabled.png \ - linphone-speaker-enabled.png \ - linphone-status-online.png \ - linphone-status-away.png \ - linphone-status-donotdisturb.png \ - linphone-status-offline.png \ - linphone-chat-nothing.png \ - linphone-chat-new-message.png \ - linphone-chat-writing.png \ - linphone-chat-new-message-and-writing.png \ - linphone-call-status-incoming.png \ - linphone-call-status-outgoing.png \ - linphone-call-status-missed.png \ - linphone-ok.png \ - linphone-inprogress.png \ - linphone-failed.png \ - linphone-camera-enabled.png \ - linphone-camera-disabled.png \ - linphone-security-ok.png \ - linphone-security-pending.png \ - linphone-media-play.png \ - linphone-media-pause.png \ - linphone-warning.png \ - linphone-take-screenshot.png - -statussvgiconsdir=$(iconsdir)/scalable/status -dist_statussvgicons_DATA= \ - svg/linphone-micro-muted.svg \ - svg/linphone-speaker-muted.svg \ - svg/linphone-micro-enabled.svg \ - svg/linphone-speaker-enabled.svg \ - svg/linphone-status-online.svg \ - svg/linphone-status-away.svg \ - svg/linphone-status-donotdisturb.svg \ - svg/linphone-status-offline.svg \ - svg/linphone-call-status-incoming.svg \ - svg/linphone-call-status-missed.svg \ - svg/linphone-call-status-outgoing.svg \ - svg/linphone-chat-new-message-and-writing.svg \ - svg/linphone-chat-new-message.svg \ - svg/linphone-chat-nothing.svg \ - svg/linphone-chat-writing.svg \ - svg/linphone-ok.svg \ - svg/linphone-inprogress.svg \ - svg/linphone-failed.svg \ - svg/linphone-camera-enabled.svg \ - svg/linphone-camera-disabled.svg \ - svg/linphone-security-ok.svg \ - svg/linphone-security-pending.svg \ - svg/linphone-media-play.svg \ - svg/linphone-media-pause.svg \ - svg/linphone-warning.svg - -actions48iconsdir=$(iconsdir)/48x48/actions -dist_actions48icons_DATA= \ - linphone-start-call2.png \ - linphone-add-call.png \ - linphone-start-call.png \ - linphone-start-chat.png \ - linphone-stop-call.png \ - linphone-hold-on.png \ - linphone-hold-off.png \ - linphone-history.png \ - linphone-edit.png \ - linphone-delete.png \ - linphone-contact-add.png \ - linphone-conference-start.png \ - linphone-call-transfer.png \ - linphone-record.png \ - linphone-chat-send.png - -actionssvgiconsdir=$(iconsdir)/scalable/actions -dist_actionssvgicons_DATA= \ - svg/linphone-start-call.svg \ - svg/linphone-add-call.svg \ - svg/linphone-hold-off.svg \ - svg/linphone-hold-on.svg \ - svg/linphone-start-call2.svg \ - svg/linphone-start-chat.svg \ - svg/linphone-history.svg \ - svg/linphone-edit.svg \ - svg/linphone-delete.svg \ - svg/linphone-contact-add.svg \ - svg/linphone-conference-start.svg \ - svg/linphone-call-transfer.svg \ - svg/linphone-record.svg \ - svg/linphone-chat-send.svg diff --git a/pixmaps/index.theme b/pixmaps/index.theme deleted file mode 100644 index d17354741..000000000 --- a/pixmaps/index.theme +++ /dev/null @@ -1,1836 +0,0 @@ -[Icon Theme] -Name=Hicolor -Comment=Fallback icon theme -Hidden=true -Directories=16x16/actions,16x16/animations,16x16/apps,16x16/categories,16x16/devices,16x16/emblems,16x16/emotes,16x16/filesystems,16x16/intl,16x16/mimetypes,16x16/places,16x16/status,16x16/stock/chart,16x16/stock/code,16x16/stock/data,16x16/stock/form,16x16/stock/image,16x16/stock/io,16x16/stock/media,16x16/stock/navigation,16x16/stock/net,16x16/stock/object,16x16/stock/table,16x16/stock/text,22x22/actions,22x22/animations,22x22/apps,22x22/categories,22x22/devices,22x22/emblems,22x22/emotes,22x22/filesystems,22x22/intl,22x22/mimetypes,22x22/places,22x22/status,22x22/stock/chart,22x22/stock/code,22x22/stock/data,22x22/stock/form,22x22/stock/image,22x22/stock/io,22x22/stock/media,22x22/stock/navigation,22x22/stock/net,22x22/stock/object,22x22/stock/table,22x22/stock/text,24x24/actions,24x24/animations,24x24/apps,24x24/categories,24x24/devices,24x24/emblems,24x24/emotes,24x24/filesystems,24x24/intl,24x24/mimetypes,24x24/places,24x24/status,24x24/stock/chart,24x24/stock/code,24x24/stock/data,24x24/stock/form,24x24/stock/image,24x24/stock/io,24x24/stock/media,24x24/stock/navigation,24x24/stock/net,24x24/stock/object,24x24/stock/table,24x24/stock/text,32x32/actions,32x32/animations,32x32/apps,32x32/categories,32x32/devices,32x32/emblems,32x32/emotes,32x32/filesystems,32x32/intl,32x32/mimetypes,32x32/places,32x32/status,32x32/stock/chart,32x32/stock/code,32x32/stock/data,32x32/stock/form,32x32/stock/image,32x32/stock/io,32x32/stock/media,32x32/stock/navigation,32x32/stock/net,32x32/stock/object,32x32/stock/table,32x32/stock/text,36x36/actions,36x36/animations,36x36/apps,36x36/categories,36x36/devices,36x36/emblems,36x36/emotes,36x36/filesystems,36x36/intl,36x36/mimetypes,36x36/places,36x36/status,36x36/stock/chart,36x36/stock/code,36x36/stock/data,36x36/stock/form,36x36/stock/image,36x36/stock/io,36x36/stock/media,36x36/stock/navigation,36x36/stock/net,36x36/stock/object,36x36/stock/table,36x36/stock/text,48x48/actions,48x48/animations,48x48/apps,48x48/categories,48x48/devices,48x48/emblems,48x48/emotes,48x48/filesystems,48x48/intl,48x48/mimetypes,48x48/places,48x48/status,48x48/stock/chart,48x48/stock/code,48x48/stock/data,48x48/stock/form,48x48/stock/image,48x48/stock/io,48x48/stock/media,48x48/stock/navigation,48x48/stock/net,48x48/stock/object,48x48/stock/table,48x48/stock/text,64x64/actions,64x64/animations,64x64/apps,64x64/categories,64x64/devices,64x64/emblems,64x64/emotes,64x64/filesystems,64x64/intl,64x64/mimetypes,64x64/places,64x64/status,64x64/stock/chart,64x64/stock/code,64x64/stock/data,64x64/stock/form,64x64/stock/image,64x64/stock/io,64x64/stock/media,64x64/stock/navigation,64x64/stock/net,64x64/stock/object,64x64/stock/table,64x64/stock/text,72x72/actions,72x72/animations,72x72/apps,72x72/categories,72x72/devices,72x72/emblems,72x72/emotes,72x72/filesystems,72x72/intl,72x72/mimetypes,72x72/places,72x72/status,72x72/stock/chart,72x72/stock/code,72x72/stock/data,72x72/stock/form,72x72/stock/image,72x72/stock/io,72x72/stock/media,72x72/stock/navigation,72x72/stock/net,72x72/stock/object,72x72/stock/table,72x72/stock/text,96x96/actions,96x96/animations,96x96/apps,96x96/categories,96x96/devices,96x96/emblems,96x96/emotes,96x96/filesystems,96x96/intl,96x96/mimetypes,96x96/places,96x96/status,96x96/stock/chart,96x96/stock/code,96x96/stock/data,96x96/stock/form,96x96/stock/image,96x96/stock/io,96x96/stock/media,96x96/stock/navigation,96x96/stock/net,96x96/stock/object,96x96/stock/table,96x96/stock/text,128x128/actions,128x128/animations,128x128/apps,128x128/categories,128x128/devices,128x128/emblems,128x128/emotes,128x128/filesystems,128x128/intl,128x128/mimetypes,128x128/places,128x128/status,128x128/stock/chart,128x128/stock/code,128x128/stock/data,128x128/stock/form,128x128/stock/image,128x128/stock/io,128x128/stock/media,128x128/stock/navigation,128x128/stock/net,128x128/stock/object,128x128/stock/table,128x128/stock/text,192x192/actions,192x192/animations,192x192/apps,192x192/categories,192x192/devices,192x192/emblems,192x192/emotes,192x192/filesystems,192x192/intl,192x192/mimetypes,192x192/places,192x192/status,192x192/stock/chart,192x192/stock/code,192x192/stock/data,192x192/stock/form,192x192/stock/image,192x192/stock/io,192x192/stock/media,192x192/stock/navigation,192x192/stock/net,192x192/stock/object,192x192/stock/table,192x192/stock/text,256x256/actions,256x256/animations,256x256/apps,256x256/categories,256x256/devices,256x256/emblems,256x256/emotes,256x256/filesystems,256x256/intl,256x256/mimetypes,256x256/places,256x256/status,256x256/stock/chart,256x256/stock/code,256x256/stock/data,256x256/stock/form,256x256/stock/image,256x256/stock/io,256x256/stock/media,256x256/stock/navigation,256x256/stock/net,256x256/stock/object,256x256/stock/table,256x256/stock/text,512x512/actions,512x512/animations,512x512/apps,512x512/categories,512x512/devices,512x512/emblems,512x512/emotes,512x512/filesystems,512x512/intl,512x512/mimetypes,512x512/places,512x512/status,512x512/stock/chart,512x512/stock/code,512x512/stock/data,512x512/stock/form,512x512/stock/image,512x512/stock/io,512x512/stock/media,512x512/stock/navigation,512x512/stock/net,512x512/stock/object,512x512/stock/table,512x512/stock/text,scalable/actions,scalable/animations,scalable/apps,scalable/categories,scalable/devices,scalable/emblems,scalable/emotes,scalable/filesystems,scalable/intl,scalable/mimetypes,scalable/places,scalable/status,scalable/stock/chart,scalable/stock/code,scalable/stock/data,scalable/stock/form,scalable/stock/image,scalable/stock/io,scalable/stock/media,scalable/stock/navigation,scalable/stock/net,scalable/stock/object,scalable/stock/table,scalable/stock/text,symbolic/apps - - -[16x16/actions] -Size=16 -Context=Actions -Type=Threshold - -[16x16/animations] -Size=16 -Context=Animations -Type=Threshold - -[16x16/apps] -Size=16 -Context=Applications -Type=Threshold - -[16x16/categories] -Size=16 -Context=Categories -Type=Threshold - -[16x16/devices] -Size=16 -Context=Devices -Type=Threshold - -[16x16/emblems] -Size=16 -Context=Emblems -Type=Threshold - -[16x16/emotes] -Size=16 -Context=Emotes -Type=Threshold - -[16x16/filesystems] -Size=16 -Context=FileSystems -Type=Threshold - -[16x16/intl] -Size=16 -Context=International -Type=Threshold - -[16x16/mimetypes] -Size=16 -Context=MimeTypes -Type=Threshold - -[16x16/places] -Size=16 -Context=Places -Type=Threshold - -[16x16/status] -Size=16 -Context=Status -Type=Threshold - -[16x16/stock/chart] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/code] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/data] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/form] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/image] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/io] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/media] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/navigation] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/net] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/object] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/table] -Size=16 -Context=Stock -Type=Threshold - -[16x16/stock/text] -Size=16 -Context=Stock -Type=Threshold - -[22x22/actions] -Size=22 -Context=Actions -Type=Threshold - -[22x22/animations] -Size=22 -Context=Animations -Type=Threshold - -[22x22/apps] -Size=22 -Context=Applications -Type=Threshold - -[22x22/categories] -Size=22 -Context=Categories -Type=Threshold - -[22x22/devices] -Size=22 -Context=Devices -Type=Threshold - -[22x22/emblems] -Size=22 -Context=Emblems -Type=Threshold - -[22x22/emotes] -Size=22 -Context=Emotes -Type=Threshold - -[22x22/filesystems] -Size=22 -Context=FileSystems -Type=Threshold - -[22x22/intl] -Size=22 -Context=International -Type=Threshold - -[22x22/mimetypes] -Size=22 -Context=MimeTypes -Type=Threshold - -[22x22/places] -Size=22 -Context=Places -Type=Threshold - -[22x22/status] -Size=22 -Context=Status -Type=Threshold - -[22x22/stock/chart] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/code] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/data] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/form] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/image] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/io] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/media] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/navigation] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/net] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/object] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/table] -Size=22 -Context=Stock -Type=Threshold - -[22x22/stock/text] -Size=22 -Context=Stock -Type=Threshold - -[24x24/actions] -Size=24 -Context=Actions -Type=Threshold - -[24x24/animations] -Size=24 -Context=Animations -Type=Threshold - -[24x24/apps] -Size=24 -Context=Applications -Type=Threshold - -[24x24/categories] -Size=24 -Context=Categories -Type=Threshold - -[24x24/devices] -Size=24 -Context=Devices -Type=Threshold - -[24x24/emblems] -Size=24 -Context=Emblems -Type=Threshold - -[24x24/emotes] -Size=24 -Context=Emotes -Type=Threshold - -[24x24/filesystems] -Size=24 -Context=FileSystems -Type=Threshold - -[24x24/intl] -Size=24 -Context=International -Type=Threshold - -[24x24/mimetypes] -Size=24 -Context=MimeTypes -Type=Threshold - -[24x24/places] -Size=24 -Context=Places -Type=Threshold - -[24x24/status] -Size=24 -Context=Status -Type=Threshold - -[24x24/stock/chart] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/code] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/data] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/form] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/image] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/io] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/media] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/navigation] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/net] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/object] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/table] -Size=24 -Context=Stock -Type=Threshold - -[24x24/stock/text] -Size=24 -Context=Stock -Type=Threshold - -[32x32/actions] -Size=32 -Context=Actions -Type=Threshold - -[32x32/animations] -Size=32 -Context=Animations -Type=Threshold - -[32x32/apps] -Size=32 -Context=Applications -Type=Threshold - -[32x32/categories] -Size=32 -Context=Categories -Type=Threshold - -[32x32/devices] -Size=32 -Context=Devices -Type=Threshold - -[32x32/emblems] -Size=32 -Context=Emblems -Type=Threshold - -[32x32/emotes] -Size=32 -Context=Emotes -Type=Threshold - -[32x32/filesystems] -Size=32 -Context=FileSystems -Type=Threshold - -[32x32/intl] -Size=32 -Context=International -Type=Threshold - -[32x32/mimetypes] -Size=32 -Context=MimeTypes -Type=Threshold - -[32x32/places] -Size=32 -Context=Places -Type=Threshold - -[32x32/status] -Size=32 -Context=Status -Type=Threshold - -[32x32/stock/chart] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/code] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/data] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/form] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/image] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/io] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/media] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/navigation] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/net] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/object] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/table] -Size=32 -Context=Stock -Type=Threshold - -[32x32/stock/text] -Size=32 -Context=Stock -Type=Threshold - -[36x36/actions] -Size=36 -Context=Actions -Type=Threshold - -[36x36/animations] -Size=36 -Context=Animations -Type=Threshold - -[36x36/apps] -Size=36 -Context=Applications -Type=Threshold - -[36x36/categories] -Size=36 -Context=Categories -Type=Threshold - -[36x36/devices] -Size=36 -Context=Devices -Type=Threshold - -[36x36/emblems] -Size=36 -Context=Emblems -Type=Threshold - -[36x36/emotes] -Size=36 -Context=Emotes -Type=Threshold - -[36x36/filesystems] -Size=36 -Context=FileSystems -Type=Threshold - -[36x36/intl] -Size=36 -Context=International -Type=Threshold - -[36x36/mimetypes] -Size=36 -Context=MimeTypes -Type=Threshold - -[36x36/places] -Size=36 -Context=Places -Type=Threshold - -[36x36/status] -Size=36 -Context=Status -Type=Threshold - -[36x36/stock/chart] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/code] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/data] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/form] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/image] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/io] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/media] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/navigation] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/net] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/object] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/table] -Size=36 -Context=Stock -Type=Threshold - -[36x36/stock/text] -Size=36 -Context=Stock -Type=Threshold - -[48x48/actions] -Size=48 -Context=Actions -Type=Threshold - -[48x48/animations] -Size=48 -Context=Animations -Type=Threshold - -[48x48/apps] -Size=48 -Context=Applications -Type=Threshold - -[48x48/categories] -Size=48 -Context=Categories -Type=Threshold - -[48x48/devices] -Size=48 -Context=Devices -Type=Threshold - -[48x48/emblems] -Size=48 -Context=Emblems -Type=Threshold - -[48x48/emotes] -Size=48 -Context=Emotes -Type=Threshold - -[48x48/filesystems] -Size=48 -Context=FileSystems -Type=Threshold - -[48x48/intl] -Size=48 -Context=International -Type=Threshold - -[48x48/mimetypes] -Size=48 -Context=MimeTypes -Type=Threshold - -[48x48/places] -Size=48 -Context=Places -Type=Threshold - -[48x48/status] -Size=48 -Context=Status -Type=Threshold - -[48x48/stock/chart] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/code] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/data] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/form] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/image] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/io] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/media] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/navigation] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/net] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/object] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/table] -Size=48 -Context=Stock -Type=Threshold - -[48x48/stock/text] -Size=48 -Context=Stock -Type=Threshold - -[64x64/actions] -Size=64 -Context=Actions -Type=Threshold - -[64x64/animations] -Size=64 -Context=Animations -Type=Threshold - -[64x64/apps] -Size=64 -Context=Applications -Type=Threshold - -[64x64/categories] -Size=64 -Context=Categories -Type=Threshold - -[64x64/devices] -Size=64 -Context=Devices -Type=Threshold - -[64x64/emblems] -Size=64 -Context=Emblems -Type=Threshold - -[64x64/emotes] -Size=64 -Context=Emotes -Type=Threshold - -[64x64/filesystems] -Size=64 -Context=FileSystems -Type=Threshold - -[64x64/intl] -Size=64 -Context=International -Type=Threshold - -[64x64/mimetypes] -Size=64 -Context=MimeTypes -Type=Threshold - -[64x64/places] -Size=64 -Context=Places -Type=Threshold - -[64x64/status] -Size=64 -Context=Status -Type=Threshold - -[64x64/stock/chart] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/code] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/data] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/form] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/image] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/io] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/media] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/navigation] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/net] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/object] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/table] -Size=64 -Context=Stock -Type=Threshold - -[64x64/stock/text] -Size=64 -Context=Stock -Type=Threshold -[72x72/actions] -Size=72 -Context=Actions -Type=Threshold - -[72x72/animations] -Size=72 -Context=Animations -Type=Threshold - -[72x72/apps] -Size=72 -Context=Applications -Type=Threshold - -[72x72/categories] -Size=72 -Context=Categories -Type=Threshold - -[72x72/devices] -Size=72 -Context=Devices -Type=Threshold - -[72x72/emblems] -Size=72 -Context=Emblems -Type=Threshold - -[72x72/emotes] -Size=72 -Context=Emotes -Type=Threshold - -[72x72/filesystems] -Size=72 -Context=FileSystems -Type=Threshold - -[72x72/intl] -Size=72 -Context=International -Type=Threshold - -[72x72/mimetypes] -Size=72 -Context=MimeTypes -Type=Threshold - -[72x72/places] -Size=72 -Context=Places -Type=Threshold - -[72x72/status] -Size=72 -Context=Status -Type=Threshold - -[72x72/stock/chart] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/code] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/data] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/form] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/image] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/io] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/media] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/navigation] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/net] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/object] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/table] -Size=72 -Context=Stock -Type=Threshold - -[72x72/stock/text] -Size=72 -Context=Stock -Type=Threshold - -[96x96/actions] -Size=96 -Context=Actions -Type=Threshold - -[96x96/animations] -Size=96 -Context=Animations -Type=Threshold - -[96x96/apps] -Size=96 -Context=Applications -Type=Threshold - -[96x96/categories] -Size=96 -Context=Categories -Type=Threshold - -[96x96/devices] -Size=96 -Context=Devices -Type=Threshold - -[96x96/emblems] -Size=96 -Context=Emblems -Type=Threshold - -[96x96/emotes] -Size=96 -Context=Emotes -Type=Threshold - -[96x96/filesystems] -Size=96 -Context=FileSystems -Type=Threshold - -[96x96/intl] -Size=96 -Context=International -Type=Threshold - -[96x96/mimetypes] -Size=96 -Context=MimeTypes -Type=Threshold - -[96x96/places] -Size=96 -Context=Places -Type=Threshold - -[96x96/status] -Size=96 -Context=Status -Type=Threshold - -[96x96/stock/chart] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/code] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/data] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/form] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/image] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/io] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/media] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/navigation] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/net] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/object] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/table] -Size=96 -Context=Stock -Type=Threshold - -[96x96/stock/text] -Size=96 -Context=Stock -Type=Threshold - -[128x128/actions] -Size=128 -Context=Actions -Type=Threshold - -[128x128/animations] -Size=128 -Context=Animations -Type=Threshold - -[128x128/apps] -Size=128 -Context=Applications -Type=Threshold - -[128x128/categories] -Size=128 -Context=Categories -Type=Threshold - -[128x128/devices] -Size=128 -Context=Devices -Type=Threshold - -[128x128/emblems] -Size=128 -Context=Emblems -Type=Threshold - -[128x128/emotes] -Size=128 -Context=Emotes -Type=Threshold - -[128x128/filesystems] -Size=128 -Context=FileSystems -Type=Threshold - -[128x128/intl] -Size=128 -Context=International -Type=Threshold - -[128x128/mimetypes] -Size=128 -Context=MimeTypes -Type=Threshold - -[128x128/places] -Size=128 -Context=Places -Type=Threshold - -[128x128/status] -Size=128 -Context=Status -Type=Threshold - -[128x128/stock/chart] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/code] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/data] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/form] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/image] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/io] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/media] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/navigation] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/net] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/object] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/table] -Size=128 -Context=Stock -Type=Threshold - -[128x128/stock/text] -Size=128 -Context=Stock -Type=Threshold - -[192x192/actions] -Size=192 -Context=Actions -Type=Threshold - -[192x192/animations] -Size=192 -Context=Animations -Type=Threshold - -[192x192/apps] -Size=192 -Context=Applications -Type=Threshold - -[192x192/categories] -Size=192 -Context=Categories -Type=Threshold - -[192x192/devices] -Size=192 -Context=Devices -Type=Threshold - -[192x192/emblems] -Size=192 -Context=Emblems -Type=Threshold - -[192x192/emotes] -Size=192 -Context=Emotes -Type=Threshold - -[192x192/filesystems] -Size=192 -Context=FileSystems -Type=Threshold - -[192x192/intl] -Size=192 -Context=International -Type=Threshold - -[192x192/mimetypes] -Size=192 -Context=MimeTypes -Type=Threshold - -[192x192/places] -Size=192 -Context=Places -Type=Threshold - -[192x192/status] -Size=192 -Context=Status -Type=Threshold - -[192x192/stock/chart] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/code] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/data] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/form] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/image] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/io] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/media] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/navigation] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/net] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/object] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/table] -Size=192 -Context=Stock -Type=Threshold - -[192x192/stock/text] -Size=192 -Context=Stock -Type=Threshold - -[256x256/actions] -MinSize=64 -Size=256 -MaxSize=256 -Context=Actions -Type=Scalable - -[256x256/animations] -MinSize=64 -Size=256 -MaxSize=256 -Context=Animations -Type=Scalable - -[256x256/apps] -MinSize=64 -Size=256 -MaxSize=256 -Context=Applications -Type=Scalable - -[256x256/categories] -MinSize=64 -Size=256 -MaxSize=256 -Context=Categories -Type=Scalable - -[256x256/devices] -MinSize=64 -Size=256 -MaxSize=256 -Context=Devices -Type=Scalable - -[256x256/emblems] -MinSize=64 -Size=256 -MaxSize=256 -Context=Emblems -Type=Scalable - -[256x256/emotes] -MinSize=64 -Size=256 -MaxSize=256 -Context=Emotes -Type=Scalable - -[256x256/filesystems] -MinSize=64 -Size=256 -MaxSize=256 -Context=FileSystems -Type=Scalable - -[256x256/intl] -MinSize=64 -Size=256 -MaxSize=256 -Context=International -Type=Scalable - -[256x256/mimetypes] -MinSize=64 -Size=256 -MaxSize=256 -Context=MimeTypes -Type=Scalable - -[256x256/places] -MinSize=64 -Size=256 -MaxSize=256 -Context=Places -Type=Scalable - -[256x256/status] -MinSize=64 -Size=256 -MaxSize=256 -Context=Status -Type=Scalable - -[256x256/stock/chart] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/code] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/data] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/form] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/image] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/io] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/media] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/navigation] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/net] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/object] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/table] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[256x256/stock/text] -MinSize=64 -Size=256 -MaxSize=256 -Context=Stock -Type=Scalable - -[512x512/actions] -MinSize=64 -Size=512 -MaxSize=512 -Context=Actions -Type=Scalable - -[512x512/animations] -MinSize=64 -Size=512 -MaxSize=512 -Context=Animations -Type=Scalable - -[512x512/apps] -MinSize=64 -Size=512 -MaxSize=512 -Context=Applications -Type=Scalable - -[512x512/categories] -MinSize=64 -Size=512 -MaxSize=512 -Context=Categories -Type=Scalable - -[512x512/devices] -MinSize=64 -Size=512 -MaxSize=512 -Context=Devices -Type=Scalable - -[512x512/emblems] -MinSize=64 -Size=512 -MaxSize=512 -Context=Emblems -Type=Scalable - -[512x512/emotes] -MinSize=64 -Size=512 -MaxSize=512 -Context=Emotes -Type=Scalable - -[512x512/filesystems] -MinSize=64 -Size=512 -MaxSize=512 -Context=FileSystems -Type=Scalable - -[512x512/intl] -MinSize=64 -Size=512 -MaxSize=512 -Context=International -Type=Scalable - -[512x512/mimetypes] -MinSize=64 -Size=512 -MaxSize=512 -Context=MimeTypes -Type=Scalable - -[512x512/places] -MinSize=64 -Size=512 -MaxSize=512 -Context=Places -Type=Scalable - -[512x512/status] -MinSize=64 -Size=512 -MaxSize=512 -Context=Status -Type=Scalable - -[512x512/stock/chart] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/code] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/data] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/form] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/image] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/io] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/media] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/navigation] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/net] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/object] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/table] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[512x512/stock/text] -MinSize=64 -Size=512 -MaxSize=512 -Context=Stock -Type=Scalable - -[scalable/actions] -MinSize=1 -Size=128 -MaxSize=256 -Context=Actions -Type=Scalable - -[scalable/animations] -MinSize=1 -Size=128 -MaxSize=256 -Context=Animations -Type=Scalable - -[scalable/apps] -MinSize=1 -Size=128 -MaxSize=256 -Context=Applications -Type=Scalable - -[scalable/categories] -MinSize=1 -Size=128 -MaxSize=256 -Context=Categories -Type=Scalable - -[scalable/devices] -MinSize=1 -Size=128 -MaxSize=512 -Context=Devices -Type=Scalable - -[scalable/emblems] -MinSize=1 -Size=128 -MaxSize=256 -Context=Emblems -Type=Scalable - -[scalable/emotes] -MinSize=1 -Size=128 -MaxSize=512 -Context=Emotes -Type=Scalable - -[scalable/filesystems] -MinSize=1 -Size=128 -MaxSize=256 -Context=FileSystems -Type=Scalable - -[scalable/intl] -MinSize=1 -Size=128 -MaxSize=512 -Context=International -Type=Scalable - -[scalable/mimetypes] -MinSize=1 -Size=128 -MaxSize=256 -Context=MimeTypes -Type=Scalable - -[scalable/places] -MinSize=1 -Size=128 -MaxSize=512 -Context=Places -Type=Scalable - -[scalable/status] -MinSize=1 -Size=128 -MaxSize=256 -Context=Status -Type=Scalable - -[scalable/stock/chart] -MinSize=1 -Size=128 -MaxSize=512 -Context=Stock -Type=Scalable - -[scalable/stock/code] -MinSize=1 -Size=128 -MaxSize=256 -Context=Stock -Type=Scalable - -[scalable/stock/data] -MinSize=1 -Size=128 -MaxSize=512 -Context=Stock -Type=Scalable - -[scalable/stock/form] -MinSize=1 -Size=128 -MaxSize=256 -Context=Stock -Type=Scalable - -[scalable/stock/image] -MinSize=1 -Size=128 -MaxSize=512 -Context=Stock -Type=Scalable - -[scalable/stock/io] -MinSize=1 -Size=128 -MaxSize=256 -Context=Stock -Type=Scalable - -[scalable/stock/media] -MinSize=1 -Size=128 -MaxSize=512 -Context=Stock -Type=Scalable - -[scalable/stock/navigation] -MinSize=1 -Size=128 -MaxSize=256 -Context=Stock -Type=Scalable - -[scalable/stock/net] -MinSize=1 -Size=128 -MaxSize=512 -Context=Stock -Type=Scalable - -[scalable/stock/object] -MinSize=1 -Size=128 -MaxSize=256 -Context=Stock -Type=Scalable - -[scalable/stock/table] -MinSize=1 -Size=128 -MaxSize=512 -Context=Stock -Type=Scalable - -[scalable/stock/text] -MinSize=1 -Size=128 -MaxSize=256 -Context=Stock -Type=Scalable - -[symbolic/apps] -MinSize=8 -Size=16 -MaxSize=512 -Context=Applications -Type=Scalable diff --git a/pixmaps/linphone-add-call.png b/pixmaps/linphone-add-call.png deleted file mode 100644 index 9c9edeef8..000000000 Binary files a/pixmaps/linphone-add-call.png and /dev/null differ diff --git a/pixmaps/linphone-banner.png b/pixmaps/linphone-banner.png deleted file mode 100644 index 6fe99ab77..000000000 Binary files a/pixmaps/linphone-banner.png and /dev/null differ diff --git a/pixmaps/linphone-call-status-incoming.png b/pixmaps/linphone-call-status-incoming.png deleted file mode 100644 index 58bf8633c..000000000 Binary files a/pixmaps/linphone-call-status-incoming.png and /dev/null differ diff --git a/pixmaps/linphone-call-status-missed.png b/pixmaps/linphone-call-status-missed.png deleted file mode 100644 index ba6bee6ee..000000000 Binary files a/pixmaps/linphone-call-status-missed.png and /dev/null differ diff --git a/pixmaps/linphone-call-status-outgoing.png b/pixmaps/linphone-call-status-outgoing.png deleted file mode 100644 index 73587dc7a..000000000 Binary files a/pixmaps/linphone-call-status-outgoing.png and /dev/null differ diff --git a/pixmaps/linphone-call-transfer.png b/pixmaps/linphone-call-transfer.png deleted file mode 100644 index 4dc24ce42..000000000 Binary files a/pixmaps/linphone-call-transfer.png and /dev/null differ diff --git a/pixmaps/linphone-camera-disabled.png b/pixmaps/linphone-camera-disabled.png deleted file mode 100644 index dfcc711cd..000000000 Binary files a/pixmaps/linphone-camera-disabled.png and /dev/null differ diff --git a/pixmaps/linphone-camera-enabled.png b/pixmaps/linphone-camera-enabled.png deleted file mode 100644 index 4c929b52b..000000000 Binary files a/pixmaps/linphone-camera-enabled.png and /dev/null differ diff --git a/pixmaps/linphone-chat-new-message-and-writing.png b/pixmaps/linphone-chat-new-message-and-writing.png deleted file mode 100644 index f64f525bb..000000000 Binary files a/pixmaps/linphone-chat-new-message-and-writing.png and /dev/null differ diff --git a/pixmaps/linphone-chat-new-message.png b/pixmaps/linphone-chat-new-message.png deleted file mode 100644 index 61341af11..000000000 Binary files a/pixmaps/linphone-chat-new-message.png and /dev/null differ diff --git a/pixmaps/linphone-chat-nothing.png b/pixmaps/linphone-chat-nothing.png deleted file mode 100644 index 9f6e1adc2..000000000 Binary files a/pixmaps/linphone-chat-nothing.png and /dev/null differ diff --git a/pixmaps/linphone-chat-send.png b/pixmaps/linphone-chat-send.png deleted file mode 100644 index 9a9f9d731..000000000 Binary files a/pixmaps/linphone-chat-send.png and /dev/null differ diff --git a/pixmaps/linphone-chat-writing.png b/pixmaps/linphone-chat-writing.png deleted file mode 100644 index 74c1a8269..000000000 Binary files a/pixmaps/linphone-chat-writing.png and /dev/null differ diff --git a/pixmaps/linphone-conference-start.png b/pixmaps/linphone-conference-start.png deleted file mode 100644 index 23dabbc35..000000000 Binary files a/pixmaps/linphone-conference-start.png and /dev/null differ diff --git a/pixmaps/linphone-contact-add.png b/pixmaps/linphone-contact-add.png deleted file mode 100644 index f78852d01..000000000 Binary files a/pixmaps/linphone-contact-add.png and /dev/null differ diff --git a/pixmaps/linphone-delete.png b/pixmaps/linphone-delete.png deleted file mode 100644 index d8ff8da4a..000000000 Binary files a/pixmaps/linphone-delete.png and /dev/null differ diff --git a/pixmaps/linphone-edit.png b/pixmaps/linphone-edit.png deleted file mode 100644 index 772770988..000000000 Binary files a/pixmaps/linphone-edit.png and /dev/null differ diff --git a/pixmaps/linphone-failed.png b/pixmaps/linphone-failed.png deleted file mode 100644 index f72412139..000000000 Binary files a/pixmaps/linphone-failed.png and /dev/null differ diff --git a/pixmaps/linphone-history.png b/pixmaps/linphone-history.png deleted file mode 100644 index 825bdeb68..000000000 Binary files a/pixmaps/linphone-history.png and /dev/null differ diff --git a/pixmaps/linphone-hold-off.png b/pixmaps/linphone-hold-off.png deleted file mode 100644 index b008a6896..000000000 Binary files a/pixmaps/linphone-hold-off.png and /dev/null differ diff --git a/pixmaps/linphone-hold-on.png b/pixmaps/linphone-hold-on.png deleted file mode 100644 index 1590a63b0..000000000 Binary files a/pixmaps/linphone-hold-on.png and /dev/null differ diff --git a/pixmaps/linphone-inprogress.png b/pixmaps/linphone-inprogress.png deleted file mode 100644 index 4a4371430..000000000 Binary files a/pixmaps/linphone-inprogress.png and /dev/null differ diff --git a/pixmaps/linphone-media-pause.png b/pixmaps/linphone-media-pause.png deleted file mode 100644 index f9e062f38..000000000 Binary files a/pixmaps/linphone-media-pause.png and /dev/null differ diff --git a/pixmaps/linphone-media-play.png b/pixmaps/linphone-media-play.png deleted file mode 100644 index 382d07760..000000000 Binary files a/pixmaps/linphone-media-play.png and /dev/null differ diff --git a/pixmaps/linphone-micro-enabled.png b/pixmaps/linphone-micro-enabled.png deleted file mode 100644 index 44ba551af..000000000 Binary files a/pixmaps/linphone-micro-enabled.png and /dev/null differ diff --git a/pixmaps/linphone-micro-muted.png b/pixmaps/linphone-micro-muted.png deleted file mode 100644 index cf666ebd0..000000000 Binary files a/pixmaps/linphone-micro-muted.png and /dev/null differ diff --git a/pixmaps/linphone-ok.png b/pixmaps/linphone-ok.png deleted file mode 100644 index 4bcd6f634..000000000 Binary files a/pixmaps/linphone-ok.png and /dev/null differ diff --git a/pixmaps/linphone-record.png b/pixmaps/linphone-record.png deleted file mode 100644 index 4ef4b064d..000000000 Binary files a/pixmaps/linphone-record.png and /dev/null differ diff --git a/pixmaps/linphone-security-ok.png b/pixmaps/linphone-security-ok.png deleted file mode 100644 index 38d2ec61c..000000000 Binary files a/pixmaps/linphone-security-ok.png and /dev/null differ diff --git a/pixmaps/linphone-security-pending.png b/pixmaps/linphone-security-pending.png deleted file mode 100644 index d61faa39a..000000000 Binary files a/pixmaps/linphone-security-pending.png and /dev/null differ diff --git a/pixmaps/linphone-speaker-enabled.png b/pixmaps/linphone-speaker-enabled.png deleted file mode 100644 index 0c8d7a951..000000000 Binary files a/pixmaps/linphone-speaker-enabled.png and /dev/null differ diff --git a/pixmaps/linphone-speaker-muted.png b/pixmaps/linphone-speaker-muted.png deleted file mode 100644 index 91e96eddb..000000000 Binary files a/pixmaps/linphone-speaker-muted.png and /dev/null differ diff --git a/pixmaps/linphone-start-call.png b/pixmaps/linphone-start-call.png deleted file mode 100644 index ade0e15a4..000000000 Binary files a/pixmaps/linphone-start-call.png and /dev/null differ diff --git a/pixmaps/linphone-start-call2.png b/pixmaps/linphone-start-call2.png deleted file mode 100644 index 097271ce2..000000000 Binary files a/pixmaps/linphone-start-call2.png and /dev/null differ diff --git a/pixmaps/linphone-start-chat.png b/pixmaps/linphone-start-chat.png deleted file mode 100644 index 15b050f6f..000000000 Binary files a/pixmaps/linphone-start-chat.png and /dev/null differ diff --git a/pixmaps/linphone-status-away.png b/pixmaps/linphone-status-away.png deleted file mode 100644 index 56c7fb367..000000000 Binary files a/pixmaps/linphone-status-away.png and /dev/null differ diff --git a/pixmaps/linphone-status-donotdisturb.png b/pixmaps/linphone-status-donotdisturb.png deleted file mode 100644 index d5a1391de..000000000 Binary files a/pixmaps/linphone-status-donotdisturb.png and /dev/null differ diff --git a/pixmaps/linphone-status-offline.png b/pixmaps/linphone-status-offline.png deleted file mode 100644 index c4f236f55..000000000 Binary files a/pixmaps/linphone-status-offline.png and /dev/null differ diff --git a/pixmaps/linphone-status-online.png b/pixmaps/linphone-status-online.png deleted file mode 100644 index 7fb4a1276..000000000 Binary files a/pixmaps/linphone-status-online.png and /dev/null differ diff --git a/pixmaps/linphone-stop-call.png b/pixmaps/linphone-stop-call.png deleted file mode 100644 index da1a2eab5..000000000 Binary files a/pixmaps/linphone-stop-call.png and /dev/null differ diff --git a/pixmaps/linphone-take-screenshot.png b/pixmaps/linphone-take-screenshot.png deleted file mode 100644 index 7a54a9928..000000000 Binary files a/pixmaps/linphone-take-screenshot.png and /dev/null differ diff --git a/pixmaps/linphone-warning.png b/pixmaps/linphone-warning.png deleted file mode 100644 index 044bcd8f0..000000000 Binary files a/pixmaps/linphone-warning.png and /dev/null differ diff --git a/pixmaps/linphone.icns b/pixmaps/linphone.icns deleted file mode 100644 index 3b8f1bd0a..000000000 Binary files a/pixmaps/linphone.icns and /dev/null differ diff --git a/pixmaps/linphone.png b/pixmaps/linphone.png deleted file mode 100644 index 4031d7205..000000000 Binary files a/pixmaps/linphone.png and /dev/null differ diff --git a/pixmaps/svg/linphone-add-call.svg b/pixmaps/svg/linphone-add-call.svg deleted file mode 100644 index ed8da23bc..000000000 --- a/pixmaps/svg/linphone-add-call.svg +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - image/svg+xml - - options_add_call + Rectangle 250 Copy 19 - - - - - - options_add_call + Rectangle 250 Copy 19 - Created with Sketch. - - - - - - - - diff --git a/pixmaps/svg/linphone-call-status-incoming.svg b/pixmaps/svg/linphone-call-status-incoming.svg deleted file mode 100644 index af9dd9bf6..000000000 --- a/pixmaps/svg/linphone-call-status-incoming.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - image/svg+xml - - - - - - - call_status_incoming - Created with Sketch. - - - - - - - diff --git a/pixmaps/svg/linphone-call-status-missed.svg b/pixmaps/svg/linphone-call-status-missed.svg deleted file mode 100644 index abb146cf1..000000000 --- a/pixmaps/svg/linphone-call-status-missed.svg +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - image/svg+xml - - call_status_missed - - - - - - call_status_missed - Created with Sketch. - - - - - - - - diff --git a/pixmaps/svg/linphone-call-status-outgoing.svg b/pixmaps/svg/linphone-call-status-outgoing.svg deleted file mode 100644 index cc8c66efb..000000000 --- a/pixmaps/svg/linphone-call-status-outgoing.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - image/svg+xml - - call_status_outgoing - - - - - - call_status_outgoing - Created with Sketch. - - - - - diff --git a/pixmaps/svg/linphone-call-transfer.svg b/pixmaps/svg/linphone-call-transfer.svg deleted file mode 100644 index 357ccfad7..000000000 --- a/pixmaps/svg/linphone-call-transfer.svg +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - image/svg+xml - - call_transfer - - - - - - call_transfer - Created with Sketch. - - - - - - - - - - - - - - - - - diff --git a/pixmaps/svg/linphone-camera-disabled.svg b/pixmaps/svg/linphone-camera-disabled.svg deleted file mode 100644 index f5ddde244..000000000 --- a/pixmaps/svg/linphone-camera-disabled.svg +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - image/svg+xml - - camera_default - - - - - - camera_default - Created with Sketch. - - - - - - - - - - - diff --git a/pixmaps/svg/linphone-camera-enabled.svg b/pixmaps/svg/linphone-camera-enabled.svg deleted file mode 100644 index 5138510e3..000000000 --- a/pixmaps/svg/linphone-camera-enabled.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - image/svg+xml - - camera_default - - - - - - camera_default - Created with Sketch. - - - - - - - - - - diff --git a/pixmaps/svg/linphone-chat-new-message-and-writing.svg b/pixmaps/svg/linphone-chat-new-message-and-writing.svg deleted file mode 100644 index 9cd538ea3..000000000 --- a/pixmaps/svg/linphone-chat-new-message-and-writing.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - image/svg+xml - - - - - - - chat_start_body_over - Created with Sketch. - - - - - - diff --git a/pixmaps/svg/linphone-chat-new-message.svg b/pixmaps/svg/linphone-chat-new-message.svg deleted file mode 100644 index 8ad456ca2..000000000 --- a/pixmaps/svg/linphone-chat-new-message.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - image/svg+xml - - - - - - - chat_start_body_over - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-chat-nothing.svg b/pixmaps/svg/linphone-chat-nothing.svg deleted file mode 100644 index 4835b5255..000000000 --- a/pixmaps/svg/linphone-chat-nothing.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - image/svg+xml - - - - - - - chat_start_body_over - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-chat-send.svg b/pixmaps/svg/linphone-chat-send.svg deleted file mode 100644 index 4f0924ab7..000000000 --- a/pixmaps/svg/linphone-chat-send.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - image/svg+xml - - chat_send - - - - - - chat_send - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-chat-writing.svg b/pixmaps/svg/linphone-chat-writing.svg deleted file mode 100644 index 7183818a1..000000000 --- a/pixmaps/svg/linphone-chat-writing.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - image/svg+xml - - - - - - - chat_start_body_over - Created with Sketch. - - - - - - diff --git a/pixmaps/svg/linphone-conference-start.svg b/pixmaps/svg/linphone-conference-start.svg deleted file mode 100644 index eedb7136b..000000000 --- a/pixmaps/svg/linphone-conference-start.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - image/svg+xml - - conference_start - - - - - - conference_start - Created with Sketch. - - - diff --git a/pixmaps/svg/linphone-contact-add.svg b/pixmaps/svg/linphone-contact-add.svg deleted file mode 100644 index 08882723a..000000000 --- a/pixmaps/svg/linphone-contact-add.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - contact_add - Created with Sketch. - - - - - - - - - - - - \ No newline at end of file diff --git a/pixmaps/svg/linphone-delete.svg b/pixmaps/svg/linphone-delete.svg deleted file mode 100644 index 51b051ac0..000000000 --- a/pixmaps/svg/linphone-delete.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - delete - Created with Sketch. - - - - - - - - - - - - \ No newline at end of file diff --git a/pixmaps/svg/linphone-edit.svg b/pixmaps/svg/linphone-edit.svg deleted file mode 100644 index 21d72cfbc..000000000 --- a/pixmaps/svg/linphone-edit.svg +++ /dev/null @@ -1,15 +0,0 @@ - - - - edit - Created with Sketch. - - - - - - - - - - \ No newline at end of file diff --git a/pixmaps/svg/linphone-failed.svg b/pixmaps/svg/linphone-failed.svg deleted file mode 100644 index 98e3fc67f..000000000 --- a/pixmaps/svg/linphone-failed.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - image/svg+xml - - call_missed - - - - - - call_missed - Created with Sketch. - - - - - - diff --git a/pixmaps/svg/linphone-history.svg b/pixmaps/svg/linphone-history.svg deleted file mode 100644 index c4b4f4936..000000000 --- a/pixmaps/svg/linphone-history.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - image/svg+xml - - - - - - - footer_history - Created with Sketch. - - - - - - - - - - diff --git a/pixmaps/svg/linphone-hold-off.svg b/pixmaps/svg/linphone-hold-off.svg deleted file mode 100644 index bd44bbf3a..000000000 --- a/pixmaps/svg/linphone-hold-off.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - image/svg+xml - - pause_big_default - - - - - - pause_big_default - Created with Sketch. - - - diff --git a/pixmaps/svg/linphone-hold-on.svg b/pixmaps/svg/linphone-hold-on.svg deleted file mode 100644 index b25a411fd..000000000 --- a/pixmaps/svg/linphone-hold-on.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - image/svg+xml - - - - - - - pause_small_over_selected - Created with Sketch. - - - diff --git a/pixmaps/svg/linphone-inprogress.svg b/pixmaps/svg/linphone-inprogress.svg deleted file mode 100644 index 871be13b5..000000000 --- a/pixmaps/svg/linphone-inprogress.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - image/svg+xml - - chat_message_inprogress - - - - - - chat_message_inprogress - Created with Sketch. - - - diff --git a/pixmaps/svg/linphone-logo.svg b/pixmaps/svg/linphone-logo.svg deleted file mode 100644 index 6861fef41..000000000 --- a/pixmaps/svg/linphone-logo.svg +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pixmaps/svg/linphone-media-pause.svg b/pixmaps/svg/linphone-media-pause.svg deleted file mode 100644 index 0e8ed0de7..000000000 --- a/pixmaps/svg/linphone-media-pause.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - image/svg+xml - - pause_big_default - - - - - - pause_big_default - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-media-play.svg b/pixmaps/svg/linphone-media-play.svg deleted file mode 100644 index 3eb7f0066..000000000 --- a/pixmaps/svg/linphone-media-play.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - image/svg+xml - - pause_big_default - - - - - - pause_big_default - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-micro-enabled.svg b/pixmaps/svg/linphone-micro-enabled.svg deleted file mode 100644 index a23354bc1..000000000 --- a/pixmaps/svg/linphone-micro-enabled.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - image/svg+xml - - micro_default - - - - - - micro_default - Created with Sketch. - - - - - - diff --git a/pixmaps/svg/linphone-micro-muted.svg b/pixmaps/svg/linphone-micro-muted.svg deleted file mode 100644 index 09d505c59..000000000 --- a/pixmaps/svg/linphone-micro-muted.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - image/svg+xml - - micro_default - - - - - - micro_default - Created with Sketch. - - - - - - - - - - diff --git a/pixmaps/svg/linphone-ok.svg b/pixmaps/svg/linphone-ok.svg deleted file mode 100644 index db08198f7..000000000 --- a/pixmaps/svg/linphone-ok.svg +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - image/svg+xml - - valid - valid - - - - - - valid - Created with Sketch. - - - - - - - - - - - - diff --git a/pixmaps/svg/linphone-record.svg b/pixmaps/svg/linphone-record.svg deleted file mode 100644 index 8709e9509..000000000 --- a/pixmaps/svg/linphone-record.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - image/svg+xml - - status_busy - - - - - - status_busy - Created with Sketch. - - - - - diff --git a/pixmaps/svg/linphone-security-ok.svg b/pixmaps/svg/linphone-security-ok.svg deleted file mode 100644 index 83e518e9b..000000000 --- a/pixmaps/svg/linphone-security-ok.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - image/svg+xml - - security_ok - - - - - - security_ok - Created with Sketch. - - - - - - diff --git a/pixmaps/svg/linphone-security-pending.svg b/pixmaps/svg/linphone-security-pending.svg deleted file mode 100644 index 084755a29..000000000 --- a/pixmaps/svg/linphone-security-pending.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - image/svg+xml - - security_pending - - - - - - security_pending - Created with Sketch. - - - - - - diff --git a/pixmaps/svg/linphone-speaker-enabled.svg b/pixmaps/svg/linphone-speaker-enabled.svg deleted file mode 100644 index 8a122795d..000000000 --- a/pixmaps/svg/linphone-speaker-enabled.svg +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - image/svg+xml - - speaker_default - - - - - - speaker_default - Created with Sketch. - - - - - - - - - - diff --git a/pixmaps/svg/linphone-speaker-muted.svg b/pixmaps/svg/linphone-speaker-muted.svg deleted file mode 100644 index 1e85b85be..000000000 --- a/pixmaps/svg/linphone-speaker-muted.svg +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - image/svg+xml - - speaker_default - - - - - - speaker_default - Created with Sketch. - - - - - diff --git a/pixmaps/svg/linphone-start-call.svg b/pixmaps/svg/linphone-start-call.svg deleted file mode 100644 index b7783041a..000000000 --- a/pixmaps/svg/linphone-start-call.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - image/svg+xml - - - - - - - call_alt_start - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-start-call2.svg b/pixmaps/svg/linphone-start-call2.svg deleted file mode 100644 index 4e6f22d9a..000000000 --- a/pixmaps/svg/linphone-start-call2.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - image/svg+xml - - - - - - - call_start_body_over - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-start-chat.svg b/pixmaps/svg/linphone-start-chat.svg deleted file mode 100644 index aa71e6c0f..000000000 --- a/pixmaps/svg/linphone-start-chat.svg +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - image/svg+xml - - footer_chat - - - - - - footer_chat - Created with Sketch. - - - - - - diff --git a/pixmaps/svg/linphone-status-away.svg b/pixmaps/svg/linphone-status-away.svg deleted file mode 100644 index 46beec033..000000000 --- a/pixmaps/svg/linphone-status-away.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - image/svg+xml - - statut_absent - - - - - - statut_absent - Created with Sketch. - - - diff --git a/pixmaps/svg/linphone-status-donotdisturb.svg b/pixmaps/svg/linphone-status-donotdisturb.svg deleted file mode 100644 index 54e2ef8fe..000000000 --- a/pixmaps/svg/linphone-status-donotdisturb.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - image/svg+xml - - - - - - - led_error - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-status-offline.svg b/pixmaps/svg/linphone-status-offline.svg deleted file mode 100644 index 890ee2f7f..000000000 --- a/pixmaps/svg/linphone-status-offline.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - image/svg+xml - - - - - - - led_disconnected - Created with Sketch. - - - - diff --git a/pixmaps/svg/linphone-status-online.svg b/pixmaps/svg/linphone-status-online.svg deleted file mode 100644 index 5f7149e4d..000000000 --- a/pixmaps/svg/linphone-status-online.svg +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - image/svg+xml - - status_available - - - - - - status_available - Created with Sketch. - - - diff --git a/pixmaps/svg/linphone-stop-call.svg b/pixmaps/svg/linphone-stop-call.svg deleted file mode 100644 index ab4fa3b28..000000000 --- a/pixmaps/svg/linphone-stop-call.svg +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - image/svg+xml - - call_hangup - - - - - - call_hangup - Created with Sketch. - - - - - diff --git a/pixmaps/svg/linphone-warning.svg b/pixmaps/svg/linphone-warning.svg deleted file mode 100644 index e1cbb91d9..000000000 --- a/pixmaps/svg/linphone-warning.svg +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - image/svg+xml - - chat_message_not_delivered - - - - - - chat_message_not_delivered - Created with Sketch. - - - - - - - - - - - - - - diff --git a/pixmaps/svg/linphone.svg b/pixmaps/svg/linphone.svg deleted file mode 100644 index 528247c89..000000000 --- a/pixmaps/svg/linphone.svg +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/po/.gitignore b/po/.gitignore deleted file mode 100644 index 5af53230f..000000000 --- a/po/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.intltool-merge-cache -Makefile -Makefile.in -Makefile.in.in -POTFILES -*.gmo -stamp-* diff --git a/po/ChangeLog b/po/ChangeLog deleted file mode 100644 index 63269d9a1..000000000 --- a/po/ChangeLog +++ /dev/null @@ -1,97 +0,0 @@ -2007-01-17 gettextize - - * Makefile.in.in: Upgrade to gettext-0.16.1. - * cat-id-tbl.c: Remove file. - -2006-07-20 gettextize - - * Makefile.in.in: Upgrade to gettext-0.14.6. - * boldquot.sed: New file, from gettext-0.14.6. - * en@boldquot.header: New file, from gettext-0.14.6. - * en@quot.header: New file, from gettext-0.14.6. - * insert-header.sin: New file, from gettext-0.14.6. - * quot.sed: New file, from gettext-0.14.6. - * remove-potcdate.sin: New file, from gettext-0.14.6. - * Rules-quot: New file, from gettext-0.14.6. - * cat-id-tbl.c: Remove file. - -2002-10-15 gettextize - - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-10-08 gettextize - - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-10-08 gettextize - - * boldquot.sed: New file, from gettext-0.11.5. - * en@boldquot.header: New file, from gettext-0.11.5. - * en@quot.header: New file, from gettext-0.11.5. - * insert-header.sin: New file, from gettext-0.11.5. - * quot.sed: New file, from gettext-0.11.5. - * remove-potcdate.sin: New file, from gettext-0.11.5. - * Rules-quot: New file, from gettext-0.11.5. - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-10-04 gettextize - - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-10-04 gettextize - - * Makefile.in.in: Upgrade to gettext-0.11.5. - -2002-10-04 gettextize - - * Makefile.in.in: New file, from gettext-0.11.5. - -2002-10-01 gettextize - - * Makefile.in.in: Upgrade to gettext-0.11.5. - * boldquot.sed: New file, from gettext-0.11.5. - * en@boldquot.header: New file, from gettext-0.11.5. - * en@quot.header: New file, from gettext-0.11.5. - * insert-header.sin: New file, from gettext-0.11.5. - * quot.sed: New file, from gettext-0.11.5. - * remove-potcdate.sin: New file, from gettext-0.11.5. - * Rules-quot: New file, from gettext-0.11.5. - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-08-04 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-08-04 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-07-16 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-02-16 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - -2002-02-10 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - -2002-02-10 gettextize - - * Makefile.in.in: Upgrade to gettext-0.10.40. - * cat-id-tbl.c: Remove file. - * stamp-cat-id: Remove file. - diff --git a/po/Makevars b/po/Makevars deleted file mode 100644 index 32692ab4b..000000000 --- a/po/Makevars +++ /dev/null @@ -1,41 +0,0 @@ -# Makefile variables for PO directory in any package using GNU gettext. - -# Usually the message domain is the same as the package name. -DOMAIN = $(PACKAGE) - -# These two variables depend on the location of this directory. -subdir = po -top_builddir = .. - -# These options get passed to xgettext. -XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ - -# This is the copyright holder that gets inserted into the header of the -# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding -# package. (Note that the msgstr strings, extracted from the package's -# sources, belong to the copyright holder of the package.) Translators are -# expected to transfer the copyright for their translations to this person -# or entity, or to disclaim their copyright. The empty string stands for -# the public domain; in this case the translators are expected to disclaim -# their copyright. -COPYRIGHT_HOLDER = Free Software Foundation, Inc. - -# This is the email address or URL to which the translators shall report -# bugs in the untranslated strings: -# - Strings which are not entire sentences, see the maintainer guidelines -# in the GNU gettext documentation, section 'Preparing Strings'. -# - Strings which use unclear terms or require additional context to be -# understood. -# - Strings which make invalid assumptions about notation of date, time or -# money. -# - Pluralisation problems. -# - Incorrect English spelling. -# - Incorrect formatting. -# It can be your email address, or a mailing list address where translators -# can write to without being subscribed, or the URL of a web page through -# which the translators can contact you. -MSGID_BUGS_ADDRESS = - -# This is the list of locale categories, beyond LC_MESSAGES, for which the -# message catalogs shall be used. It is usually empty. -EXTRA_LOCALE_CATEGORIES = diff --git a/po/Makevars.template b/po/Makevars.template deleted file mode 100644 index 32692ab4b..000000000 --- a/po/Makevars.template +++ /dev/null @@ -1,41 +0,0 @@ -# Makefile variables for PO directory in any package using GNU gettext. - -# Usually the message domain is the same as the package name. -DOMAIN = $(PACKAGE) - -# These two variables depend on the location of this directory. -subdir = po -top_builddir = .. - -# These options get passed to xgettext. -XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ - -# This is the copyright holder that gets inserted into the header of the -# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding -# package. (Note that the msgstr strings, extracted from the package's -# sources, belong to the copyright holder of the package.) Translators are -# expected to transfer the copyright for their translations to this person -# or entity, or to disclaim their copyright. The empty string stands for -# the public domain; in this case the translators are expected to disclaim -# their copyright. -COPYRIGHT_HOLDER = Free Software Foundation, Inc. - -# This is the email address or URL to which the translators shall report -# bugs in the untranslated strings: -# - Strings which are not entire sentences, see the maintainer guidelines -# in the GNU gettext documentation, section 'Preparing Strings'. -# - Strings which use unclear terms or require additional context to be -# understood. -# - Strings which make invalid assumptions about notation of date, time or -# money. -# - Pluralisation problems. -# - Incorrect English spelling. -# - Incorrect formatting. -# It can be your email address, or a mailing list address where translators -# can write to without being subscribed, or the URL of a web page through -# which the translators can contact you. -MSGID_BUGS_ADDRESS = - -# This is the list of locale categories, beyond LC_MESSAGES, for which the -# message catalogs shall be used. It is usually empty. -EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES.in b/po/POTFILES.in deleted file mode 100644 index c44eab3a2..000000000 --- a/po/POTFILES.in +++ /dev/null @@ -1,50 +0,0 @@ -# List of source files containing translatable strings. -gtk/calllogs.c -gtk/conference.c -gtk/logging.c -gtk/support.c -gtk/chat.c -gtk/main.c -gtk/friendlist.c -gtk/propertybox.c -gtk/update.c -gtk/buddylookup.c -gtk/setupwizard.c -gtk/incall_view.c -gtk/loginframe.c -gtk/config-fetching.c -gtk/audio_assistant.c -[type: gettext/glade]gtk/about.ui -[type: gettext/glade]gtk/audio_assistant.ui -[type: gettext/glade]gtk/buddylookup.ui -[type: gettext/glade]gtk/callee_frame.ui -[type: gettext/glade]gtk/call_logs.ui -[type: gettext/glade]gtk/call_statistics.ui -[type: gettext/glade]gtk/chatroom_frame.ui -[type: gettext/glade]gtk/conf_frame.ui -[type: gettext/glade]gtk/config-uri.ui -[type: gettext/glade]gtk/contact.ui -[type: gettext/glade]gtk/dscp_settings.ui -[type: gettext/glade]gtk/in_call_frame.ui -[type: gettext/glade]gtk/keypad.ui -[type: gettext/glade]gtk/ldap.ui -[type: gettext/glade]gtk/login_frame.ui -[type: gettext/glade]gtk/log.ui -[type: gettext/glade]gtk/main.ui -[type: gettext/glade]gtk/parameters.ui -[type: gettext/glade]gtk/password.ui -[type: gettext/glade]gtk/provisioning-fetch.ui -[type: gettext/glade]gtk/setup_wizard.ui -[type: gettext/glade]gtk/sip_account.ui -[type: gettext/glade]gtk/tunnel_config.ui -[type: gettext/glade]gtk/waiting.ui -coreapi/linphonecore.c -coreapi/misc.c -coreapi/presence.c -coreapi/friend.c -coreapi/proxy.c -coreapi/callbacks.c -coreapi/linphonecall.c - -coreapi/call_log.c -gtk/videowindow.c diff --git a/po/POTFILES.skip b/po/POTFILES.skip deleted file mode 100755 index 573d0bea5..000000000 --- a/po/POTFILES.skip +++ /dev/null @@ -1,56 +0,0 @@ -gtk/p2pwizard.ui -mediastreamer2/src/otherfilters/mspcapfileplayer.c -mediastreamer2/src/android/androidsound_depr.cpp -mediastreamer2/src/android/androidvideo.cpp -mediastreamer2/src/audiofilters/alaw.c -mediastreamer2/src/audiofilters/alsa.c -mediastreamer2/src/audiofilters/aqsnd.m -mediastreamer2/src/audiofilters/audiomixer.c -mediastreamer2/src/audiofilters/chanadapt.c -mediastreamer2/src/audiofilters/dtmfgen.c -mediastreamer2/src/audiofilters/equalizer.c -mediastreamer2/src/audiofilters/gsm.c -mediastreamer2/src/audiofilters/genericplc.c -mediastreamer2/src/audiofilters/msgenericplc.c -mediastreamer2/src/audiofilters/macsnd.c -mediastreamer2/src/audiofilters/msconf.c -mediastreamer2/src/audiofilters/msfileplayer.c -mediastreamer2/src/audiofilters/msfilerec.c -mediastreamer2/src/audiofilters/msfilerec_win.c -mediastreamer2/src/audiofilters/msiounit.m -mediastreamer2/src/audiofilters/msresample.c -mediastreamer2/src/audiofilters/msspeex.c -mediastreamer2/src/audiofilters/msvolume.c -mediastreamer2/src/audiofilters/oss.c -mediastreamer2/src/audiofilters/speexec.c -mediastreamer2/src/audiofilters/ulaw.c -mediastreamer2/src/audiofilters/webrtc_aec.c -mediastreamer2/src/otherfilters/itc.c -mediastreamer2/src/otherfilters/join.c -mediastreamer2/src/otherfilters/msrtp.c -mediastreamer2/src/otherfilters/tee.c -mediastreamer2/src/otherfilters/void.c -mediastreamer2/src/videofilters/drawdib-display.c -mediastreamer2/src/videofilters/extdisplay.c -mediastreamer2/src/videofilters/msdscap-mingw.cc -mediastreamer2/src/videofilters/msv4l.c -mediastreamer2/src/videofilters/msv4l2.c -mediastreamer2/src/videofilters/nowebcam.c -mediastreamer2/src/videofilters/pixconv.c -mediastreamer2/src/videofilters/sizeconv.c -mediastreamer2/src/videofilters/theora.c -mediastreamer2/src/videofilters/videodec.c -mediastreamer2/src/videofilters/videoenc.c -mediastreamer2/src/videofilters/videoout.c -mediastreamer2/src/videofilters/vp8.c -mediastreamer2/src/videofilters/wincevideods.c -mediastreamer2/src/videofilters/winvideo.c -mediastreamer2/src/videofilters/winvideods.c -mediastreamer2/src/videofilters/winvideo2.c -mediastreamer2/src/videofilters/x11video.c -mediastreamer2/src/videofilters/msdscap.cc -mediastreamer2/src/voip/ice.c -build/vsx/LibLinphoneTester-wp8/LibLinphoneTester-wp8/Resources/AppResources.Designer.cs -build/wp8/LibLinphoneTester-wp8/Resources/AppResources.Designer.cs -mediastreamer2/build/wp8/mediastreamer2-tester-wp8/Resources/AppResources.Designer.cs -share/linphone.desktop.in diff --git a/po/README b/po/README deleted file mode 100644 index 68c47a874..000000000 --- a/po/README +++ /dev/null @@ -1,13 +0,0 @@ -How to add a translation file -***************************** -To add a translation file in linphone project you should first : - - add the file .po in the directory /po - - run ./autogen.sh - -Update the translation files -*************************** -To update all the translation files, in the directory /po run the following command - $ make update-po - - - diff --git a/po/Rules-quot b/po/Rules-quot deleted file mode 100644 index 9c2a995e3..000000000 --- a/po/Rules-quot +++ /dev/null @@ -1,47 +0,0 @@ -# Special Makefile rules for English message catalogs with quotation marks. - -DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot - -.SUFFIXES: .insert-header .po-update-en - -en@quot.po-create: - $(MAKE) en@quot.po-update -en@boldquot.po-create: - $(MAKE) en@boldquot.po-update - -en@quot.po-update: en@quot.po-update-en -en@boldquot.po-update: en@boldquot.po-update-en - -.insert-header.po-update-en: - @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \ - if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \ - tmpdir=`pwd`; \ - echo "$$lang:"; \ - ll=`echo $$lang | sed -e 's/@.*//'`; \ - LC_ALL=C; export LC_ALL; \ - cd $(srcdir); \ - if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \ - if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ - rm -f $$tmpdir/$$lang.new.po; \ - else \ - if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ - :; \ - else \ - echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ - exit 1; \ - fi; \ - fi; \ - else \ - echo "creation of $$lang.po failed!" 1>&2; \ - rm -f $$tmpdir/$$lang.new.po; \ - fi - -en@quot.insert-header: insert-header.sin - sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header - -en@boldquot.insert-header: insert-header.sin - sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header - -mostlyclean: mostlyclean-quot -mostlyclean-quot: - rm -f *.insert-header diff --git a/po/ar.po b/po/ar.po deleted file mode 100644 index 6fff00113..000000000 --- a/po/ar.po +++ /dev/null @@ -1,2107 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# محيي الدين , 2014 -# محيي الدين , 2014-2016 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Arabic (http://www.transifex.com/belledonne-communications/linphone-gtk/language/ar/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ar\n" -"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "اتصل بـ %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "أرسل رسالة إلى %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "إضافة %s إلى قائمة جهات اتصالك" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "المكالمات السابقة" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "المكالمات الفائتة (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "—" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "أُلغيت" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "فائتة" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "مرفوضة" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i دقيقة" -msgstr[1] "دقيقة واحدة" -msgstr[2] "دقيقتان" -msgstr[3] "%i دقائق" -msgstr[4] "%i دقيقة" -msgstr[5] "%i دقيقة" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i ثانية" -msgstr[1] "ثانية واحدة" -msgstr[2] "ثانيتان" -msgstr[3] "%i ثوان" -msgstr[4] "%i ثانية" -msgstr[5] "%i ثانية" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tالجودة : %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "اجتماع" - -#: ../gtk/conference.c:46 -msgid "Me" -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:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "يجري الإرسال...‏" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "لم تُرسَل الرسالة" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "نسخ" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "أظهِرْ بعض معلومات التنقيح خلال التشغيل." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "عرض الإصدار ثم المغادرة" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "الدليل إلى الملف الذي سيُكتَب فيه سجل الوقائع." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "ابدأ لِنْفُونْ لكن دون تفعيل الفيديو." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "شغِّله مُصغَّرا، ولا تُظهِر الواجهة الرئيسية." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "العنوان المُراد الاتصال به الآن" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "حدِّد مجلد العمل (الذي سيكون مجلد التثبيت، مثلا c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "ملف التهيئة" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "ابدأ مرشد الصوت" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "شغِّل الاختبار الذاتي ثم اخرِجْ 0 إذا نجح" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "يود %s إضافتك إلى جهات اتصاله.\nهل تريد إضافته إلى جهات اتصالك والسماح له برؤية حالة حضورك ؟\nإن كان الجواب بالرفض، سوف يجري حظر هذا الشخص مؤقتا." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "ادخل كلمة السر لـ %s\n في نطاق %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "خطأ في المكالمة" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "إنتهت المكالمة" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "مكالمة واردة" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "أجِبْ" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "ارفضْ" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "المكالمة متوقفة" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "بواسطة %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "يود %s تشغيل الفيديو. هل تقبل ذلك ؟" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "وصلة إلى الموقع وِبْ" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "لِنْفُونْ" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "الهاتف المرئي عبر الإنترنت" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (افتراضي)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "التحويل إلى %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "لا وجود للوحة الصوت على هذا الحاسوب.\nلن تتمكن من تلقي أو إجراء أي مكالمة." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "هاتف SIP المرئي الحر" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "أهلا\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "أضف إلى دفتر العناوين" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "ابحث في دليل %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "جهة اتصال sip غير صالحة !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "إضافة جهة الاتصال جديدة" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "حرر جهة الاتصال '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "احذف جهة الاتصال '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "احذف تاريخ دردشات '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "اضف جهة اتصال انطلاقا من الدليل %s" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "الاسم" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "التردد (هرتز)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "الحالة" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "صبيب IP (ك.بِتْ/ثانية)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "الإعدادات" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "مفعَّل" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "غير مفعَّل" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "الحساب" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "English" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Français" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Svenska" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italiano" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Español" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Português do Brasil" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polski" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Deutsch" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Русский" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "日本語" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Nederlands" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Magyar" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Čeština" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "简体中文" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "繁体中文" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norsk bokmål" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "עברית" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Српски" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "العربية" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Türkçe" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "يجب إعادة تشغيل لِنْفُونْ لكي تٌفعَّل اللغة المختارة." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "بدون" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "يوجد إصدار حديث من طرف %s.\nهل تريد فتح المتصفح لتنزيله ؟" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "أنت تستخدم الإصدار الأحدث." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "الاسم، اللقب" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "خطأ في الاتصال مع الخادم." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "يجري الاتصال..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "متصل" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "يجري تلقي البيانات..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "لم يُعثَر على أي جهة اتصال" -msgstr[1] "عُثِر على جهة اتصال واحدة" -msgstr[2] "عُثِر على جهتي اتصال" -msgstr[3] "عُثِر على %i جهات اتصال" -msgstr[4] "عُثِر على %i جهة اتصال" -msgstr[5] "عُثِر على %i جهة اتصال" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "إن اسم المستخدم يُستخدَم مسبقا !" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "فشل التحقق من إمكانية إتاحة اسم المستخدم. يُرجى الإعادة لاحقا." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "مكالمة #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "حوِّل إلى المكالمة #%i مع %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "غير مستخدَم" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE غير مفعَّل" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "فَشِل ICE" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "تجري مساومة ICE" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "المرور عبد واحد أو عدة NAT" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "مباشر" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "عبر خادم بديل" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP غير مفعَّل" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "يجري uPnP" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnP غير متوفر" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP مشغَّل" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "فَشِل uPnP" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "مباشرة أو عبر خادم" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "التنزيل % f\nالرفع : %f (ك.بِتْ/الثانية)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f fps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f ثانية" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "ضع السماعة" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "يجري الاتصال..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "المكالمة الواردة" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "جيدة" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "متوسطة" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "ضعيفة" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "ضعيفة جدا" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "سيِّئة جيدا" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "غير متاحة" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "آمن بواسطة SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "مُؤمَّن بواسطة DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "آمن بواسطة ZRTP - [شارة الهوية : %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "أكِّدْ عدم تحقُّقك" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "أكِّدْ تحقُّقَك" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "في اجتماع" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "المكالمة جارية" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "المكالمة متوقفة مؤقتا" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "إنتهت المكالمة." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "يجري الإرسال" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "انتهى الإرسال." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "فَشِل الإرسال." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "استأنِفْ" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "إيقاف مؤقت" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "يسجل في\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(متوقف)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "يُرجى إدخال معلومات الولوج ل %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "يجلب من %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "فَشِل تنزيل التهيئة عن بعد من %s ." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "لم يكتشف صوتاً" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "خافِت" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "جيد" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "صاخب" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "هل سمعت ثلاث رنات ؟" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "لم يعثر على تفضيلات الصوت" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "لم يتمكن من تشغيل التحكم في الصوت للنظام" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "مرحبا !\nسيمكنك هذا المرشد من تهيئة إعدادات الصوت من أجل لِنْفُونْ" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "جهاز الالتقاط" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "الحجم المسجَّل" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "صامت" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "تفضيلات الصوت للنظام" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "جهاز السماع" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "شغِّل ثلاث رنَّات" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "اضغط على زر التسجيل وانطق ببعض الكلمات" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "استمع لصوتك المسجَّل" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "تسجيل" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "تشغيل" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "لنُشغِّل لِنْفُونْ الآن" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "مرشد الصوت" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "مرشد الصوت" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "معايرة كسب الميكروفون" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "معايرة شدة مكبر الصوت" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "سَجِّل واقرأ " - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "في طور الإنهاء" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "حول لِنْفُونْ" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -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)‎." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \nar: Muhiyeddine Cherik \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "البحث عن جهات الاتصال في الدليل" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "الإضافة إلى قائمتي" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "البحث عن شخص" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "اسم المنادَى" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "تاريخ المكالمات" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "أفْرِغ الكل" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "إعادة الاتصال" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "إحصاء المكالمات" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "مرمازات الصوت" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "مرمازات الفيديو" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "سعة القناة الصوتية" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "اتصالات الصوت" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "سعة قناة الفيديو" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "اتصالات الفيديو" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "مدة الذهاب والإياب" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "حجم الفيديو المستلَم" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "حجم الفيديو المرسَل" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "تشكيلة RTP" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "إحصاء المكالمات والمعلومات" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "أرسِلْ" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "أنْهِ الاجتماع" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "تحديد عنوان URI التهيئة عن بعد" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "يسمح لك مربع الحوار هذا بإعداد عنوان http أو https الذي من خلاله تود جلب التهيئة عند بدء البرنامج.\nأدخل العنوان أسفله. بعد تأكيد الأمر، ستجري إعادة تشغيل لِنْفُونْ تلقائيا من أجل جلب والأخذ بعين الاعتبار الإعدادات الحديثة." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "عنوان SIP" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "رؤية حالة حضور جهة الاتصال هذه" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "السماح لجهة الاتصال هذه برؤية حالة حضوري" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "معلومات جهة الاتصال" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "إعدادات DSCP" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "تدفق RTP الصوتي" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "تدفق RTP المرئي" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "حدد قيم DSCP (بالنظام الست-عشري)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "اضغط هنا لتحديد شدة مكبر الصوت" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "سَجِّل هذه المكالمة في ملف صوتي" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "مرئي" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "اصمُتْ" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "إرسال" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "المكالمة جارية" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "المدة" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "تقييم جودة المكالمة" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "إعدادات LDAP" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "عنوان الخادم :" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "طريقة التحقق من الهوية :" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "اسم المستخدم :" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "كلمة السر :" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "استخدم TLS" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "غير متاح" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "الاتصال " - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "ربط DN" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "اسم الهوية" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "النطاق" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "الكائن الأساسي :" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "رشِّح (%s كاسم) :" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "خاصية الاسم :" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "خاصية عنوان SIP :" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "الخاصيات المبحوث عنها :" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "البحث" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "المهلة القصوى للبحث :" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "العدد الأقصى للنتائج :" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "متابعة الكنية" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "متفرقات" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "مجهول الهوية" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "بسيط" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "DIGEST-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "اسم المستخدم" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "كلمة السر" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "الاتصال بالإنترنت :" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "سَجِّل دخولي تلقائيا" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "مُعرِّف المستخدم" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "معلومات الولوج" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "مرحبا !" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "قناة الألياف الضوئية" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "نافذة تنقيح لِنْفُونْ" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "مرِّر إلى الآخر" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "افتراضي" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "احذف" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "الخ_يارات" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "عنوان URI للتهيئة" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "شغِّل الفيديو دائما" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "فعِّل رؤية نفسي" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "إظهار لوحة الأرقام" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "استورد جهات الاتصال من أنساق vCard" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "صدِّر جهات الاتصال بنسق vCard" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "ال_مساعدة" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "أظهِر نافذة التنقيح" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "موق_ع الوِبْ" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "تحقق من التح_ديثات" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "مرشد الحساب" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "عنوان SIP أو رقم الهاتف :" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "ابدأ مكالمة جديدة" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "جهات الاتصال" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "بحث" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "إضافة جهات الاتصال من الدليل" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "إضافة جهة الاتصال" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "محو تاريخ المكالمات" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "هويتي الحالية :" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "الإجابة التلقائية مُفعَّلة" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "مجهول" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "لوحة الصوت الافتراضية" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "لوحة الصوت" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "الكاميرا الافتراضية" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "مرمازات الصوت" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "مرمازات الفيديو" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "الإعدادات" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "هذه الفقرة تحدد عنوانك SIP إن كنت لا تستخدم حساب SIP" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "اسمك المعروض (مثلا : زيد عمرو) :" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "اسم المستخدم :" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "عنوانك SIP :" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "الهوية الافتراضية" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "المرشد" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "إضافة" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "حرر" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "أزل" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "حسابات الوكيل" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "احذف جميع كلمات السر" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "الأمان" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "الإجابة تلقائيا فور تلقي المكالمة" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "التأخير قبل الإجابة (ميلي ث,)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "الإجابة تلقائيا" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "إدارة حسابات SIP" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "صوت الجرس :" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "عتاد ALSA الخصوصي (اختياري) :" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "جهاز الالتقاط :" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "جهاز الرنين :" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "جهاز السمع :" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "فعِّل إزالة الصدى" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "الصوت" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "جهاز إدخال الفيديو :" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "المقدار المُراد لدقة الفيديو :" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "طريقة إخراج الفيديو :" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "اظهر معاينة الكاميرا" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "الفيديو المُسبَق :" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "المقدار المُراد لمعدل إطارات الفيديو :" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "حدِّد 0 لعدم وضع أي حد" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "الفيديو" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "حد سرعة الرفع بالكيلوبِتْ/الثانية :" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "حد سرعة التنزيل بالكيلوبِتْ/الثانية :" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "فعِّل التحكم المتكيف مع الصبيب" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "التحكم المتكيف مع الصبيب هو تقنية لملائمة جودة الصوت والصورة بناءً على سعة قناة الاتصال المتاحة خلال المكالمة." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "إدارة سعة القناة" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "إعدادات الوسائط المتعددة" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "حدِّد Maximum Transmission Unit :" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "أرسِل الأرقام الهاتفية على هيئة SIP INFO" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "السماح باستخدام IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "النقل" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "منفذ SIP/UDP" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "عشوائي" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "منفذ SIP/TCP" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "صوت RTP/UDP :" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "ثابت" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "فيديو RTP/UDP :" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "النفق" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "حقول DSCP" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "بروتوكول الشبكة والمنافذ" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "الاتصال مباشر بالإنترنت" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "وراء جدار ناري (حدِّد عنوان IP البوابة)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "وراء جدار ناري (استخدم STUN)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "وراء جدار ناري (استخدم ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "وراء جدار ناري (استخدم uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "عنوان IP العمومي :" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "خادم STUN :" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "إعدادات حول الجدار الناري" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "نوع وسيط التعمية" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "‫استخدم Lime لرسائل المحادثات الصادرة‬" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "وسيط التعمية إجباري" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "واجب" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "مستحب" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "التعمية" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "إعدادات الشبكة" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "فعِّل" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "إلغاء التفعيل" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "مرمازات الصوت" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "مرمازات الفيديو" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "المراميز" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "اللغة" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "أظهر الإعدادات المتقدمة" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "المستوى" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "واجهة المستخدم" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "تهيئة LDAP" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "أغلق" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "لِنْفُونْ - يجب التحقق من الهوية" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "أدخل كلمة سر النطاق" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "تجري التهيئة..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "رجاءً انتظر ريثما ينتهي من جلب الإعدادات من الخادم..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "مرشد تهيئة حساب SIP" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "مرحبا !\nسيمكنك هذا المرشد من إعداد حسابك SIP لإجراء المكالمات." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "مرحبا بك في مرشد إعداد الحساب" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "إنشاء حساب في linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "أتوفر مسبقا على حساب في linphone.org وأريد فقط استخدامه" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "أتوفر مسبقا على حساب sip وأريد فقط استخدامه" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "أريد تحديد عنوان التهيئة عن بعد" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "مرشد تهيئة الحساب" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "ادخل معلومات حسابك" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "اسم المستخدم*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "كلمة السر*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "النطاق*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "الوكيل" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "تهيئة حسابك (المرحلة 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "أدخِل اسم المستخدم في linphone.org" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "أدخل اسم المستخدم SIP (المرحلة 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) حقول ضرورية" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "البريد الالكتروني : (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "اسم المستخدم* : (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "كلمة السر* : (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "أكِّد كلمة السر : (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "أحطني علما بتحديثات لِنْفُونْ" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "أدخل معلومات حسابك (المرحلة 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "يُرجى الانتظار، يجري الآن إنشاء حسابك." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "إنشاء الحساب في تقدم" - -#: ../gtk/setup_wizard.ui.h:29 -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ثم ارجع إلى هنا واضغط على زر التالي." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "تأكيد (المرحلة 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "يُرجى الانتظار، يجري الآن فحص التحقق من صحة حسابك." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "التحقق من الحساب في تقدم" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "خطأ، لم يتم تأكيد الحساب، سبق استخدام اسم المستخدم أو تعذر الوصول للخادم.\nيُرجى إعادة المحاولة لاحقا." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "خطأ" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "شكرا لك، لقد جرت تهيئة حسابك وهو الآن قابل للاستخدام." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "لِنْفُونْ - تهيئة حساب SIP" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "هوية SIP لديك :" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "يشبه sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "عنوان وكيل SIP :" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "يشبه sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "مدة التسجيل (بالثواني) :" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "إعدادات جهة الاتصال (اختيارية) :" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "مجال RTCP الاعتيادي ل AVPF (بالثواني) :" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "التوجيه (اختياري) :" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "النقل" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "التسجيل" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "انشر معلومات الحضور" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "فعِّل AVPF " - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "تهيئة حساب SIP" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "تهيئة نفق VoIP" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "المضيف" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "المنفذ" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "تهيئة النفق" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "تهيئة وكيل http (اختياري)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "يُرجى الانتظار" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "جاهز" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "تجري التهيئة" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "يتصل ب" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "لم يتمكن من الاتصال" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "آسف، وصل عدد المكالمات الآنية إلى حده الأقصى" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "يتصل بك" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "ويطلب ردا تلقائيا." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "يجري تعديل إعدادات المكالمة..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "متصل." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "أُلغيت المكالمة" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "لم يتمكن من توقيف المكالمة مؤقتا" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "وضع المكالمة قيد الانتظار..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "يجري بحث STUN..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "يجري جلب مرشَّحي ICE المحلين..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "على الخط" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "مشغول" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "سأعود" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "غائب" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "على الهاتف" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "أمام مائدة الطعام" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "لا تزعجني" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "ذهبتُ" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "أستخدم خدمة أخرى للتراسل الفوري" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "غير متصل" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "قيد الانتظار" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "في عطلة" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "حالة مجهولة" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "إن عنوان SIP الذي أدخلت غير صحيح، يجب أن يبدأ بـ \"sip:‎\" متبوعا باسم المضيف." - -#: ../coreapi/proxy.c:345 -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، مثلا sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "يجري البحث عن وجهة رقم الهاتف..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "لم يتمكن من إيجاد هذا الرقم." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "تعذر الولوج بالهوية %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "‫يجري إنعاش في %s...‬" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "يرن الجرس عن بعد..." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "يرن الجرس عن بعد..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "أخذ المكالمة مبكرا." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "‫أجاب عن المكالمة %s‬" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "استُعيدت المكالمة." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "غير موائم، تحقق من المراميز أو إعدادات الأمان..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "إعدادات الوسائط غير موائمة." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "استُأنِفت المكالمة." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "وُقِّفت المكالمة مؤقتا من طرف آخر." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "حُدِّث الاتصال من البعيد." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "أُنهيت المكالمة." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "المستخدم مشغول." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "المستخدم غير متاح مؤقتا." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "لا يريد المستخدم أي إزعاج." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "تم تجاهل المكالمة." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "انتهت مهلة الطلب." - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "مُوجَّه" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "فشل الاتصال." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "تم التسجيل في %s بنجاح." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "أُلغي التسجيل في %s ." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "لا إجابة قبل انتهاء المهلة" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "فَشِل التسجيل في %s: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "خدمة غير متاحة، تجري الإعادة" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "شارة التحقق من الهوية هي %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "‫لم تُعدَّل معاملات المكالمات : %s.‬" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "عُدِّلت معاملات المكالمات بنجاج." - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "لم تفتك أي مكالمة." -msgstr[1] "فاتتك مكالمة واحدة." -msgstr[2] "فاتتك مكالمتان." -msgstr[3] "فاتتك %i مكالمات." -msgstr[4] "فاتتك %i مكالمة." -msgstr[5] "فاتتك %i مكالمة." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "أُجهِضت" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "اكتملت" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "فاتت" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "مجهول" - -#: ../coreapi/call_log.c:234 -#, 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/call_log.c:235 -msgid "Outgoing call" -msgstr "المكالمة الصادرة" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "لم يتمكن من تشغيل %s" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/boldquot.sed b/po/boldquot.sed deleted file mode 100644 index 4b937aa51..000000000 --- a/po/boldquot.sed +++ /dev/null @@ -1,10 +0,0 @@ -s/"\([^"]*\)"/“\1”/g -s/`\([^`']*\)'/‘\1’/g -s/ '\([^`']*\)' / ‘\1’ /g -s/ '\([^`']*\)'$/ ‘\1’/g -s/^'\([^`']*\)' /‘\1’ /g -s/“”/""/g -s/“/“/g -s/”/”/g -s/‘/‘/g -s/’/’/g diff --git a/po/cs.po b/po/cs.po deleted file mode 100644 index 70d394fa7..000000000 --- a/po/cs.po +++ /dev/null @@ -1,2095 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Klara Cihlarova , 2005 -# Petr Pisar , 2006-2011,2013 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Czech (http://www.transifex.com/belledonne-communications/linphone-gtk/language/cs/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: cs\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Volat komu: %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Poslat text komu: %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Nedávné hovory" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Nedávné hovory (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "–" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Přerušen" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Zmeškán" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Odmítnut" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minuta" -msgstr[1] "%i minuty" -msgstr[2] "%i minut" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i sekunda" -msgstr[1] "%i sekundy" -msgstr[2] "%i sekund" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tKvalita: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Konference" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Já" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Nelze najít soubor s obrázkem: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "Za běhu vypisuje některé ladicí informace na standardní výstup." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "Soubor, kam zapisovat protokol." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Spustí linphone se zakázaným obrazem." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Spustí se pouze do systémové oblasti, nezobrazí hlavní okno." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "Zavolá právě teď na tuto adresu" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Zadejte pracovní adresář (měl by být základní instalační adresář, například c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Chyba hovoru" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Hovor ukončen" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Příchozí hovor" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Odpovědět" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Odmítnout" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Hovor odložen" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "kým: %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s navrhuje začít videohovor. Přijímáte?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Odkaz na webovou stránku" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Výchozí)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Byly jsme přepojeni na %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Na tomto počítači nebyla objevena žádná zvuková karta.\nNebudete moci vytáčet a přijímat a zvukové hovory." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Volný SIP videofon" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Přidat do adresáře" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Hledat v adresáři %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Neplatný sipový kontakt!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Upravit kontakt „%s“" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Odstranit kontakt „%s“" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Odstranit historii diskuze u kontaktu „%s“" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Přidat nový kontakt z adresáře %s" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Jméno" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Kmitočet (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Stav" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parametry" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Povoleno" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Zakázáno" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Účet" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "angličtina" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "francouzština" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "švédština" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "italština" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "španělština" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "brazilská portugalština" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "polština" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "němčina" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "ruština" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "japonština" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "dánština" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "maďarština" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "čeština" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "čínština" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "tradiční čínština" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "norština" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "hebrejština" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "srbština" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -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." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Žádné" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Na %s je dostupná novější verze.\nPřejete si otevřít prohlížeč, abyste si ji mohli stáhnout?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Máte spuštěnou poslední verzi." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "První jméno, Poslední jméno" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Chyba komunikace se serverem." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Připojuje se…" - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Připojeno" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Přijímají se data…" - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Nalezen %i kontakt" -msgstr[1] "Nalezeny %i kontakty" -msgstr[2] "Nalezeno %i kontaktů" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Hovor č. %i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Přepojit hovor č. %i s %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Nepoužito" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE není zapnuto" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE selhalo" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "Probíhá ICE" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Prochází se jedním nebo více NATy" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Přímé" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Skrze relay server" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "UPnP není zapnuto" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "Probíhá UPnP" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "UPnP není nedostupné" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "UPnP běží" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "UPnP selhalo" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Přímé nebo skrze server" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "příchozí: %f\nodchozí: %f (kb/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f sekund" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Zavěsit" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Volá se…" - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Příchozí hovor" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "dobrá" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "průměrná" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "slabá" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "velmi slabá" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "příliš špatná" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "nedostupná" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Zabezpečeno pomocí SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Zabezpečeno pomocí ZRTP – [ověřovací klíč: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Nastavit na neověřeno" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Nastavit na ověřeno" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "Probíhá konference" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "Probíhá hovor" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Odložený hovor" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Hovor skončil." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Probíhá přepojení" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Přepojení dokončeno." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Přepojení selhalo." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Obnovit" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Odložit" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Nahrává se do\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Odloženo)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Prosím, zadejte své přihlašovací jméno pro %s:" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Ukončuje se" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Internetový videofon používající standardní protokol SIP (RFC 3261)." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Hledat kontakty v adresáři" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Přidat na svůj seznam" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Hledat někoho" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Jméno volaného" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Historie volání" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Vše smazat" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Zavolat zpátky" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Statistické údaje o hovoru" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Kodek zvuku" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Kodek obrazu" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Přenosová rychlost zvuku na úrovni IP" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Zvukové spojení" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Přenosová rychlost obrazu na úrovni IP" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Obrazové spojení" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Odezva" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Statistické a ostatní údaje o hovoru" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Odeslat" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Ukončit konferenci" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP adresa" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "U tohoto kontaktu zobrazovat stav přítomnosti" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Dovolit tomuto kontaktu, aby viděl můj stav přítomnosti" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Informace o kontaktu" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "RTP proud zvuku" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "RTP proud obrazu" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Nastavit hodnoty DSCP (šestnáctkově)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Nahrát tento hovor do zvukového souboru" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Obraz" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Ztišit" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Přepojit" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "Telefonuje se" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Délka" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Hodnocení kvality hovoru" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Uživatelské jméno:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Heslo:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Uživatelské jméno" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Heslo" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Připojení k Internetu:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Přihlašovat mě automaticky" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Identifikátor uživatele" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Informace o přihlášení" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fiber Channel" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Ladicí okno Linphonu" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Přejít na konec" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Výchozí" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Smazat" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "V_olby" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Vždy spustit obraz" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Zobrazovat sám sebe" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "Nápo_věda" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Zobrazit ladicí okno" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Domovská stránka" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Vyhledat akt_ualizace" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Průvodce účtem" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP adresa nebo telefonní číslo:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Zahájit nový hovor" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Kontakty" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Hledat" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Přidat kontakty z adresáře" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Přidat kontakt" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Moje současná totožnost:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "implicitní zvuková karta" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "zvuková karta" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "implicitní kamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Kodeky zvuku" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Kodeky obrazu" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Nastavení" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Tento oddíl určuje vaši SIP adresu, když se nepoužívá žádný účet" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Vaše zobrazované jméno (např. Jan Novák):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Vaše uživatelské jméno:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Vaše výsledná SIP adresa:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Implicitní totožnost" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Průvodce" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Přidat" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Upravit" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Odstranit" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Proxy účty" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Vymazat všechna hesla" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Soukromí" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Nastavení SIP účtů" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Vyzvánění:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Zvláštní ALSA zařízení (volitelné):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Zařízení pro nahrávání:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Zařízení pro vyzvánění:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Zařízení pro přehrávání:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Zapnout potlačení ozvěny" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Zvuk" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Vstupní zařízení obrazu:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 znamená „neomezeno“" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Obraz" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Omezení odchozí rychlosti (kb/s):" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Omezení příchozí rychlosti (kb/s):" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Zapnout přizpůsobující se řízení rychlosti" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Přizpůsobující se řízení rychlosti je technika dynamického odhadu dostupného pásma během hovoru." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Využití šířky pásma" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Nastavení multimédií" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Nastavit MTU (největší přenositelná zpráva):" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Odesílat tóny DTMF jako SIP INFO zprávy" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Přenos" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Zvukový RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Stálý" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Obrazový RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "Položky DSCP" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Síťové protokoly a porty" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Přímé připojení do Internetu" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Za NAT/firewallem (adresu určí STUN)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Za NAT/firewallem (adresu určí ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Za NAT/firewallem (adresu určí UPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Veřejná IP adresa:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "STUN server:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT a firewall" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Druh šifrování médií" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Šifrování médií je povinné" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Nastavení sítě" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Povolit" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Zakázat" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Kodeky" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Jazyk" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Zobrazit podrobnější nastavení" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Úroveň" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Uživatelské rozhraní" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Hotovo" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone – Ověření totožnosti vyžadováno" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Prosím, zadejte heslo pro doménu" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Vítejte v průvodci nastavení účtu" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Vytvořit účet na linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Účet na linphone.org již mám a chci jej použít" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "SIP účet již mám a chci jej použít" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Průvodce nastavením účtu" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Uživatelské jméno*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Heslo*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Doména*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Nastavit účet (krok 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Zadejte uživatelské jméno na linphone.org" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Zadejte vaše sipové uživatelské jméno (krok 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Povinné položky" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "E-mail: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Uživatelské jméno: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Heslo: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Potvrďte heslo: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Zadejte údaje o účtu (krok 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Prosím, ověřte svůj účet tak, že kliknete na odkaz, který jsme vám právě zaslali e-mailem.\nPak se sem vraťte a stiskněte tlačítko Další." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Ověření (krok 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Došlo k chybě (účet nebyl ověřen, uživatelské jméno již existuje nebo server není dostupný).\nProsím, vraťte se a zkoste to znovu." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Chyba" - -#: ../gtk/setup_wizard.ui.h:37 -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/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone – Nastav SIP účet" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Vaše SIP totožnost:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Vypadá jako sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "Adresa SIP proxy:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Vypadá jako sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Registrační období (s):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Směrování (volitelné):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Zaregistrovat se" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Zveřejnit stav přítomnosti" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Nastavit SIP účet" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Nastavit VoIP tunel" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Stroj" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Port" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Nastavit tunel" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Nastavit HTTP proxy (volitelné)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Prosím, čekejte" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Připraven." - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Navazuje se spojení" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Nelze volat" - -#: ../coreapi/linphonecore.c:3228 -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:3388 -msgid "is contacting you" -msgstr "vás volá" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr " a požaduje automatickou zvednutí." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Upravují se parametry hovoru…" - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Připojeno." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Hovor přerušen" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Hovor nebylo možné odložit" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Současný hovor se odkládá…" - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Hledá se adresa pomocí STUN…" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Shromažďují se místní kandidáti ICE…" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Připojen" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Zaneprázdněn" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Za chvíli se vrátím" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Pryč" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "U telefonu" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Na obědě" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Nerušit" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Přestěhoval jsem se" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Používám jinou službu přenosu zpráv" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Odpojen" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Čekám" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -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:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "SIP identita, kterou jste zadali, není platná.\nMěla by mít tvar sip:uživatel@proxydoména, například sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Vyhledává se umístění čísla…" - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Toto číslo nelze vyhledat." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Nelze se přihlásit jako %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Vyzvání na druhé straně." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Vyzvání na druhé straně…" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Časná média." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Hovor obnoven." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Není slučitelné. Zkontrolujte nastavení kodeků a zabezpečení…" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Neslučitelné parametry médií." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Byli jsme obnoveni." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Byli jsme odloženi protistranou." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "Hovor byl aktualizován protistranou." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Hovor ukončen." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Uživatel je zaneprázdněn." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Uživatel je dočasně nedostupný." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Uživatel si nepřeje být rušen." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Volání odmítnuto." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Přesměrováno" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Volání se nezdařilo." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Registrace na %s byla úspěšná." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Odregistrování z %s hotovo." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "odpověď nedorazila včas" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Registrace na %s selhala: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Klíč k ověření totožnosti je %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -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ů." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/de.po b/po/de.po deleted file mode 100644 index 50aef056b..000000000 --- a/po/de.po +++ /dev/null @@ -1,2094 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# andreas, 2014 -# andreas, 2014 -# Ettore Atalan , 2015-2016 -# Gerhard Stengel , 2011-2012 -# Simon Morlat , 2001 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: German (http://www.transifex.com/belledonne-communications/linphone-gtk/language/de/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "„%s“ anrufen" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Text zu „%s“ schicken" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "%s zu Ihrer Kontaktliste hinzufügen" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Letzte Gespräche" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Letzte Anrufe (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "n/v" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Abgebrochen" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Verpasst" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Abgewiesen" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i Minute" -msgstr[1] "%i Minuten" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i Sekunde" -msgstr[1] "%i Sekunden" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tQualität: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Konferenz" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Eigenes Telefon" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Pixmapdatei %s kann nicht gefunden werden." - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Sendevorgang..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Nachricht nicht gesendet" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Kopieren" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "Ausgabe von Debug-Informationen auf stdout während der Laufzeit" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "Version anzeigen und beenden." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "Pfad zu einer Datei, in die Protokolle geschrieben werden." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Linphone mit ausgeschaltetem Video starten." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Nur im Systemabschnitt der Kontrollleiste starten, aber das Hauptfenster nicht zeigen." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "Im Moment anzurufende Adresse" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Geben Sie einen Arbeitsordner an (sollte der Installationsordner sein, z. B. C:\\Programme\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Konfigurationsdatei" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Starte den Audio-Assistent" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Selbsttest ausführen und mit 0 beenden, wenn erfolgreich" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Bitte geben Sie Ihr Passwort für den Benutzernamen %s\n für Bereich %s ein:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Anruf fehlgeschlagen" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Anruf beendet" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Eingehender Anruf" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Annehmen" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Abweisen" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Anruf wird gehalten" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "von %s" - -#: ../gtk/main.c:1336 -#, 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:1502 -msgid "Website link" -msgstr "Website-Verknüpfung" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Ein Internet-Video-Telefon" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Vorgabe)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Vermittlung nach %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Auf diesem Rechner können keine Soundkarten gefunden werden.\nSie können keine Audio-Anrufe tätigen oder entgegennehmen." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Ein freies SIP-Video-Telefon" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Hallo\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Zum Adressbuch hinzufügen" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Im %s-Verzeichnis suchen" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Ungültiger SIP-Kontakt!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Neuen Kontakt hinzufügen" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Kontakt „%s“ bearbeiten" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Kontakt „%s“ löschen" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Lösche Gesprächshistorie von '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Einen neuen Kontakt aus dem %s-Verzeichnis hinzufügen" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Name" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Rate (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Status" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "IP Bit-Rate (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parameter" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Freigegeben" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Gesperrt" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Konto" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Englisch" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Französisch" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Schwedisch" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italienisch" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Spanisch" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Brasilianisches Portugiesisch" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polnisch" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Deutsch" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Russisch" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japanisch" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Niederländisch" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Ungarisch" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Tschechisch" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Chinesisch" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Traditionelles Chinesisch" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norwegisch" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Hebräisch" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Serbisch" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Arabisch" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Türkisch" - -#: ../gtk/propertybox.c:1246 -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:1332 -msgid "None" -msgstr "Keinen" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Eine neuere Version ist von %s verfügbar.\nMöchten Sie einen Browser zum Herunterladen öffnen?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Sie verwenden bereits die aktuellste Version." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Vorname, Nachname" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Fehler bei der Kommunikation mit dem Server." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Verbinden..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Verbunden" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Daten werden empfangen..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "%i Kontakt gefunden" -msgstr[1] "%i Kontakte gefunden" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Benutzername wird bereits verwendet!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Fehler beim Überprüfen der Benutzernamenverfügbarkeit. Bitte versuchen Sie es später erneut." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Anruf #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Vermittlung zum Anruf #%i mit %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Nicht verwendet" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE nicht aktiviert" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE fehlgeschlagen" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE läuft" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Ein oder mehrere NATs werden durchquert" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Direkt" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Über einen Relay-Server" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP nicht aktiviert" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP läuft" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnp nicht verfügbar" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP läuft" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP fehlgeschlagen" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Direkt oder über Server" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "Herunterladen: %f\nHochladen: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f bps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f Sekunden" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Auflegen" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Verbindungsaufbau..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Eingehender Anruf" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "gut" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "durchschnittlich" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "schlecht" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "sehr schlecht" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "zu schlecht" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "nicht verfügbar" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Gesichert durch SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Gesichert durch DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Gesichert durch ZRTP - [Auth.-Token: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Auf „Ungeprüft“ setzen" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Auf „Geprüft“ setzen" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "In Konferenz" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "Im Gespräch" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Gehaltener Anruf" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Anruf beendet." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Vermittlung läuft" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Vermittlung abgeschlossen." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Vermittlung fehlgeschlagen." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Fortsetzen" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Halten" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Recording into\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(pausiert)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Bitte geben Sie die Anmeldeinformationen für %s ein." - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "abrufen von %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Herunterladen der Fernkonfiguration von %s fehlgeschlagen" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Keine Stimme ermittelt" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "zu gering" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "gut" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "zu laut" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Haben Sie die drei Signaltöne gehört?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Toneinstellungen nicht gefunden" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Systemtonsteuerung kann nicht gestartet werden" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Willkommen!\nDieser Assistent hilft Ihnen die Audioeinstellungen für Linphone einzurichten." - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Aufnahmegerät" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "aufgenommene Lautstärke" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Keine Stimme" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Systemtoneinstellungen" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Wiedergabegerät" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "spiele drei Pieptöne ab" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Drücken Sie den Aufnahmeknopf und sagen Sie etwas" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Hören Sie das Aufgenommene" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Aufnahme" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Wiedergabe" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Linphone jetzt starten" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Audio-Assistant" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Audio-Assistant" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Einrichtung MIkrofonverstärker" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Einrichtung Lautstärke" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "aufnehmen und abspielen" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Fertigstellen" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Über Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Ein Internet-Video-Telefon, das das Standard-SIP-Protokoll (RFC3261) verwendet." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Kontakte im Verzeichnis suchen" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Zur Kontaktliste hinzufügen" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Kontaktsuche" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Name des Angerufenen" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Anrufchronik" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Alle löschen" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Anrufen" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Anrufstatistik" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Audiocodec" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Videocodec" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Genutzte IP-Bandbreite Audio" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Audio-Konnektivität" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Genutzte IP-Bandbreite Video" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Video-Konnektivität" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Umlaufzeit" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Videoauflösung empfangen" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Videoauflösung gesendet" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "RTP-Profil" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Anrufstatistik und -informationen" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Senden" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Konferenz beenden" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Eine URI zur FErnkonfiguration angeben" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Diese Maske erlaubt Ihnen für das Laden der Konfiguration beim Programmstart eine http- oder https-Adresse anzugeben.\nBitte geben Sie unten die Konfigurations-URI ein oder ändern diese. Nach dem Bestätigen mit OK wird Linphone automatisch neustarten, um die neuen Einstellungen zu übernehmen." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP-Adresse" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Anwesenheitsstatus dieses Kontakts zeigen" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Diesem Kontakt erlauben, meinen Anwesenheitsstatus zu sehen" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Kontaktinformationen" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "DSCP-Einstellungen" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Audio-RTP-Datenstrom" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Video-RTP-Datenstrom" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "DSCP-Werte setzen (hexadezimal)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Klicken Sie hier, um die Lautsprecherlautstärke festzulegen" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Speichere den Anruf in eine Audio-Datei" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Video" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Stumm" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Vermittlung" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "Im Gespräch" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Dauer" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Bewertung der Verbindungsqualität" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "LDAP-Einstellungen" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Server-Adresse" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Authentifizierungsmethode" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Benutzername:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Passwort:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "TLS-Verbindung verwenden" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Aktuell nicht verfügbar" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Verbindung" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "Bind-DN" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Authentifizierungsname" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Bereich" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Basis-Objekt:" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "Filter (%s nach Name):" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Name:" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "SIP-Adresse:" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "Sucheigenschaft:" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Suche" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Zeitüberschreitung bei der Suche:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "Max Ergebnisse:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "folge Pseudonymen" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Sonstiges" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "ANONYMOUS" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "SIMPLE" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "DIGEST-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Benutzername" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Passwort" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Internetverbindung:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Automatisch anmelden" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Benutzer-ID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Anmeldeinformationen" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Willkommen!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Glasfaserkabel" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone Debug-Fenster" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Ans Ende rollen" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Vorgabe" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Löschen" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Optionen" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Konfigurations URI angeben" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Video immer starten" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Selbstansicht ein" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Tastatur anzeigen" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "Kontakte aus vCards importieren" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "Kontakte als vCards exportieren" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Hilfe" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Debug-Fenster anzeigen" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Homepage" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Auf _Aktualisierungen überprüfen" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Konto-Einrichtungsassistent" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP-Adresse oder Telefonnummer:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Einen neuen Anruf beginnen" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Kontakte" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Suchen" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Kontakte aus einem Verzeichnis hinzufügen" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Kontakt hinzufügen" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Anrufchronik löschen" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Aktuelle Identität:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Automatische Antwort ist aktiviert" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "Anonym" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "Standard-Soundkarte" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "eine Soundkarte" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "Standard-Kamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Audiocodecs" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Videocodecs" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Einstellungen" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "In diesem Bereich legen Sie Ihre SIP-Adresse fest, wenn Sie kein SIP-Konto verwenden." - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Ihr angezeigter Name (z. B. Heinz Müller):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Ihr Benutzername:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Sich ergebende SIP-Adresse:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Standard-Identität" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Assistent" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Hinzufügen" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Bearbeiten" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Entfernen" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Proxy-Konten" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Alle Passwörter löschen" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Privatsphäre" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Automatisch antworten, wenn ein Anruf eingeht" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Verzögerung vor der Beantwortung (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Automatische Antwort" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "SIP-Konten verwalten" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Klingelton:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Spezielles ALSA-Gerät (optional):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Aufnahmegerät:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Gerät für Klingelton:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Wiedergabegerät:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Echounterdrückung ein" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Audio" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Video-Aufnahmegerät:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Bevorzugte Videoauflösung:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Methode zur Videoausgabe" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Kameravorschau anzeigen" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Videovoreinstellung:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Bevorzugte Videobildfrequenz:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 bedeutet „unbegrenzt“" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Video" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Upload-Bandbreite (kbit/sec):" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Download-Bandbreite (kbit/sec):" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Adaptive Ratenregelung ein" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Adaptive Ratenregelung ist eine Technik zur dynamischen Abschätzung der zur Verfügung stehenden Bandbreite während eines Anrufs." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Bandbreiten-Einstellungen" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Multimedia-Einstellungen" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Maximum Transmission Unit setzen:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "DTMFs als SIP-Info senden" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "IPv6 erlauben" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Übertragung" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "SIP/UDP Port" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Zufällig" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "SIP/TCP Port" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Audio RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Fest" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Video RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunnel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP-Felder" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Netzwerkprotokoll und Ports" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Direkte Verbindung ins Internet" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Hinter NAT / Firewall (Gateway IP angeben)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Hinter NAT / Firewall (STUN verwenden)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Hinter NAT / Firewall (ICE verwenden)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Hinter NAT / Firewall (uPnP verwenden)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Öffentliche IP-Adresse:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "STUN-Server:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT und Firewall" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Verschlüsselungstyp der Medien" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "Lime für ausgehende Chatnachrichten verwenden" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Medienverschlüsselung erzwingen" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "Verbindlich" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "Bevorzugt" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Verschlüsselung" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Netzwerkeinstellungen" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Freigeben" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Sperren" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Audiocodecs" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Videocodecs" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Codecs" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Sprache" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Fortgeschrittene Einstellungen anzeigen" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Detaillierung" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Benutzeroberfläche" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "LDAP-Kontoeinrichtung" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Fertig" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Authentifikation erforderlich" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Bitte das Passwort der Domäne eingeben" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Einstellen..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Bitte warten Sie während die Einstellungen vom Server abgerufen werden..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "SIP-Konto-Einrichtungsassistent" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Willkommen!\nDieser Assistent hilft Ihnen dabei ein SIP-Konto einzurichten." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Willkommen zum Konto-Einrichtungsassistenten" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Ein Konto bei linphone.org erstellen." - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Ich habe bereits ein Konto bei linphone.org und möchte es jetzt benutzen." - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Ich habe bereits ein SIP-Konto und möchte es jetzt benutzen." - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Ich möchte eine URI zur Fernkonfiguration angeben" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Konto-Einrichtungsassistent" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Geben Sie Ihre Zugangsdaten ein" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Benutzername*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Passwort*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Domäne*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Konto einrichten (Schritt 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Geben Sie Ihren Benutzernamen bei linphone.org ein." - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Geben Sie Ihren SIP-Benutzernamen ein (Schritt 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) erforderliche Felder" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "E-Mail: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Benutzername: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Passwort: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Bestätigen Sie Ihr Passwort: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Halte mich über linphone Aktualisierungen auf dem laufenden" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Geben Sie Ihre Zugangsdaten ein (Schritt 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Ihr Konto wird erstellt, bitte warten." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Kontoerstellung läuft" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Bitte bestätigen Sie Ihr Konto, indem Sie auf die Verknüpfung klicken, die wir Ihnen soeben per E-Mail geschickt haben.\nDanach gehen Sie hierher zurück und drücken auf „Vor“." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Bestätigung (Schritt 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Es wird überprüft, ob Ihr Konto gültig ist, bitte warten." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Kontogültigkeitsprüfung läuft" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Fehler, Konto kann nicht bestätigt werden. Der Benutzername wird bereits\nverwendet oder der Server ist unerreichbar.\nBitte gehen Sie zurück und versuchen Sie es noch einmal." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Fehler" - -#: ../gtk/setup_wizard.ui.h:37 -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/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - SIP-Konto einrichten" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Ihre SIP-Identität:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Sieht aus wie sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP-Proxy-Adresse:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Sieht aus wie sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Registrierungsdauer (sec):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Kontaktdetails (optional)" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "AVPF Standard RTCP Interval (sek):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Route (optional):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Übertragung" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Registrieren" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Anwesenheitsstatus veröffentlichen" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Aktiviere AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "SIP-Konto einrichten" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "VoIP-Tunnel einrichten" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Host" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Port" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Tunnel einrichten" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Configure http proxy (optional)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Bitte warten" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Bereit" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Einstellen" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Verbindungsaufbau" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Anruf kann nicht getätigt werden." - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Die maximale Anzahl der gleichzeitigen Anrufe ist erreicht." - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "ruft Sie an" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr " und fragt nach automatischer Antwort." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Die Anrufparameter werden verändert..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Verbunden." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Anruf abgebrochen" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Anruf kann nicht gehalten werden" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Aktueller Anruf wird gehalten..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "STUN-Ermittlung läuft..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Lokale Kandidaten für ICE werden zusammengestellt..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Angemeldet" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Besetzt" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Bald wieder da" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Abwesend" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Im Gespräch" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Beim Essen" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Nicht stören" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Umgezogen" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Ein anderer Nachrichtendienst wird benutzt" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Abgemeldet" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Ausstehend" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "Urlaub" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Unbekannter Status" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "Die von Ihnen eingegebene SIP-Proxy-Adresse ist ungültig, sie muss mit „sip:“ gefolgt vom Hostnamen beginnen." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "Die von Ihnen eingegebene SIP-Identität ist ungültig.\nSie sollte wie sip:benutzername@proxydomain aussehen, also z.B. sip:alice@beispiel.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Telefonnummernziel wird gesucht..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Diese Nummer kann nicht aufgelöst werden." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Anmeldung als %s fehlgeschlagen" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "Wird auf %s aktualisiert..." - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Klingeln bei der Gegenseite." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Klingeln bei der Gegenseite..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "nicht kompatibel, prüfe Codecs oder Sicherheitseinstellungen..." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "Anruf wird von %s entgegengenommen" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Anruf fortgesetzt." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Inkompatibel, überprüfen Sie die Codecs oder die Sicherheitseinstellungen..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Inkompatible Medienparameter." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Anruf wird fortgesetzt." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Anruf wird von der Gegenseite gehalten." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "Anruf ist von der Gegenseite aktualisiert worden." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Anruf beendet." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Teilnehmer ist besetzt." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Teilnehmer zur Zeit nicht verfügbar." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Teilnehmer möchte nicht gestört werden." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Anruf abgewiesen" - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Zeitüberschreitung bei der Anfrage" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Umgeleitet" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Anruf fehlgeschlagen." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Registrierung auf %s erfolgreich." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Abmeldung von %s ist erfolgt." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "Zeitüberschreitung bei der Antwort" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Registrierung auf %s fehlgeschlagen: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Service nicht verfügbar, versuche erneut" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Authentifizierungs-Token ist %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Anrufparameter konnten nicht geändert werden: %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Anrufparameter wurden erfolgreich geändert." - -#: ../coreapi/linphonecall.c:4636 -#, 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." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "abgebrochen" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "abgeschlossen" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "verpasst" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "unbekannt" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "%s um %s\nVon: %s\nAn: %s\nStatus: %s\nDauer: %i Min. %i Sek.\n" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "Ausgehender Anruf" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Kann %s nicht wiedergeben." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/en@boldquot.header b/po/en@boldquot.header deleted file mode 100644 index fedb6a06d..000000000 --- a/po/en@boldquot.header +++ /dev/null @@ -1,25 +0,0 @@ -# All this catalog "translates" are quotation characters. -# The msgids must be ASCII and therefore cannot contain real quotation -# characters, only substitutes like grave accent (0x60), apostrophe (0x27) -# and double quote (0x22). These substitutes look strange; see -# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html -# -# This catalog translates grave accent (0x60) and apostrophe (0x27) to -# left single quotation mark (U+2018) and right single quotation mark (U+2019). -# It also translates pairs of apostrophe (0x27) to -# left single quotation mark (U+2018) and right single quotation mark (U+2019) -# and pairs of quotation mark (0x22) to -# left double quotation mark (U+201C) and right double quotation mark (U+201D). -# -# When output to an UTF-8 terminal, the quotation characters appear perfectly. -# When output to an ISO-8859-1 terminal, the single quotation marks are -# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to -# grave/acute accent (by libiconv), and the double quotation marks are -# transliterated to 0x22. -# When output to an ASCII terminal, the single quotation marks are -# transliterated to apostrophes, and the double quotation marks are -# transliterated to 0x22. -# -# This catalog furthermore displays the text between the quotation marks in -# bold face, assuming the VT100/XTerm escape sequences. -# diff --git a/po/en@quot.header b/po/en@quot.header deleted file mode 100644 index a9647fc35..000000000 --- a/po/en@quot.header +++ /dev/null @@ -1,22 +0,0 @@ -# All this catalog "translates" are quotation characters. -# The msgids must be ASCII and therefore cannot contain real quotation -# characters, only substitutes like grave accent (0x60), apostrophe (0x27) -# and double quote (0x22). These substitutes look strange; see -# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html -# -# This catalog translates grave accent (0x60) and apostrophe (0x27) to -# left single quotation mark (U+2018) and right single quotation mark (U+2019). -# It also translates pairs of apostrophe (0x27) to -# left single quotation mark (U+2018) and right single quotation mark (U+2019) -# and pairs of quotation mark (0x22) to -# left double quotation mark (U+201C) and right double quotation mark (U+201D). -# -# When output to an UTF-8 terminal, the quotation characters appear perfectly. -# When output to an ISO-8859-1 terminal, the single quotation marks are -# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to -# grave/acute accent (by libiconv), and the double quotation marks are -# transliterated to 0x22. -# When output to an ASCII terminal, the single quotation marks are -# transliterated to apostrophes, and the double quotation marks are -# transliterated to 0x22. -# diff --git a/po/es.po b/po/es.po deleted file mode 100644 index d166e8cb1..000000000 --- a/po/es.po +++ /dev/null @@ -1,2090 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Daniel S , 2016 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Spanish (http://www.transifex.com/belledonne-communications/linphone-gtk/language/es/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Llamar a %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Enviar mensaje a %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Añadir %s a la lista de contactos" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Llamadas recientes" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Llamadas recientes (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "n/a" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Abortado" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Perdida" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Rechazado" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minuto" -msgstr[1] "%i minutos" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i segundo" -msgstr[1] "%i segundos" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%sCalidad: %s\n%s⇥%s⇥" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s⇥%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Conferencia" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Yo" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "No se pudo encontrar el archivo pixmap: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Enviando..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Mensaje no enviado" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Copiar" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "registra a stdout cierta información de depuración durante la ejecución." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "mostrar versión y salir" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "ruta a un fichero donde escribir logs." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Iniciar linphone con el vídeo desactivado" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Iniciar sólo en la barra de tareas, no mostrar la interfaz principal." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "dirección a la que llamar inmediatamente" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Especifique un directorio de trabajo (debería ser la raíz de la instalación, ej: c:\\Archivos de Programa\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Fichero de configuración" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Iniciar el asistente de audio" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s quiere añadirle a su lista de contactos.\nQuieres añadirle a tu lista de contactos y permitirle que vea su estado de presencia?\nSi contesta no, esta persona será bloqueada temporalmente." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Por favor, introduzca la contraseña para el usuario %s\n en el dominio %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Error en llamada" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Llamada terminada" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Llamada entrante" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Contestar" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Rechazar" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Llamada en pausa" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "por %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s solicita iniciar vídeo. ¿Acepta?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Enlace a la Web" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Opción predeterminada)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Somos transferidos a %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "No se ha encontrado una tarjeta de sonido en este equipo.\nNo será posible realizar o recibir llamadas de audio." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Un video-teléfono SIP gratuito" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Hola\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Añadir a la agenda" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Buscar en el directorio %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "¡Contacto SIP no válido!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Añadir un contacto nuevo" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Editar contacto '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Eliminar contacto '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Eliminar histórico de '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Añadir nuevo contacto desde el directorio %s" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Nombre" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Frecuencia (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Estado" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parámetros" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Activado" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Desactivado" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Cuenta" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Inglés" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Francés" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Sueco" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italiano" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Español" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Portugués de Brasil" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polaco" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Alemán" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Ruso" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japonés" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Holandés" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Húngaro" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Checo" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Chino" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Chino Tradicional" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Noruego" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Hebreo" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Serbio" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Árabe" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Turco" - -#: ../gtk/propertybox.c:1246 -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:1332 -msgid "None" -msgstr "Ninguno." - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Una nueva versión está disponible en %s.\n¿Desea abrir el navegador para descargarla?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Ya está corriendo la última versión disponible." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Nombre, Apellidos" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Error al comunicar con el servidor." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Conectando..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Conectado" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Recibiendo datos..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Se encontró %i contacto" -msgstr[1] "Se encontraron %i contactos" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Llamar a #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Transferir a llamada #%i con %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Sin uso" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE no activo" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE ha fallado" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE en progreso" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Atravesando uno o más NATs" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Directo" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "A través de un servidor de relay" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP no activado" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP en progreso" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnp not disponible" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP en ejecución" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP ha fallado" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Directo o a través del servidor" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "bajada: %f\nsubida: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f segundos" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Colgar" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Llamando..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Llamada entrante" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "buena" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "media" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "mala" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "muy mala" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "demasiado mala" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "no disponible" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Cifrada con SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Cifrada con DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Cifrada con ZRTP - [token de autenticación: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Set sin verificar" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Set verificado" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "En conferencia" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "En conversación" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Llamada en pausa" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Llamada finalizada." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Transfiriendo llamada" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Transferido correctamente" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Transferencia fallida" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Reanudar" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pausar" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Grabando en\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Pausada)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Por favor, introduzca los datos de inicio de sesión para %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "cargando desde %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Descarga de la configuración remota desde %s fallida." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "No se detectó voz" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Demasiado bajo" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Buena" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Demasiado alto" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "¿Escuchaste los tres pitidos?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Preferencias de sonido no encontradas" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "No se pudo arrancar el control de sonido del sistema" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Bienvenido!\nEste asistente le ayudará a configurar el audio para Linphone." - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Dispositivo de captura:" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Volumen grabado" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "No hay voz" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Preferencias de audio del sistema" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Dispositivo de reproducción:" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Reproducir tres pitidos" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Use el botón de grabar y diga unas palabras" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Escucha tu grabación de voz" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Grabar" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Reproducir" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Iniciar Linphone ahora" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Asistente de sonido" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Asistente de sonido" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Calibración de ganancia de microfono" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Calibración de volumen de altavoz" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Grabar y reproducir" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Finalizando" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Sobre Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Un vídeo-teléfono a través de Internet que usa el protocolo estándar SIP (rfc3261)" - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Buscar contactos en directorio" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Añadir a mi lista" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Buscar a alguien" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Nombre del destinatario" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Registro de llamadas" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Borrar todos" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Devolver llamada" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Estadística de llamada" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Códec de Audio" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Códec de vídeo" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Resolución de vídeo recivida" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Resolución de vídeo enviada" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "Perfil RTP" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Estadísticas de llamada e información" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Enviar" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Terminar conferencia" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Especificando una URI remota de configuración" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Esta ventana le permite fijar una dirección http o https para que la configuración sea cargada en el arranque.\nPor favor, introduzca o modifique la URI. Después de aceptar, Linphone se reiniciará automáticamente para cargar la configuración y la nueva cuenta." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "Dirección SIP" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Mostrar el estado de presencia de este contacto" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Permitir que este contacto vea mi estado de presencia" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Información de contacto" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "Configuración DSCP" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Volumen del altavoz" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Graba esta llamada a un fichero de audio" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Vídeo" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Silenciar" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Transferir" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "En conversación" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Duración" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Calidad de la llamada" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "Configuración LDAP" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Dirección del Servidor:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Método de autenticación:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Nombre de usuario:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Contraseña:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "Usar conexión TLS" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "No disponible" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Conexión" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Buscar" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Otros" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "ANONIMO" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "SIMPLE" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "DIGEST-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Nombre de usuario" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Contraseña" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Conexión a Internet" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Iniciar sesión automáticamente" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "UserID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Datos de inicio de sesión" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Bienvenido/a!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Canal de Fibra" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Ventana de depuración de linphone" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Ir al final" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Por defecto" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Borrar" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Opciones" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Especificar URI de configuración" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Siempre iniciar vídeo" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Activar vista propia" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Mostrar marcador" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Ayuda" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Mostrar ventana de depuración" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Pagina_de_Inicio" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Buscar_Actualizaciones" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Asistente de configuración de cuenta" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "Dirección SIP o número de teléfono" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Iniciar nueva llamada" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Contactos" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Buscar" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Añadir contactos desde un directorio" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Añadir contacto" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Borrar registro de llamadas" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Mi identidad actual:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Autoanswer está activado" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "anónimo" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "tarjeta de sonido predeterminada" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "una tarjeta de sonido" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "cámara predeterminada" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Códecs de Audio" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Códecs de Vídeo" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Configuración" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Esta sección define su dirección SIP cuando no utiliza una cuenta SIP" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Su nombre a mostrar (x ej: Pepito Pérez):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Su nombre de usuario:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Su dirección SIP resultante:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Identidad predeterminada" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Asistente" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Añadir" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Editar" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Eliminar" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Cuentas Proxy" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Borrar todas las contraseñas" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Privacidad" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "si está activo, responder a llamadas entrantes automáticamente" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Retraso antes de contestar (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Auto-answer" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Gestionar cuentas SIP" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Tono de llamada:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Dispositivo especial ALSA (opcional):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Dispositivo de captura:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Dispositivo de Ring:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Dispositivo de reproducción:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Activar cancelación de eco" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Audio" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Dispositivo de entrada de vídeo:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Resolución de vídeo preferida:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Dispositivo de salida de vídeo:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Mostrar vista previa de la cámara" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Framerate de vídeo preferido:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 significa \"ilimitado\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Vídeo " - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Velocidad límite de subida en Kbit/seg" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Velocidad límite de descarga en Kbit/seg:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Activar control de frecuencia adaptativo" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Control de frecuencia adaptativo es una técnica que estima dinámicamente el ancho de banda disponible durante la llamada." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Control de ancho de banda" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Configuración multimedia" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Fijar Unidad de Transmisión Máxima:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Enviar DTMFs como información SIP" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Soportar IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Transporte " - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "Puerto SIP/UDP" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Aleatorio" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "Puerto SIP/TCP" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Audio RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Fijo" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Vídeo RTP/UDP" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "Campos DSCP" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Protocolo de red y puertos" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Conexión directa a Internet" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Tras un NAT/Firewall (especificar la IP de la puerta de enlace)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Tras un NAT/Firewall (utilizar STUN para resolver)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Tras un NAT/Firewall (utilizar ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Tras un NAT/Firewall (utilizar uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Dirección IP pública:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Servidor STUN" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT y Firewall" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Tipo de cifrado de medios" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Es obligatorio el cifrado de medios" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Configuración de red" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Activar" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Desactivar" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Códecs de audio" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Códecs de vídeo" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Códecs" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Idioma" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Mostrar opciones avanzadas" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Nivel" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Interfaz de Usuario" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "Configuración de cuenta LDAP" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Hecho" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Autenticación necesaria" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Por favor introduzca la contraseña del dominio" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Configurando..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Por favor, espere mientras se carga la configuración del servidor..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "Asistente de configuración de cuenta" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "¡Bienvenido/a !\nEste asistente le ayudará a utilizar una cuenta SIP para sus llamadas." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Bienvenido al asistente de configuración de cuenta" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Crear una cuenta en linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Ya tengo una cuenta en linphone.org y quiero usarla" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Ya tengo una cuenta SIP y quiero usarla" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Quiero indicar una URI remota de configuración" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Asistente de configuración de cuenta" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Información de cuenta" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Nombre de usuario*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Contraseña*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Dominio*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Configurar una cuenta (paso 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Introduzca su nombre de usuario de linphone.org" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Introduzca su nombre de usuario SIP (paso 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Campos obligatorios" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "Email: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Nombre de usuario: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Contraseña: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Confirme su contraseña: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Informame de las actualizaciones de linphone" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Introduzca la información de su cuenta (paso 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Su cuenta esta siendo creada, por favor espere." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Creando cuenta" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Por favor confirme su cuenta haciendo click en el link que la hemos enviado a su email.\nLuego vuelva y presione el botón Siguiente." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Validación (paso 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Comprobando si su cuenta ha sido validada, por favor espere." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Validación de cuenta en progreso" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Error, cuenta no validada, el nombre de usuario esta en uso o no se puede acceder al servidor.\nPor favor, vaya atrás y vuelva a intentarlo." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Error" - -#: ../gtk/setup_wizard.ui.h:37 -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/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Configurar una cuenta SIP" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Su identidad SIP" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Del tipo sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "Dirección del SIP Proxy" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Del tipo sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Duración del registro (seg):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Ruta (opcional):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Transporte" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Registrarse" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Publicar información de presencia" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Activar AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Configurar una cuenta SIP" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Configurar tunel VoIP" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Puerto" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Configurar tunel" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Configurara el proxy http (opcional)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Espere por favor" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Preparado" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Configurando" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Contactando" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "No se pudo llamar" - -#: ../coreapi/linphonecore.c:3228 -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:3388 -msgid "is contacting you" -msgstr "le está llamando" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "y ha solicitado auto respuesta." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Modificando parámetros de llamada…" - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Conectado." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Llamada abortada" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "No se pudo pausar la llamada" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Pausando la llamada actual..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Búsqueda STUN en proceso…" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Recolección de candidatos ICE locales en progreso..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Conectado" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Ocupado" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Vuelvo enseguida" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Ausente" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Al teléfono" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "A comer" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "No molestar" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Fuera" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Utilizando otro servicio de mensajería" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Desconectado" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Pendiente" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Estado desconocido" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "La dirección del Proxy SIP que ha introducido no es válida, debe empezar con \"sip:\" seguido del hostname." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "La identidad SIP que ha introducido no es válida.\nDebe ser del tipo sip:username@proxydomain, como por ejemplo sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Buscando el número de teléfono del destinatario…" - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "No se ha podido resolver este número." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "No se pudo iniciar sesión como %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "Cargando desde %s" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "El destinatario está sonando..." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "El destinatario está sonando..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Medios iniciales." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "Llamada respondida por %s" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Llamada reanudada." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Incompatible, compruebe la configuración de códecs o de seguridad..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Parámetros de media incompatibles" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Nos han reanudado..." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Nos han pausado." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "La llamada ha sido actualizada por el destinatario." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Llamada finalizada." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "El usuario está ocupado." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "El usuario no está disponible temporalmente." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "El usuario no quiere que le molesten." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Llamada rechazada." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Petición caducada (timeout)" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Redigirida" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "La llamada ha fallado." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Se ha registrado con éxito en %s." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Cancelación de registro en %s completada." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "timeout sin respuesta" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "El registro en %s ha fallado: %s." - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Servicio no disponible, reintentando" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "El tóken de autenticación es%s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Parámetros de llamada no pudieron ser modificados: %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Parámetros de llamada modificados correctamente." - -#: ../coreapi/linphonecall.c:4636 -#, 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." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "abortado" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "terminado" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "perdida" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "desconocido" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "%s a las %s\nDe: %s\nPara: %s\nEstado: %s\nDuración: %i mn %i sec\n" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "Llamada saliente" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "No se puede reproducir %s" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/fi.po b/po/fi.po deleted file mode 100644 index 5f8ffbe18..000000000 --- a/po/fi.po +++ /dev/null @@ -1,2090 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Matti Koivunen , 2016 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Finnish (http://www.transifex.com/belledonne-communications/linphone-gtk/language/fi/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fi\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Soita %s:lle" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Lähetä tekstiviesti %s:lle" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Lisää %s yhtestietoihin" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Viimeiset puhelut" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Viimeiset puhelut (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "tyhjä" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Kesketetty" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Puuttuu" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Estetty" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minuuttia" -msgstr[1] "%i minuuttia" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i sekunttia" -msgstr[1] "%i sekunttia" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tLaatu: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Kokous" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Minä" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Ei kyennyt lyötämään Pixmap kuvatiedostoa: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Lähetetään..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Viesti ei lähetetty" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Kopio" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "Kirjaudu 'stadardi viestin palautukseen' 'stdout' saadaksesi tietoja virheestä käytön aikana." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "Näytä versio ja poistu." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "polku tiedostolle johon loki kirjoitetaan." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Aloita linphone ilman videota." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Käynnistä vain tehtäväpalkki, älä pääkäyttöliittymää." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "osoite mihin nyt soitetaan" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Määritä työkansio (eli mihin asennus tehdään, kuten: c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Kokoonpano tiedosto" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Käytä ääni avustajaa" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Käytä omaa testiä ja poistu 0 jo valmis" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s haluaa lisätä sinut yhteystitohinsa.\nHaluatko hänen näkevän sinun läsnäolosi?\nJos ei, niin hänet lisätään hetkeksi mustalle listalle." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Anna salasana käyttäjänimelle %s\nmaasta %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Virhe puhelussa" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Puhelu päättyi" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Tuleva puhelu" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Vastaa" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Hylkää" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Puhelu laitettu tauolle" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "%s toimesta" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s pyytää video kuvaa. Sallitaanko?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Internet linkki" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Internet video puhelu" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Vakio)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Olemme siirtyneet %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Tähässä tietokeneessa ei ole havaittavissa ääni korttia.\nEt voi lähettää tai vastaanottaa äänellisiä puheluita." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Ilmainen SIP video puhelin." - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Hei\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Lisää osoitekirjaan" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Etsi %s hakemistosta" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Kelvoton sip yhtyestieto !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Lisää uusi yhteystieto" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Muokkaa yhteystietoa '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Poista yhteysto '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Poista '%s'n keskustelu historia" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Lisää uusi yhteystieto %s hakemistoon" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Nimi" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Laatutaso (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Tila" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "IP Siirtonopeus (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Raja-arvot" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Sallittu" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Kielletty" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Tili" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "eglaniksi" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "French" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Swedish" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italian" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Spanish" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Brazilian Portugese" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polish" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "German" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Russian" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japanese" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Dutch" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Hungarian" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Czech" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Chinese" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Traditional Chinese" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norwegian" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Hebrew" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Serbian" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Arabic" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Turkish" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "Sinun tarvitsee uudelleen käynnistää linphone, että uudet kieliasetukset tulevat voimaan." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Ei mitään" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP 'realiaikainen salaus'" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS 'paketti kytketty salaus'" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP 'tunnusteleva realiaikainen salaus'" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Uudempi versio on saatavilla: %s\nHaluatko avata selaimen ja ladata sen? " - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Käytät viimeisintä versiota." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Etunimi,Sukunimi" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Virhe palvelimen yhteyden pidossa" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Yhdistää..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Yhdistetty" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Vastaanottaa tietoa..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Lydetty %i yhteystietoa" -msgstr[1] "Lydetty %i yhteystietoa" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Käyttäjätunnus on jo käytössä!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Käyttäjätunnuksen saatavuuden tarkistus epäonnistui. Yritä uudelleen myöhemmin. " - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Puhelu #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Siirrä puhelu #%i %s kanssa" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Ei ole käytössä" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE 'vuorovaikutteinen yhteys' ei ole toiminnassa" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE 'vuorovaikutteinen yhteys' epäonnistui" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE 'vuorovaikutteinen yhteys' toiminnassa" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Menee läpi yhden tai useamman NAT-ositemuutoksen" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Suoraan" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Läpi välityspalvelimen" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP 'laite tunnistus' ei ole toiminnassa" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP 'laite tunnistus' on toiminnassa" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnP 'laite tunnistus' ei ole saatavilla" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP 'laite tunnistus' on käytössä" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP 'laite tunnistus' epäonnistui" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Suoraan tai palvelimen kautta" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "lataa: %f\nlähettää: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f fps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f sekunttia" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Katkaise puhelu" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Soittaa..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "tuleva puhelu" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "hyvä" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "keskiverto" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "heikko" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "todella heikko" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "liian huono" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "saavuttamattomissa" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Käytä SRTP salausta" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Käytä DTLS salausta" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Käytä ZRTP salausta - [todennustunnus: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Aseta vahvistamattomaksi" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Aseta vahvistetuksi" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "Kokouksessa" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "Puhuu puhelua" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Puhelu laitettu tauolle" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Puhelu loppu." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Siirto käynnissä" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Siirto tehty." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Siirto epäonnistui." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Yritä uudelleen" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pysäytä" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Nauhoita\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Pysäytetty)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Anna kirjautumistiedot %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "hae: %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Etäsäätöjen lataus %s :stä epäonnistui." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Laitetta ei havaittu" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Liian hiljainen" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Hyvä" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Liian kova ääninen" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Kuulitko kolme piippausta ?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Toivottuja ääniasetuksia ei löytynyt" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Ei voi käynnistää järjestelmän äänien hallintaa" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Tervetuloa!\nTämä avustaja auttaa sinua Linphonen ääniasetuksissa" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Tallennus laite" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Tallennuksen äänen voimakkuus" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Äänetön" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Järjestelmän toivotut ääni asetukset" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Kaiutin laite" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Anna kolme piippausta" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Paina nauhoita nappulaa ja sano muutamia sanoja" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Kuuntele nauhoittamasi puhe" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Nauhoita" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Toista" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Käynnitetäänpä Linphone nyt" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Ääni avustaja" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Ääni avustaja" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Mikrofooni tulon kalibrointi" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Kaiuttimen kalibrointi" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Nauhoita ja Toista" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Lopeta" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Tietoja Linphonesta" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Internet video puhelin, joka kyttää SIP (rfc3261) protokollaa." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \nfi: Matti Koivunen\n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Etsi yhteystietoja hakemistosta" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Lisää minun listaan" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Etsi henkilöä" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Soitettu" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Soitetut" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Tyhjennä kaikki" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Soita takaisin" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Soitto tilastot" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Äänen codec 'pakkaus'" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Videon codec 'pakkaus'" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Äänen käyttämä IP kaistaleveys " - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Ääni tiedon yhdistettävyys" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Videon käyttämä IP kaistaleveys" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Video tiedon yhdistettävyys" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Kierto aika" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Saatu videon tarkkuus" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Lähetetty videon tarkkuus" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "RTP 'realiaikaisen videon' profiili" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Puhelu tilastot ja tiedot" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Lähetä" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Päätä kokous" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Määritetään etäsäätöjä, URI-osoite" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Anna alapuolelle muokattu URI, eli http tai https. Kun olet painanut OK, Linphone uudelleen käynnistyy ja hakee tilin uudet säädöt." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP osoite" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Näytä henkilön läsnäolo" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Anna lupa tälle henkilölle nähdä läsnäoloni" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Yhteystiedot" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "DSCP 'pakettien erittely' asetukset" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Äänen RTP stream 'realiaikainen virta'" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Videon RTP stream 'realiaikainen virta'" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Aseta DSCP 'pakettien erittely' arvot (heksadesimaaleina)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Paina tästä asettaaksesi kaiuttimien äänen voimakkuuden" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Nauhoita tämä puhelu äänitiedostoksi" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Video" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Mykkä" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Siirto" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "Puhelussa" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Pituus" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Puhelun laadun luokitus" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "LDAP 'Käyttäjän tunnistus' asetukset" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Palvelimen osoite:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Todennus menetelmä:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Käyttäjätunnus:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Salasana:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "Käytä TLS 'lähetyksen salaus' yhteyttä" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Ei vielä saatavilla" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Yhteys" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "Käyttäjän tunnistus: yhdistä DN nimeen" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Valtuutettu nimi" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Realm 'hallittu alue'" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL 'yksinkertainen tunnistus ja salaus'" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Perus kohde:" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "Suodatin (%s nimelle)" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Nimen tuntomerkit" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "SIP osoitteen tuntomerkki:" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "Tuntomerkkiä jonossa" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Hae" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Haun aikakatkaisu:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "Tulosten yläraja:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "Seuraa peitenimiä" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Sekalaiset" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "ANONYYMI" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "YKSINKERTAINEN" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "DIGEST-MD5 'tiivistetty käyttäjän tunnistus '" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM 'Microsoft käyttäjän tunnistus'" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Käyttäjätunnus" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Salasana" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Internet yhteys:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Automaattisesti kirjaudu sisään" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Käyttäjän tiedot" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Kirjautumistiedot" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Tervetuloa!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Kuitu kanava" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone virheen korjaus ikkuna" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Vieritä loppuun" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Vakio" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Poista" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Valinnat" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Aseta URI säädöt" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Aloita aina videon kanssa" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Näytä omakuva" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Näytä näppäimistö" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Apua" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Näytä virheen korjaus ikkuna" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Kotisivu" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Tarkista _Päivitykset" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Käyttäjätili avustaja" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP osoite tai puhelin numero" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Aloita uusi puhelu" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Yhteystiedot" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Hae" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Lisää yhteystiedot hakemistosta" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Lisää yhteystieto" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Tyhjennä puhelu historia" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Minun nykyinen henkilllisyys" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Automaattinen vastaaminen käytössä" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "anonyymi" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI 'tietoturva ohjelmointi käskypohja'" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL 'yksinkertainen salaus'" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "vakio äänikortti" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "äänikortti" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "vakio kamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF 'keskimääräinen kuvan tarkkuus'" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Ääni pakkaukset 'codecs'" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Video pakkaukset 'codecs'" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP 'siirto ilman yhteyttä')" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP 'luotettu siirto tavuttain')" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS 'siirto SSL varmentimilla')" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Asetukset" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Tämä osio märittää sinun SIP osoitteen kun et käytä SIP tiliä" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Sinun näyttö nimi (esim: Matti Meikäläinen):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Sinun käyttäjänimi:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Tuloksena sinun SIP osoitteesi on:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Vakio henkilöllisyys" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Velho - automaattisäätö" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Lisää" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Muokkaa" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Poista" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Välityspalvelin tilit" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Poista kaikki salasanat" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Yksityisyys" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Automaattinen vastaus kun puhelu on saapunut" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Odota ennen vastaamista (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Automaattinen vastaaja" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Hallitse SIP tilejä" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Soittoääni:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "ALSA-'ääne parannus' erikoilaite (valinnainen):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Tallennus laite:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Soittoäänen laite:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Äänentoistolaite:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Käytä kaiun poistoa" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Ääni" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Videokuvan lähde:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Toivottu videon tarkkuus:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Videon ulostulo:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Näytä kameran esikatselu" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Video esiasetus:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Toivottu videon kuvataajuus:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 tarkoittaa \"rajoittamaton\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Video" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Lähetys nopeus raja Kbit/sec:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Lataus raja Kbit/sec:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Käytä mukautuvaa tason säätöä" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Mukautuva tason säätö arvailee käytettävissä olevan kastaleveyden puheun aikana." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Kastaleveyden hallinta" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Multimedia asetukset" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Aseta suurin siirto yksikkö:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Lähetä DTMF:t SIP infona" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Salli IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Siirto" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "SIP/UDP portti" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Satunnainen" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "SIP/TCP portti" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Ääni RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Korjattu" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Video RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunneli" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP kentät" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Veskko protokolla ja portti" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Suora yhteys internettiin " - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "NAT / Palomuurin takaa (määritä yhdyskäytävä IP)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "NAT-osoitteenmuunnoksen / Palomuurin takaa (käytä STUN:nia)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "NAT-osoitteenmuunnoksen / Palomuurin takaa (käytä ICE:tä)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "NAT-osoitteenmuunnoksen / Palomuurin takaa (käytä uPnP:tä)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Julkinen IP osoite:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Stun-palvelin eli 'osoitteenmuunoksen takaisin haku'-palvelin:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT-osoitteenmuunos ja Palomuuri" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Median salaus tyyppi" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "Käytä Lime:ä lähteviin viesteihin " - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Median salaus on pakollinen" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Salaus" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Verkko asetukset:" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Käytössä" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Poissa käytöstä" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Ääni codecs" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Video codecs" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Codecs" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Kieli" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Näytä edistyneet asetukset" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Taso" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Käyttöliittymä" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "LDAP Tili asetukset" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Tehty" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linhone - Tunnistautuminen vaaditaan" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Anna domain/verkkotunnussen salasana" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Säädetään..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Odota, säätöjä noudetaan palvelimelta..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "SIP tilin säätö avustaja" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Tervetuoa!\nTämä avustaja auttaa sinua käyttämään SIP tiliä puheluissasi. " - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Tervetuloa tili asetusten avustajaan" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Luo linphone.org tili" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Minulla on jo linphone.org tili ja haluan kayttää sitä" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Minulla on jo sip tilli ja haluan käyttää sitä" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Haluan täsmentää etäsäätöjä; URI-osoite" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Tili asetusten avustaja" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Anna tili tietosi" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Käyttäjätunnus*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Salasana*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Domain/verkkotunnus*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Välitysavelin" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Muokkaa tiliäsi (osa 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Anna linphone.org käyttäjätunnus" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Anna sip käyttäjätunnus (osa 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Vaaditus kohdat" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "Sähköposti: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Käyttäjätunnus: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Salasana: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Vahvista salasana: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Ilmoita linphone päivityksistä" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Anna tili tiedot (osa 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Sinun tiliäsi luodaan, pyydän odota." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Tilin luominen edistyy" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Vahvista tilisi avaamala linkin, joka on juuri lähetetty sähköpostiisi.\nSitten palaa ja paina seuraava." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Vahvistus (osa 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Tarkistetaan että tilisi on vahvistettu, pyydän odota." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Tarkistetaan tilin vahvistusta " - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Virhe, tili ei ole vahvistettu, käyttäjätunnus oli jo käytössä tai palvelin tavoittamattomissa.\nPyydän palaa ja yritä uudelleen." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Virhe" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Kiitos. Tilisi on muokattu ja valmis käyttöön." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Muokkaa SIP tiliä" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Sinun SIP henkilöllisyys:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Näyttää seuraavalta sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP välityspalvelin osoite:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Näyttää seuraavalta sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Rekisteröinnin kesto (sekunttia):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Yhteystiedot (valinnainen):" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "AVPF-'media siirto' tahdistusväli RTCP-'realiaikaisen tiedonsiirron' kanssa (sekunttia):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Reitti (valinnainen):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Siirto" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Rekisteri" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Julkaise läsnäolo tiedot" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Käytä AVPF:ää" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Muokkaa SIP tiliä" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Muokkaa VoIP tunnelia" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Host eli Verkon solmu" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Portti" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Muokkaa tunnelia" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Muokkaa http välityspalinta (valinnainen)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Odota" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Valmis" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Säädetään" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Yhdistetään" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Ei voinut soittaa" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Olen pahoillani, suurin yhtäaikaisten puheluiden määrä on saavutettu" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "on ottamassa yhteyttä sinuun" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "ja pyytää automaattista vastausta." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Maukataan soiton raja-arvoja..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Yhdistetty" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Puhelu keskeytetty" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Ei voinut laittaa puhelua tauolle" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Laitetaan tauolle nykyinen puhelu..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Stun-'osoite haun' lukkiutuminen käynnissä..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "ICE paikallisia ehdokkaita kerätään..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Verkossa" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Kiireinen" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Palaan pian" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Poissa" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Puhuu puhelua" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Syömässä" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Älä häiritse" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Siirtynyt" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Käyttää toista yhteys ohjelmaa" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Verkossa" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Odottaa" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "Lomalla" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Tuntematon tila" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "Antamasi välityspalvelin osoite on kelvoton. Se täytyy alkaa \"sip:\" minkä jälkeen tulee host-verkkosolmuntunnus." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "Antamasi sip tiedot ovat kelvoton.\nSen pitäisi näyttää sip:käyttäjätunnus@välityspalvelin, kuten sip:alice@esimerkki.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Etsitään puhelinnumeron kohdetta..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Ei voi käsittää tätä numeroa." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "%s ei pystynyt kirjautumaan" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "%s on huilaamassa..." - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "vastapuoli pirisee" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "vastapuoli pirisee..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Aikainen media eli aloita puhelu ennen yhteyden lukittautumista" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "Puheluun vastasi %s" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Puhelu jaettiin." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Yhteensopimaton, tarkista kodekit tai suojaus asetukset..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Yhteensopimattomat media raja-arvot." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Meidän puhelu on jaettu." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Meidän puhelu on laitettu taauolle toisen osapuolen taholta." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "Vastapuoli on päivittänyt puhelun." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Puhelu keskeytetty." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Käyttäjä on kiireinen." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Käyttäjä hetkellisesti tavoittamattomissa." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Käyttäjä ei halua tulla häirityksi." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Soitto evätty." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Soitto yritys aikakatkaistiin." - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Uudelleen ohjattu" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Puhelu epäonnistui." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Rekitöröityminen %sn onnistui." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Rekisterin poisto %s:stä on tehty." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "ei vastausta, aikakatkaistiin" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Rekistöröityminen %sn epäonnistui: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Palvelin saavuttamattomissa, uudelleen yritetään" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Todennus merkki on %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Soiton raja-arvoja ei voitu muokata: %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Soiton raja-arvot ovat onnistuneesti muokattu." - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "Sinulla on %i vastaamaton puhelu." -msgstr[1] "Sinulla on %i vastaamatonta puhelua." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "keskeytetty" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "valmis" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "vastaamaton" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "tuntematon" - -#: ../coreapi/call_log.c:234 -#, 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\nMistä: %s\nMihin: %s\nTila: %s\nKasto: %i minuuttia %i sekunttia\n" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "Lähtevä puhelu" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Ei voi toistaa %s." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/fr.po b/po/fr.po deleted file mode 100644 index 0b8c6ae59..000000000 --- a/po/fr.po +++ /dev/null @@ -1,2094 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Belledonne Communications , 2015-2016 -# Gautier Pelloux , 2014 -# Gautier Pelloux , 2014 -# Gautier Pelloux , 2014-2016 -# Simon Morlat , 2001 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:59+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: French (http://www.transifex.com/belledonne-communications/linphone-gtk/language/fr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Appeler %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Chatter avec %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Ajouter %s à la liste de contacts" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Appels récents" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Appels récents (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "inconnu" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Abandonné" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Manqué" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Refusé" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minute" -msgstr[1] "%i minutes" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i seconde" -msgstr[1] "%i secondes" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tQualité: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Conférence" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Moi" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Icone non trouvée: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Envoi en cours..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Message non envoyé" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Copier" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "affiche des informations de debogage" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "Afficher la version et quitter." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "chemin vers le fichier de logs." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Démarrer linphone avec la vidéo désactivée." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Démarre iconifié, sans interface principale." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "adresse à appeler maintenant" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Spécifie un répertoire de travail (qui devrait être le répertoire d'installation, par exemple c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Ficher de configuration" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Démarre l'assistant audio" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Exécuter le test local et retourner 0 en cas de succès" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s souhaite vous ajouter à sa liste de contact.\nSouhaitez vous l'ajouter à votre liste également et l'autoriser à voir votre information de présence ?\nSi vous répondez non, cette personne sera mise temporairement sur liste noire." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Entrez le mot de passe pour %s\n sur le domaine %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Erreur lors de l'appel" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Appel terminé." - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Appel entrant" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Répondre" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Refuser" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Appel en pause" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "b>par %s" - -#: ../gtk/main.c:1336 -#, 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:1502 -msgid "Website link" -msgstr "Lien site web" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Appels vidéo via internet" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (par défaut)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Transfert vers %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Aucune carte son n'a été détectée sur cet ordinateur.\nVous ne pourrez pas effectuer d'appels audio." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Un visiophone libre" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Bonjour\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Ajouter au carnet d'adresse" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Rechercher dans l'annuaire de %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Contact sip invalide !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Ajouter un nouveau contact" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Editer le contact '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Supprimer le contact '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Supprimer l'historique de chat de '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Ajouter un contact depuis l'annuaire %s" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Nom" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Fréquence (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Etat" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "Débit IP (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Paramètres" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Activé" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Désactivé" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Compte" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Anglais" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Français" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Suédois" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italien" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Espagnol" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Portugais brésilien" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polonais" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Allemand" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Russe" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "日本語" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Néérlandais" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Hongrois" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Tchèque" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "简体中文" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Chinois traditionnel" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norvégien" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Hébreu" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Serbe" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Arabe" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Turc" - -#: ../gtk/propertybox.c:1246 -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:1332 -msgid "None" -msgstr "Aucun" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Une version plus récente est disponible sur %s.\nVoulez vous ouvrir le navigateur afin de pouvoir télécharger la dernière version ?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Vous utilisez la dernière version." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Prénom, Nom" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Erreur de communication avec le serveur." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Connexion..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Connecté" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Reception des données" - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "%i contact trouvé." -msgstr[1] "%i contacts trouvés." - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Ce nom d'utilisateur est déjà pris." - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Impossible de vérifier la disponibilité de ce nom d'utilisateur. Veuillez réessayer plus tard." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Appel #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Transférer vers l'appel #%i avec %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Non utilisé" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE non activé" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "Erreur ICE" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "Négociation ICE en cours" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Via un ou plusieurs NATs" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "En direct" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Via un serveur relais" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP non activé" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP en cours" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnP est indisponible" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP en cours d’exécution" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP a échoué." - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Directe ou via un serveur" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "débit descendant : %f\ndébit ascendant : %f (kbits/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f fps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f secondes" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Raccrocher" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Tentative d'appel..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Appel entrant" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "bon" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "moyen" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "faible" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "très faible" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "nulle" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "indisponible" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Sécurisé par SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Sécurisé par DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Sécurisé par ZRTP- [jeton: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Marquer comme non vérifié" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Marquer comme vérifié" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "En conférence" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "Appel en cours" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Appel en attente" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Appel terminé." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Transfert en cours" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Transfert terminé" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Transfert échoué" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Reprendre" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pause" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Enregistrement dans\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(en attente)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Entrez vos identifiants pour %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "chargement depuis %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Le chargement de la configuration depuis %s a échoué." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Voix non détectée" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Trop bas" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Bien" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Trop bruyant" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Avez-vous entendu trois bips ?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Préférences son non trouvé" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Impossible de démarrer le contrôleur système du son" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Bienvenue !\nCet assistant va vous aider à régler les paramètres audio de votre ordinateur pour une utilisation optimale avec Linphone." - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Périphérique de capture" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Volume enregistré" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Silencieux" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Préférences son système" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Périphérique d'écoute" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Joue trois bips" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Appuyer sur le bouton enregistrer et dites quelques mots" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Ecoutez votre voix enregistrée" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Enregistrer" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Jouer" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Démarrons Linphone maintenant" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Assistant audio" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Assistant audio" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Calibration du gain du microphone" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Calibration du volume du haut parleur" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Enregistrer et joue" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "En cours d’arrêt." - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "À propos de Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Un visiophone pour l'internet, compatible SIP (rfc3261)" - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Rechercher dans l'annuaire" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Ajouter à ma liste" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Rechercher une personne" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Nom du correspondant" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Historique des appels" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Tout vider" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Rappeler" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Statistiques de l'appel" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Codec audio" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Codec vidéo" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Bande passante audio" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Connectivité audio" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Bande passante video" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Connectivité video" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Temps d'aller retour" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Taille de video reçue" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Taille de video envoyée" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "Profil RTP" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Statistiques de l'appel et informations" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Envoyer" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Fin de conférence" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Spécifier une URI de configuration" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -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.\nVeuillez 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/contact.ui.h:2 -msgid "SIP Address" -msgstr "Adresse SIP" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Voir l'état de présence de ce contact" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Autoriser ce contact à voir ma présence" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Information sur le contact" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "Réglages DSCP" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Flux RTP audio" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Flux RTP vidéo" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Indiquez les valeurs DSCP (en hexacdécimal)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Cliquer ici pour modifier le volume des haut-parleurs" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Enregistrement de l'appel dans un fichier audio." - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Vidéo" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Couper le micro" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Transférer" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "Appel en cours" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Durée" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Qualité de l'appel" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "Paramètres LDAP" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Adresse du serveur:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Méthode d'authentification:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Nom d'utilisateur:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Mot de passe:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "Utiliser TLS" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Non disponible" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Connexion" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "Assigner ND" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Nom d'authentification" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Realm" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Object de base :" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "Filtre (nom avec %s) : " - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Attribut nom :" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "Attribut pour l'addresse SIP:" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "Attributs à chercher:" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Rechercher" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Temps de recherche maximum:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "Nombre de résultats maximum:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "Suivre les alias" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Divers" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "ANONYME" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "SIMPLE" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "DIGEST-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Nom d'utilisateur" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Mot de passe" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Connexion internet:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Me connecter automatiquement" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "ID utilisateur" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Information de login" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Bienvenue !" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fibre optique" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Fenêtre de débogage de linphone" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Défiler jusqu'à la fin" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Par défaut" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Supprimer" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Options" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "URI de configuration" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Toujours activer la vidéo" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Se voir" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Afficher le pavé numérique" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "Importer des contacts depuis des vCards" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "Exporter les contacts en vCards" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Aide" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Fenêtre de débogage" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Site web" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "_Mises à jour" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Assistant de compte" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "Adresse SIP ou numéro" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Démarrer un nouvel appel" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Contacts" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Rechercher" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Ajouter un contact depuis l'annuaire" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Ajouter un contact." - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Effacer l'historique d'appel" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Mon identité SIP :" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Décrochage automatique activé" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "anonyme" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "Carte son par défaut" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "une carte son" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "camera par défaut" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Codecs audio" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Codecs vidéo" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Réglages" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Cette rubrique permet de définir son adresse SIP lorsqu'on ne possède pas de compte SIP" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Votre nom d'affichage (ex: John Doe)" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Votre nom d'utilisateur:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Votre adresse SIP:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Identité par défaut" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Assistant" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Ajouter" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Editer" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Enlever" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Comptes SIP via des proxy" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Effacer tous les mots de passe" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Sécurité" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Répondre automatiquement aux appels entrants" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Temps d'attente avant réponse (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Décrochage automatique" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Gérer mes comptes SIP" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Sonnerie:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Appareil ALSA spécifique (optionnel) :" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Périphérique de capture:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Périphérique de sonnerie:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Périphérique d'écoute:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Activer l'annulation d'écho" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Son" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Périphérique d'entrée vidéo" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Résolution vidéo préférée :" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Type de rendu video:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Afficher la vidéo" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Profile vidéo:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Fréquence d'images préférée" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "Indiquez 0 pour ne pas mettre de limite" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Video" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Limite de débit montant en kbits/sec:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Limite de débit descendant en kbits/sec:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Activer le control de débit adaptatif." - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Le control de débit adaptatif est une technique pour adapter la qualité de l'audio et de la video en fonction de la bande passante disponible, durant l'appel." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Gestion de la bande passante" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Paramètres multimedia" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Spécifier la Maximum Transmission Unit" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Envoyer les digits en tant que SIP INFO" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Utiliser IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Transport" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "Port SIP / UDP" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Aléatoire" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "Port SIP / TCP" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Audio RTP / UDP :" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Fixe" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Vidéo RTP / UDP :" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunnel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "Champs DSCP" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Protocoles réseaux et ports" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Connexion directe à l'Internet" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Derrière un pare-feu (spécifier la passerelle ci dessous)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Derrière un pare-feu (utiliser STUN)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Derrière un pare-feu (utiliser ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Derrière un pare-feu (utiliser uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Adresse IP publique:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Serveur STUN:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "Paramètres liés au pare-feu" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Type d'encryption media" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "Utiliser Lime pour les messages de discussions sortants" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Le chiffrement media est obligatoire" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "Obligatoire" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "Privilégié" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Chiffrement" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Paramètres réseau" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Activer" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Désactiver" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Codecs audio" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Codecs vidéo" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Codecs" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Langue" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Montrer les réglages avancés" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Niveau" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Interface utilisateur" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "Configuration LDAP" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Fermer" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Authentification demandée" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Entrez votre mot de passe pour le domaine" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Configuration en cours" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Veuillez patenter un instant pendant le chargement de la configuration distante..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "Assistant de configuration de compte." - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Bienvenue !\nCet assistant va vous aider à utiliser un compte SIP pour vos appels." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Bienvenue dans l'assistant de configuration de compte." - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Créer un compte sur linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "J'ai déjà un compte linphone.org et je souhaite l'utiliser" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "J'ai déjà un compte Sip et je souhaite l'utiliser" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Je veux spécifier une URI de configuration" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Assistant de configuration de compte." - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Entrez vos paramètres de compte" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Nom d'utilisateur*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Mot de passe*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Domaine*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Configurez votre compte (étape 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Entrez votre identifiant linphone.org" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Entrez votre identifiant sip (étape 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Champs requis" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "Email : (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Nom d'utilisateur: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Mot de passe: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Confirmez votre mot de passe: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Me tenir informé des mises à jour de Linphone " - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Entrez les informations concernant votre compte (étape 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Votre compte est en cours de création. Veuillez patienter." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Création du compte en cours" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Merci de valider votre compte en cliquant sur le lien que nous avons envoyé par email.\nPuis appuyez sur suivant." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Validation (étape 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Vérification que le compte a été validé. Veuillez patienter." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Vérification de la validité du compte en cours" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Erreur, le compte n'est pas validé, l'identifiant est déjà utilisé ou le serveur n'est pas accessible.\nMerci d'essayer à nouveau." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Erreur" - -#: ../gtk/setup_wizard.ui.h:37 -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/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Configurer un compte SIP" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Votre identité SIP :" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "De la forme sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "Adresse du proxy SIP:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "De la forme sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Période d'enregistrement (secondes):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Paramètres de contact (optionnel):" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "Intervalle standard RTCP AVPF (sec) :" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Route (optionnel):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Transport" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "S'enregistrer" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Publier la présence" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Activer AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Configurer un compte SIP" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Configuer le mode tunnel" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Hôte" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Port" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Configuration du tunnel" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Configuration d'un proxy http (optionel)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "En attente" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Prêt." - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Configuration en cours" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Appel de" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Echec de l'appel" - -#: ../coreapi/linphonecore.c:3228 -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:3388 -msgid "is contacting you" -msgstr "vous appelle" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "et sollicite un décrochage automatique." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Modifications des paramètres d'appels..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "En ligne." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Appel abandonné" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "La mise en attente a échoué" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Mise en attente de l'appel..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Découverte STUN en cours" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Collection des candidats locaux ICE en cours..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Disponible" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Occupé" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "De retour" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Absent" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Au téléphone" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "A table" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Ne pas déranger" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Parti" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Utilisation d'un autre service de messagerie" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Non connecté" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "En attente" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "En congé" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Status inconnu" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "L'adresse SIP du proxy est invalide. Elle doit commencer par \"sip:\" suivie par un nom de domaine." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "L'identité SIP que vous avez fourni est invalide.\nElle doit être de la forme sip:utilisateur@domaine, comme par exemple sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Recherche de la destination du numéro de téléphone..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "La destination n'a pu être trouvée." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Echec de la connexion en tant que %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "Rafraichissement de %s..." - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Sonnerie distante." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Sonnerie distante..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Prise d'appel anticipée." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "Appel répondu par %s" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Appel repris." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Incompatible, vérfiez les codecs ou les paramètres de sécurité..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Paramètres media incompatibles." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Appel repris." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "L'appel a été mis en attente." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "L'appel est modifié par la partie distante." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Appel terminé." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Occupé..." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "L'usager est temporairement indisponible." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "L'usager ne souhaite pas être dérangé" - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Appel décliné." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Délai d'attente de la requête dépassé." - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Redirection" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "L'appel a échoué." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Enregistrement sur %s effectué." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Désenregistrement sur %s effectué." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "Pas de réponse" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Echec de l'enregistrement sur %s: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Service indisponible, nouvelle tentative" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Le jeton d'authentification est %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Les paramètres d'appel n'ont pas pu être modifiés : %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Les paramètres d'appel ont été modifiés avec succès." - -#: ../coreapi/linphonecall.c:4636 -#, 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" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "interrompu" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "terminé" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "manqué" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "inconnu" - -#: ../coreapi/call_log.c:234 -#, 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\nDe : %s\nVers : %s\nStatus : %s\nDurée : %i min %i sec\n" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "Appel sortant" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Impossible de jouer %s." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "Capture d'écran" diff --git a/po/he.po b/po/he.po deleted file mode 100644 index bb53d7e06..000000000 --- a/po/he.po +++ /dev/null @@ -1,2094 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Eli Zaretskii , 2012 -# Gautier Pelloux , 2015 -# GenghisKhan , 2014 -# GenghisKhan , 2014,2016 -# GenghisKhan , 2012-2013 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Hebrew (http://www.transifex.com/belledonne-communications/linphone-gtk/language/he/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: he\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "התקשר %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "שלח טקסט אל %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "הוסף את %s לרשימת הקשר שלך" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "שיחות אחרונות" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "שיחות אחרונות (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "לא זמין (n/a)" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "ננטשה" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "הוחמצה" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "נדחתה" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "דקה %i" -msgstr[1] "%i דקות" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "שניה %i" -msgstr[1] "%i שניות" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tאיכות: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "ועידה" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "אני" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "לא ניתן למצוא קובץ ‫pixmap: ‫%s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "כעת שולח..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "הודעה לא נשלחה" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "העתק" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "נתיב לקובץ שברצונך לרשום אליו את הרשומות." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "התחל את לינפון עם וידאו מנוטרל." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "" - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "קובץ תצורה" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "אנא הזן סיסמה עבור משתמש %s\nבמתחם %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "שגיאת קריאה" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "שיחה הסתיימה" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "קריאה נכנסת" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "לענות" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "לדחות" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "שיחה הושהתה" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "על ידי %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "‏%s רוצה להתחיל וידאו. האם אתה מסכים ?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "קישור אתר רשת" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "וידאופון אינטרנטי" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "‫%s (ברירת מחדל)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "אנחנו מועברים אל %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "לא אותרו כרטיסי קול במחשב זה.\nלא תהיה ביכולתך לשלוח או לקבל שיחות אודיו." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "וידאופון SIP חופשי" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "שלום\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "הוסף אל ספר כתובות" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "חיפוש במדור %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "כתובת sip לא תקפה !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "הוסף איש קשר חדש" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "ערוך איש קשר '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "מחק איש קשר '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "מחק היסטוריית שיחה של '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "הוסף איש קשר חדש מן מדור %s" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "שם" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "שיעור (הרץ)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "מצב" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "פרמטרים" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "מופעל" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "לא מופעל" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "חשבון" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "English" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Français" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Svenska" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italiano" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Español" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "português brasileiro" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polski" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Deutsch" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Русский" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "日本語" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Nederlands" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Magyar" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Česky" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "中文" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "繁體字" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "norsk" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "עברית" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "српски srpski" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "עליך לאתחל את לינפון כדי שהשפה החדשה תיכנס לתוקף." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "ללא" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "גרסא מאוחרת יותר זמינה מן %s.\nהאם ברצונך לפתוח דפדפן בכדי להורידה ?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "ברשותך הגרסא האחרונה של לינפון." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "שם פרטי , שם משפחה" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "שגיאה בהתקשרות עם שרת." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "מתחבר כעת..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "מקושר" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "מאחזר כעת מידע..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "נמצא איש קשר %i" -msgstr[1] "נמצאו %i אנשי קשר" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "שם משתמש כבר מצוי בשימוש!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "שיחה מס׳ %i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "העברה אל שיחה מס׳ %i עם %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "לא בשימוש" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "‏ICE לא מופעלת" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "‏ICE נכשלה" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "‏ICE מצויה כעת בעיצומה" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "עובר דרך NAT אחד או יותר" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "ישיר" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "דרך שרת ממסר" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "‏uPnP לא מופעלת" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "‏uPnP מצויה כעת בעיצומה" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "‏uPnp לא זמינה" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "‏uPnP מורצת כעת" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "‏uPnP נכשלה" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "ישיר או דרך שרת" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "הורדה: %f\nהעלאה: %f (קי״ב/שנ׳)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f שניות" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "נתק" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "מתקשר כעת..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "קריאה נכנסת" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "טובה" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "ממוצעת" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "דלה" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "דלה מאוד" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "גרועה מדי" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "לא זמינה" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "מאובטחת על ידי SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "מאובטח על ידי DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "מאובטחת על ידי ZRTP - [אות אימות: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "הגדר כלא מאומתת" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "הגדר כמאומתת" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "בשיחת ועידה" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "בשיחה כעת" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "שיחה מושהית" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "שיחה הסתיימה." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "העברה מצויה כעת בעיצומה" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "העברה הסתיימה." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "העברה נכשלה." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "חזור" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "השהה" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "מקליט אל תוך\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(מושהה)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "נא להזין מידע התחברות עבור %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "נמוך מדי" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "טוב" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "חזק מדי" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "האם שמעת שלושה צפצופים ?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "התקן לכידה" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "אין קול" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "התקן השמעה" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "נגן שלושה צפצופים" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "הקלט" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "נגן" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "הבא נתחיל את Linphone עכשיו" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "מסיים כעת" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "אודות Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "וידאופון אינטרנטי באמצעות תקן הפרוטוקול SIP (‫rfc3261)." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "חיפוש אנשי קשר בתוך מדור" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "הוסף אל הרשימה שלי" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "חיפוש אחר מישהו" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "שם מקבל" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "היסטוריית שיחות" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "טיהור מוחלט" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "חיוג חוזר" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "סטטיסטיקות שיחה" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "קודק של אודיו" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "קודק של וידאו" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "ניצול רוחב פס IP אודיו" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "קישוריות מדיום אודיו" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "ניצול רוחב פס IP וידאו" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "קישוריות מדיום וידאו" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "זמן הלוך ושוב" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "פרופיל RTP" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "סטטיסטיקות ומידע שיחה" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "שלח" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "סיים ועידה" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "כתובת ‫SIP" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "הצג את מצב נוכחותו של איש קשר זה" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "הרשה לאיש קשר זה לראות את מצב הנוכחות שלי" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "מידע איש קשר" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "אפשרויות DSCP" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "זרם RTP אודיו" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "זרם RTP וידאו" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "קבע ערכי DSCP (בהקסדצימלי)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "הקלט את שיחה זו אל קובץ אודיו" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "וידאו" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "השתק" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "העבר" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "בשיחה כעת" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "משך זמן" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "אומדן איכות שיחה" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "הגדרות LDAP" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "כתובת שרת:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "שם משתמש:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "סיסמה:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "חיבור" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "חיפוש" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "שונות" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "שם משתמש" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "סיסמה" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "חיבור אינטרנט:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "חבר אותי אוטומטית" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "מזהה משתמש" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "מידע התחברות" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "ברוכים הבאים!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "‫ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "ערוץ סיב" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "חלון ניפוי שגיאות ‫Linphone" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "גלול אוטומטית לסוף" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "ברירת מחדל" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "מחק" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_אפשרויות" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "התחל תמיד וידאו" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "אפשר ראות-עצמית" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "הצג לוח חיוג" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_עזרה" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "הצג חלון ניפוי שגיאות" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_עמוד הבית" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "בדיקת _עדכונים" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "אשף חשבון" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "כתובת SIP או מספר טלפון" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "התחל שיחה חדשה" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "אנשי קשר" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "חיפוש" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "הוסף אנשי קשר מן מדור" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "הוסף איש קשר" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "טהר היסטוריית שיחות" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "זהותי הנוכחית:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "מענה אוטומטי הינו מאופשר" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "אנונימי" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "כרטיס קול משתמט" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "כרטיס קול" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "מצלמה משתמטת" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "קודקים של אודיו" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "קודקים של וידאו" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "‏SIP ‏(UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "‏SIP ‏(TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "‏SIP ‏(TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "הגדרות" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "חלק זה מגדיר את כתובת ה־SIP כאשר אינך עושה שימוש בחשבון SIP" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "שם התצוגה שלך (למשל: יורם יהודה):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "שם המשתמש שלך:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "כתובת SIP נובעת:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "זהות משתמטת" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "אשף" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "הוסף" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "ערוך" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "הסר" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "חשבונות Proxy" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "מחק סיסמאות" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "פרטיות" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "מענה-אוטומטי" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "ניהול חשבונות ‫SIP" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "צליל צלצול:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "התקן ALSA מיוחד (רשות):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "התקן לכידה:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "התקן צלצול:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "התקן פס קול:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "אפשר ביטול הד" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "אודיו" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "התקן קלט וידאו:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 מסמל \"בלי הגבלה\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "וידאו" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "מגבלת מהירות העלאה בקי״ב/שנ׳:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "מגבלת מהירות הורדה בקי״ב/שנ׳:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "אפשר בקרת קצב מסתגלת" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "בקרת קצב מסתגלת הינה טכניקה להשערה דינמית של רוחב הפס הזמין במהלך שיחה." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "בקרת רוחב פס" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "הגדרות מולטימדיה" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "הגדר יחידת תמסורת מרבית:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "שלח טזמ״תים (DTMFs) כמידע SIP" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "התר IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "טרנספורט" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "פורט SIP/UDP" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "אקראי" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "פורט SIP/TCP" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "אודיו RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "מקובע" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "וידאו RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "מינהור" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "שדות DSCP" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "פרוטוקולי רשת תקשורת ופורטים" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "חיבור ישיר אל האינטרנט" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "מאחורי NAT / חומת אש (בעזרת STUN לפתירה)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "מאחורי NAT / חומת אש (בעזרת ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "מאחורי NAT / חומת אש (בעזרת uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "כתובת IP פומבית:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "שרת STUN:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "‫NAT וחומת אש" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "סוג הצפנת מדיה" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "הצפנת מדיה הינה מנדטורית" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "הגדרות רשת תקשורת" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "אפשר" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "נטרל" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "קודקים" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "שפה" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "הצג הגדרות מתקדמות" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "רמה" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "ממשק משתמש" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "הבניית חשבון LDAP" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "סיום" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "‫Linphone - נדרש אימות" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "נא להזין את סיסמת המתחם" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "כעת מגדיר..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "ברוך בואך אל אשף הגדרת החשבון" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "צור חשבון אצל linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "כבר קיים חשבון linphone.org ברשותי וברצוני לעשות בו שימוש" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "כבר קיים חשבון sip ברשותי וברצוני לעשות בו שימוש" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "אשף הגדרת חשבון" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "שם משתמש*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "סיסמה*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "מתחם*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "פרוקסי" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "הגדרת חשבונך (צעד 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "הזן את שם משתמשך אצל linphone.org" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "הזנת שם משתמש sip (צעד 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) שדות חובה" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "דוא״ל: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "שם משתמש: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "סיסמה: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "אימות סיסמתך: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "הזנת מידע חשבון (צעד 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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אחרי כן נא לחזור לכאן וללחוץ על הלחצן 'קדימה'." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "אימות (צעד 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "שגיאה, חשבון לא אומת, שם משתמש כבר בשימוש או שרת לא ניתן להשגה.\nנא לחזור ולנסות שוב." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "שגיאה" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "תודה לך. חשבונך מוגדר ומוכן לשימוש כעת." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "‫Linphone - הגדרת חשבון ‫SIP" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "זהות ה־SIP שלך:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "נראה כמו ‪sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "כתובת SIP Proxy:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "נראה כמו ‪sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "משך רישום (בשניות):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "ניתוב (רשות):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "טרנספורט" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "רישום" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "פרסם מידע נוכחות" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "אפשר AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "הגדרת חשבון ‫SIP" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "הגדר תיעול VoIP" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "מארח" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "פורט" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "הגדר מינהור" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "הגדר http proxy (רשות)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "נא להמתין" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "מוכן" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "תצורה" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "מתקשר כעת" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "לא ניתן להתקשר" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "הגענו אל המספר המרבי של שיחות מקבילות, עמך הסליחה" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "מתקשר/ת אליך" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr " ומבקש/ת מענה אוטומטי." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "מתאים כעת פרמטרים של שיחה..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "מקושר." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "קריאה בוטלה" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "לא ניתן להשהות את השיחה" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "משהה כעת שיחה נוכחית..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "בדיקת STUN מצויה כעת בעיצומה..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "צבירת מועמדים מקומיים של ICE מצויה כעת בעיצומה..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "מקוון" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "עסוק" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "כבר אשוב" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "נעדר" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "בטלפון" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "בארוחת צהריים" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "נא לא להפריע" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "עברתי דירה" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "אני עושה כעת שימוש בשירות מסרים אחר" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "לא מקוון" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "בהמתנה" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "חופשה" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "מצב לא ידוע" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "כתובת sip proxy שהזנת הינה שגויה, זו צריכה להתחיל עם‭\"sip:\" ‬ לאחר שם מארח." - -#: ../coreapi/proxy.c:345 -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, למשל sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "מחפש כעת עבור יעד מספר טלפון..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "לא ניתן לפתור את מספר זה." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "לא ניתן להתחבר בזהות %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "צלצול מרוחק." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "צלצול מרוחק..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "מדיה מוקדמת." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "קריאה חודשה." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "חוסר תאימות, בדוק קודקים או הגדרות אבטחה..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "פרמטריי מדיה חסרי תואמים." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "חזרנו." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "אנו מושהים על ידי צד אחר." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "שיחה עודכנה מרחוק." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "קריאה הסתיימה." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "משתמש עסוק כעת." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "משתמש לא זמין זמנית." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "משתמש לא מעוניין שיפריעו לו." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "קריאה סורבה." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "מכוון מחדש" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "קריאה נכשלה." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "רישום אצל %s הושלם בהצלחה." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "אי רישום אצל %s סוים." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "אין היענות תוך זמן מוגדר" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "רישום אצל %s נכשל: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "אות האימות הינה %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "החמצת שיחה %i." -msgstr[1] "החמצת %i שיחות." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/hu.po b/po/hu.po deleted file mode 100644 index bee6d8fdf..000000000 --- a/po/hu.po +++ /dev/null @@ -1,2090 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Free Bill , 2015 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Hungarian (http://www.transifex.com/belledonne-communications/linphone-gtk/language/hu/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "%s hívása" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Szöveg küldése a következőnek: %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Legutóbbi hívások" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "-" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Megszakítva" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Nem fogadott" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Elutasítva" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i perc" -msgstr[1] "%i perc" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i másodperc" -msgstr[1] "%i másodperc" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tMinőség: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Konferencia" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "én" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Nemtalálható a pixmap fájl: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "Futás közben némi hibakeresési információ az stdout-ra naplózása." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "fájl elérési útja, melybe a naplók kerülnek." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Linphone indítása, videó kikpacsolva. " - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Csak a tálcaikon indítása, ne mutassa a fő ablakot." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "Cím azonnali híváshoz" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Adjon meg egy munkakönyvtárat (ennek az installációs könyvtárnak kéne lennie, pl. C:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Hiba a hívás közben" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Hívás vége" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Beérkező hívás" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Hívás fogadása" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Elutasítás" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Hívás várakoztatva" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "a következő által: %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s szerené elidítani a videót. Elfogadja?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Internetes oldal" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Alapértelmezett)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Át vagyunk irányítva ide: %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Hangkártya nincs érzékelve ezen a számítógépen.\nNem fog tudni hang hívásokat küldeni vagy fogadni." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Egy ingyenes SIP video-telefon" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Hozzáadás címjegyzékhez" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Keresés ebben a könyvtárban: %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Érvénytelen sip partner !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Kapcsolatinformációk szerkesztése: '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "'%s' partner törlése" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "" - -#: ../gtk/friendlist.c:862 -#, 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:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Név" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Érték (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Állapot" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Paraméterek" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Engedélyezve" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Tiltva" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Hozzáférés" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "angol" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "francia" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "svéd" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "olasz" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "spanyol" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "brazil-portugál" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "lengyel" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "német" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "orosz" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "japán" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "holland" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "magyar" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "cseh" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "egyszerúsített kínai" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "tradícionális kínai" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "norvég" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "héber" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "szerb" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "arab" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "török" - -#: ../gtk/propertybox.c:1246 -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:1332 -msgid "None" -msgstr "Nincs" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Elérhető egy újabb verzió a következőn: %s.\nSzeretné, hogy a letöltéshez egy új böngésző ablak nyíljon?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Ön a legfrissebb verziót használja." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Utónév, Családnév" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Hiba a kiszolgálóval történő kommunikáció során." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Kapcsolódás..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Kapcsolódva" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Adatok fogadása..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "" -msgstr[1] "" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Hívás #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Átirányítás #%i híváshoz ezzel: %s " - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Nem használt" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE nincs aktiválva" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE nem sikerült" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE folyamatban" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Átmegy egy vagy több NAT-on" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Közvetlen" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Közvetítő kiszolgálón keresztül" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP nincs aktiválva" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP folyamatban" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnP nem elérhető" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP fut" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP nem sikerült" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "közvetlen vagy kiszolgálón keresztül" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "letöltés: %f\nfeltöltés: %f (kbit/mp)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f másodperc" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Befejezés" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Hívás folyamatban..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Beérkező hívás" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "jó" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "közepes" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "gyenge" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "nagyon gyenge" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "rossz" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "nem elérhető" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "SRTP-vel titkosítva" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "ZRTP-vel titkosítva - [hitelesítési jel: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Beállítás ellenőrizetlenként" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Beállítás ellenőrzöttként" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "Konferencián" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "vonalban" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Várakoztatott hívás" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Hívás vége." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Átvitel folyamatban" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Átvitel befejezve." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Az átvitel sikertelen." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Visszatérés" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Várakoztatás" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Felvétel a következőbe\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Várakoztatva)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Kérem, adja meg a bejelentkezési információt %s -hoz" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Jó" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Befejezés" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Internetes videó telefon, mely a szabványos SIP (rfc3261) protokolt használja." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Partnerek keresése könyvtárban" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Hozzáadása a listámhoz" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Keres valakit" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Hívott neve" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Híváselőzmények" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Mind törlése" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Visszahívás" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Hívási statisztika" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Audió kódek" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Videó kódek" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Audió IP sávszélesség használat" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Audió média kapcsolat" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Videó IP sávszélesség használat" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Videó média kapcsolat" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Körbeérés ideje" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Hívási statisztika és információ" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Küld" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Konferencia vége" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP cím" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "A partner jelenlétének mutatása" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Megengedem ennek a partnernek, hogy lássa a jelenlétemet" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Partner információ" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Audió RTP folyam" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Videó RTP folyam" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "DSCP értékek beállítása (hexadecimális)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Beszélgetés felvétele hangfájlba" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Videó" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Elnémítás" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Átvitel" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "vonalban" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Időtartam" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Hívásminőség" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Felhasználónév:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Jelszó:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Felhasználónév" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Jelszó" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Internet kapcsolat:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Jelentkeztessen be automatikusan" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Felhasználó azonosító" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Bejelentkezési információ" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fiber csatorna" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone Hibakereső Ablak" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Görgetés a végéhez" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Alapértelmezett" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Törlés" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Beállítások" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Videó indítása mindig" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Saját nézet" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Segítség" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Hibakeresési ablak mutatása" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Honlap" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Frissítések keresése" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Fiók varázsló" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "Adja meg a SIP címet vagy a telefonszámot:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Új hívás kezdeményezése" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Partnerek" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Keresés" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Partnerek hozzáadása könyvtárból" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Partner hozzáadása" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Jelenlegi identitásom:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "alapértelmezett hangkártya" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "egy hangkártya" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "alapértelmezett kamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Audió kódekek" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Videó kódekek" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Beállítások" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Ez a rész határozza meg az Ön SIP címét, amikor nem használ SIP fiókot" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Az Ön megjelenített neve (pl. Kis József):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Az Ön felhasználóneve:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Az Ön így keletkezett SIP címe:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Alapértelmezett identitás" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Varázsló" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Hozzáadás" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Szerkesztés" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Eltávolítás" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Proxy fiókok" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Minden kulcsszó törlése" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Titoktartás" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "SIP fiókok beállítása" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Csengőhang:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Különleges ALSA eszköz (nem kötelező):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Felvevő hang eszköz:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Csengőhang eszköz:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Lejátszó hang eszköz:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Visszhang-elnyomás engedélyezése" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Audió" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Videó bemeneti eszköz:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "A 0 jelentése \"végtelen\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Videó" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Feltöltési sebesség korlát (kbit/mp):" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Letöltési sebesség korlát (kbit/mp):" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Alkalmazkodó mérték-szabályozás engedélyezése" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Az alkalmazkodó mérték-szabályozás egy módszer, mely erőteljesen próbálja megállapítani a rendelkezésre álló sávszélességet hívás alatt." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Sávszélesség szabályozása" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Multimédia beállítások" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Maximum Továbbítási Egység beállítása:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "DTMF küldése SIP infóként" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Átvitel" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Audió RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Javítva" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Videó RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Alagút" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP mezők" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Hálózati protokoll és port" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Közvetlen Internet kapcsolat" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "NAT / tűzfal mögött (STUN használata a feloldáshoz)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "NAT / tűzfal mögött (ICE használata)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "NAT / tűzfal mögött (uPnP használata)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Publikus IP cím:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "STUN kiszolgáló:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT és tűzfal" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Média titkosítás típusa" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Média titkosítás kötelező" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Hálózati beállítások" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Engedélyezés" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Tiltás" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Kódekek" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Nyelv" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Haladó beállítások megjelenítése" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Szint" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Felhasználói környezet" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Kész" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Hitelesítés szükséges" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Kérem adja meg a tartomány jelszavát" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "A fiók beállítása varázsló üdvözli Önt" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Fiók létrehozása a linphone.org -on" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Már rendelkezem linphone.org fiókkal, azt szeretném használni" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Már rendelkezem sip fiókkal, azt szeretném használni" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Fiók beállítása varázsló" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Felhasználónév*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Jelszó*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Tartomány" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Az Ön fiókjának beállítása (1/1 lépés)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Adja meg linphone.org felhasználónevét" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Adja meg sip felhasználónevét (1/2 lépés)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Mező kitöltése szükséges" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "E-mail: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Felhasználónév: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Jelszó: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Jelszó megerősítése: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Adja meg a fiókinformációt (1/2 lépés)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Kérjük, érvényesítse fiókját az általunk elektronikus levélben küldött hivatkozásra kattintva.\nAzután térjen vissza ide és kattintson a Következő gombra." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Érvényesítés (2/2 lépés)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Hiba, a fiók nincs érvényesítve. Valaki már használja ezt a felhasználónevet vagy a kiszolgáló nem elérhető.\nKérjük, lépjen vissza és próbálja újra." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Hiba" - -#: ../gtk/setup_wizard.ui.h:37 -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/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - SIP fiók beállítása" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Az Ön SIP azonosítója:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Így néz ki: sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP Proxy cím:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Így néz ki: sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Regisztrálási Időköz (mp):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Út (nem kötelező):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Regisztráció" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Jelenléti információ közlése" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "SIP fiók beállítása" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "VoIP alagút beállítása" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Hoszt" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Port" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Alagút beállítása" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "http proxy beállítása (nem kötelező)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Kérem várjon" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Kész" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Kapcsolódás" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Nem sikerült hívni" - -#: ../coreapi/linphonecore.c:3228 -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:3388 -msgid "is contacting you" -msgstr "kapcsolatba lépett veled." - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "és automatikus választ kért." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "A hívási jellemzők módosítása..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Kapcsolódva." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Hívás megszakítva" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Nem sikerült várakoztatni a hívást" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Jelenlegi hívás várakoztatásának aktiválása..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Stun keresés folyamatban..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "ICE helyi jelentkezők begyűjtése folyamatban..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Elérhető" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Foglalt" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Mindjárt visszajön" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Nem elérhető" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Vonalban" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Ebédelni ment" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Ne zavarj" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Elment" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Másik üzenő szolgáltatás használata" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Nem elérhető" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Függőben" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -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:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "Az Ön által megadott SIP identitás érvénytelen.\nÍgy kéne kinéznie: sip:felhasznalonev@proxytartomany, például sip:aladar@pelda.hu" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Telefonszám-cél keresése..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Nem sikkerült értelmezni a számot." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Nem sikerült belépni ezzel: %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Távoli csengés." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Távoli csengés..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Korai médiák." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Hívás visszatért" - -#: ../coreapi/callbacks.c:577 -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:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Nem kompatibilis médiajellemzők." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Visszatértünk." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Megállítva a másik fél által." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "A hívás távolról frissítve." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "A hívás befejezve." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "A felhasználó foglalt." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "A felhasználó ideiglenesen nem elérhető" - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "A felhasználó nem akarja, hogy zavarják." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Hívás elutasítva" - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Átirányítva" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Nem sikerült a hívás." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "A regisztáció a %s -n sikerült." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "A kiregisztrálás kész a következőn: %s ." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "időtúllépés után nincs válasz" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "A regisztáció a %s -n nem sikerült: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Hitelesítési jel: %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "" -msgstr[1] "" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/insert-header.sin b/po/insert-header.sin deleted file mode 100644 index b26de01f6..000000000 --- a/po/insert-header.sin +++ /dev/null @@ -1,23 +0,0 @@ -# Sed script that inserts the file called HEADER before the header entry. -# -# At each occurrence of a line starting with "msgid ", we execute the following -# commands. At the first occurrence, insert the file. At the following -# occurrences, do nothing. The distinction between the first and the following -# occurrences is achieved by looking at the hold space. -/^msgid /{ -x -# Test if the hold space is empty. -s/m/m/ -ta -# Yes it was empty. First occurrence. Read the file. -r HEADER -# Output the file's contents by reading the next line. But don't lose the -# current line while doing this. -g -N -bb -:a -# The hold space was nonempty. Following occurrences. Do nothing. -x -:b -} diff --git a/po/it.po b/po/it.po deleted file mode 100644 index 63dc17acb..000000000 --- a/po/it.po +++ /dev/null @@ -1,2091 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Daniele , 2015 -# Fabrizio Carrai, 2015 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Italian (http://www.transifex.com/belledonne-communications/linphone-gtk/language/it/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Chiama %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Invia messaggio a %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Aggiungi %s alla tua lista dei contatti" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Chiamate recenti" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Chiamate recenti (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "n/d" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Annullata" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Persa" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Rifiutata" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minuto" -msgstr[1] "%i minuti" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i secondo" -msgstr[1] "%i secondi" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tQualità: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Conferenza" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Me" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Impossibile trovare il file pixmap %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Invio in corso..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Messaggio non inviato" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Copia" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "alcune informazioni di debug verranno registrate sullo stdout durante l'esecuzione" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "mostra la versione e termina." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "percorso del file di log." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Avvia linphone con il video disabilitato." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Avvia solo nel system tray, non mostrare l'interfaccia principale." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "indirizzo da chiamare adesso" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Specificare una directory di lavoro (dovrebbe essere quella di installazione, es: c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "File di configurazione" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Avvia l'assistente audio" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Esegui il self test e esci con 0 in caso di successo" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s vorrebbe aggiungerti alla sua lista dei contatti.\nVuoi aggiungerlo/a ai tuoi contatti e pemettergli di conoscere la tua presenza?\nSe rispondi NO questa persona verrà temporaneamente bloccata." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Digitare la password per l'utente %s\nnel dominio %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Errore durante la chiamata" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Chiamata terminata" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Chiamata in arrivo" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Risposta" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Rifiuta" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Chiamata in pausa" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "da %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s chiede di avviare il video. Accetti ?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Collegamento al sito web" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Un videotelefono su internet" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Default)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Siamo trasferiti verso %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Non è stata trovata nessuna scheda audio.\nNon sarà possibile effettuare o ricevere chiamate in voce." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Un videotelefono SIP free" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Salve\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Aggiungi alla rubrica" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Cerca contatti nella directory %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Contatto SIP non valido" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Aggiungi un nuovo contatto" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Modifica contatto %s" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Elimina il contatto %s" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Cancella la cronologia della chat con '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Aggiungi nuovo contatto dalla directory %s" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Nome" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Frequenza (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Stato" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "IP Bitrate (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parametri" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Attivato" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Disattivato" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Account" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Inglese" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Francese" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Svedese" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italiano" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Spagnolo" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Portoghese brasiliano" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polacco" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Tedesco" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Russo" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Giapponese" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Olandese" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Ungherese" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Ceco" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Cinese" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Cinese tradizionale" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norvegese" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Ebraico" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Serbo" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Arabo" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Turco" - -#: ../gtk/propertybox.c:1246 -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:1332 -msgid "None" -msgstr "Nessuno" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Una versione più recente è disponibile su %s.\nVuoi aprire un browser per eseguire il download ?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Stai eseguendo la versione più aggiornata." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Nome, Cognome" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Errore di comunicazione con il server." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "In connessione..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Connesso" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Ricezione dei dati..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Trovato %i contatto" -msgstr[1] "Trovati %i contatti" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Chiamata #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Trasferimento per chiamare #%i con %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Non usato" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE non attivato" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE fallito" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE in corso" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Attraversando uno o più NAT" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Diretto" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Attraverso un relay server" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP non attivo" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP in corso" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnP non disponibile" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP in esecuzione" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP ha fallito" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Diretto o attraverso un server" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "download: %f\nupload: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f fps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f secondi" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Riagganciare" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Chiamando..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Chiamata in ingresso" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "bene" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "media" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "ridotto" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "molto poco" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "troppo brutto" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "non disponibile" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Trasmissione sicura con SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Trasmissione sicura con DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Trasmissione sicura con ZRTP - [auth token: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Marcato come non verificato" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Marcato come verificato" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "In conferenza" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "Chiamata in corso" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Chiamata sospesa" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Chiamata terminata." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Trasferimento in corso" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Trasferimento completato." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Trasferimento fallito." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Riprendere" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pausa" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Registrare in\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Sospeso)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Prego inserire le proprie credenziali di accesso per %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "prelevando da %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Il trasferimento della configurazione remota da %s è fallito." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Non è stata riconosciuta nessuna voce" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Troppo basso" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Bene" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Troppo forte" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Hai sentito tre segnali ?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Le preferenze sui suoni non sono state trovate" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Non è possibile eseguire il controllo dell'audio di sistema" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Benvenuto!\nL'assistente ti aiuterà a configurare i settaggi audio di Linphone" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Dispositivo di acquisizione" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Volume di registrazione" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Nessuna voce" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Preferenze per l'audio di sistema" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Dispositivo di riproduzione" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Riproduci tre segnali" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Premere il pulsante registrazione e parlare" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Ascoltare la voce registrata" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Registra" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Riproduci" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Ora è possibile usare Linphone" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Assistente Audio" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Assistente Audio" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Calibrazione del guadagano del microfono" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Calibrazione del volume di riproduzione" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Registra e Riproduci" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Procedura completata" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Su Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Un videotelefono con protocollo standard SIP (RFC 3261) " - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nit: Fabrizio Carrai\nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Cerca contatti nella directory" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Aggiungi alla mia lista" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Cerca" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Nome del chiamato" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Cronologia" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Pulisci tutto" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Richiamata" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Statistiche della chiamata" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Codec audio" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Codec video" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Banda IP impiegata per l'audio" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Supporto audio" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Banda IP impiegata per il video" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Supporto video" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Tempo di andata/ritorno" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Risoluzione video ricevuta" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Risoluzione video trasmessa" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "Profilo RTP" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Statistiche della chiamata e informazioni" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Invia" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Fine della conferenza" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Specificare un URI per la configurazione remota" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Questo modulo permette di impostare un indirizzo http o https da cui prelevare la configurazione all'avvio.\nDi seguito inserire o modificare l' URI della configurazione. Dopo aver selezionato OK Linphone verrà automaticamente riavvato per leggere ed usare la nuova configurazione." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "Indirizzo SIP" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Mostra lo stato di presenza del contatto" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Permetti al contatto di vedere il mio stato di presenza" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Informazioni sul contatto" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "Configurazione DSCP" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Stream audio RTP" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Stream video RTP" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Valore DSCP (in esadecimale)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Selezionare qui per regolare il volume" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Registra questa chiamata su un file audio" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Video" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Silenzia" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Trasferimento" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "In chiamata" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Durata" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Giudizio della qualità della chiamata" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "Configurazione LDAP" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Indirizzo del server:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Metodo di autenticazione" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Nome utente:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Password:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "Usa connessione TLS" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Not ancora disponibile" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Connessione" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "Bind DN" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Authname" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Dominio" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Oggetto di base" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "Filtro (%s per il nome):" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Attributo Nome:" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "Attributo SIP address" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "Attributo da cercare:" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Ricerca" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Tempo limite per la ricerca:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "Massimo numero di risultati:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "Segui gli Aliases" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Varie" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "ANONYMOUS" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "SEMPLICE" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "DIGEST-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Nome utente" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Password" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Connessione Internet:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Login Automatico" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Identificativo utente" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Credenziali di accesso" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Benvenuto!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fibra ottica" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone debug window" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Vai in fondo" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Default" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Cancellare" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Opzioni" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Imposta l' URI di configurazione" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Avvia sempre il video" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Self-view abilitato" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Mostra il tastierino" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Aiuto" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Mostra la finestra di debug" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Homepage" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Check _Updates" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Assistente per l'account" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "Indirizzo sip o numero." - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Inizia una nuova chiamata" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Contatti" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Ricerca" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Aggiungi contatti dalla directory" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Aggiungi un contatto" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Cancella la cronologia della chiamate" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Identità corrente" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Risponditore automatico attivato" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "anonimo" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "default scheda audio" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "una scheda audio" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "default videocamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Codificatori audio" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Codificatori video" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Preferenze" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "questa sezione definisce il tuo indirizzo SIP se non hai account attivi" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Nome visualizzato (es: Mario Rossi):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Nome utente:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Il tuo indirizzo sip:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Identità di default" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Wizard" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Aggiungi" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Edita" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Rimuovi" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Account proxy" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Cancella tutte le password" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Privacy" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Rispondi automaticamente alla chiamata in arrivo" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Ritardo prima della risposta (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Risposta automatica" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Gestici SIP Account" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Suoneria:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Dispositivo ALSA (optional):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Dispositivo microfono:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Dispositivo squillo:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Dispositivo uscita audio:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Attiva cancellazione eco" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Audio" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Dispositivo Video:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Risoluzione video preferita:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Modalità video in uscita:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Mostra il preview della videocamera" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Preconfigurazione del video:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Frame rate video preferito:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 sta per illimitato" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Video" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Velocità massima in upload Kbit/sec:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Velocita massima in Dowload Kbit/sec" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Abilita il controllo adattivo del rate" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Il controllo adattivo del rate è una tecnica per la stima dinamica della banda disponibile durante una chiamata" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Gestione banda" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Impostazioni multimediali" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Imposta Maximum Transmission Unit:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Invia DTMF come SIP info" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Permetti IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Transporto" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "Porta SIP/UDP" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Casuale" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "Porta SIP/TCP" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Audio RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Fissa" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Video RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunnel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "Campi DSCP" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Protocollo di rete e porte" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Connessione diretta a internet" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Dietro ad un NAT / Firewall (specificare IP del gateway)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Dietro NAT / Firewall (utilizza STUN)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Dietro ad un NAT / Firewall (usa ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Dietro ad un NAT / Fiewall (usa uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Indirizzo IP pubblico:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Server STUN:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT and Firewall" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Tipo di cifratura" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "La cifratura è obbligatoria" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Impostazioni di rete" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Attivato" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Disattivato" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Codificatori audio" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Codificatori video" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Codec" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Linguaggio" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Mostra la configurazione avanzata" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Livello" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Interfaccia utente" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "Configurazione dell' account LDAP" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Fatto" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - E' richiesta l'autenticazione" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Prego inserire la password di dominio" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Configurando..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Caricamento della configurazione dal server, attendere..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "Assistente per la configurazione di un account SIP" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Benvenuto!\nL'assistente vi aiuterà ad usare un indirizzo SIP per le vostre chiamate." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Benvenuto nel configuratore di account" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Creare un account su linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Ho già un account su linphone.org che voglio usare." - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Ho già un account SIP e voglio usarlo" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Voglio specificare un URI per la configurazione remota" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Configuratore di account" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Inserire i dati del vostro account" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Nome utente*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Password*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Dominio*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Configurare il tuo account (passo 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Immettere il vostro nome utente su linphone.org" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Introdurre il vostro nome utente SIP (passo 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Campi obbligatori" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "Email: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Nome utente: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Password: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Confermare la password: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Mantenetemi aggiornato sugli aggiornamenti di linphone" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Introdurre le informazioni dell'account (passo 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Il vostro account è stato creato, attendere." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Creazione dell'account in corso" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Attivate il vostro account cin il link che vi è appena stato inviato per posta elettronica.\nQuindi tornare qui e premere il tasto \"Avanti\"." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Validazione (passo 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Verifica della validazione dell'account, attendere." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Controllo della validazione dell'account in corso" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Errore, account non valido, nome utente già in uso o server non raggiungibile.\nTornare indietro e riprovare." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Errore" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Grazie. Il tuo account è configurato e pronto all'uso" - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Configurazione SIP account" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Identità SIP" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Simile a sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "Indirizzo sip proxy:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Simile a sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Durata registrazione (sec)" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Parametri del contatto (opzionali)" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "AVPF regular RTCP interval (sec):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Rotta (opzionale)" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Trasporto" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Registro" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Pubblica stato della presenza" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Abilita AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Configurazione SIP account" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Configurare il tunnel VoIP" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Host" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Porta" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Configurazione del tunnel" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Configurazione del proxy http (opzionale)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Prego attendere" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Pronto" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Configurando" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "In connessione" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Impossibile chiamare" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Spiacenti, è stato raggiunto il massimo numero di chiamate simultanee" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "ti sta contattando" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "e ha richiesto la risposta automatica" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Modificando i parametri di chiamata..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Connessione" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Chiamata annullata" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Impossibile sospendere la chiamata" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Sospensione della chiamata in corso..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Ricerca Stun in progresso ..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Raccolta dei candidati ICE locali in corso..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "In linea" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Occupato" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Torno subito" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Assente" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Al telefono" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Fuori per pranzo" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Non disturbare" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Trasferito" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Utilizza una altro servizio di messaggistica" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Offline" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Pendente" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "Assente" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Stato sconosciuto" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "L'indirizzo sip proxy utilizzato è invalido, deve iniziare con \"sip:\" seguito dall' hostaname." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "L'identità sip utilizza è invalida.\nDovrebbre essere sip:username@proxydomain, esempio: sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Ricerca numero destinazione..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Impossibile risolvere il numero." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "impossibile login come %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "Aggiornamento da %s..." - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Il chiamato sta squillando." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Il chiamato sta squillando..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Early media." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "Risposta da %s." - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Prosecuzione della chiamata." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Incompatibile, controllare i codecs o i parametri della sicurezza..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Parametri di comunicazione incompatibili." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "La comunicazione è stata ripresa." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "L'interlocutore ci ha messi in attesa." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "Aggiornamento della chiamata dalla parte remota." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Chiamata terminata." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Utente occupato" - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Utente non disponibile" - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "L'utente non vuole essere disturbato" - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Chiamata rifiutata" - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Richiesta scaduta" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Trasferito" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Chiamata non riuscita." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Registrazione su %s attiva" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Unregistrazione su %s" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "timeout no risposta" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Registrazione su %s fallita: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Servizio non disponibile, nuovo tentativo in corso" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Il codice di autenticazione è %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "I parametri della chiamata sono stati modificati con successo: %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "I parametri della chiamata sono stati modificati con successo." - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "%i chiamata persa." -msgstr[1] "%i chiamate perse." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "annulata" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "completata" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "persa" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "sconosciuto" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "%s a %s\nDa: %s\nA: %s\nStato: %s\nDurata: %i min %i sec\n" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "chiamata in uscita" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Impossibile riprodurre %s." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/ja.po b/po/ja.po deleted file mode 100644 index 851003f4e..000000000 --- a/po/ja.po +++ /dev/null @@ -1,2087 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Alexander, 2014 -# Alexander, 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Japanese (http://www.transifex.com/belledonne-communications/linphone-gtk/language/ja/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ja\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "%s を呼び出し中" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "%s に文章を送信" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "%sを連絡先に追加" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "通話時間" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "通話時間 (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "n/a" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "中断" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "失敗" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "辞退" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i 分" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i 秒" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s品質: %s\n%s⇥%s⇥" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s⇥%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "会議" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "自分" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "pixmapファイルが見つかりません %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "コピー" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "実行中にいくつかのデバッグ情報をstdoutに送信します。" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "バージョン表示と退出" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "ログを書き込むファイルへのパス。" - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "ビデオを無効にしてLinphoneを開始します。" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "主なインターフェイスを表示しないでシステムトレイに移動します。" - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "今すぐに呼び出す" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "作業ディレクトリをSpecifiy (インストールした時のベースである必要があります。例:c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "設定ファイル" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "オーディオアシスタントを実行" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "セルフテストは0で終了したら成功です" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "相手が自分の連絡先に%sを追加したいそうです。\nあなたが自分の連絡先に相手を追加したらできるようになり相手のステータスも表示されるようになります。\n拒否した場合その相手は一時的にブラックリストに登録されます。" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "パスワードを入力してください %s\nrealm %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "呼出エラー" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "呼出終了" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "着信" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "応答" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "拒否" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "呼び出しの一時停止" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "%s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%sがテレビ電話をしたいそうですが受け入れますか?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "ウェブサイトリンク" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "テレビ電話" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (デフォルト)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "%s に転送しました" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "サウンドカードが検出されていません。\n音声通話の送受信はできません。" - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "無料 SIP ビデオ-電話" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "こんにちは\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "電話帳に追加する" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "%s のディレクトリ内を検索" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "無効なSIP接続です!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "新しい連絡先を追加する" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "'%s' の連絡先を編集" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "'%s' の連絡先を削除" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "'%s' のチャット履歴を削除" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "フォルダ %s から連絡先を追加する" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "名前" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "レート (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "状態" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "IP ビットレート (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "パラメーター" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "使用する" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "使用しない" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "アカウント" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "English" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Français" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Svenska" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italiano" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Español" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Português do Brasil" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polski" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Deutsch" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Pусский" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "日本語" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Nederlands" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Magyar" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "čeština" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "简体中文" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "繁体中文" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norsk" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "עברית" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Cрпски" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "アラビア語" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "トルコ語" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "言語の選択を有効にするには、 Linphoneを再起動する必要があります。" - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "なし" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "%s よりも新しいバージョンが利用可能です。\nダウンロードするために、ブラウザを開きますか?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "最新版です。" - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "名前、名字" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "サーバーとの通信エラーが発生しました。" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "接続中..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "接続" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "データを受信中…" - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "%i 件発見" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "呼び出し #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "通話 #%i を %s に転送する" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "使用しない" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE 未認証" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE 失敗" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE 進行中" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "NATを通ります" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "直接" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "間接的にリレーサーバーを使う" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnPは作動しておりません" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnPを使用中" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnPは利用できません" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP作動中" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP失敗" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "直接またはサーバー経由" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "ダウンロード: %f\nアップロード: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f fps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f 秒" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "電話を切る" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "かけています…" - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "着信" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "良い" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "アベレージ" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "悪い" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "非常にプアな" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "非常にバッドな" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "利用できません" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "SRTPのセキュリティ" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "DTLSセキュリティ" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "ZRTP によるセキュリティ - [auth token: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "セット未検証" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "セット検証済" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "会議で" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "呼び出し中" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "呼び出し停止" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "呼び出し終了" - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "進行中の転送" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "転送完了。" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "転送失敗。" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "レジューム" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "一時停止" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "記録\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(停止中)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "%sの情報はログインしてご確認ください" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "%sからのフェッチ" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "音声が検出できません" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "小さい" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "丁度よい" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "大きい" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "3回のビープ音が聞こえましたか?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "音声の設定が見つかりません" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "音声制御システムを起動できません" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "キャプチャーデバイス" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "録音音量" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "音声なし" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "システムサウンド設定" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "3回分のビープ音を再生する" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "録音した音声を聞く" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "録音" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "再生" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Linphoneをはじめる" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "音声アシスタント" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "音声アシスタント" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "マイクのゲイン測定" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "スピーカーの音量測定" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "録音して再生" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "終了" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Linphoneについて" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -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) を使用しています。" - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "呼出履歴" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "すべて消去する" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "通信統計" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "オーディオのコーデック" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "ビデオのコーデック" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "音声で使用しているIP通信帯域" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "接続している音声用メディア" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "ビデオで使用しているIP通信帯域" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "接続しているビデオ用メディア" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "RTT" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "RTPプロファイル" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "送信" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "会議を終了する" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIPアドレス" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "DSCP設定" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "オーディオのRTP" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "ビデオのRTP" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "この通話をファイルに録音する" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "ビデオ" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "消音" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "転送" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "着信" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "期限" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "LDAP設定" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "サーバーアドレス:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "ユーザー名:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "パスワード:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "TLS接続を使用する" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "接続" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Authname" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Realm" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "検索" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "種々" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "匿名" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "シンプル" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "ダイジェスト-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "ユーザー名" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "パスワード" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "インターネット接続:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "自動的にログインする" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "ユーザーID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "ログイン情報" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "ようこそ!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphoneデバッグウインドウ" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "最下部までスクロールする" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "デフォルト" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "削除" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_オプション" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "いつでもビデオをスタートする" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "セルフビューを有効にする" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "キーパッドを表示する" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_ヘルプ" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "デバッグウインドウを見る" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_ホームページ" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "チェック _アップデート" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "アカウントのアシスタント" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIPアドレスもしくは電話番号:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "連絡相手" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "検索" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "連絡相手に追加する" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "通話履歴を削除する" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "anonymous" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "サウンドカード" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "デフォルトのカメラ" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "オーディオのコーデック" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "ビデオのコーデック" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "設定" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "あなたの表示名 (例: John Doe):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "あなたのユーザー名:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "ウィザード" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "追加する" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "編集する" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "削除する" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "プロキシアカウント" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "すべてのパスワードを消去する" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "プライバシー" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "鳴動音:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "エコーキャンセラーを有効にする" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "オーディオ" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0で制限なしになります" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "ビデオ" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "アップロード速度制限 Kbit/sec:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "ダウンロード速度制限 Kbit/sec:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "帯域幅制御" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "マルチメディア設定" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "DTMFをSIP情報で送信する" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "IPv6を有効にする" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "転送" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "SIP/UDP ポート" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "ランダム" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "SIP/TCP ポート" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "オーディオ RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "ビデオ RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "トンネル" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP値" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "ネットワークのプロトコルとポート" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "NAT / ファイヤーウォール (ICEを使う)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "NAT / ファイヤーウォール (uPnPを使う)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "パブリック IP アドレス:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Stunサーバー:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT と ファイヤーウォール" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "メディアの暗号化の種類" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "ネットワーク設定" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "使用する" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "使用しない" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "音声コーデック" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "動画コーデック" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "コーデック" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "言語" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "拡張設定を表示する" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "レベル" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "ユーザーインターフェイス" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "完了" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "SIPアカウント設定アシスタント" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "ようこそ!\nあなたの通話のためのSIPアカウント設定をお手伝いします。" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "アカウント設定アシスタントへようこそ" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "linphone.orgのアカウントを作成" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "linphone.orgのアカウントを持っているのでそれを使います" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "SIPアカウントを持っているのでそれを使います" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "アカウント設定アシスタント" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "ユーザー名*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "パスワード*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "ドメイン*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "プロキシ*" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "アカウントを設定します (1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "linphone.orgで取得したユーザー名を入力" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "SIPのユーザー名を入力してください (1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) 必須" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "メールアドレス: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "ユーザー名: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "パスワード: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "パスワードを再入力: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "アップデートでLinphoneを常に最新にする" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "アカウント情報を入力してください (1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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その後こちらへ戻って「次へ」を押してください。" - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "検証します (2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "エラー" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "ありがとう。あなたのアカウントは無事に設定され、使用する準備ができました。" - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - SIPアカウントを設定します" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP プロキシ:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "転送" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "登録" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "パブリッシュ情報" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "AVPFを有効にする" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "ホスト" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "ポート" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "お待ちください" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "準備" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "と自動応答を尋ねる" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "コールパラメーターの変更..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "接続しました。" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "呼び出しを打ち切る" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "呼び出しを一時停止できませんでした" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "現在の通話を一時停止..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Stunによるルックアップの進行中…" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "オンライン" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "ビジー" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "離席中" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "手が離せません" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "移動中" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "オフライン" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "保留" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "休暇中" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "不明なステータス" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "" - -#: ../coreapi/proxy.c:345 -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:979 -msgid "Looking for telephone number destination..." -msgstr "" - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "" - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Early media." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "" - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "呼び出し終了。" - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "相手はビジーです。" - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "相手は、今出られません。" - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "相手は手が離せないようです。" - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "通話は拒否されました。" - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "リクエストは時間切れです。" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "" - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "不明" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "%s が再生出来ません。" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/lt.po b/po/lt.po deleted file mode 100644 index 70a798dbf..000000000 --- a/po/lt.po +++ /dev/null @@ -1,2094 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Moo, 2015-2016 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Lithuanian (http://www.transifex.com/belledonne-communications/linphone-gtk/language/lt/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: lt\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Skambinti %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Siųsti tekstą į %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Pridėti %s į jūsų kontaktų sąrašą" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Paskiausi skambučiai" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Paskiausi skambučiai (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "—" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Nutrauktas" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Praleistas" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Atmestas" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minutė" -msgstr[1] "%i minutės" -msgstr[2] "%i minučių" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i sekundė" -msgstr[1] "%i sekundės" -msgstr[2] "%i sekundžių" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tKokybė: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Konferencija" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Nepavyko rasti paveikslo žemėlapio failo: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Siunčiama..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Pranešimas neišsiųstas" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Kopijuoti" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "kol vykdoma, registruoti į stdout kai kurią derinimo informaciją." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "parodyti versiją ir išeiti." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "kelias į failą, į kurį rašyti žurnalus." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Paleisti linphone su išjungtu vaizdu." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Paleisti tik sistemos dėkle, nerodyti pagrindinės sąsajos." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "adresas, į kurį tuoj pat skambinti" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Nurodyti darbinį katalogą (turėtų būti diegimo bazė, pvz.,: c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Konfigūracijos failas" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Vykdyti garso pagelbiklį" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Vykdyti savikontrolę ir išeiti 0, jei pavyks" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s norėtų jus pridėti į savo kontaktų sąrašą.\nAr jūs norėtumėte taip pat pridėti jį/ją į savo kontaktų sąrašą ir leisti jam/jai matyti jūsų prisijungimo būseną?\nJeigu atsakysite ne, šis asmuo bus laikinai pridėtas į juodąjį sąrašą." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Skambučio klaida" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Skambutis užbaigtas" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Įeinantis skambutis" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Atsiliepti" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Atmesti" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Skambutis pristabdytas" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "naudotojo %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s pasiūlė pradėti vaizdą. Jūs sutinkate ?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Svetainės nuoroda" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Internetinis vaizdo telefonas" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Numatytoji)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Šiame kompiuteryje nebuvo aptikta jokių garso plokščių.\nJūs negalėsite siųsti ir priimti garso skambučių." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Nemokamas SIP vaizdo telefonas" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Sveiki\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Pridėti į adresų knygą" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Netaisyklingas sip kontaktas !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Pridėti naują kontaktą" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Redaguoti kontaktą \"%s\"" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Ištrinti kontaktą \"%s\"" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Ištrinti \"%s\" pokalbių istoriją" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Pridėti naują kontaktą iš %s katalogo" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Vardas" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Sparta (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Būsena" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "IP Pralaidumas (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parametrai" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Įjungta" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Išjungta" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Paskyra" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Anglų" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Prancūzų" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Švedų" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italų" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Ispanų" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Brazilijos Portugalų" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Lenkų" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Vokiečių" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Rusų" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japonų" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Olandų" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Vengrų" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Čekų" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Kinų" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Tradicinė Kinų" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norvegų" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Hebrajų" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Serbų" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Arabų" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Turkų" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "Tam, kad įsigaliotų naujas kalbos pasirinkimas, turite iš naujo paleisti programą linphone." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Nėra" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Yra prieinama naujesnė versija iš %s.\nAr norėtumėte atverti naršyklę ir ją atsisiųsti?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Jūs naudojatės paskiausia versija." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Vardas, Pavardė" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Klaida, susisiekiant su serveriu." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Jungiamasi..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Prisijungta" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Gaunami duomenys..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Rastas %i kontaktas" -msgstr[1] "Rasti %i kontaktai" -msgstr[2] "Rasta %i kontaktų" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Naudotojo vardas jau yra naudojamas!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Nepavyko patikrinti naudotojo vardo prieinamumą. Prašome vėliau bandyti dar kartą." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Skambutis #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Nenaudojama" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE neaktyvuota" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE nepavyko" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE yra eigoje" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP neaktyvuota" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP yra eigoje" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnp neprieinama" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP yra vykdoma" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP nepavyko" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "atsiuntimas: %f\nišsiuntimas: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f kadr./s" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f sekundžių" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Padėti ragelį" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Skambinama..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Įeinantis skambutis" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "geras" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "vidutinis" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "žemas" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "labai žemas" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "pernelyg blogas" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "neprieinama" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "Konferencijoje" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "Skambutyje" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Skambutis pristabdytas" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Skambutis užbaigtas." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Tęsti" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pristabdyti" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Įrašoma į\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Pristabdyta)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Prašome įvesti %s prisijungimo informaciją" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "gaunama iš %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Nuotolinės konfigūracijos atsiuntimas iš %s nepavyko." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Neaptikta jokio balso" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Per tyliai" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Gerai" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Per garsiai" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Ar girdėjote tris byptelėjimus?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Garso nuostatos nerastos" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Nepavyko paleisti sistemos garso valdymą" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Sveiki!\nŠis pagelbiklis padės jums sukonfigūruoti Linphone garso nustatymus" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Mikrofonas" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Įrašomas garsis" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Nėra balso" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Sistemos garso nuostatos" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Atkūrimo įrenginys" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Groti tris byptelėjimus" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Spustelėkite įrašymo mygtuką ir tarkite kelis žodžius" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Klausytis savo įrašyto balso" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Įrašyti" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Groti" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Dabar, paleiskime Linphone" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Garso Pagelbiklis" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Garso pagelbiklis" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Mikrofono stiprinimo gradavimas" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Garsiakalbių garsio gradavimas" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Įrašykite ir Grokite" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Baigiama" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Apie Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Internetinis vaizdo telefonas, naudojantis standartinį SIP (rfc3261) protokolą." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Pridėti į mano sąrašą" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Išvalyti viską" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Skambučio statistika" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Garso kodekas" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Vaizdo kodekas" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Garso IP pralaidumo naudojimas" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Vaizdo IP pralaidumo naudojimas" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Gaunamo vaizdo raiška" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Siunčiamo vaizdo raiška" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "RTP profilis" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Skambučio statistika ir informacija" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Siųsti" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Užbaigti konferenciją" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Nuotolinės konfigūracijos URI nurodymas" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Šis dialogas leidžia nustatyti http ar https adresą, kai konfigūracija bus gaunama paleisties metu.\nPrašome žemiau įvesti ar pakeisti konfigūracijos URI. Po to, kai nuspausite mygtuką Gerai, programa Linphone bus automatiškai paleista iš naujo, kad gautų ir naudotų naująją konfigūraciją." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP adresas" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Rodyti šio kontakto prisijungimo būseną" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Leisti šiam kontaktui matyti mano prisijungimo būseną" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Kontakto informacija" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "DSCP nustatymai" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Garso RTP srautas" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Vaizdo RTP srautas" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Nustatykite DSCP reikšmes (šešioliktainiais)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Spustelėkite čia, kad nustatytumėte garsiakalbių garsį" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Įrašyti šį skambutį į garso įrašo failą" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Vaizdas" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Nutildyti" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Trukmė" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Skambučio kokybės įvertinimas" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "LDAP nustatymai" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Serverio adresas:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Tapatybės nustatymo metodas:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Naudotojo vardas:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Slaptažodis:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Kol kas neprieinama" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Ryšys" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Naudotojo vardas" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Slaptažodis" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Interneto ryšys:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Prijungti mane automatiškai" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Naudotojo ID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Prisijungimo informacija" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Sveiki!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone derinimo langas" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Slinkti į pabaigą" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Ištrinti" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Parinktys" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Nustatyti konfigūracijos URI" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Visada pradėti vaizdą" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Rodyti pagalbinę klaviatūrą" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "P_agalba" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Rodyti derinimo langą" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Internetinė svetainė" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Tikrinti ar yra at_naujinimų" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Paskyros pagelbiklis" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP adresas arba telefono numeris:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Inicijuoti naują skambutį" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Kontaktai" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Pridėti kontaktą" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Išvalyti skambučių istoriją" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Mano esama tapatybė:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Automatinis atsiliepimas yra įjungtas" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "numatytoji garso plokštė" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "garso plokštė" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "numatytoji kamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Garso kodekai" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Vaizdo kodekai" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Nustatymai" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Ši sekcija apibrėžia jūsų SIP adresą tais atvejais, kai nenaudojate SIP paskyros" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Jūsų rodomas vardas (pvz., Džonas Do):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Jūsų naudotojo vardas:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Jūsų galutinis SIP adresas:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Numatytoji tapatybė" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Vediklis" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Pridėti" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Keisti" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Šalinti" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Įgaliotojo serverio paskyros" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Ištrinti visus slaptažodžius" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Privatumas" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Automatiškai atsiliepti, kai yra gaunamas skambutis" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Delsa, prieš atsiliepiant (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Automatinis atsiliepimas" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Tvarkyti SIP paskyras" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Skambinimo garsas:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Specialus ALSA įrenginys (nebūtina):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Mikrofonas:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Skambinimo įrenginys:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Atkūrimo įrenginys:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Įjungti aido panaikinimą" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Garsas" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Vaizdo įvesties įrenginys:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Pageidaujama vaizdo raiška:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Vaizdo išvesties metodas:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Rodyti kameros peržiūrą" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Vaizdo išankstinė parinktis:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Pageidaujamas vaizdo kadrų dažnis:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 reiškia \"neribota\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Vaizdas" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Išsiuntimo greičio riba, Kbit/sek.:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Atsiuntimo greičio riba, Kbit/sek.:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Įjungti adaptyvų spartos valdymą" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Adaptyvus spartos valdymas yra technika, skirta, skambučio metu, dinamiškai atspėti prieinamą pralaidumą." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Pralaidumo valdymas" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Multimedijos nustatymai" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Nustatyti didžiausią duomenų persiuntimo įtaisą:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Siųsti DTMF kaip SIP informaciją" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Leisti IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Perdavimas" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "SIP/UDP prievadas" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Atsitiktinis" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "SIP/TCP prievadas" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Garso RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Fiksuotas" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Vaizdo RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP laukai" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Tinklo protokolas ir prievadai" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Tiesioginis sujungimas su internetu" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Už NAT / Užkardos (nurodyti tinklų sietuvo IP )" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Už NAT / Užkardos (naudoti STUN, siekiant išspręsti)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Už NAT / Užkardos (naudoti ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Už NAT / Užkardos (naudoti uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Viešas IP adresas:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Stun serveris:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT ir Užkarda" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Medijos šifravimo tipas" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Medijos šifravimas yra privalomas" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Šifravimas" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Tinklo nustatymai" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Įjungti" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Išjungti" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Garso kodekai" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Vaizdo kodekai" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Kodekai" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Kalba" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Rodyti išplėstinius nustatymus" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Lygmuo" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Naudotojo sąsaja" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "LDAP paskyros sąranka" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Atlikta" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Reikalingas tapatybės nustatymas" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Prašome įvesti srities slaptažodį" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Konfigūruojama..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Prašome palaukti kol iš serverio yra gaunama konfigūracija..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "SIP paskyros konfigūravimo pagelbiklis" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Sveiki!\nŠis pagelbiklis padės jums savo skambučiams naudoti SIP paskyrą." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Sveiki atvykę į paskyros sąrankos pagelbiklį" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Susikurti linphone.org paskyrą" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Aš jau turiu linphone.org paskyrą ir, tiesiog, noriu ją naudoti" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Aš jau turiu sip paskyrą ir, tiesiog, noriu ją naudoti" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Aš noriu nurodyti nuotolinės konfigūracijos URI" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Paskyros sąrankos pagelbiklis" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Įveskite savo paskyros informaciją" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Naudotojo vardas*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Slaptažodis*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Sritis*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Įgaliotasis serveris" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Konfigūruokite savo paskyrą (žingsnis 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Įveskite savo linphone.org naudotojo vardą" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Įveskite savo sip paskyros naudotojo vardą (žingsnis 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Būtini laukai" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "El. paštas: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Naudotojo vardas: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Slaptažodis: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Patvirtinkite savo slaptažodį: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Informuokite mane apie linphone atnaujinimus" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Įveskite paskyros informaciją (žingsnis 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Jūsų paskyra yra kuriama, prašome palaukti." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Paskyra kūrimo eigoje" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Prašome patvirtinti savo paskyrą, nuspaudžiant nuorodą, kurią ką tik atsiuntėme jums el. paštu.\nTuomet grįžkite čia ir spauskite mygtuką Pirmyn." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Patvirtinimas (žingsnis 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Tikrinama ar jūsų paskyra buvo patvirtinta, prašome palaukti." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Pakyros patvirtinimo patikrinimas eigoje" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Klaida, paskyra nepatvirtinta, naudotojo vardas jau yra naudojamas arba serveris nepasiekiamas.\nPrašome grįžti atgal ir bandyti dar kartą." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Klaida" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Dėkojame. Jūsų paskyra yra sukonfigūruota ir paruošta naudoti." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - SIP paskyros konfigūravimas" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Jūsų SIP tapatybė:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Atrodo taip sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP Įgaliotojo serverio adresas:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Registravimo trukmė (sek.):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Kontakto parametrai (nebūtinai):" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "AVPF reguliarus RTCP intervalas (sek.):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Maršrutas (nebūtinai):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Perdavimas" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Registruoti" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Skelbti prisijungimo būsenos informaciją" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Įjungti AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Konfigūruokite SIP paskyrą" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Prievadas" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Prašome palaukti" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Pasiruošę" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Konfigūruojama" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Susisiekiama su" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Nepavyko skambinti" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "bando su jumis susisiekti" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Modifikuojami skambučio parametrai..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Prisijungta." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Skambutis nutrauktas" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Nepavyko pristabdyti skambučio" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Pristabdomas esamas skambutis..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Prisijungęs" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Užimtas" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Netrukus sugrįš" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Pasišalinęs" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Kalba telefonu" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Pietauja" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Netrukdyti" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Perkeltas" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Naudoja kitą pokalbių tarnybą" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Atsijungęs" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Nežinoma būsena" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "" - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "jūsų įvesta sip tapatybė yra neteisinga.\nJi turėtų atrodyti taip sip:naudotojovardas@įgaliotojoserveriosritis, kaip, pavyzdžiui, sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "" - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "" - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Nepavyko prisijungti kaip %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "%s atsiliepė į skambutį" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Skambutis pratęstas." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Nesuderinama, patikrinkite kodekus ar saugos nustatymus..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Nesuderinami medijos parametrai." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Mūsų skambutis yra pratęstas." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Kita šalis pristabdė skambutį." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Skambutis baigtas." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Naudotojas yra užimtas." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Naudotojas laikinai neprieinamas." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Naudotojas nenori būti trukdomas." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Skambutis atmestas." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Baigėsi užklausos laikas." - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Skambutis nepavyko." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Paslauga neprieinama, bandoma iš naujo" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Nepavyko modifikuoti skambučio parametrų: %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Skambučio parametrai buvo sėkmingai modifikuoti." - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "Jūs turite %i praleistą skambutį." -msgstr[1] "Jūs turite %i praleistus skambučius." -msgstr[2] "Jūs turite %i praleistų skambučių." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "nutrauktas" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "užbaigtas" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "praleistas" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "nežinoma" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "%s ties %s\nNuo: %s\nKam: %s\nBūsena: %s\nTrukmė: %i min. %i sek.\n" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "Išeinantis skambutis" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Nepavyksta groti %s." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/nb_NO.po b/po/nb_NO.po deleted file mode 100644 index 87aff17c0..000000000 --- a/po/nb_NO.po +++ /dev/null @@ -1,2090 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Øyvind Sæther , 2011 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Norwegian Bokmål (Norway) (http://www.transifex.com/belledonne-communications/linphone-gtk/language/nb_NO/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: nb_NO\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Ring %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Send tekst til %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "" -msgstr[1] "" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "" -msgstr[1] "" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Fant ikke pixmap fli: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "skriv logg-informasjon under kjøring" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "" - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Start skjult i systemkurven, ikke vis programbildet." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "address som skal ringes nå" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Spesifiser arbeidsmappe (bør være base for installasjonen, f.eks: c:\\Programfiler\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Samtale avsluttet" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Innkommende samtale" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Svarer" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Avvis" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Peker til nettsted" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Standard)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Vi er overført til %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Klarte ikke å finne noe lydkort på denne datamaskinen.\nDu vil ikke kunne sende eller motta lydsamtaler." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "En gratis SIP video-telefon" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Søk i %s katalogen" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Ugyldig SIP kontakt !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Rediger kontakt '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Slett kontakt '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Legg til kontakt fra %s katalogen" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Navn" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Frekvens (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Status" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parametere" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "På" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Av" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Konto" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Engelsk" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Fransk" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Svensk" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italisensk" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Spansk" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Portugisisk" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polsk" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Tysk" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Russisk" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japansk" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Nederlandsk" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Ungarsk" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Tjekkisk" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Kinesisk" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -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:1332 -msgid "None" -msgstr "" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "En nyere utgave er tilgjengelig fra %s.\nVil du åpne en nettleser og laste den ned ?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Du kjører siste utgave." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Fornavn, Etternavn" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Feil med forbindelsen til serveren." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Tilknytter..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Tilknyttet" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Mottar data..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Fant kontakt %i" -msgstr[1] "Hittat kontakt %i" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Ringer..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Innkommende samtale" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "I samtale med" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Pauset samtale" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Samtale avsluttet." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Fortsett" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pause" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Skriv inn påloggingsinformasjon for %s:" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "En Internet Videotelefon som bruker den standardiserte SIP-protokollen (rfc3261)." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Søk kontakter i katalogen" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Legg til listen min" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Søk noen" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Samtalehistorikk" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Fjern alle" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Ring tilbake" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Send" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP Addresse" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Vis kontaktens tilstedestatus" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "La denne kontakten se min tilstedestatus" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Kontaktinformasjon" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Overfører" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "I samtale" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Varighet" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Brukernavn:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Passord:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Brukernavn" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Passord" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Internet forbindelse:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Logg meg på automatisk" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "BrukerID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Innlogginsinformasjon" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fiber Kanal" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone avlusningsvindu" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Standard" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Alternativer" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Vis video av deg selv" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Hjelp" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Vis avlusningsvindu" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "H_jemmeside" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Sjekk _Oppdateringer" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "Sip adresse eller telefonnummer:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Start en ny samtale" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Kontakter" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Søk" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Legg til kontakter fra katalogen" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Legg til kontakt" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Min nåværende identitet:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "standard lydkort" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "ett lydkort" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "standard kamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Lyd kodek" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Video kodek" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Innstillinger" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Denne seksjonen velger SIP-addresse når du ikke bruker en SIP-konto" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Vist navn (eks: Ola Nordmann):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Ditt brukernavn:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Din resulterende SIP addresse:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Standard identitet" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Legg til" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Rediger" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Fjern" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Proxy kontoer" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Slett alle passord" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Personvern" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Behandle SIP-kontoer" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Ringelyd:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Spesiell ALSA enhet (valgfritt):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Mikrofonenhet:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Ringe-enhet:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Avspillingsenhet:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Bruk ekko-kansellering" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Lyd" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Videoenhet:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 betyr \"ubegrenset\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Video" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Maks opplastningshastighet i Kbit/sek:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Nedlastningsbegrensning i Kbit/sek:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Båndbreddekontrol" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Multimediainnstillinger" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Velg MTU (Maximum Transmission Unit):" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Send DTMF som SIP-info" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Transport" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Lyd RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Video RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Tilkoblet Internett direkte" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Bak NAT / Brannmur (bruk STUN for å avgjøre)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Offentlig IP-addresse:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "STUN tjener:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT og Brannvegg" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Nettverksinnstillinger" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Aktiver" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Deaktiver" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Kodek" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Språk" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Vis avanserte innstillinger" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Nivå" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Brukergrensesnitt" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Ferdig" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Autorisering kreves" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Skriv inn passordet for domenet" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Velkommen til brukerkontoveiviseren" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Brukerkontoveiviser" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:37 -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/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Konfigurer en SIP konto" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Din SIP identitet:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Ser ut som sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP Proxy addresse:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Ser ut som sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Registreringsfrekvens (sek.):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Route (valgfritt):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Publiser tilstedestatus" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Konfigurer en SIP konto" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Vennligst vent" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Klar" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Tilknytter" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Kunne ikke ringe" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Beklager, du har nådd maksimalt antall samtidige samtaler" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "Kontakter deg." - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr " og ba om autosvar." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Endrer ringeparametre..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Tilkoblet" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Samtale avbrutt" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Kunne ikke pause samtalen" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Pauser nåværende samtale" - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "STUN oppslag pågår..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Tilknyttet" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Opptatt" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Kommer plutselig tilbake" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Borte" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "I telefonen" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Ute til lunsj" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Ikke forstyrr" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Flyttet" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Bruker en annen tjeneste" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Frakoblet" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Pågående" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "SIP proxy adressen du har angitt er ugyldig, den må begynne med \"sip:\" etterfult av vertsnavn." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -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:979 -msgid "Looking for telephone number destination..." -msgstr "Ser etter telefonnummer for destinasjonen..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Kan ikke tilkoble dette nummeret." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Ikke ikke logge inn som %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Ringer hos motparten." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Tidlig media" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Samtale gjenopptatt." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Samtale avsluttet." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Brukeren er opptatt." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Brukeren er midlertidig ikke tilgjengelig." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Brukeren vil ikke bli forstyrret." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Samtale avvist." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Omdirigert" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Samtale feilet." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Registrering hos %s lykkes." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Avregistrering hos %s lykkes." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "ingen svar innen angitt tid" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Registrering hos %s mislykkes: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, 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" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/nl.po b/po/nl.po deleted file mode 100644 index a833e03b7..000000000 --- a/po/nl.po +++ /dev/null @@ -1,2090 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Heimen Stoffels , 2015 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Dutch (http://www.transifex.com/belledonne-communications/linphone-gtk/language/nl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: nl\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "%s bellen" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "SMS versturen aan %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Recente gesprekken" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Recent oproepen (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "n.v.t." - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Afgebroken" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Gemist" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Geweigerd" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minuut" -msgstr[1] "%i minuten" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i seconde" -msgstr[1] "%i seconden" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tKwaliteit: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Vergadering" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Ik" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Het pixmap-bestand %s kon niet worden gevonden" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "loggen naar stdout om wat foutopsporingsinformatie te verkrijgen tijdens uitvoeren." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "Pad naar een bestand om logbestanden heen te schrijven." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Linphone opstarten met uitgeschakelde video." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Alleen in het systeemvak opstarten, niet met venster en al." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "adres om nu naar toe te bellen" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Specificeer een werkmap (dit moet de basis van uw installatie zijn, bijv.: C:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Configuratiebestand" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Doorloop de audio-instelwizard" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Draai een zelftest en exit 0 wanneer succesvol" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Vul uw wachtwoord in voor gebruikersnaam %s\nop realm %s" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Oproepfout" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Oproep beëindigd" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Inkomende oproep" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Opnemen" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Weigeren" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Oproep gepauzeerd" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "door %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s stelt u voor om video in te schakelen. Wilt u dit accepteren?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Websitelink" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Standaard)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "We zijn overgeschakeld naar %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Er zijn geluidskaarten aangetroffen op deze computer.\nU zult niet in staat zijn om audio-oproepen te ontvangen of versturen." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Een gratis SIP-videotelefoon" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Toevoegen aan adresboek" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Zoeken in de map %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Ongeldig SIP-contactpersoon" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Contactpersoon '%s' bewerken" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Contactpersoon '%s' verwijderen" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Chatgeschiedenis van '%s' verwijderen" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Nieuw contactpersoon toevoegen vanuit de map %s" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Naam" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Frequentie (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Status" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "IP-bitrate (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Argumenten" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Ingeschakeld" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Uitgeschakeld" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Account" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Engels" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Frans" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Zweeds" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italiaans" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Spaans" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Braziliaans Portugees" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Pools" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Duits" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Russisch" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japans" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Nederlands" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Hongaars" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Tjechisch" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Chinees" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Traditioneel Chinees" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Noors" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Hebreeuws" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Servisch" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "U moet linphone herstarten om de nieuw geselecteerde taal toe te passen." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Geen" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Er is een nieuwere versie beschikbaar op %s.\nWilt een webbrowser openen en deze downloaden?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "U gebruikt de nieuwste versie." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Voornaam, Achternaam" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Er is een fout opgetreden tijdens het communiceren met de server." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Bezig met verbinden..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Verbonden" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Bezig met ontvangen van gegevens..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "%i contactpersoon gevonden" -msgstr[1] "%i contactpersonen gevonden" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "#%i bellen" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Overschakelen naar gesprek #%i met %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Niet in gebruik" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE is niet geactiveerd" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE is mislukt" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE is bezig" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Die door één of meer NATs gaan" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Direct" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Via een relay-server" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP is niet geactiveerd" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP is bezig" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnP is niet beschikbaar" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP wordt uitgevoerd" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP is mislukt" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Direct of via een server" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "download: %f\nupload: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f fps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f seconden" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Ophangen" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Bezig met bellen..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Inkomende oproep" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "goed" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "gemiddeld" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "slecht" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "erg slecht" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "verschrikkelijk" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "niet beschikbaar" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Beveiligd door SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Beveiligd door DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Beveiligd door ZRTP - [authenticatiesleutel: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Instellen als niet-geverifieerd" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Instellen als geverifieerd" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "In een vergadering" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "In gesprek" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Gepauzeerde oproep" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Oproep is beëindigd." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "De overdracht is bezig" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "De overdracht is voltooid." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "De overdracht is mislukt." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Hervatten" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pauzeren" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Bezig met opnemen naar%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Gepauzeerd)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Vul uw inloggegevens in voor %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "bezig met ophalen van %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Het downloaden van de externe configuratie van %s is mislukt." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Er is geen stem gedetecteerd" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Te zacht" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Goed" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Te hard" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Heeft u drie pieptonen gehoord?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "De geluidsvoorkeuren zijn niet gevonden" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Het systeemgeluidspaneel kon niet worden gestart" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Welkom!\nDeze instelwizard zal u begeleiden bij het instellen van de audio-instellingen van Linphone" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Opname-apparaat" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Opgenomen volume" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Geen stem" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Systeemgeluidsinstellingen" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Afspeelapparaat" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Drie pieptonen afspelen" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Klik op de opnameknop en zeg enkele woorden" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Luister naar uw opgenomen stem" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Opnemen" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Afspelen" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Laten we nu Linphone opstarten" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Audio-instelwizard" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Audio-instelwizard" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Kalibratie van het microfoonbereik" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Kalibratie van het luidsprekervolume" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Opnemen en afspelen" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Bezig met vernietigen" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Over Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Een internetvideotelefoon gebruikmakende van het standaard SIP (rfc3261) protocol." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Bellernaam" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Gespreksgeschiedenis" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Alles wissen" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Terugbellen" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Verzenden" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Vergadering beëindigen" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP-adres" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "De aanwezigheidsstatus van dit contactpersoon weergeven" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Toestaan dat deze contactpersoon mijn aanwezigheidsstatus kan weergeven" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Contactinformatie" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Deze oproep opnemen naar een audiobestand" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Video" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Dempen" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Overdracht" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "In gesprek" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Duur" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Waardering van de gesprekskwaliteit" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Gebruikersnaam:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Wachtwoord:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Gebruikersnaam" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Wachtwoord" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Internetverbinding:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Automatisch inloggen" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Gebruikersidentificatie" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Inloginformatie" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Welkom!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fiber-kanaal" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone-foutopsporingsvenster" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Scroll naar het einde" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Standaard" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Verwijderen" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Opties" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Configuratie-URI instellen" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Video altijd starten" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Eigen weergave inschakelen" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Hulp" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Foutopsporingsvenster weergeven" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Website" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Controleren op _updates" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Account-instelwizard" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP-adres of telefoonnummer:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Een nieuw gesprek beginnen" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Contactpersonen" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Zoeken" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Voeg contactpersonen toe uit map" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Contactpersoon toevoegen" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Mijn huidige identiteit:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "anoniem" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "standaard geluidskaart" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "een geluidskaart" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "standaard camera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Audio-codecs" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Video-codecs" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Instellingen" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Uw weergavenaam (bijv.: Jan Noniem):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Uw gebruikersnaam:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Standaardidentiteit" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Instelhulp" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Toevoegen" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Bewerken" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Verwijderen" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Belgeluid:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "ALSA speciaal apparaat (optioneel)" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Opnameapparaat:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Belapparaat:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Afspeelapparaat:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Echo-onderdrukking inschakelen" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Audio" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Videoingang-apparaat:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Videouitgangsmethode:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Cameravoorbeeld weergeven" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Video" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Multimedia-instellingen" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Maximale Transmissie-unit instellen:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "DTMF's als SIP-informatie versturen" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Overdracht" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "SIP/UDP-poort" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Willekeurig" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "SIP/TCP-poort" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "AUDIO RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Vastgezet" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Video RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunnel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP-velden" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Netwerkprotocol en -poorten" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Directe verbinding met het internet" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Achter een NAT / Firewall (specificeer de gateway IP)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Openbaar IP-adres:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Stun-server" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT en Firewall" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Mediaversleutelingstype" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Mediaversleuteling is vereist" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Netwerkinstellingen" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Aan" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Uit" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Authenticatie is vereist" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Vul het domeinnaamwachtwoord in" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "SIP-account-instelwizard" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Welkom!\nDeze instelwizard zal u begeleiden bij het gebruiken van een SIP-account voor oproepen." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Welkom bij de account-instelwizard" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Creëer een account op linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Ik heb al een linphone.org-account en wil deze graag gebruiken" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Ik heb al een SIP-account en wil deze graag gebruiken" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Ik wil een externe URI-configuratie opgeven" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Account-instelwizard" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Gebruikersnaam*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Wachtwoord*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Domeinnaam*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Uw account instellen (stap 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Vul uw linphone.org-gebruikersnaam in" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Vul uw SIP-gebruikersnaam in (stap 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Verplichte velden" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "E-mailadres: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Gebruikersnaam: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Wachtwoord: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Bevestig uw wachtwoord: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Houdt me op de hoogte van linphone-updates" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Vul uw accountinformatie in (stap 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Valideer uw account door te klikken op de link die we zojuist naar uw e-mailadres hebben verstuurd.\nKom dan terug naar dit venster en klik op de knop Volgende." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Geldigheid (stap 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Er is een fout opgetreden: uw account is niet gevalideerd, de gebruikersnaam wordt al door iemand anders gebruikt of de server is onbereikbaar.\nGa terug en probeer het opnieuw." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Fout" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Bedankt. Uw account is nu ingesteld en klaar voor gebruik." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Een SIP-account instellen" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Uw SIP-identiteit:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Lijkt op:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP-proxyadres:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Lijkt op sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Registratieduur (sec):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Contactparameters (optioneel):" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "AVPF regulier RTCP-tussenpose (sec):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Route (optioneel):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Overdracht" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Registreren" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Aanwezigheidsinformatie publiceren" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "AVPF inschakelen" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Een SIP-account instellen" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Gereed." - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Verbinden" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "" - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Verbonden." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "" - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "STUN adres wordt opgezocht..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Aanwezig" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Bezet" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Afwezig" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Niet storen" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "" - -#: ../coreapi/proxy.c:345 -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:979 -msgid "Looking for telephone number destination..." -msgstr "Zoekt de lokatie van het telefoonnummer..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Kon dit nummer niet vinden." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "" - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Oproep beeindigd." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Gebruiker is bezet." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Gebruiker is tijdelijk niet beschikbaar." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "De gebruiker wenst niet gestoord te worden." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Oproep geweigerd." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "" - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Registratie op %s gelukt." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "" -msgstr[1] "" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/pl.po b/po/pl.po deleted file mode 100644 index 00d4e22cd..000000000 --- a/po/pl.po +++ /dev/null @@ -1,2093 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Polish (http://www.transifex.com/belledonne-communications/linphone-gtk/language/pl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pl\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Nie można znaleźć pixmapy: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "" - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "" - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "" - -#: ../gtk/main.c:2008 -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:2173 -msgid "A free SIP video-phone" -msgstr "" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Nazwa" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Jakość (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Status" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parametr" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Włączone" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Wyłączone" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "" - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "" - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "" - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "" - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "" - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "" - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "" - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Włączony" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Wyłącz" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "" - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "" - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Połączony" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "" - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Zajęty" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Nie przeszkadzać" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "" - -#: ../coreapi/proxy.c:345 -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:979 -msgid "Looking for telephone number destination..." -msgstr "" - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "" - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "" - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "" - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Osoba jest zajęta." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Osoba jest tymczasowo niedostępna." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Osoba nie chce, aby jej przeszkadzać." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Rozmowa odrzucona." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "" - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/pt_BR.po b/po/pt_BR.po deleted file mode 100644 index 2fa82eac4..000000000 --- a/po/pt_BR.po +++ /dev/null @@ -1,2089 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/belledonne-communications/linphone-gtk/language/pt_BR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "" -msgstr[1] "" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "" -msgstr[1] "" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Não é possível achar arquivo pixmap: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "" - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "" - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Camadas recebidas" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "" - -#: ../gtk/main.c:2008 -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:2173 -msgid "A free SIP video-phone" -msgstr "" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Nome" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Taxa (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parâmetros" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Ativado" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Desativado" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "" - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Nenhum" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "" - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "" - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "" - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "" -msgstr[1] "" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "" - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "" - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "" - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Editar" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Remover" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Ativado" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Desativar" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "" - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Rota (opcional):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "" - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Conectado." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "" - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Ocupado" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Não perturbe" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "" - -#: ../coreapi/proxy.c:345 -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:979 -msgid "Looking for telephone number destination..." -msgstr "Procurando por telefone de destino..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Não foi possível encontrar este número." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "" - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "" - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Usuário está ocupado." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Usuário está temporáriamente indisponível." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "" - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "" - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "" - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "" -msgstr[1] "" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/quot.sed b/po/quot.sed deleted file mode 100644 index 0122c4631..000000000 --- a/po/quot.sed +++ /dev/null @@ -1,6 +0,0 @@ -s/"\([^"]*\)"/“\1”/g -s/`\([^`']*\)'/‘\1’/g -s/ '\([^`']*\)' / ‘\1’ /g -s/ '\([^`']*\)'$/ ‘\1’/g -s/^'\([^`']*\)' /‘\1’ /g -s/“”/""/g diff --git a/po/remove-potcdate.sin b/po/remove-potcdate.sin deleted file mode 100644 index 2436c49e7..000000000 --- a/po/remove-potcdate.sin +++ /dev/null @@ -1,19 +0,0 @@ -# Sed script that remove the POT-Creation-Date line in the header entry -# from a POT file. -# -# The distinction between the first and the following occurrences of the -# pattern is achieved by looking at the hold space. -/^"POT-Creation-Date: .*"$/{ -x -# Test if the hold space is empty. -s/P/P/ -ta -# Yes it was empty. First occurrence. Remove the line. -g -d -bb -:a -# The hold space was nonempty. Following occurrences. Do nothing. -x -:b -} diff --git a/po/ru.po b/po/ru.po deleted file mode 100644 index 294f2f35a..000000000 --- a/po/ru.po +++ /dev/null @@ -1,2102 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# AlexL , 2014 -# AlexL , 2014-2016 -# AlexL , 2014 -# Maxim Prokopyev , 2010 -# Simon Morlat , 2001 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 12:36+0000\n" -"Last-Translator: AlexL \n" -"Language-Team: Russian (http://www.transifex.com/belledonne-communications/linphone-gtk/language/ru/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ru\n" -"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Звонок %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Послать текст для %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Добавить %s в мой список контактов" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Последние звонки" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Последние вызовы (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "—" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Прервано" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Пропущено" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Отклонено" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i минута" -msgstr[1] "%i минуты" -msgstr[2] "%i минут" -msgstr[3] "%i минут" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i секунда" -msgstr[1] "%i секунды" -msgstr[2] "%i секунд" -msgstr[3] "%i секунд" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tКачество: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Конференция" - -#: ../gtk/conference.c:46 -msgid "Me" -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:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Отправка..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Сообщение не отправилось" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Копировать" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "Вывод некоторой отладочной информации на устройство стандартного вывода во время работы." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "показать версию и выйти." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "Путь к файлу для записи логов." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Запуск linphone с видео отключен." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Показывать только в системном лотке, не запуская главное окно." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "Адрес для звонка прямо сейчас." - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Определить рабочий каталог (относительно каталога установки, например: c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Файл конфигурации" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Запустить помощника аудио" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Запустить самотест и выйти при успехе со статусом 0" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s хочет добавить Вас в его/её список контактов.\nВы бы добавили его/её в свой список контактов и позволили ему/ей видеть ваш статус присутствия?\nЕсли вы ответите нет, то этот человек будет временно занесён в чёрный список." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Пожалуйста, введите пароль для пользователя %s\n для реалм (рилм) %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Ошибка звонка" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Звонок окончен" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Входящий звонок" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Ответ" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Отклонить" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Звонок приостановлен" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "%s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s предложил запустить видео. Вы принимаете?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Домашняя страница" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Видео интернет телефон" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (по умолчанию)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Мы передали в %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Звуковые карты не были обнаружены на этом компьютере.\nВы не сможете отправлять или получать аудио звонки." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Свободный SIP видео-телефон" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Привет\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Добавить в адресную книгу" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Поиск в директории %s" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Неверный sip контакт!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Добавить новый контакт" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Редактировать контакт '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Удалить контакт '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Удалить историю чата для '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Добавить новый контакт из директории '%s'" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Имя" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Частота (Гц)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Статус" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "IP битрейт (КБит/сек)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Параметры" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Разрешён" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Не разрешён" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Учётная запись" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Английский" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Французский" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Шведский" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Итальянский" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Испанский" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Бразильский португальский" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Польский" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Немецкий" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Русский" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Японский" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Датский" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Венгерский" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Чешский" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Китайский" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Традиционный китайский" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Норвежский" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Иврит" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Сербский" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Арабский" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Турецкий" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "Вы должны перезагрузить linphone для того, чтобы языковые настройки вступили в силу." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Нет" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Доступна новая версия с %s.\nОткрыть браузер для загрузки?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Вы работаете с последней версией." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Имя, Фамилия" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Ошибка связи с сервером" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Подключение..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Соединено" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Получение данных..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Найден %i контакт" -msgstr[1] "Найдено %i контакта" -msgstr[2] "Найдено %i контактов" -msgstr[3] "Найдено %i контактов" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Имя пользователя уже используется!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Не удалось проверить наличие имени пользователя. Пожалуйста, повторите попытку позднее." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Звонок #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Передача позвонить #%i с %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Не используется" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE не активировано" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "Неудача ICE" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE в прогрессе" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Пройти через один или несколько NAT" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Напрямую" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Через сервер ретрансляции" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP не активировано" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP в прогрессе" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnp недоступен" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP выполняется" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "Неудача uPnP" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Напрямую или через сервер" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "загрузка: %f\nотдача: %f (КБит/сек)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f кадр/сек" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f секунд" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Повесить трубку" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Звоним..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Входящий звонок" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "хороший" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "средний" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "плохой" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "очень плохой" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "совсем плохой" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "недоступен" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Защищённые с помощью SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Защищённые с помощью DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Защищённые с помощью ZRTP - [знак аутентификации: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Установить непроверенный" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Установить проверенный" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "В конференции" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "Звоним" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Звонок приостановлен" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Звонок закончен." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Передача в прогрессе" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Передача завершена." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Передача неудачна." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Продолжить" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Пауза" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Записывается в\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Пауза)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Пожалуйста, введите информацию для входа %s:" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "получение от %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Загрузка удалённой конфигурации из %s неудачна." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Голос не обнаружен" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Слишком тихо" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Хорошо" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Слишком громко" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Вы слышали 3 сигнала?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Настройки звука не найдены" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Не удаётся запустить системное управление звуком" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Добро пожаловать!\nЭтот ассистент поможет вам настроить настройки аудио для Linphone." - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Устройство захвата" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Уровень записи" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Нет голоса" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Системные настройки звука" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Устройство воспроизведения" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Проиграть три сигнала" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Нажмите кнопку записи и скажите несколько слов" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Прослушайте ваш записанный голос" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Запись" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Воспроизведение" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Давайте сейчас запустим linphone" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Помощник аудио" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Помощник аудио" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Калибровка усиления микрофона" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Калибровка громкости динамика" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Записать и проиграть" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Прерывание" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "О Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -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)." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Поиск контактов в директории" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Добавить в мой список" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Поиск кого-нибудь" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Имя вызываемого" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "История звонков" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Очистить всё" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Позвонить повторно" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Вызов статистики" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Аудио кодек" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Видео кодек" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Использование пропускной способности аудио IP" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Подключение медиа-аудио" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Использование пропускной способности видео IP" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Подключение медиа-видео" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Округлять время в действии" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Получено разрешение видео" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Разрешение видео отправлено" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "Профиль RTP" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Вызов статистики и информации" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Отправить" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Конец конференции" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Указание удалённой конфигурации URI" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Этот диалог позволяет установить HTTP или HTTPS адрес, когда конфигурация будет получена при запуске.\nПожалуйста, введите или измените настройки URI ниже. После нажатия OK linphone автоматически перезагрузится чтобы получить и учесть новую конфигурацию в учётной записи." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP адрес" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Показывать этому контакту статус присутствия" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Разрешить этому контакту видеть мой статус присутствия" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Контактная информация" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "Настройки DSCP" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Аудио поток RTP" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Видео поток RTP" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Установить значения DSCP (в шестнадцатеричном формате)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Щёлкните здесь чтобы установить громкость динамиков" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Записать этот вызов в аудио файл" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Видео" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Без звука" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Передача" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "Входящий звонок" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Продолжительность" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Вызвать рейтинг качества" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "Настройки LDAP" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Адрес сервера:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Метод аутентификации:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Имя пользователя:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Пароль:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "Использовать соединение TLS" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Ещё недоступно" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Соединение" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "Привязать DN" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Имя для аутентификации" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Реалм (рилм)" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Базовый объект:" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "Фильтр (%s для имени):" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Атрибут имени:" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "Атрибут SIP-адреса:" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "Атрибуты для запроса:" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Поиск" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Таймаут для поиска:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "Максимум результатов:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "Следовать алиасам" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Разное" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "АНОНИМ" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "ПРОСТОЙ" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "ДАЙДЖЕСТ-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Имя пользователя" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Пароль" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Интернет-соединение:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Входить автоматически" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Идентификатор пользователя" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Информация для входа" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Добро пожаловать!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Оптоволоконный канал" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Окно отладки linphone" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Прокрутка в конец" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "По умолчанию" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Удалить" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Опции" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Установить конфигурацию URI" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Всегда запускать видео" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Показать окно видео" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Показать клавиатуру" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "Импорт контактов из vCards" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "Экспорт контактов как vCards" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Помощь" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Показать окно отладки" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Домашняя страница" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Проверить _обновления" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Помощник учётной записи" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP-адрес или номер телефона:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Начать новый звонок" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Контакты" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Поиск" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Добавить контакты из директории" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Добавить контакт" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Очистить историю звонков" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Мой текущий идентификатор:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Автоответ включен" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "аноним" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "звуковая карта по умолчанию" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "звуковая карта" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "камера по умолчанию" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Аудио кодеки" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Видео кодеки" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Настройки" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Эта секция определяет ваш SIP адрес, когда вы не используете учётную запись SIP" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Отображаемое имя (например: Иван Сидоров):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Ваше имя пользователя:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Ваш результирующий SIP адрес:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Идентификатор по умолчанию" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Мастер" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Добавить" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Редактировать" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Удалить" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Учётные записи" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Стереть все пароли" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Секретность" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Автоматический ответ при получении звонка" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Задержка перед ответом (мс)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Автоответ" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Управление учётными записями SIP" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Мелодия звонка:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Специальное устройство ALSA (опционально)" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Устройство захвата:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Устройство звонка:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Устройство воспроизведения:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Разрешить подавление эха" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Аудио" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Устройство для вывода видео:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Предпочтительное разрешение видео:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Метод вывода видео:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Показать предпросмотр с камеры" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Предустановки видео:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Предпочтительная частота кадров:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 означает \"безлимитный\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Видео" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Ограничение исходящего потока КБит/сек:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Ограничение скорости входящего потока КБит/сек:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Разрешить адаптивное управление скоростью" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Адаптивное управление скоростью - это технология динамического угадывания доступной пропускной способности во время звонка." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Пропускная способность" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Настройки мультимедиа" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Установить MTU (максимально передаваемый блок):" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Отправлять DTFM как SIP-информацию" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Разрешить IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Транспорт" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "Порт SIP/UDP" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Случайно" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "Порт SIP/TCP" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Аудио RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Фиксированный" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Видео RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Тунель" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "Поля DSCP" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Сетевые протоколы и порты" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Прямое подключение к интернет" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "За NAT / брандмауэром (указать IP шлюза)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "За NAT / брандмауэром (использовать STUN)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "За NAT / брандмауэром (использовать ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "За NAT / брандмауэром (использовать uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Выделенный (публичный) IP-адрес:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "STUN сервер:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT и брандмауэр" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Тип медиа-шифрования" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "Использовать лайм для исходящих сообщений чата" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Медиа-шифрование обязательно" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "Обязательный" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "Предпочтительный" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Шифрование" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Настройки сети" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Разрешить" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Выключить" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Аудио кодеки" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Видео кодеки" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Кодеки" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Язык" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Показать дополнительные настройки" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Уровень" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Пользовательский интерфейс" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "Установка учётной записи LDAP" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Готово" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - необходима регистрация" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Введите пароль для домена" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Конфигурирование..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Пожалуйста, подождите пока получается конфигурация с сервера..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "Помощник настройки учётной записи SIP" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Добро пожаловать!\nЭтот ассистент поможет вам использовать SIP аккаунт для ваших звонков." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Добро пожаловать в помощник настройки учётной записи" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Создать учётную запись на linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Я уже имею учётную запись на linphone.org и только хочу использовать её" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Я уже имею учётную запись sip и только хочу использовать её" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Я хочу указать удалённую конфигурацию URI" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Помощник настройки учётной записи" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Введите вашу информацию об учётной записи" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Имя пользователя*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Пароль*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Домен*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Прокси" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Настроить вашу учётную запись (шаг 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Введите ваше имя пользователя для linphone.org" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Введите ваше sip имя пользователя (шаг 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Обязательные поля" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "Электронная почта: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Имя пользователя: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Пароль: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Подтвердите ваш пароль: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Информировать об обновлениях linphone" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Введите информацию об учётной записи (шаг 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Ваша учётная запись создаётся, пожалуйста, подождите." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Создание учётной записи в прогрессе" - -#: ../gtk/setup_wizard.ui.h:29 -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что получили по электронной почте. Затем вернитесь сюда и нажмите кнопку Далее." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Подтверждение (шаг 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Проверяется действительность вашей учётной записи, пожалуйста, подождите." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Проверка действительности учётной записи в прогрессе" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Ошибка, учётная запись не подтверждена, имя пользователя уже используется или\nсервер недоступен. Пожалуйста, зайдите снова и попробуйте ещё раз." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Ошибка" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Спасибо! Учётная запись успешно настроена и готова к использованию." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - настроить учётную запись SIP" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Ваш идентификатор SIP:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Выглядит как sip:<имя_пользователя>@<домен>" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "Адрес SIP прокси:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Выглядит как sip:<прокси имя_хоста>" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Продолжительность регистрации (сек):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Параметры контакта (опционально):" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "AVPF постоянный интервал RTCP (сек):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Маршрут (опционально):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Транспорт" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Регистрация" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Опубликовать статус присутствия" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Разрешить AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Настроить учётную запись SIP" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Настроить тунель VoIP" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Хост" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Порт" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Конфигурировать тунель" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Конфигурировать http прокси (опционально)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Пожалуйста, подождите" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Готов" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Конфигурирование" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Соединение" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Невозможно позвонить" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "К сожалению, мы достигли максимального количества одновременных звонков" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "контактирует с вами" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "и спросил автоматический ответ." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Изменение параметров звонка..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Соединён." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Звонок отменён" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Невозможно приостановить звонок" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Приостановка текущего звонка..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "Идет поиск STUN..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Сбор локальных кандидатов ICE в прогрессе..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "В сети" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Занят" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Скоро вернусь" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Нет на месте" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "На телефоне" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "На обеде" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Не беспокоить" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Отошёл" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Разговариваю" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Не в сети" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "В ожидании" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "Отдых" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Неизвестный статус" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "Введённый SIP-адрес прокси является недействительным, он должен начинаться с \"sip:имя_хоста\"" - -#: ../coreapi/proxy.c:345 -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:имя_пользователя@домен_прокси, как например, sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Поиск назначения для телефонного номера.." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Не получилось принять решение по этому номеру." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Невозможно зайти как: %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "Обновление %s..." - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Дистанционный звонок." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Дистанционный звонок..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Предответное проключение." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "На звонок ответил %s" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Звонок возобновлён." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Несовместимость, проверьте кодеки или параметры безопасности..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Несовместимость медиа-параметров." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Мы возобновили." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Мы приостановлены другой стороной." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "Звонок был дистанционно обновлён." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Звонок прерван." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Пользователь занят." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Пользователь временно недоступен." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Пользователь не хочет чтобы его беспокоили." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Звонок отклонён." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Таймаут запроса." - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Переадресован" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Звонок не удался." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Регистрация на %s прошла успешно." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Отмена регистрации на %s завершена." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "время ожидания истекло" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Регистрация на %s не удалась: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Сервис недоступен, повтор" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Маркер проверки подлинности: %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Параметры звонка не были изменены: %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Параметры звонка были успешно изменены." - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "У вас %i пропущенный вызов." -msgstr[1] "У вас %i пропущенных вызова." -msgstr[2] "У вас %i пропущенных вызов." -msgstr[3] "У вас %i пропущенных вызов." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "прервано" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "завершено" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "пропущено" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "неизвестно" - -#: ../coreapi/call_log.c:234 -#, 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/call_log.c:235 -msgid "Outgoing call" -msgstr "Исходящий вызов" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Невозможно воспроизвести %s." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "Сделать скриншот" diff --git a/po/sr.po b/po/sr.po deleted file mode 100644 index eb96493a2..000000000 --- a/po/sr.po +++ /dev/null @@ -1,2094 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Мирослав Николић , 2014 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Serbian (http://www.transifex.com/belledonne-communications/linphone-gtk/language/sr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sr\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" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Позови „%s“" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Пошаљи текст за %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Додајте „%s“ на списак контаката" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Скорашњи позиви" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Недавни позиви (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "н/д" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Прекинут" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Пропуштен" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Одбијен" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i минут" -msgstr[1] "%i минута" -msgstr[2] "%i минута" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i секунда" -msgstr[1] "%i секунде" -msgstr[2] "%i секунди" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tКвалитет: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Конференција" - -#: ../gtk/conference.c:46 -msgid "Me" -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:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Шаљем..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Порука није послата" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Умножи" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "бележи на стандардни излаз неке податке прочишћавања док ради." - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "приказује издање и излази." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "путања до датотеке за уписивање дневника." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Покреће линфон са искљученим видеом." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Покреће се само у системској фиоци, не приказује главно сучеље." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "адреса за позивање управо сада" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Наводи радни директоријум (треба да буде основа инсталације, нпр: „c:\\Program Files\\Linphone“)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Датотека подешавања" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Покреће помоћника звука" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Покреће самоиспробавање и излази 0 ако је успешно" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s жели да вас дода на свој списак контакта.\nДа ли желите да га/је додате на ваш списак контакта и да му/јој омогућите да види ваше стање присуства?\nАко одговорите негативно, ова особа ће тренутно бити стављена на списак забрањених." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Унесите вашу лозинку за корисничко име %s\n на подручју %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Грешка позива" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Позив је завршен" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Долазни позив" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Јави се" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Одбиј" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Позив је заустављен" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "од %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s предлаже да започнете видео. Да ли прихватате ?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Веза веб сајта" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Линфон" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Интернетски видео телефон" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (основно)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Преселили смо се на %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Ниједна звучна картица није откривена на овом рачунару.\nНећете бити у могућности да шаљете или да примате звучне позиве." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Слободан СИП телефон са снимком" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Здраво\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Додајте у адресар" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Тражи у директоријуму „%s“" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Неисправан сип контакт !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Додај нови контакт" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Уредите контакт „%s“" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Обришите контакт „%s“" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Обришите историјат ћаскања за „%s“" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Додајте нови контакт из директоријума „%s“" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Име" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Проток (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Стање" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "Проток бита ИП-а (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Параметри" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Укључено" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Искључено" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Налог" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Енглески" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Француски" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Шведски" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Италијански" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Шпански" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Бразилски португалски" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Пољски" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Немачки" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Руски" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Јапански" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Холандски" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Мађарски" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Чешки" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Кинески" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Традиционални кинески" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Норвешки" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Јеврејски" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Српски" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Арапски" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Турски" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "Треба поново да покренете линфон да би нови изабрани језик ступио у дејство." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Ништа" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "СРТП" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "ДТЛС" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ЗРТП" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "Новије издање је доступно са „%s“.\nДа ли желите да отворите прегледник и да га преузмете ?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Радите на најновијем издању." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Име и презиме" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Грешка у коминикацији са сервером." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Повезујем се..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Повезан сам" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Примам податке..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Нашао сам %i контакт" -msgstr[1] "Нашао сам %i контакта" -msgstr[2] "Нашао сам %i контаката" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Корисничко име је већ у употреби!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Нисам успео да проверим доступност корисничког имена. Касније покушајте опет." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Позив бр. %i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Пребаци позив #%i са %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Не користи се" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ИЦЕ није покренут" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ИЦЕ није успео" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ИЦЕ је у току" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Пролазим кроз један или више НАТ-са" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Непосредно" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Преко преносног сервера" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "уПнП није покренут" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "уПнП је у току" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "уПнП није доступан" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "уПнП ради" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "уПнП није успео" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Непосредно или кроз сервер" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "преузимање: %f\nотпремање: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f к/с" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f секунде" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Прекини" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Позивам..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Долазни позив" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "добро" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "просечно" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "оскудно" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "јадно" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "много лоше" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "недоступно" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Осигурано СРТП-ом" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Осигурано ДТЛС-ом" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Осигурано ЗРТП-ом [потврђивање идентитета: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Непроверено подешавање" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Проверено подешавање" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "На конференцији" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "У позиву" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Заустављен позив" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Позив је завршен." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Пренос је у току" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Пренос је обављен." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Пренос није успео." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Настави" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Застани" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Снимам у\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Паузирано)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Унесите податке пријављивања за %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "довлачим са „%s“" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Преузимање удаљеног подешавања са „%s“ није успело." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Глас није откривен" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Сувише низак" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Добар" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Сувише гласан" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Да ли сте чули три писка ?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Нисам пронашао поставке звука " - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Не могу да покренем управљање звуком система " - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Добро дошли!\nОвај помоћник ће вам помоћи да подесите поставке звука за Линфон" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Уређај за снимање" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Снимљени волумен" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Нема гласа" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Поставке звука система" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Уређај за пуштање" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Пусти три писка" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Притисните дугме за снимање и реците нешто" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Слушајте ваш снимљени глас" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Сними" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Пусти" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Хајде сада да покренемо Линфон" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Помоћник звука" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Помоћник звука" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Дотеривање појачања микрофона" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Дотеривање јачине звука звучника" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Снимите и пустите" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Завршавам" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "О Линфону" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Беледоне комуникације, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Интернет телефон са снимком који користи уобичајени СИП протокол (rfc3261)." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \nsr: Мирослав Николић \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Потражите пријатеље у директоријуму" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Додај на мој списак" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Потражите неког" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Име позивника" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Историјат позива" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Очистите све" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Повратни позив" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Статистика позива" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Звучни кодек" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Видео кодек" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Искоришћеност ИП пропусног опсега звука" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Повезивост медија звука" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Искоришћеност ИП пропусног опсега снимка" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Повезивост медија снимка" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Време повратног путовања" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Примљена резолуција снимка" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Послата резолуција снимка" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "РТП профил" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Статистика позива и подаци" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Пошаљи" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Заврши конференцију" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Наводим удаљену путању подешавања" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Ово прозорче омогућава подешавање хттп или хттпс адресе када се подешавање добавља на покретању.\nУнесите или измените путању подешавања. Након што притиснете „У реду“, Линфон ће се сам поново покренути како би довукао и унео у налог нова подешавања. " - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "СИП адреса" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Прикажи стање присуства овог пријатеља" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Дозволи овом пријатељу да види стање мог присуства" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Подаци о пријатељу" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "ДСЦП подешавања" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "СИП" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "РТП ток звука" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "РТП ток снимка" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Подесите ДСЦП вредности (хексадецимално)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Притисните овде да подесите јачину звучника" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Сними овај позив у звучну датотеку" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Видео" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Утишај" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Пренос" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "Долазни позив" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Трајање" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Оцена квалитета позива" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "ЛДАП подешавања" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Адреса сервера:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Начин потврђивања идентитета:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Корисничко име:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Лозинка:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "Користи ТЛС везу" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Још није доступно" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Веза" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "Свежи назив домена" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Назив потврђивања" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Подручје" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "САСЛ" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Предмет основе:" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "Пропусник (%s за име):" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Особине имена:" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "Особине СИП адресе:" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "Особине за пропитивање:" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Потражите" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Време за претрагу:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "Највише резултата:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "Прати надимке" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Разно" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "БЕЗИМЕНО" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "ЈЕДНОСТАВНО" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "ДИГЕСТ-МД5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "НТЛМ" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Корисник" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Лозинка" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Интернет веза:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Сам ме пријави" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "ИБ корисника" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Подаци пријављивања" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Добро дошли!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "АДСЛ" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Оптички канал" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Линфоново прозорче прочишћавања" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Премакни на крај" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Основно" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Обриши" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Могућности" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Постави путању подешавања" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Увек покрени видео" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Укључи самовиђење" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Прикажи тастатуру" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "Увези контакте из вКарти" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "Извези контакте у вКарте" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "По_моћ" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Прикажи прозорче прочишћавања" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Матична страница" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Провери _ажурирања" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Помоћник налога" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "СИП адреса или број телефона:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Започните нови позив" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Пријатељи" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Тражи" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Додај пријатеље из директоријума" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Додај пријатеља" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Очисти историјат озива" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Мој тренутни идентитет:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Самојављање је укључено" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "безимено" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "ГССАПИ" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "САСЛ" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "основна звучна картица" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "звучна картица" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "основна камерица" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "ЦИФ" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Кодеци звука" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Кодеци снимка" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "В" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "СИП (УДП)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "СИП (ТЦП)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "СИП (ТЛС)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Подешавања" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Овај одељак одређује вашу СИП адресу када не користите СИП налог" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Ваше приказано име (нпр: Пера Перић):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Ваше корисничко име:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Ваша резултирајућа СИП адреса:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Основни идентитет" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Чаробњак" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Додај" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Уреди" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Уклони" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Посреднички налози" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Обриши све лозинке" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Приватност" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Сам одговори када се прими позив" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Сачекај пре него што одговориш (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Самостални-одговор" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "СИП налози" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Звук звона:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "АЛСА-ин посебни уређај (изборно):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Уређај за снимање:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Уређај за звоно:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Уређај за пуштање:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Укључи поништавање одјека" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Звук" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Улазни уређај снимка:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Жељена резолуција снимка:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Начин излаза снимка:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Прикажи претпреглед камерице" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Претподешавање снимка:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Жељени проток кадрова снимка:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 значи „неограничено“" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Снимак" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Ограничи брзину слања на (Kb/s):" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Ограничи брзину преузимања на (Kb/s):" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Укључи прилагодљиво управљање протоком" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Прилагодљиво управљање протоком је техника за променљиво погађање доступног пропусног опсега за време позива." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Управљање пропусним опсегом" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Мултимедија" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Подеси јединицу највећег преноса:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Пошаљи ДТМФ као СИП податке" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Омогући ИПв6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Пренос" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "СИП/УДП прикључник" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Насумично" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "СИП/ТЦП прикључник" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "РТП/УДП звука:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Неизмењиво" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "РТП/УДП снимка:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Тунел" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "ДСЦП поља" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Мрежни протокол и прикључници" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Непосредна веза на Интернет" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Иза НАТ-а / мрежне баријере (наведите ИП мрежног пролаза)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Иза НАТ-а / мрежне баријере (користите СТУН за решавање)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Иза НАТ-а / мрежне баријере (користите ИЦЕ)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Иза НАТ-а / мрежне баријере (користите уПнП)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Јавна ИП адреса:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Стун сервер:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "НАТ и мрежна баријера" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Врста шифровања медија" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "Користи Лиме за одлазне поруке ћаскања" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Шифровање медија је обавезно" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "Обавезно" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "Жељено" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Шифровање" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Мрежа" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Укључи" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Искључи" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Кодеци звука" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Кодеци снимка" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Kодеци" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Језик" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Прикажи напредна подешавања" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Ниво" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Корисничко сучеље" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "Подешавања ЛДАП налога" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "ЛДАП" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Готово" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Линфон — Потребно је потврђивање идентитета" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Унесите лозинку домена" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Подешавам..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Сачекајте док довучем подешавања са сервера..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "Помоћник подешавања СИП налога" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Добро дошли!\nОвај помоћник ће вам помоћи да користите СИП налог за ваше позиве." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Добро дошли у помоћника подешавања налога" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Направи налог на линфон.орг-у" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Већ имам налог линфон.орг-а и желим да га користим" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Већ имам сип налог и желим да га користим" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Желим да наведем удаљену путању подешавања" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Помоћник подешавања налога" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Унесите податке вашег налога" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Корисник*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Лозинка*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Домен*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Посредник" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Подесите ваш налог (корак 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Унесите ваше корисничко име линфон.орг-а" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Унесите ваше корисничко име сип-а (корак 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Обавезна поља" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "Ел. пошта: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Корисник: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Лозинка: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Потврдите вашу лозинку: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Обавештавај ме о ажурирањима линфона" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Унесите податке налога (корак 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Ваш налог је направљен, сачекајте тренутак." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Прављење налога је у току" - -#: ../gtk/setup_wizard.ui.h:29 -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Затим се вратите овде и притисните дугме „Напред“." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Потврђивање (корак 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Проверавам да ли је ваш налог потврђен, сачекајте тренутак." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Провера налога је у току" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Грешка, налог није потврђен, корисничко име је већ у употреби или је сервер недоступан.\nВратите се назад и покушајте опет." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Грешка" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Хвала вам. Ваш налог је сада подешен и спреман за употребу." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Линфон — Подесите СИП налог" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Ваш СИП идентитет:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Изгледа као „sip:<корисничко-име>@<домен>“" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "сип:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "Адреса СИП посредника:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Изгледа као „sip:<назив посредника>“" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Трајање уписа (сек):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Параметри пријатеља (изборно):" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "АВПФ редован РТЦП интервал (сек):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Рута (изборно):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Пренос" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Упиши се" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Објави податке о присуству" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Укључи АВПФ" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Подесите СИП налог" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Подесите ВоИП тунел" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Домаћин" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Прикључник" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Подесите тунел" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Подесите хттп посредника (изборно)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Сачекајте мало" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Спреман" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Подешавам" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Ступам у везу" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Не могу да позовем" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Извините, достигли смо највећи број истовремених позива" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "вам се обраћа" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr " и затражени само-одговор." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Мењам параметре позива..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Повезан сам." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Позив је прекинут" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Не могу да зауставим позив" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Заустављам тренутни позив..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "У току је тражење стуна..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Прикупљање месних ИЦЕ кандидата је у току..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "На вези" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Заузет" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Одмах се враћам" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Одсутан" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "На телефону" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "На ручку сам" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Не узнемиравај" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Премештен" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Користим другу услугу дописивања" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Неповезан" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "На чекању" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "На одмору" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Непознато стање" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "Адреса сип посредника коју сте унели је неисправна, мора почети на „sip:“ за којим следи назив домаћина." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "Сип идентитет који сте унели није исправан.\nТреба да буде у облику „sip:корисник@домен-посредника“, као што је „sip:alice@example.net“" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Тражим одредиште телефонског броја..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Не могу да решим овај број." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Не могу да се пријавим као %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "Освежавам на %s..." - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Удаљено звоњење." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Удаљено звоњење..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Ранији медиј." - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "На позив је одговорио/ла %s" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Позив је настављен." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Несагласно, проверите кодеке или безбедносна подешавања..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Медијски параметри су несагласни." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Наставили смо." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Друга страна нас је паузирала." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "Позив је освежен удаљеним." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Позив је завршен." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Корисник је заузет." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Корисник је привремено недоступан." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Корисник не жели да буде узнемираван." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Позив је одбијен." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Истекло је време захтева." - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Преусмерен" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Позив није успео." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Уписивање на „%s“ је успело." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Исписивање са „%s“ је обављено." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "нема ограничења одговора" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Уписивање на „%s“ није успело: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Услуга није доступна, поново покушавам" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Симбол потврђивања идентитета је „%s“" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Параметри позива не могу бити измењени: %s." - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Параметри позива су успешно измењени." - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "Пропустили сте %i позив." -msgstr[1] "Пропустили сте %i позива." -msgstr[2] "Пропустили сте %i позива." - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "прекинут" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "завршен" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "пропуштен" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "непознато" - -#: ../coreapi/call_log.c:234 -#, 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/call_log.c:235 -msgid "Outgoing call" -msgstr "Одлазни позив" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Не могу да пустим „%s“." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/sv.po b/po/sv.po deleted file mode 100644 index 983966d5a..000000000 --- a/po/sv.po +++ /dev/null @@ -1,2091 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Henrik Mattsson-Mårn , 2016 -# Magnus Johansson , 2016 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Swedish (http://www.transifex.com/belledonne-communications/linphone-gtk/language/sv/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sv\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "Ringer %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "Skicka text till %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "Lägg till %s till din kontaktlista" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Senaste samtal" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Senaste samtal (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "n/a" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "Avbrutna" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Missade" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Avvisade" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i minut" -msgstr[1] "%i minuter" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i sekund" -msgstr[1] "%i sekunder" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tKvalitet: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Konferens" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Jag" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "Kunde inte hitta pixmap filen: %s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Skickar..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "Meddelande ej skickat" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Kopiera" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "skriv loggning information under körning" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "visa version och avsluta." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "sökväg till en fil att skriva loggar i." - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Starta linphone med video inaktiverat." - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Starta ikonifierat, visa inte huvudfönstret" - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "Samtalsmottagare" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Välj en arbetskatalog som ska vara basen för installationen, såsom C:\\Program\\Linphone" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Konfigurationsfil" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Kör ljudassistenten" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "Kör självtest och avsluta 0 om möjligt" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "%s skulle vilja lägga dig till sin kontaktlista.\nVill du lägga denna person till din kontaktlista och tillåta den att se din närvarostatus?\nOm du svarar nej kommer personen att bli tillfälligt svartlistad." - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "Var vänlig och ange ditt lösenord för användarnam %s\n i område %s:" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Samtalsfel" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Samtalet slut" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Inkommande samtal" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Svara" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Avböj" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Samtal pausat" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "av %s" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s föreslår att starta video. Godtar du det?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "Webbsajt" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "En internetvideotelefon" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Default)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "Vi är överförda till %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Inget ljudkort har upptäckts på denna dator.\nDu kommer inte att kunna skicka och ta emot samtal." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "En gratis SIP video-telefon" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Hej\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Lägg till i adressbok" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "Sök i %s katalogen" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "ogiltig SIP kontakt!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Lägg till en ny kontakt" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "Ändra kontakt '%s'" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "Ta bort kontakt '%s'" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "Ta bort chatthistorik för '%s'" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "Lägg till kontakt ifrån %s katalogen" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Namn" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Frekvens (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Status" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "Datahastighet (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Parametrar" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "På" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Av" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Konto" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "Engelska" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Franska" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "Svenska" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "Italienska" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "Spanska" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Portugisiska (Brasilien)" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Polska" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Tyska" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Ryska" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japanska" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Nederländksa" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Ungerska" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Tjekiska" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Kinesiska" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Kinesiska (traditionell)" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norska" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "Hebreiska" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Serbiska" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Arabiska" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Turkiska" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "Du behöver starta om Linphone för att det nya språket ska synas." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Ingen" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "En nyare version är tillgänglig på %s.\nVill du öppna en webbläsare för att ladda ner den?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "Du kör den sensaste versionen." - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "Förnamn, Efternamn" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Kommunikationsfel med servern." - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Kontaktar ..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Kopplad" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Tar emot data..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "Hittat kontakt %i" -msgstr[1] "Hittat kontakt %i" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Användarnamnet är upptaget!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Misslyckades att kontrollera tillgänglighet. Var vänlig och försök senare." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "Ring #%i" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "Övergår till att ringa #%i med %s" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Används ej" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE inte aktiverat" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE misslyckades" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE pågår" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "Går igenom en eller flera NAT:s" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Direkt" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Genom en reläserver" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "uPnP inte aktiverat" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "uPnP pågår" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "uPnP ej tillgängligt" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "uPnP körs" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "uPnP misslyckades" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Direkt eller genom server" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "nedladdning: %f\nuppladdning: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "%ix%i @ %f fps" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "%.3f sekunder" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Lägg på" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Ringer..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Inkommande samtal" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "bra" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "medelmåttig" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "dålig" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "mycket dålig" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "för dålig" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "ej tillgänglig" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "Säkrad av SRTP" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "Säkrad av DTLS" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "Säkrad av ZRTP - [auth token: %s]" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Ange som obekräftad" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Ange som bekräftad" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "I konferens" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "I samtal" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Pausat samtal" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Samtalet slut." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Överföring pågår" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Överföring klar." - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Överföring misslyckades." - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Fortsätt" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Pausa" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "Spelar in i\n%s %s" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Pauserad)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "Ange inloggningsuppgifter för %s" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "hämtar från %s" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "Hämtning av fjärrkonfiguration från %s misslyckades." - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Ingen röst upptäckt" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "För svag" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "Bra" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "För stark" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Hörde du tre pip?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Ljudinställningar ej funna" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Kan inte starta systemljudkontroll" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Välkommen\nDenna assistent kommer att hjälpa dig ställa in ljudet för Linphone" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Inspelningsenhet" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "Inspelad volym" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Ingen röst" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Systemljudsinställningar" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Uppspelningsenhet" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Spela tre pip" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Klicka på inspelningsknappen och säg några ord" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Lyssna på din inspelade röst" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Spela in" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Spela" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Låt oss starta Linphone nu" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Ljudassistent" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Ljudassistent" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "Mikrofonkalibrering" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Högtalarvolymkalibrering" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Spela in och upp" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Avslutar" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Om Linphone" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "En internetvideotelefon som använder SIP (rfc3261)." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat och Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: Yoshiya Yamaguchi \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonym\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Sök kontakter i katalogen" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Lägg till min lista" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "Sök någon" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "Den uppringdas namn" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Samtalshistorik" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Rensa alla" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Ring tillbaka" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Samtalsstatistik" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Ljudkodek" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Videokodek" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "Bandbreddsanvändning för ljud" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Ljudanslutningsbarhet" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "Bandbreddsanvändning för bild" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Videoanslutningsbarhet" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Rundturstid" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Videoupplösning mottagen" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Videoupplösning skickad" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "RTP-profil" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Samtalsstatistik och information" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Skicka" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Avsluta konferens" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "Anger en fjärrkonfigurations-URI" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "Detta dialogfönster tillåter angivandet av en http- eller https-adress när konfigurationen hämtas vid starten.\nVar vänlig och ange eller modifiera konfigurations-URI:n nedan. Sedan du klickat på OK kommer Linphone att starta om automatiskt för att kunna hämta och använda den nya konfigurationen." - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP Adress" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Visa kontaktens närvarostatus" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "Tillåt den här kontakten att se min närvarostatus" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Kontakt information" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "DSCP-inställningar" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SIP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "Ljud-RTP-ström" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "Video-RTP-ström" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "Ange DSCP-värden (med hexadecimal)" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Klicka här för att ställa in högtalarvolymen" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Spela in detta samtal till en ljudfil" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Video" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Tysta" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Överför" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "I samtal" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Längd" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Samtalskvalitetsbetyg" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "LDAP-inställningar" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Serveradress:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Autentiseringsmetod:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Användarnamn:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Lösenord:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "Använd TLS-anslutning" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Inte tillgänglig än" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Anslutning" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "Bind DN" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Autentiseringsnamn" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Område" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Basobjekt:" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "Filter (%s för namn):" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Namnattribut:" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "SIP-adressattribut:" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "Attribut för fråga:" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Sök" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Tidsgräns för sökning:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "Max resultat:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "Följ alias" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Diverse" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "ANONYMOUS" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "SIMPLE" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "DIGEST-MD5" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "NTLM" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Användarnamn" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Lösenord" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "Internetförbindelse:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "Logga in mig automatiskt" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "AnvändarID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Inloggningsuppgifter" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Välkommen!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fiberkanal" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphones felrättningsfönster" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Rulla till slutet" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Standard" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Ta bort" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Alternativ" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "Ange konfigurations-URI" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Starta alltid video" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Självbild" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Visa knappsats" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Hjälp" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Visa felrättningsfönster" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Hemsida" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Sök efter _uppdateringar" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Kontoassistent" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP-adress eller telefonnummer:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Påbörja ett nytt samtal" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Kontakter" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Sök" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Lägg till kontakt ifrån katalogen" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Lägg till kontakt" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Rensa samtalshistorik" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Min nuvarande identitet" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Autosvar är aktiverat" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "anonym" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "standardljudkort" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "ett ljudkort" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "standardkamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Ljudkodekar" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Videokodekar" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Inställningar" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Denna sektion specificerar din SIP-adress när du inte använder ett SIP-konto" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Ditt synliga namn (t.ex. Kalle Karlsson):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Ditt användarnamn:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "Din SIP-adress:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Standardidentitet" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Guide" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Lägg till" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Editera" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Ta bort" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Proxykonton" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Radera alla lösenord" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Integritet" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Svara automatiskt när ett samtal tas emot" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Fördröjning före svar (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Autosvar" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "Hantera SIP-konton" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Ringsignal:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "Speciell enhet för ALSA (tillval):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Inspelningsenhet:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Ringningsenhet:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Uppspelningsenhet:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "Tillåt ekoborttagning" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Ljud" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Videoinmatningsenhet:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Föredragen videoupplösning:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Videoutmatningsmetod:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Visa kameraförhandsgranskning" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Videoförval:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Föredragen videobildfrekvens:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 står för \"utan begränsning\"" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Video" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Max uppladdningshastighet i Kbit/sek:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "Max nedladdningshastighet i Kbit/sek:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Aktivera anpassningsbar hastighetskontroll" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "Anpassningsbar hastighetskontroll är en teknik för att dynamiskt gissa tillgänglig bandbredd under ett samtal." - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Bandbreddskontroll" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Multimediainställningar" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Välj MTU (Maximum Transmission Unit):" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "Skicka DTMF-koder som SIP-information" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "Tillåt IPv6" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Transport" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "SIP/UDP-port" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Slumpmässig" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "SIP/TCP-port" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "Ljud-RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Låst" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "Video-RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tunnel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP-fält" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Nätverksprotokoll och portar" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "Direkt förbindelse till internet" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "Bakom NAT / brandvägg (specificera IP)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "Bakom en NAT / brandvägg (använd STUN för att avgöra adressen)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "Bakom NAT / brandvägg (använd ICE)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "Bakom NAT / brandvägg (använd uPnP)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Publik IP-adress:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "STUN-server:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT och Brandvägg" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Mediakrypteringstyp" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "Använd Lime för utgående chattmeddelanden" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Mediakryptering är obligatorisk" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Kryptering" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Nätverksinställningar" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Aktivera" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Inaktivera" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Ljudkodekar" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Videokodekar" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Kodekar" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Språk" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Visa avancerade inställningar" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Nivå" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Användargränssnitt" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "LDAP-kontoinställning" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Klar" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Autentisering krävs" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Ange lösenordet för domänen" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Konfigurerar ..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Var vänlig och vänta medan konfiguration hämtas från server ..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "Inställningsassistent för SIP-konto" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Välkommen!\nDenna assistent kommer att hjälpa dig använda ett SIP-konto för dina samtal." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Välkommen till kontoinstallationsassistenten" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "Skapa ett konto på linphone.org" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Jag har redan ett linphone.org-konto och jag vill bara använda det" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Jag har redan ett sip-konto och jag vill bara använda det" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Jag vill ange ett fjärrkonfigurations-URI" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Kontoinstallationsassistenten" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Ange din konto-information" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Användarnamn*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Lösenord*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Domän*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Proxy" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Konfigurera ditt konto (steg 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "Ange ditt linphone.org-användarnamn" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "Ange ditt sip-användarnamn (steg 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Obligatoriska fält" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "E-post: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Användarnamn: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Lösenord: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Bekräfta ditt lösenord: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "Håll mig informerad om Linphone-uppdateringar" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Ange kontoinformation (steg 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Ditt konto skapas. Var vänlig vänta." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Kontoskapande pågår" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Var vänlig och bekräfta ditt konto genom att klicka på länken vi nyss skickade dig via e-post.\nKom sedan tillbaka hit och klicka på knappen Nästa." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Bekräftelse (steg 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Kontrollerar om ditt konto bekräftas. Var vänlig, vänta." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Kontobekräftelsekontroll pågår" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Fel. Konto ej bekräftat, användarnamn upptaget eller server onåbar.\nVar vänlig, gå tillbaka och försök igen." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Fel" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Tack. Ditt konto är nu konfigurerat och färdigt att användas." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Konfigurera ett SIP-konto" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "Din SIP-identitet:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "Ser ut som sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP-proxyadress:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "Ser ut som sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Registreringstid (sek.):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "Kontaktparametrar (tillval):" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "AVPF regular RTCP intervall (sek):" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Route (tillval):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Transport" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Registrera" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Publicera närvaroinformation" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "Aktivera AVPF" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Konfigurera ett SIP-konto" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "Konfigurera VoIP-tunnel" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Värd" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Port" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Konfigurera tunnel" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "Konfigurera http-proxy (valfritt)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Vänta" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Redo" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Konfigurerar" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Kontaktar" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Kunde inte ringa" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "Beklagar. Vi har nått det maximala antalet samtidiga samtal." - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "kontaktar dig" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "och frågade autosvar." - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Modifierar samtalsparametrar ..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Kopplad" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Samtal avbrutet" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Kunde inte pausa samtalet" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Pausar nuvarande samtal..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "STUN-uppslagning pågår ..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "Samlande av ICE-lokalkandidater pågår ..." - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Online" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Upptagen" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Kommer strax tillbaka" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Borta" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "I telefon" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "På lunch" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Stör ej" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Flyttat" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Använder en annan meddelandetjänst" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Frånkopplad" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Pågående" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "Ledighet" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Okänd status" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "SIP-proxyadressen du angav är inte rätt. Adressen måste starta med \"sip:\" följt av ett värdnamn." - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "SIP-adressen du angav är inte rätt.\nAdressen bör se ut som sip:användarnamn@domän, såsom sip:alice@exempel.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "Leta efter telefonnummerdestinationen ..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "Kan inte nå detta nummer." - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "Kunde inte logga in som %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "Förnyar på %s ..." - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "Ringer hos motparten." - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "Ringer hos motparten ..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "Tidig media" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "Samtal besvarat av %s" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Samtal återupptaget." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "Inkompatibel. Kontrollera kodekar eller säkerhetsinställningar ..." - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "Inkompatibla mediaparametrar." - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "Vi har återupptagits." - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "Vi har pauserats av annan part." - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "Samtalet är uppdaterat av motpart." - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Samtalet slut." - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Användare är upptagen." - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "Användaren är tillfälligt otillgänglig." - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Användaren vill inte bli störd." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Samtalet avböjdes." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "Förfråganstid" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Omdirigerad" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Samtal misslyckades." - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "Registrering hos %s lyckades." - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "Avregistrering hos %s lyckades." - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "Inget svar inom angiven tid" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "Registrering hos %s mislyckades: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Tjänst ej tillgänglig, försöker igen" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "Autentiseringstecken är %s" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "Samtalsparametrar kunde inte ändras: %s" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "Samtalsparametrar ändrades framgångsrikt." - -#: ../coreapi/linphonecall.c:4636 -#, 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" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "avbruten" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "slutförd" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "missad" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "okänd" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "%s vid %s\nFrån: %s\nTill: %s\nStatus: %s\nLängd: %i min %i sek\n" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "Utgående samtal" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "Kan inte spela %s." - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/tr.po b/po/tr.po deleted file mode 100644 index 4b27eecfa..000000000 --- a/po/tr.po +++ /dev/null @@ -1,2091 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Emin Tufan , 2016 -# faradundamarti , 2015-2016 -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Turkish (http://www.transifex.com/belledonne-communications/linphone-gtk/language/tr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: tr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "Son çağrılar" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "Son çağrılar (%i)" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "yok" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "İptal edildi" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "Yanıtsız" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "Reddedildi" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "%i dakika" -msgstr[1] "%i dakika" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "%i saniye" -msgstr[1] "%i saniye" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "%s\tKalite: %s\n%s\t%s\t" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "%s\t%s" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "Grup görüşme" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "Bana" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "Gönderiliyor..." - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "İleti gitmedi" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "Kopya" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "sürümü görüntüle ve çık." - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "Günlükleri içine yazmak için bir dosya yolu" - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "Linphonu görüntü olmadan başlat" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "Sadece sistem tepsisinde başlat, ana arayüzü gösterme." - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "adres ara" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "Bir çalışma dizini belirtin (kurulum temelinde olmalı,örneğin: c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "Yapılandırma dosyası" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "Ses yardımcısını çalıştır" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "Çağrı yanlış" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "Çağrı sonlandırıldı" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "Gelen çağrı" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "Yanıt" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "Reddet" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "Çağrı duraklatıldı" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "%s tarafından" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "%s görüntü başlatmayı önerdi.Kabul ediyor musun?" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "İnternet " - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "Görüntülü internet telefonu" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (Öntanımlı)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "%s ye aktardık" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "Bu bilgisayarda bir ses kartı bulunamadı.\nSesli görüşme yapamazsınız." - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "Özgür bir SİP görüntülü-telefon" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "Merhaba\n" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "Adres defterine ekle" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "%s dizininde ara" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "Geçersiz sip bağlantısı !" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "Yeni bir bağlantı ekle" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "'%s' bağlantısını düzenle" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "'%s' bağlantısını sil" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "'%s' sohbet geçmişini sil" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "%s dizininden yeni bağlantı ekle" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "Ad" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "Hız (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "Durum" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "İP Bit hızı (kbit/s)" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "Değişkenler" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "Etkin" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "Devre dışı" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "Hesap" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "İngilizce" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "Fransızca" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "İsveççe" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "İtalyanca" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "İspanyolca" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "Brezilya Portekizcesi" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "Lehçe" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "Almanca" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "Rusca" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "Japonca" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "Flemenkçe" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "Macarca" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "Çekce" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "Çince" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "Geleneksel Çince" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "Norveççe" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "İbranice" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "Sırpça" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "Arapça" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "Türkçe" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "Yeni dil seçiminizin etkili olabilmesi için linfonu yeniden başlatmalısınız." - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "Hiçbiri" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "SRTP (Güvenli Gerçek Zamanlı Aktarım Protokolü)" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "DTLS" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "ZRTP" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "%s den indirilebilir daha yeni bir sürüm var.\nOnu indirmek için internet tarayıcınızı açmak istiyor musunuz?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "En son sürümü çalıştırıyorsunuz" - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "İlk ad, Son ad" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "Sunucuya bağlanma hatası" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "Bağlanıyor..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "Bağlandı" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "Veri alınıyor..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "" -msgstr[1] "" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "Kullanıcı adınız zaten kullanılıyor!" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "Kullanıcı adınızın geçerlilik denetimi başarısız.Daha sonra tekrar deneyin." - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "Kullanılmıyor" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "ICE etkin değil" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "ICE başarısız" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "ICE sürüyor" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "Doğrudan" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "Bir röle sunucu aracılığı ile" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "Evrensel Tak-Çalıştır etkin değil" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "Evrensel Tak-Çalıştır ilerliyor" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "Evrensel Tak-Çalıştır kullanılamaz" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "Evrensel Tak-Çalıştır çalışıyor" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "Evrensel Tak-Çalıştır başarısız" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "Doğrudan veya sunucu aracılığıyla" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "İndime: %f\nkarşıya yükleme: %f (kbit/s)" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "Telefonu kapatma" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "Arıyor..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "00:00:00" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "Gelen çağrı" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "iyi" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "orta" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "zayıf" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "çok zayıf" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "çok kötü" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "kullanılamaz" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "SRTP güvencesi altında" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "DLTS güvencesi altında" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "Doğrulanmamış ayar" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "Doğrulanmış ayar" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "Grup görüşmede" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "Duraklatılmış çağrı" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "Çağrı sonlandı." - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "Aktarım sürüyor" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "Aktarım tamam" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "Aktarım başarısız" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "Devam et" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "Duraklat" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "(Duraklatıldı)" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "%s için giriş bilgisini girin " - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "Ses olmadığı algılandı" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "Çok düşük" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "İyi" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "Çok yüksek" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "Üç bip sesi duydun mu?" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "Ses tercihleri bulunamadı" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "Ses kontrol sistemi başlatılamıyor" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "Hoşgeldiniz!\nBu yardımcı,Linphone'un ses ayarlarını yapılandırmanıza yardım edecek" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "Görüntü yakalama aygıtı" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "Ses yok" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "Sistem ses tercihleri" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "Oynatma aygıtı" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "Üç bip sesi çal" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "Kayıt tuşuna bas ve bazı kelimeler söyle" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "Kaydettiğin sesi dinle" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "Kayıt" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "Çalma" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "Haydi şimdi Linphona başlayalım" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "Ses Yardımcısı" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "Ses yardımcısı" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "Hoparlör ses yüksekliği ayarı" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "Kaydet ve Oynat" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "Sonlandırma" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "Linphone Hakkında" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "(C) Belledonne Communications, 2010\n\n" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "Standart SİP (rfc3261) protokolü kullanan görüntülü internet telefonu." - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "fr: Simon Morlat\nen: Simon Morlat and Delphine Perreau\nit: Alberto Zanoni \nde: Jean-Jacques Sarton \nsv: Daniel Nylander \nes: Jesus Benitez \nja: YAMAGUCHI YOSHIYA \npt_BR: Rafael Caesar Lenzi \npl: Robert Nasiadek \ncs: Petr Pisar \nhu: anonymous\nhe: Eli Zaretskii \n" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "Dizinde bağlantılar ara" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "Listeme ekle" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "Çağrı geçmişi" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "Hepsini temizle" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "Geri arama" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "Çağrı istatistikleri" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "Ses çözücü" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "Görüntü çözücü" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "Ses Ortamı bağlanırlığı" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "Görüntü Ortamı bağlanırlığı" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "Sinyal gidiş-dönüş süresi" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "Alınan görüntü çözünürlüğü" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "Giden görüntü çözünürlüğü" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "RTP profili" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "Çağrı istatistikleri ve bilgisi" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "Gönder" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "Grup görüşme son" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SİP Adresi" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "Bu bağlantının varolan durumunu göster" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "Bağlantı bilgisi" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "DSCP ayarları" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "SİP" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "Hoparlör ses miktarı ayarı için buraya tıkla" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "Bu aramayı bir ses dosyasına kaydet" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "Görüntü" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "Sessiz" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "Aktarım" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "arıyor" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "Süre" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "Çağrı kalitesi düzeyi" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "LDAP Ayarları" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "Sunucu adresi:" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "Kimlik doğrulama yöntemi:" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "Kullanıcı adı:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "Parola:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "TLS Bağlantısı Kullan" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "Henüz kullanılabilir değil" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "Bağlantı" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "Yazar Adı" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "Ülke" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "Temel nesne:" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "Öznitelik Adı:" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "SIP adresi özniteliği" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "Ara" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "Arama zamanaşımına uğradı:" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "En çok sonuç:" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "Takma Adları İzle" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "Çeşitli" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "Kallanıcı adı" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "Parola" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "İnternet bağlantısı:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "Kullanıcı kimliği" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "Giriş bilgisi" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "Hoşgeldiniz!" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "Fiber Kanal" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone hata giderme penceresi" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "Sonuna kadar ilerleyin" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "Öntanımlı" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "Sil" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "_Seçenekler" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "URl yapılandırma ayarları" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "Her zaman görüntüyü başlat" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "Özgörüntü etkin" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "Tuştakımını göster" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "_Yardım" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "Hata düzeltme penceresini göster" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "_Anasayfa" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "Güncellemeleri _Denetle" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "Hesap yardımcısı" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SİP adresi veya telefon numarası:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "Yeni bir arama başlat" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "Bağlantılar" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "Arama" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "Rehberden bağlantılar ekle" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "Bağlantı ekle" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "Çağrı geçmişini temizle" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "Güncel kimliğim:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "Otomatik yanıtlama etkin" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "kimliği belirsiz" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "GSSAPI" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "SASL" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "öntanımlı ses kartı" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "Ses kartı" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "öntanımlı kamera" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "Ses çözücüleri" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "Görüntü çözücüleri" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "SIP (UDP)" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "SIP (TCP)" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "SIP (TLS)" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "Ayarlar" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "Bu bölüm bir SİP hesabı kullanmadığınız zaman sizin SİP adresinizi tanımlar" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "Görünecek adınız (örneğin: Faradunda Marti)" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "Kullanıcı adınız:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "Öntanımlı kimlik" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "Yardımcı" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "Ekle" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "Düzenle" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "Kaldır" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "Vekil sunucu hesapları" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "Bütün parolaları sil" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "Gizlilik" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "Bir çağrı alındığında otomatik olarak yanıtla" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "Yanıtlamadan önceki gecikme (ms)" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "Otomatik yanıt" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "SİP Hesaplarını Yönet" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "Zil sesi:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "ALSA özel aygıt (seçmeli)" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "Görüntü yakalama aygıtı" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "Ses çalma aygıtı:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "Oynatma aygıtı:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "yankı giderme etkin" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "Ses" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "Görüntü aygıtı:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "Tercih edilen görüntü çözünürlüğü:" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "Görüntü çıkış yöntemi:" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "Kamera önizlemesi göster" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "Görüntü ön ayarları:" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "Tercih edilen görüntü kare sayısı:" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "Görüntü" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "Gönderim hız sınırı Kbit/saniye:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "İndirme hız sınırı Kbit/saniye:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "Uyarlanabilir hız denetimi etkin" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "Bantgenişliği denetimi" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "Çokluortam ayarları" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "Maksimum İletim Birimi Ayarları" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "IPv6'ya izin ver" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "Taşıma" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "SIP/UDP bağlantı noktası" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "Rastgele" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "SIP/TCP bağlantı noktası" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "Sabitlenmiş" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "Tünel" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "DSCP alanları" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "Ağ protokol ve bağlanma yerleri" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "İnternete doğrudan bağlantı" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "NAT Arkasından / Güvenlik Duvarı (IP ağ geçidi belirleme)" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "NAT Arkasından / Güvenlik Duvarı (ICE kullan)" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "NAT arkasından / Güvenlik Duvarı (evrensel tak-çalıştır kullan)" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "Ortak İP adresi:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Stun sunucusu:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT ve Güvenlik Duvarı" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "Ortam şifreleme türü" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "Giden sohbet iletileri için Lime kullan" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "Ortam şifrelemesi zorunludur" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "Şifreleme" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "Ağ ayarları" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "Etkinleştirme" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "Devre dışı" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "Ses çözücüleri" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "Görüntü çözücüleri" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "Çözücüler" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "Dil" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "Gelişmiş ayarları göster" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "Aşama" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "Kullanıcı arayüzü" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "LDAP Hesap ayarı" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "LDAP" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "Tamam" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - Kimlik doğrulaması gerekli" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "Lütfen alan adı parolası girin" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "Yapılandırılıyor..." - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "Sunucudan yapılandırma ayarlarınız getirilirken bekleyin..." - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "SİP hesabı yapılandırma yardımcısı" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "Hoşgeldiniz!\nBu yardımcı,çağrılarınız için bir SIP hesabı kullanmanıza yardım edecek." - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "Hesap açma yardımcısına hoşgeldiniz" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "linphone.org'da bir hesap oluştur" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "Önceden bir linphone.org hesabım var ve onu kullanmak istiyorum" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "Önceden bir sip hesabım var ve onu kullanmak istiyorum" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "Bir uzaktan URl yapılandırma belirlemek istiyorum" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "Hesap açma yardımcısı" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "Hesap bilgilerinizi girin" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "Kallanıcı adı*" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "Parola*" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "Alan adı*" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "Vekil sunucu" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "Hesabınızı yapılandırın (adım 1/1)" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "linphone.org kullanıcı adınızı girin" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "sip kullanıcı adınızı girin (adım 1/1)" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "(*) Zorunlu alanlar" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "E-posta: (*)" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "Kullanıcı adı: (*)" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "Parola: (*)" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "Parolanızı onaylayın: (*)" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "linphone güncellemeleri hakkında beni bilgilendir" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "Hesap bilgilerini girin (adım 1/2)" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "Hebabınız oluşturulmaya başlandı,lütfen bekleyin." - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "Hesap oluşturma sürüyor" - -#: ../gtk/setup_wizard.ui.h:29 -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 "Lütfen size e-posta yoluyla gönderdiğimiz bağlantıyı tıklayarak hesabınızı doğrulayın.\nSonra buraya geri dönün ve İleri düğmesine basın." - -#: ../gtk/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "Doğrulama (adım 2/2)" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "Hesabınızın geçerli olup olmadığı denetleniyor,lütfen bekleyin." - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "Hesap geçerlilik sınaması sürüyor" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "Hata,hesap geçersiz,kullanıcı adı kullanılıyor veya sunucuya erişilemiyor.\nLütfen geri dönün ve tekrar deneyin." - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "Hata" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "Teşekkürler. Hesabınız yapılandırıldı ve kullanıma hazır." - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - Bir SİP hesabı yapılandır" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "SİP kimliğiniz:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SİP Vekil sunucu adresi:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "Kayıt süresi (saniye)" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "Güzergah (isteğe bağlı)" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "Taşıma" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "Kayıt" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "Yayınlama ön bilgisi" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "AVPF'yi etkinleştir" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "Bir SİP hesabı yapılandır" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "VoIP tüneli yapılandır" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "Barındırıcı" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "Bağlantı noktası" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "Tünel yapılandır" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "http vekil yapılandır (isteğe bağlı)" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "Lütfen bekleyin" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "Hazır" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "Yapılandırılıyor" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "Bağlanıyor" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "Aranamıyor" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "Çağrı değiştirgeleri değiştiriliyor..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "Bağlandı." - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "Çağrı iptal edildi" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "Çağrı duraklatılamadı" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "Geçerli çağrı duraklatılıyor..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "" - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "Çevrimiçi" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "Meşgul" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "Hemen döneceğim" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "Uzakta" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "Telefondayım" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "Yemekteyim" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "Rahatsız etmeyin" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "Taşındı" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "Diğer mesaj servisi kullanılıyor" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "Çevrimdışı" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "Bekliyor" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "Tatil" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "Bilinmeyen durum" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "" - -#: ../coreapi/proxy.c:345 -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:979 -msgid "Looking for telephone number destination..." -msgstr "" - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "" - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "Arama yeniden başlatıldı." - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "Çağrı sonlandırıldı" - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "Kullanıcı meşgul" - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "K" - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "Kullanıcı rahatsız edilmek istemiyor." - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "Çağrı reddedildi." - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "İstek zamanaşımına uğradı." - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "Yeniden yönlendirildi" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "Arama başarısız" - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "Servis kullanımdışı, tekrar deneyin" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "" -msgstr[1] "" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "iptal edildi" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "tamamlandı" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "Yanıtsız" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "bilinmeyen" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "Giden arama" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/zh_CN.po b/po/zh_CN.po deleted file mode 100644 index 3ae8176a3..000000000 --- a/po/zh_CN.po +++ /dev/null @@ -1,2085 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Chinese (China) (http://www.transifex.com/belledonne-communications/linphone-gtk/language/zh_CN/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "呼叫 %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "发送消息给 %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "" - -#: ../gtk/conference.c:46 -msgid "Me" -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:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "运行时向标准输出记录调试信息。" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "" - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "启动到系统托盘,不显示主界面。" - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "现在呼叫的地址" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "指定工作目录(应为安装目录例如 C:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "呼叫结束" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "呼入" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "拒绝" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "网站" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (默认)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "未在此计算机上检测到声卡。\n您无法发送或接收音频呼叫。" - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "免费的 SIP 视频电话" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "在 %s 目录中查找 " - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "无效的 SIP 联系人!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "编辑联系人 %s" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "删除联系人 %s" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "从 %s 目录增加联系人 " - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "名称" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "采样率(Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "状态" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "参数" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "启用" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "禁用" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "帐户" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "英语" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "法语" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "瑞典语" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "意大利语" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "西班牙语" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "巴西葡萄牙语" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "波兰语" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "德语" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "俄语" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "日语" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "荷兰语" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "匈牙利语" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "捷克语" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "中文" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "您需要重启 linphone 以使语言选择生效。" - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "%s 有新版本。\n您是否要打开浏览器下载它?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "您正在运行最新版。" - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "姓名" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "与服务器通讯失败" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "正在连接..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "已连接" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "正在接收数据..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "找到 %i 联系方式" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "正在呼叫..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "通话结束。" - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "请输入 %s 的登录信息" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "一个采用标准 SIP (rfc3261) 协议的互联网视频电话" - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "查找联系人" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "添加为联系人" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "找人" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "呼叫历史" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "发送" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP 地址" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "显示该联系人的在线状态" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "允许此人看到我的在线状态" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "联系人信息" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "呼入" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "通话时间" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "用户名:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "密码:" - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "用户名" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "密码" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "网络连接:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "自动登录" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "用户 ID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "登录信息" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone 调试窗口" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "默认" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "启用自视" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP 地址或电话号码:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "联系人" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "搜索" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "从目录增加联系人" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "当前地址:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "默认声卡" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "默认摄像头" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "设置" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "该段在您不使用SIP帐户时的SIP地址" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "您的显示名:" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "您的用户名:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "您的 SIP 地址结果:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "默认帐户" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "添加" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "编辑" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "移除" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "代理帐户" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "清除所有密码" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "隐私" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "SIP 帐户管理" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "铃声文件:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "ALSA 特殊设备(可选):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "录音设备:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "响铃设备:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "回放设备:" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "启用回声抑制" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "音频" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "视频输入设备:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 表示 “没有限制”" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "视频" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "上传速率限制 kbit/s:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "下载速率限制 kbit/s:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "带宽控制" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "音视频设置" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "设置最大传输单元(MTU):" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "以 SIP 消息发送 DTMF" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "传输协议" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "音频 RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "视频 RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "直接连接到互联网" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "在 NAT 或防火墙后(使用 STUN 解决)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "公网 IP 地址:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Stun 服务器:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT 及防火墙" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "网络设置" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "启用" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "禁用" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "编解码器" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "语言" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "显示高级设置" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "级别" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "用户界面" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "完成" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "请输入密码" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "欢迎使用帐户设置向导" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "帐户设置向导" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "谢谢,您的帐户已经配置完毕,可以使用。" - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - 配置 SIP 帐户" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "您的 SIP 地址:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "类似于 sip:<用户名>@<域>" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP 代理地址:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "类似于 sip:<代理主机名>" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "注册间隔(秒):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "路由(可选):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "发布在线状态" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "配置 SIP 帐户" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "请稍候" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "就绪" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "联系中" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "正在联系您" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr " 并询问了自动回答。" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "" - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "已连接。" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "" - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "正在进行 Stun 查找..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "在线" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "忙碌" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "很快回来" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "离开" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "正在通话" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "外出吃饭" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "请勿打扰" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "已转到其他服务" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "正在使用其他消息服务" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "离线" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "挂起" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "您输入的 SIP 代理地址无效,它必须是以“sip:”开头,并紧随一个主机名。" - -#: ../coreapi/proxy.c:345 -msgid "" -"The sip identity you entered is invalid.\n" -"It should look like sip:username@proxydomain, such as sip:alice@example.net" -msgstr "您输入的地址无效。\n它应具有“sip:用户名@代理域”的形式,例如 sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "查询电话号码目的地..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "该号码无法解析。" - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "无法登录为 %s" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "响铃。" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "" - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "" - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "通话结束。" - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "被叫正忙。" - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "您呼叫的用户暂时无法接通。" - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "用户已开启免打扰功能。" - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "呼叫被拒绝。" - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "已重定向" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "呼叫失败。" - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "成功注册到 %s" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "已在 %s 解除注册。" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "没有响应,超时" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "注册到 %s 失败: %s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "您错过了 %i 个呼叫。" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/po/zh_TW.po b/po/zh_TW.po deleted file mode 100644 index 581911162..000000000 --- a/po/zh_TW.po +++ /dev/null @@ -1,2085 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -msgid "" -msgstr "" -"Project-Id-Version: linphone-gtk\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2016-05-19 14:01+0200\n" -"PO-Revision-Date: 2016-05-10 09:58+0000\n" -"Last-Translator: Belledonne Communications \n" -"Language-Team: Chinese (Taiwan) (http://www.transifex.com/belledonne-communications/linphone-gtk/language/zh_TW/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_TW\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: ../gtk/calllogs.c:178 -#, c-format -msgid "Call %s" -msgstr "播打給 %s" - -#: ../gtk/calllogs.c:179 -#, c-format -msgid "Send text to %s" -msgstr "傳送文字給 %s" - -#: ../gtk/calllogs.c:181 -#, c-format -msgid "Add %s to your contact list" -msgstr "" - -#: ../gtk/calllogs.c:245 ../gtk/main.ui.h:23 -msgid "Recent calls" -msgstr "" - -#: ../gtk/calllogs.c:260 -#, c-format -msgid "Recent calls (%i)" -msgstr "" - -#: ../gtk/calllogs.c:334 -msgid "n/a" -msgstr "" - -#: ../gtk/calllogs.c:337 -msgid "Aborted" -msgstr "" - -#: ../gtk/calllogs.c:340 -msgid "Missed" -msgstr "" - -#: ../gtk/calllogs.c:343 -msgid "Declined" -msgstr "" - -#: ../gtk/calllogs.c:349 -#, c-format -msgid "%i minute" -msgid_plural "%i minutes" -msgstr[0] "" - -#: ../gtk/calllogs.c:352 -#, c-format -msgid "%i second" -msgid_plural "%i seconds" -msgstr[0] "" - -#: ../gtk/calllogs.c:357 -#, c-format -msgid "" -"%s\tQuality: %s\n" -"%s\t%s\t" -msgstr "" - -#: ../gtk/calllogs.c:361 -#, c-format -msgid "%s\t%s" -msgstr "" - -#: ../gtk/conference.c:38 ../gtk/in_call_frame.ui.h:11 -msgid "Conference" -msgstr "" - -#: ../gtk/conference.c:46 -msgid "Me" -msgstr "" - -#: ../gtk/support.c:49 ../gtk/support.c:73 ../gtk/support.c:102 -#, c-format -msgid "Couldn't find pixmap file: %s" -msgstr "找不到 pixmap 檔:%s" - -#: ../gtk/chat.c:207 ../gtk/chat.c:265 -msgid "Sending..." -msgstr "" - -#: ../gtk/chat.c:224 ../gtk/chat.c:274 -msgid "Message not sent" -msgstr "" - -#: ../gtk/chat.c:498 -msgid "Copy" -msgstr "" - -#: ../gtk/main.c:134 -msgid "log to stdout some debug information while running." -msgstr "執行時將一些除錯資訊記錄到標準輸出。" - -#: ../gtk/main.c:135 -msgid "display version and exit." -msgstr "" - -#: ../gtk/main.c:136 -msgid "path to a file to write logs into." -msgstr "" - -#: ../gtk/main.c:137 -msgid "Start linphone with video disabled." -msgstr "" - -#: ../gtk/main.c:138 -msgid "Start only in the system tray, do not show the main interface." -msgstr "只在系統匣啟動,不要顯示主要介面。" - -#: ../gtk/main.c:139 -msgid "address to call right now" -msgstr "現在要打電話的位址" - -#: ../gtk/main.c:140 -msgid "" -"Specifiy a working directory (should be the base of the installation, eg: " -"c:\\Program Files\\Linphone)" -msgstr "指定一個工作目錄(應該為安裝的根目錄,例如:c:\\Program Files\\Linphone)" - -#: ../gtk/main.c:141 -msgid "Configuration file" -msgstr "" - -#: ../gtk/main.c:142 -msgid "Run the audio assistant" -msgstr "" - -#: ../gtk/main.c:143 -msgid "Run self test and exit 0 if succeed" -msgstr "" - -#: ../gtk/main.c:1058 -#, c-format -msgid "" -"%s would like to add you to his/her contact list.\n" -"Would you add him/her to your contact list and allow him/her to see your presence status?\n" -"If you answer no, this person will be temporarily blacklisted." -msgstr "" - -#: ../gtk/main.c:1135 -#, c-format -msgid "" -"Please enter your password for username %s\n" -" at realm %s:" -msgstr "" - -#: ../gtk/main.c:1244 -msgid "Call error" -msgstr "" - -#: ../gtk/main.c:1247 ../coreapi/linphonecore.c:3942 -msgid "Call ended" -msgstr "通話已結束" - -#: ../gtk/main.c:1250 ../coreapi/call_log.c:235 -msgid "Incoming call" -msgstr "來電" - -#: ../gtk/main.c:1253 ../gtk/incall_view.c:579 ../gtk/in_call_frame.ui.h:2 -msgid "Answer" -msgstr "接聽" - -#: ../gtk/main.c:1255 ../gtk/in_call_frame.ui.h:3 -msgid "Decline" -msgstr "拒接" - -#: ../gtk/main.c:1262 -msgid "Call paused" -msgstr "" - -#: ../gtk/main.c:1262 -#, c-format -msgid "by %s" -msgstr "" - -#: ../gtk/main.c:1336 -#, c-format -msgid "%s proposed to start video. Do you accept ?" -msgstr "" - -#: ../gtk/main.c:1502 -msgid "Website link" -msgstr "網站連結" - -#: ../gtk/main.c:1561 ../gtk/waiting.ui.h:1 -msgid "Linphone" -msgstr "Linphone" - -#: ../gtk/main.c:1562 -msgid "A video internet phone" -msgstr "" - -#: ../gtk/main.c:1624 -#, c-format -msgid "%s (Default)" -msgstr "%s (預設值)" - -#: ../gtk/main.c:1997 ../coreapi/callbacks.c:1080 -#, c-format -msgid "We are transferred to %s" -msgstr "我們被轉接到 %s" - -#: ../gtk/main.c:2008 -msgid "" -"No sound cards have been detected on this computer.\n" -"You won't be able to send or receive audio calls." -msgstr "在這臺電腦中偵測不到音效卡。\n您將無法傳送或接收語音電話。" - -#: ../gtk/main.c:2173 -msgid "A free SIP video-phone" -msgstr "自由的 SIP 視訊電話" - -#: ../gtk/main.c:2292 -#, c-format -msgid "Hello\n" -msgstr "" - -#: ../gtk/friendlist.c:460 -msgid "Add to addressbook" -msgstr "" - -#: ../gtk/friendlist.c:626 -#, c-format -msgid "Search in %s directory" -msgstr "在 %s 目錄中搜尋" - -#: ../gtk/friendlist.c:773 -msgid "Invalid sip contact !" -msgstr "無效的 sip 連絡人!" - -#: ../gtk/friendlist.c:820 -#, c-format -msgid "Add a new contact" -msgstr "" - -#: ../gtk/friendlist.c:823 -#, c-format -msgid "Edit contact '%s'" -msgstr "編輯連絡人「%s」" - -#: ../gtk/friendlist.c:824 -#, c-format -msgid "Delete contact '%s'" -msgstr "刪除連絡人「%s」" - -#: ../gtk/friendlist.c:825 -#, c-format -msgid "Delete chat history of '%s'" -msgstr "" - -#: ../gtk/friendlist.c:862 -#, c-format -msgid "Add new contact from %s directory" -msgstr "從 %s 目錄加入新的連絡人" - -#: ../gtk/propertybox.c:592 ../gtk/contact.ui.h:1 -msgid "Name" -msgstr "名稱" - -#: ../gtk/propertybox.c:598 -msgid "Rate (Hz)" -msgstr "頻率 (Hz)" - -#: ../gtk/propertybox.c:604 -msgid "Status" -msgstr "狀態" - -#: ../gtk/propertybox.c:617 -msgid "IP Bitrate (kbit/s)" -msgstr "" - -#: ../gtk/propertybox.c:628 -msgid "Parameters" -msgstr "參數" - -#: ../gtk/propertybox.c:670 ../gtk/propertybox.c:824 -msgid "Enabled" -msgstr "已啟用" - -#: ../gtk/propertybox.c:672 ../gtk/propertybox.c:824 ../gtk/parameters.ui.h:57 -msgid "Disabled" -msgstr "已停用" - -#: ../gtk/propertybox.c:902 -msgid "Account" -msgstr "帳號" - -#: ../gtk/propertybox.c:1170 -msgid "English" -msgstr "英語" - -#: ../gtk/propertybox.c:1171 -msgid "French" -msgstr "法語" - -#: ../gtk/propertybox.c:1172 -msgid "Swedish" -msgstr "瑞典語" - -#: ../gtk/propertybox.c:1173 -msgid "Italian" -msgstr "義大利語" - -#: ../gtk/propertybox.c:1174 -msgid "Spanish" -msgstr "西班牙語" - -#: ../gtk/propertybox.c:1175 -msgid "Brazilian Portugese" -msgstr "巴西葡萄牙語" - -#: ../gtk/propertybox.c:1176 -msgid "Polish" -msgstr "波蘭語" - -#: ../gtk/propertybox.c:1177 -msgid "German" -msgstr "德語" - -#: ../gtk/propertybox.c:1178 -msgid "Russian" -msgstr "俄語" - -#: ../gtk/propertybox.c:1179 -msgid "Japanese" -msgstr "日語" - -#: ../gtk/propertybox.c:1180 -msgid "Dutch" -msgstr "荷蘭語" - -#: ../gtk/propertybox.c:1181 -msgid "Hungarian" -msgstr "匈牙利語" - -#: ../gtk/propertybox.c:1182 -msgid "Czech" -msgstr "捷克語" - -#: ../gtk/propertybox.c:1183 -msgid "Chinese" -msgstr "中文" - -#: ../gtk/propertybox.c:1184 -msgid "Traditional Chinese" -msgstr "" - -#: ../gtk/propertybox.c:1185 -msgid "Norwegian" -msgstr "" - -#: ../gtk/propertybox.c:1186 -msgid "Hebrew" -msgstr "" - -#: ../gtk/propertybox.c:1187 -msgid "Serbian" -msgstr "" - -#: ../gtk/propertybox.c:1188 -msgid "Arabic" -msgstr "" - -#: ../gtk/propertybox.c:1189 -msgid "Turkish" -msgstr "" - -#: ../gtk/propertybox.c:1246 -msgid "" -"You need to restart linphone for the new language selection to take effect." -msgstr "您需要重新啟動 linphone 才能讓新選擇的語言生效。" - -#: ../gtk/propertybox.c:1332 -msgid "None" -msgstr "" - -#: ../gtk/propertybox.c:1336 -msgid "SRTP" -msgstr "" - -#: ../gtk/propertybox.c:1342 -msgid "DTLS" -msgstr "" - -#: ../gtk/propertybox.c:1349 -msgid "ZRTP" -msgstr "" - -#: ../gtk/update.c:80 -#, c-format -msgid "" -"A more recent version is availalble from %s.\n" -"Would you like to open a browser to download it ?" -msgstr "在 %s 有最新的版本。\n您想要開啟瀏覽器下載它嗎?" - -#: ../gtk/update.c:91 -msgid "You are running the lastest version." -msgstr "您執行的是最新版本。" - -#: ../gtk/buddylookup.c:85 -msgid "Firstname, Lastname" -msgstr "名字, 姓氏" - -#: ../gtk/buddylookup.c:160 -msgid "Error communicating with server." -msgstr "與伺服器連線時發生錯誤。" - -#: ../gtk/buddylookup.c:164 -msgid "Connecting..." -msgstr "連線中..." - -#: ../gtk/buddylookup.c:168 -msgid "Connected" -msgstr "已連線" - -#: ../gtk/buddylookup.c:172 -msgid "Receiving data..." -msgstr "接收資料..." - -#: ../gtk/buddylookup.c:180 -#, c-format -msgid "Found %i contact" -msgid_plural "Found %i contacts" -msgstr[0] "找不到 %i 個連絡人" - -#: ../gtk/setupwizard.c:219 -msgid "Username is already in use!" -msgstr "" - -#: ../gtk/setupwizard.c:223 -msgid "Failed to check username availability. Please try again later." -msgstr "" - -#: ../gtk/incall_view.c:67 ../gtk/incall_view.c:87 -#, c-format -msgid "Call #%i" -msgstr "" - -#: ../gtk/incall_view.c:145 -#, c-format -msgid "Transfer to call #%i with %s" -msgstr "" - -#: ../gtk/incall_view.c:202 ../gtk/incall_view.c:205 -msgid "Not used" -msgstr "" - -#: ../gtk/incall_view.c:212 -msgid "ICE not activated" -msgstr "" - -#: ../gtk/incall_view.c:214 -msgid "ICE failed" -msgstr "" - -#: ../gtk/incall_view.c:216 -msgid "ICE in progress" -msgstr "" - -#: ../gtk/incall_view.c:218 -msgid "Going through one or more NATs" -msgstr "" - -#: ../gtk/incall_view.c:220 -msgid "Direct" -msgstr "" - -#: ../gtk/incall_view.c:222 -msgid "Through a relay server" -msgstr "" - -#: ../gtk/incall_view.c:230 -msgid "uPnP not activated" -msgstr "" - -#: ../gtk/incall_view.c:232 -msgid "uPnP in progress" -msgstr "" - -#: ../gtk/incall_view.c:234 -msgid "uPnp not available" -msgstr "" - -#: ../gtk/incall_view.c:236 -msgid "uPnP is running" -msgstr "" - -#: ../gtk/incall_view.c:238 -msgid "uPnP failed" -msgstr "" - -#: ../gtk/incall_view.c:248 ../gtk/incall_view.c:249 -msgid "Direct or through server" -msgstr "" - -#: ../gtk/incall_view.c:258 ../gtk/incall_view.c:270 -#, c-format -msgid "" -"download: %f\n" -"upload: %f (kbit/s)" -msgstr "" - -#: ../gtk/incall_view.c:263 ../gtk/incall_view.c:265 -#, c-format -msgid "%ix%i @ %f fps" -msgstr "" - -#: ../gtk/incall_view.c:295 -#, c-format -msgid "%.3f seconds" -msgstr "" - -#: ../gtk/incall_view.c:453 ../gtk/in_call_frame.ui.h:10 -#: ../gtk/videowindow.c:248 -msgid "Hang up" -msgstr "" - -#: ../gtk/incall_view.c:558 -msgid "Calling..." -msgstr "播打..." - -#: ../gtk/incall_view.c:561 ../gtk/incall_view.c:793 -msgid "00:00:00" -msgstr "" - -#: ../gtk/incall_view.c:572 -msgid "Incoming call" -msgstr "來電" - -#: ../gtk/incall_view.c:609 -msgid "good" -msgstr "" - -#: ../gtk/incall_view.c:611 -msgid "average" -msgstr "" - -#: ../gtk/incall_view.c:613 -msgid "poor" -msgstr "" - -#: ../gtk/incall_view.c:615 -msgid "very poor" -msgstr "" - -#: ../gtk/incall_view.c:617 -msgid "too bad" -msgstr "" - -#: ../gtk/incall_view.c:618 ../gtk/incall_view.c:634 -msgid "unavailable" -msgstr "" - -#: ../gtk/incall_view.c:732 -msgid "Secured by SRTP" -msgstr "" - -#: ../gtk/incall_view.c:738 -msgid "Secured by DTLS" -msgstr "" - -#: ../gtk/incall_view.c:744 -#, c-format -msgid "Secured by ZRTP - [auth token: %s]" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set unverified" -msgstr "" - -#: ../gtk/incall_view.c:748 -msgid "Set verified" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In conference" -msgstr "" - -#: ../gtk/incall_view.c:788 -msgid "In call" -msgstr "通話中" - -#: ../gtk/incall_view.c:825 -msgid "Paused call" -msgstr "暫停通話" - -#: ../gtk/incall_view.c:862 -msgid "Call ended." -msgstr "通話結束。" - -#: ../gtk/incall_view.c:893 -msgid "Transfer in progress" -msgstr "" - -#: ../gtk/incall_view.c:896 -msgid "Transfer done." -msgstr "" - -#: ../gtk/incall_view.c:899 -msgid "Transfer failed." -msgstr "" - -#: ../gtk/incall_view.c:930 -msgid "Resume" -msgstr "繼續" - -#: ../gtk/incall_view.c:930 ../gtk/in_call_frame.ui.h:7 -msgid "Pause" -msgstr "暫停" - -#: ../gtk/incall_view.c:996 -#, c-format -msgid "" -"Recording into\n" -"%s %s" -msgstr "" - -#: ../gtk/incall_view.c:996 -msgid "(Paused)" -msgstr "" - -#: ../gtk/loginframe.c:75 -#, c-format -msgid "Please enter login information for %s" -msgstr "請輸入 %s 的 登入資訊" - -#: ../gtk/config-fetching.c:57 -#, c-format -msgid "fetching from %s" -msgstr "" - -#: ../gtk/config-fetching.c:73 -#, c-format -msgid "Downloading of remote configuration from %s failed." -msgstr "" - -#: ../gtk/audio_assistant.c:103 -msgid "No voice detected" -msgstr "" - -#: ../gtk/audio_assistant.c:104 -msgid "Too low" -msgstr "" - -#: ../gtk/audio_assistant.c:105 -msgid "Good" -msgstr "" - -#: ../gtk/audio_assistant.c:106 -msgid "Too loud" -msgstr "" - -#: ../gtk/audio_assistant.c:188 -msgid "Did you hear three beeps ?" -msgstr "" - -#: ../gtk/audio_assistant.c:301 ../gtk/audio_assistant.c:306 -msgid "Sound preferences not found " -msgstr "" - -#: ../gtk/audio_assistant.c:315 -msgid "Cannot launch system sound control " -msgstr "" - -#: ../gtk/audio_assistant.c:327 -msgid "" -"Welcome!\n" -"This assistant will help you to configure audio settings for Linphone" -msgstr "" - -#: ../gtk/audio_assistant.c:337 -msgid "Capture device" -msgstr "" - -#: ../gtk/audio_assistant.c:338 -msgid "Recorded volume" -msgstr "" - -#: ../gtk/audio_assistant.c:342 -msgid "No voice" -msgstr "" - -#: ../gtk/audio_assistant.c:343 ../gtk/audio_assistant.c:382 -msgid "System sound preferences" -msgstr "" - -#: ../gtk/audio_assistant.c:378 -msgid "Playback device" -msgstr "" - -#: ../gtk/audio_assistant.c:379 -msgid "Play three beeps" -msgstr "" - -#: ../gtk/audio_assistant.c:412 -msgid "Press the record button and say some words" -msgstr "" - -#: ../gtk/audio_assistant.c:413 -msgid "Listen to your record voice" -msgstr "" - -#: ../gtk/audio_assistant.c:414 ../gtk/conf_frame.ui.h:2 -#: ../gtk/in_call_frame.ui.h:4 -msgid "Record" -msgstr "" - -#: ../gtk/audio_assistant.c:415 -msgid "Play" -msgstr "" - -#: ../gtk/audio_assistant.c:442 -msgid "Let's start Linphone now" -msgstr "" - -#: ../gtk/audio_assistant.c:513 -msgid "Audio Assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:523 ../gtk/main.ui.h:15 -msgid "Audio assistant" -msgstr "" - -#: ../gtk/audio_assistant.c:528 -msgid "Mic Gain calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:534 -msgid "Speaker volume calibration" -msgstr "" - -#: ../gtk/audio_assistant.c:539 -msgid "Record and Play" -msgstr "" - -#: ../gtk/audio_assistant.c:544 ../gtk/setup_wizard.ui.h:38 -msgid "Terminating" -msgstr "" - -#: ../gtk/about.ui.h:1 -msgid "About Linphone" -msgstr "" - -#: ../gtk/about.ui.h:2 -msgid "(C) Belledonne Communications, 2010\n" -msgstr "" - -#: ../gtk/about.ui.h:4 -msgid "An internet video phone using the standard SIP (rfc3261) protocol." -msgstr "使用標準 SIP (rfc3261) 通訊協定的網路視訊電話。" - -#: ../gtk/about.ui.h:5 -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" -"he: Eli Zaretskii \n" -msgstr "" - -#: ../gtk/buddylookup.ui.h:1 -msgid "Search contacts in directory" -msgstr "在目錄中搜尋" - -#: ../gtk/buddylookup.ui.h:2 -msgid "Add to my list" -msgstr "加入我的清單" - -#: ../gtk/buddylookup.ui.h:3 -msgid "Search somebody" -msgstr "搜尋某人" - -#: ../gtk/callee_frame.ui.h:1 -msgid "Callee name" -msgstr "" - -#: ../gtk/call_logs.ui.h:1 -msgid "Call history" -msgstr "通話紀錄" - -#: ../gtk/call_logs.ui.h:2 -msgid "Clear all" -msgstr "全部清除" - -#: ../gtk/call_logs.ui.h:3 -msgid "Call back" -msgstr "回電" - -#: ../gtk/call_statistics.ui.h:1 -msgid "Call statistics" -msgstr "" - -#: ../gtk/call_statistics.ui.h:2 -msgid "Audio codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:3 -msgid "Video codec" -msgstr "" - -#: ../gtk/call_statistics.ui.h:4 -msgid "Audio IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:5 -msgid "Audio Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:6 -msgid "Video IP bandwidth usage" -msgstr "" - -#: ../gtk/call_statistics.ui.h:7 -msgid "Video Media connectivity" -msgstr "" - -#: ../gtk/call_statistics.ui.h:8 -msgid "Round trip time" -msgstr "" - -#: ../gtk/call_statistics.ui.h:9 -msgid "Video resolution received" -msgstr "" - -#: ../gtk/call_statistics.ui.h:10 -msgid "Video resolution sent" -msgstr "" - -#: ../gtk/call_statistics.ui.h:11 -msgid "RTP profile" -msgstr "" - -#: ../gtk/call_statistics.ui.h:12 -msgid "Call statistics and information" -msgstr "" - -#: ../gtk/chatroom_frame.ui.h:1 -msgid "Send" -msgstr "傳送" - -#: ../gtk/conf_frame.ui.h:1 -msgid "End conference" -msgstr "" - -#: ../gtk/config-uri.ui.h:1 -msgid "Specifying a remote configuration URI" -msgstr "" - -#: ../gtk/config-uri.ui.h:2 -msgid "" -"This dialog allows to set an http or https address when configuration is to be fetched at startup.\n" -"Please enter or modify the configuration URI below. After clicking OK, Linphone will restart automatically in order to fetch and take into account the new configuration. " -msgstr "" - -#: ../gtk/contact.ui.h:2 -msgid "SIP Address" -msgstr "SIP 位址" - -#: ../gtk/contact.ui.h:3 -msgid "Show this contact presence status" -msgstr "顯示這個連絡人的上線狀態" - -#: ../gtk/contact.ui.h:4 -msgid "Allow this contact to see my presence status" -msgstr "允許這個連絡人看到我的上線狀態" - -#: ../gtk/contact.ui.h:5 -msgid "Contact information" -msgstr "連絡人資訊" - -#: ../gtk/dscp_settings.ui.h:1 -msgid "DSCP settings" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:2 -msgid "SIP" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:3 -msgid "Audio RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:4 -msgid "Video RTP stream" -msgstr "" - -#: ../gtk/dscp_settings.ui.h:5 -msgid "Set DSCP values (in hexadecimal)" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:1 -msgid "Click here to set the speakers volume" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:5 -msgid "Record this call to an audio file" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:6 -msgid "Video" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:8 -msgid "Mute" -msgstr "" - -#: ../gtk/in_call_frame.ui.h:9 -msgid "Transfer" -msgstr "轉接" - -#: ../gtk/in_call_frame.ui.h:12 -msgid "In call" -msgstr "通話中" - -#: ../gtk/in_call_frame.ui.h:13 -msgid "Duration" -msgstr "時間長度" - -#: ../gtk/in_call_frame.ui.h:14 -msgid "Call quality rating" -msgstr "" - -#: ../gtk/ldap.ui.h:1 -msgid "LDAP Settings" -msgstr "" - -#: ../gtk/ldap.ui.h:2 ../gtk/parameters.ui.h:90 -msgid "Server address:" -msgstr "" - -#: ../gtk/ldap.ui.h:3 ../gtk/parameters.ui.h:91 -msgid "Authentication method:" -msgstr "" - -#: ../gtk/ldap.ui.h:4 ../gtk/parameters.ui.h:92 ../gtk/setup_wizard.ui.h:17 -msgid "Username:" -msgstr "使用者名稱:" - -#: ../gtk/ldap.ui.h:5 ../gtk/password.ui.h:4 ../gtk/setup_wizard.ui.h:18 -msgid "Password:" -msgstr "密碼: " - -#: ../gtk/ldap.ui.h:6 -msgid "Use TLS Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:7 -msgid "Not yet available" -msgstr "" - -#: ../gtk/ldap.ui.h:8 -msgid "Connection" -msgstr "" - -#: ../gtk/ldap.ui.h:9 -msgid "Bind DN" -msgstr "" - -#: ../gtk/ldap.ui.h:10 -msgid "Authname" -msgstr "" - -#: ../gtk/ldap.ui.h:11 -msgid "Realm" -msgstr "" - -#: ../gtk/ldap.ui.h:12 -msgid "SASL" -msgstr "" - -#: ../gtk/ldap.ui.h:13 -msgid "Base object:" -msgstr "" - -#: ../gtk/ldap.ui.h:15 -#, no-c-format -msgid "Filter (%s for name):" -msgstr "" - -#: ../gtk/ldap.ui.h:16 -msgid "Name Attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:17 -msgid "SIP address attribute:" -msgstr "" - -#: ../gtk/ldap.ui.h:18 -msgid "Attributes to query:" -msgstr "" - -#: ../gtk/ldap.ui.h:19 -msgid "Search" -msgstr "" - -#: ../gtk/ldap.ui.h:20 -msgid "Timeout for search:" -msgstr "" - -#: ../gtk/ldap.ui.h:21 -msgid "Max results:" -msgstr "" - -#: ../gtk/ldap.ui.h:22 -msgid "Follow Aliases" -msgstr "" - -#: ../gtk/ldap.ui.h:23 -msgid "Miscellaneous" -msgstr "" - -#: ../gtk/ldap.ui.h:24 -msgid "ANONYMOUS" -msgstr "" - -#: ../gtk/ldap.ui.h:25 -msgid "SIMPLE" -msgstr "" - -#: ../gtk/ldap.ui.h:26 -msgid "DIGEST-MD5" -msgstr "" - -#: ../gtk/ldap.ui.h:27 -msgid "NTLM" -msgstr "" - -#: ../gtk/login_frame.ui.h:1 ../gtk/tunnel_config.ui.h:7 -msgid "Username" -msgstr "使用者名稱" - -#: ../gtk/login_frame.ui.h:2 ../gtk/tunnel_config.ui.h:8 -msgid "Password" -msgstr "密碼" - -#: ../gtk/login_frame.ui.h:3 -msgid "Internet connection:" -msgstr "網路連線:" - -#: ../gtk/login_frame.ui.h:4 -msgid "Automatically log me in" -msgstr "將我自動登入" - -#: ../gtk/login_frame.ui.h:5 ../gtk/password.ui.h:3 -msgid "UserID" -msgstr "使用者ID" - -#: ../gtk/login_frame.ui.h:6 -msgid "Login information" -msgstr "登入資訊" - -#: ../gtk/login_frame.ui.h:7 -msgid "Welcome!" -msgstr "" - -#: ../gtk/login_frame.ui.h:8 -msgid "ADSL" -msgstr "ADSL" - -#: ../gtk/login_frame.ui.h:9 -msgid "Fiber Channel" -msgstr "光纖通道" - -#: ../gtk/log.ui.h:1 -msgid "Linphone debug window" -msgstr "Linphone 除錯視窗" - -#: ../gtk/log.ui.h:2 -msgid "Scroll to end" -msgstr "" - -#: ../gtk/main.ui.h:1 -msgid "Default" -msgstr "預設值" - -#: ../gtk/main.ui.h:2 -msgid "Delete" -msgstr "" - -#: ../gtk/main.ui.h:3 -msgid "_Options" -msgstr "選項(_O)" - -#: ../gtk/main.ui.h:4 -msgid "Set configuration URI" -msgstr "" - -#: ../gtk/main.ui.h:5 -msgid "Always start video" -msgstr "" - -#: ../gtk/main.ui.h:6 -msgid "Enable self-view" -msgstr "啟用自拍檢視" - -#: ../gtk/main.ui.h:7 -msgid "Show keypad" -msgstr "" - -#: ../gtk/main.ui.h:8 -msgid "Import contacts from vCards" -msgstr "" - -#: ../gtk/main.ui.h:9 -msgid "Export contacts as vCards" -msgstr "" - -#: ../gtk/main.ui.h:10 -msgid "_Help" -msgstr "求助(_H)" - -#: ../gtk/main.ui.h:11 -msgid "Show debug window" -msgstr "顯示除錯視窗" - -#: ../gtk/main.ui.h:12 -msgid "_Homepage" -msgstr "官方網頁(_H)" - -#: ../gtk/main.ui.h:13 -msgid "Check _Updates" -msgstr "檢查更新(_U)" - -#: ../gtk/main.ui.h:14 -msgid "Account assistant" -msgstr "" - -#: ../gtk/main.ui.h:16 -msgid "SIP address or phone number:" -msgstr "SIP 位址或電話號碼:" - -#: ../gtk/main.ui.h:17 -msgid "Initiate a new call" -msgstr "打出新電話" - -#: ../gtk/main.ui.h:18 -msgid "Contacts" -msgstr "連絡人" - -#: ../gtk/main.ui.h:19 -msgid "Search" -msgstr "搜尋" - -#: ../gtk/main.ui.h:20 -msgid "Add contacts from directory" -msgstr "從目錄加入連絡人" - -#: ../gtk/main.ui.h:21 -msgid "Add contact" -msgstr "加入聯絡人" - -#: ../gtk/main.ui.h:22 -msgid "Clear call history" -msgstr "" - -#: ../gtk/main.ui.h:24 -msgid "My current identity:" -msgstr "我目前的使用者識別:" - -#: ../gtk/main.ui.h:25 -msgid "Autoanswer is enabled" -msgstr "" - -#: ../gtk/parameters.ui.h:1 -msgid "anonymous" -msgstr "" - -#: ../gtk/parameters.ui.h:2 -msgid "GSSAPI" -msgstr "" - -#: ../gtk/parameters.ui.h:3 -msgid "SASL" -msgstr "" - -#: ../gtk/parameters.ui.h:4 -msgid "default soundcard" -msgstr "預設的音效卡" - -#: ../gtk/parameters.ui.h:5 -msgid "a sound card" -msgstr "音效卡" - -#: ../gtk/parameters.ui.h:6 -msgid "default camera" -msgstr "預設的攝影機" - -#: ../gtk/parameters.ui.h:7 -msgid "CIF" -msgstr "CIF" - -#: ../gtk/parameters.ui.h:8 -msgid "Audio codecs" -msgstr "音訊編碼解碼器" - -#: ../gtk/parameters.ui.h:9 -msgid "Video codecs" -msgstr "視訊編碼解碼器" - -#: ../gtk/parameters.ui.h:10 -msgid "C" -msgstr "C" - -#: ../gtk/parameters.ui.h:11 -msgid "SIP (UDP)" -msgstr "" - -#: ../gtk/parameters.ui.h:12 -msgid "SIP (TCP)" -msgstr "" - -#: ../gtk/parameters.ui.h:13 -msgid "SIP (TLS)" -msgstr "" - -#: ../gtk/parameters.ui.h:14 -msgid "Settings" -msgstr "設定值" - -#: ../gtk/parameters.ui.h:15 -msgid "This section defines your SIP address when not using a SIP account" -msgstr "這一區在不使用 SIP 帳號時定義您的 SIP 位址" - -#: ../gtk/parameters.ui.h:16 -msgid "Your display name (eg: John Doe):" -msgstr "您的顯示名稱 (例如: John Doe):" - -#: ../gtk/parameters.ui.h:17 -msgid "Your username:" -msgstr "您的使用者名稱:" - -#: ../gtk/parameters.ui.h:18 -msgid "Your resulting SIP address:" -msgstr "您組成的 SIP 位址:" - -#: ../gtk/parameters.ui.h:19 -msgid "Default identity" -msgstr "預設身分識別" - -#: ../gtk/parameters.ui.h:20 -msgid "Wizard" -msgstr "" - -#: ../gtk/parameters.ui.h:21 -msgid "Add" -msgstr "加入" - -#: ../gtk/parameters.ui.h:22 -msgid "Edit" -msgstr "編輯" - -#: ../gtk/parameters.ui.h:23 -msgid "Remove" -msgstr "移除" - -#: ../gtk/parameters.ui.h:24 -msgid "Proxy accounts" -msgstr "代理伺服器帳號" - -#: ../gtk/parameters.ui.h:25 -msgid "Erase all passwords" -msgstr "消除所有的密碼" - -#: ../gtk/parameters.ui.h:26 -msgid "Privacy" -msgstr "隱私" - -#: ../gtk/parameters.ui.h:27 -msgid "Automatically answer when a call is received" -msgstr "" - -#: ../gtk/parameters.ui.h:28 -msgid "Delay before answering (ms)" -msgstr "" - -#: ../gtk/parameters.ui.h:29 -msgid "Auto-answer" -msgstr "" - -#: ../gtk/parameters.ui.h:30 -msgid "Manage SIP Accounts" -msgstr "管理 SIP 帳號" - -#: ../gtk/parameters.ui.h:31 -msgid "Ring sound:" -msgstr "鈴聲音效:" - -#: ../gtk/parameters.ui.h:32 -msgid "ALSA special device (optional):" -msgstr "ALSA 特殊裝置 (選擇性):" - -#: ../gtk/parameters.ui.h:33 -msgid "Capture device:" -msgstr "捕捉裝置:" - -#: ../gtk/parameters.ui.h:34 -msgid "Ring device:" -msgstr "響鈴裝置:" - -#: ../gtk/parameters.ui.h:35 -msgid "Playback device:" -msgstr "播放裝置" - -#: ../gtk/parameters.ui.h:36 -msgid "Enable echo cancellation" -msgstr "啟用回音消除" - -#: ../gtk/parameters.ui.h:37 -msgid "Audio" -msgstr "音效" - -#: ../gtk/parameters.ui.h:38 -msgid "Video input device:" -msgstr "視訊輸入裝置:" - -#: ../gtk/parameters.ui.h:39 -msgid "Preferred video resolution:" -msgstr "" - -#: ../gtk/parameters.ui.h:40 -msgid "Video output method:" -msgstr "" - -#: ../gtk/parameters.ui.h:41 -msgid "Show camera preview" -msgstr "" - -#: ../gtk/parameters.ui.h:42 -msgid "Video preset:" -msgstr "" - -#: ../gtk/parameters.ui.h:43 -msgid "Preferred video framerate:" -msgstr "" - -#: ../gtk/parameters.ui.h:44 -msgid "0 stands for \"unlimited\"" -msgstr "0 表示「不限制」" - -#: ../gtk/parameters.ui.h:45 -msgid "Video" -msgstr "視訊" - -#: ../gtk/parameters.ui.h:46 -msgid "Upload speed limit in Kbit/sec:" -msgstr "上傳速度限制於 Kbit/sec:" - -#: ../gtk/parameters.ui.h:47 -msgid "Download speed limit in Kbit/sec:" -msgstr "下載速度限制於 Kbit/sec:" - -#: ../gtk/parameters.ui.h:48 -msgid "Enable adaptive rate control" -msgstr "" - -#: ../gtk/parameters.ui.h:49 -msgid "" -"Adaptive rate control is a technique to dynamically guess the available " -"bandwidth during a call." -msgstr "" - -#: ../gtk/parameters.ui.h:50 -msgid "Bandwidth control" -msgstr "頻寬控制" - -#: ../gtk/parameters.ui.h:51 -msgid "Multimedia settings" -msgstr "多媒體設定值" - -#: ../gtk/parameters.ui.h:52 -msgid "Set Maximum Transmission Unit:" -msgstr "設定最大傳輸單位:" - -#: ../gtk/parameters.ui.h:53 -msgid "Send DTMFs as SIP info" -msgstr "傳送 DTMFs 為 SIP 資訊" - -#: ../gtk/parameters.ui.h:54 -msgid "Allow IPv6" -msgstr "" - -#: ../gtk/parameters.ui.h:55 -msgid "Transport" -msgstr "傳輸" - -#: ../gtk/parameters.ui.h:56 -msgid "SIP/UDP port" -msgstr "" - -#: ../gtk/parameters.ui.h:58 -msgid "Random" -msgstr "" - -#: ../gtk/parameters.ui.h:59 -msgid "SIP/TCP port" -msgstr "" - -#: ../gtk/parameters.ui.h:60 -msgid "Audio RTP/UDP:" -msgstr "音效 RTP/UDP:" - -#: ../gtk/parameters.ui.h:61 -msgid "Fixed" -msgstr "" - -#: ../gtk/parameters.ui.h:62 -msgid "Video RTP/UDP:" -msgstr "視訊 RTP/UDP:" - -#: ../gtk/parameters.ui.h:63 -msgid "Tunnel" -msgstr "" - -#: ../gtk/parameters.ui.h:64 -msgid "DSCP fields" -msgstr "" - -#: ../gtk/parameters.ui.h:65 -msgid "Network protocol and ports" -msgstr "" - -#: ../gtk/parameters.ui.h:66 -msgid "Direct connection to the Internet" -msgstr "直接連線到網際網路" - -#: ../gtk/parameters.ui.h:67 -msgid "Behind NAT / Firewall (specify gateway IP )" -msgstr "" - -#: ../gtk/parameters.ui.h:68 -msgid "Behind NAT / Firewall (use STUN to resolve)" -msgstr "在 NAT / 防火牆之後 (使用 STUN 解析)" - -#: ../gtk/parameters.ui.h:69 -msgid "Behind NAT / Firewall (use ICE)" -msgstr "" - -#: ../gtk/parameters.ui.h:70 -msgid "Behind NAT / Firewall (use uPnP)" -msgstr "" - -#: ../gtk/parameters.ui.h:71 -msgid "Public IP address:" -msgstr "公共 IP 地址:" - -#: ../gtk/parameters.ui.h:72 -msgid "Stun server:" -msgstr "Stun 伺服器:" - -#: ../gtk/parameters.ui.h:73 -msgid "NAT and Firewall" -msgstr "NAT 與防火牆" - -#: ../gtk/parameters.ui.h:74 -msgid "Media encryption type" -msgstr "" - -#: ../gtk/parameters.ui.h:75 -msgid "Use Lime for outgoing chat messages" -msgstr "" - -#: ../gtk/parameters.ui.h:76 -msgid "Media encryption is mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:77 -msgid "Mandatory" -msgstr "" - -#: ../gtk/parameters.ui.h:78 -msgid "Preferred" -msgstr "" - -#: ../gtk/parameters.ui.h:79 -msgid "Encryption" -msgstr "" - -#: ../gtk/parameters.ui.h:80 -msgid "Network settings" -msgstr "網路設定值" - -#: ../gtk/parameters.ui.h:81 ../gtk/tunnel_config.ui.h:4 -msgid "Enable" -msgstr "啟用" - -#: ../gtk/parameters.ui.h:82 ../gtk/tunnel_config.ui.h:5 -msgid "Disable" -msgstr "停用" - -#: ../gtk/parameters.ui.h:83 -msgid "Audio codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:84 -msgid "Video codecs" -msgstr "" - -#: ../gtk/parameters.ui.h:85 -msgid "Codecs" -msgstr "編碼解碼器" - -#: ../gtk/parameters.ui.h:86 -msgid "Language" -msgstr "語言" - -#: ../gtk/parameters.ui.h:87 -msgid "Show advanced settings" -msgstr "顯示進階設定值" - -#: ../gtk/parameters.ui.h:88 -msgid "Level" -msgstr "級數" - -#: ../gtk/parameters.ui.h:89 -msgid "User interface" -msgstr "使用者介面" - -#: ../gtk/parameters.ui.h:93 -msgid "LDAP Account setup" -msgstr "" - -#: ../gtk/parameters.ui.h:94 -msgid "LDAP" -msgstr "" - -#: ../gtk/parameters.ui.h:95 -msgid "Done" -msgstr "完成" - -#: ../gtk/password.ui.h:1 -msgid "Linphone - Authentication required" -msgstr "Linphone - 需要驗證" - -#: ../gtk/password.ui.h:2 -msgid "Please enter the domain password" -msgstr "請輸入這個網域的密碼" - -#: ../gtk/provisioning-fetch.ui.h:1 -msgid "Configuring..." -msgstr "" - -#: ../gtk/provisioning-fetch.ui.h:2 -msgid "Please wait while fetching configuration from server..." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:1 -msgid "SIP account configuration assistant" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:2 -msgid "" -"Welcome!\n" -"This assistant will help you to use a SIP account for your calls." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:4 -msgid "Welcome to the account setup assistant" -msgstr "歡迎使用帳號設定助理" - -#: ../gtk/setup_wizard.ui.h:5 -msgid "Create an account on linphone.org" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:6 -msgid "I have already a linphone.org account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:7 -msgid "I have already a sip account and I just want to use it" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:8 -msgid "I want to specify a remote configuration URI" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:9 -msgid "Account setup assistant" -msgstr "帳號設定助理" - -#: ../gtk/setup_wizard.ui.h:10 -msgid "Enter your account information" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:11 -msgid "Username*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:12 -msgid "Password*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:13 -msgid "Domain*" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:14 -msgid "Proxy" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:15 -msgid "Configure your account (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:16 -msgid "Enter your linphone.org username" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:19 -msgid "Enter your sip username (step 1/1)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:20 -msgid "(*) Required fields" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:21 -msgid "Email: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:22 -msgid "Username: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:23 -msgid "Password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:24 -msgid "Confirm your password: (*)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:25 -msgid "Keep me informed with linphone updates" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:26 -msgid "Enter account information (step 1/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:27 -msgid "Your account is being created, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:28 -msgid "Account creation in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:29 -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/setup_wizard.ui.h:31 -msgid "Validation (step 2/2)" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:32 -msgid "Checking if your account is been validated, please wait." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:33 -msgid "Account validation check in progress" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:34 -msgid "" -"Error, account not validated, username already used or server unreachable.\n" -"Please go back and try again." -msgstr "" - -#: ../gtk/setup_wizard.ui.h:36 -msgid "Error" -msgstr "" - -#: ../gtk/setup_wizard.ui.h:37 -msgid "Thank you. Your account is now configured and ready for use." -msgstr "謝謝您。您的帳號已設定完成並且可以使用。" - -#: ../gtk/sip_account.ui.h:1 -msgid "Linphone - Configure a SIP account" -msgstr "Linphone - 設定 SIP 帳號" - -#: ../gtk/sip_account.ui.h:2 -msgid "Your SIP identity:" -msgstr "您的 SIP 使用者識別:" - -#: ../gtk/sip_account.ui.h:3 -msgid "Looks like sip:@" -msgstr "看起來像 sip:@" - -#: ../gtk/sip_account.ui.h:4 -msgid "sip:" -msgstr "sip:" - -#: ../gtk/sip_account.ui.h:5 -msgid "SIP Proxy address:" -msgstr "SIP 代理位址:" - -#: ../gtk/sip_account.ui.h:6 -msgid "Looks like sip:" -msgstr "看起來像 sip:" - -#: ../gtk/sip_account.ui.h:7 -msgid "Registration duration (sec):" -msgstr "註冊時間 (秒):" - -#: ../gtk/sip_account.ui.h:8 -msgid "Contact params (optional):" -msgstr "" - -#: ../gtk/sip_account.ui.h:9 -msgid "AVPF regular RTCP interval (sec):" -msgstr "" - -#: ../gtk/sip_account.ui.h:10 -msgid "Route (optional):" -msgstr "路由 (選擇性):" - -#: ../gtk/sip_account.ui.h:11 -msgid "Transport" -msgstr "" - -#: ../gtk/sip_account.ui.h:12 -msgid "Register" -msgstr "" - -#: ../gtk/sip_account.ui.h:13 -msgid "Publish presence information" -msgstr "發布上線資訊" - -#: ../gtk/sip_account.ui.h:14 -msgid "Enable AVPF" -msgstr "" - -#: ../gtk/sip_account.ui.h:15 -msgid "Configure a SIP account" -msgstr "設定 SIP 帳號" - -#: ../gtk/tunnel_config.ui.h:1 -msgid "Configure VoIP tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:2 -msgid "Host" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:3 -msgid "Port" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:6 -msgid "Configure tunnel" -msgstr "" - -#: ../gtk/tunnel_config.ui.h:9 -msgid "Configure http proxy (optional)" -msgstr "" - -#: ../gtk/waiting.ui.h:2 -msgid "Please wait" -msgstr "請稍候" - -#: ../coreapi/linphonecore.c:1594 -msgid "Ready" -msgstr "準備就緒" - -#: ../coreapi/linphonecore.c:2685 -msgid "Configuring" -msgstr "" - -#. must be known at that time -#: ../coreapi/linphonecore.c:3084 -msgid "Contacting" -msgstr "正在連絡" - -#: ../coreapi/linphonecore.c:3089 -msgid "Could not call" -msgstr "無法通話" - -#: ../coreapi/linphonecore.c:3228 -msgid "Sorry, we have reached the maximum number of simultaneous calls" -msgstr "抱歉,我們已達瀏同步通話的最大數目" - -#: ../coreapi/linphonecore.c:3388 -msgid "is contacting you" -msgstr "正在連絡您" - -#: ../coreapi/linphonecore.c:3389 -msgid " and asked autoanswer." -msgstr "並要求自動接聽。" - -#: ../coreapi/linphonecore.c:3506 -msgid "Modifying call parameters..." -msgstr "修改通話參數..." - -#: ../coreapi/linphonecore.c:3898 -msgid "Connected." -msgstr "已連線。" - -#: ../coreapi/linphonecore.c:3923 -msgid "Call aborted" -msgstr "通話已放棄" - -#: ../coreapi/linphonecore.c:4125 -msgid "Could not pause the call" -msgstr "無法暫停通話" - -#: ../coreapi/linphonecore.c:4128 -msgid "Pausing the current call..." -msgstr "暫停目前的通話..." - -#: ../coreapi/misc.c:441 -msgid "Stun lookup in progress..." -msgstr "正在進行 Stun 搜尋..." - -#: ../coreapi/misc.c:657 -msgid "ICE local candidates gathering in progress..." -msgstr "" - -#: ../coreapi/friend.c:48 -msgid "Online" -msgstr "上線" - -#: ../coreapi/friend.c:51 -msgid "Busy" -msgstr "忙碌" - -#: ../coreapi/friend.c:54 -msgid "Be right back" -msgstr "馬上回來" - -#: ../coreapi/friend.c:57 -msgid "Away" -msgstr "離開" - -#: ../coreapi/friend.c:60 -msgid "On the phone" -msgstr "電話中" - -#: ../coreapi/friend.c:63 -msgid "Out to lunch" -msgstr "外出午餐" - -#: ../coreapi/friend.c:66 -msgid "Do not disturb" -msgstr "請勿打擾" - -#: ../coreapi/friend.c:69 -msgid "Moved" -msgstr "移動中" - -#: ../coreapi/friend.c:72 -msgid "Using another messaging service" -msgstr "使用另一個訊息服務" - -#: ../coreapi/friend.c:75 -msgid "Offline" -msgstr "離線" - -#: ../coreapi/friend.c:78 -msgid "Pending" -msgstr "等待中" - -#: ../coreapi/friend.c:81 -msgid "Vacation" -msgstr "" - -#: ../coreapi/friend.c:83 -msgid "Unknown status" -msgstr "" - -#: ../coreapi/proxy.c:339 -msgid "" -"The sip proxy address you entered is invalid, it must start with \"sip:\" " -"followed by a hostname." -msgstr "您輸入的 sip 代理位址是無效的,它必須要以「sip:」開頭,後面接主機名稱。" - -#: ../coreapi/proxy.c:345 -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:使用者名稱@代理網域,像是 sip:alice@example.net" - -#: ../coreapi/proxy.c:979 -msgid "Looking for telephone number destination..." -msgstr "尋找電話號碼目的端..." - -#: ../coreapi/proxy.c:983 -msgid "Could not resolve this number." -msgstr "無法解析這個號碼。" - -#: ../coreapi/proxy.c:1437 -#, c-format -msgid "Could not login as %s" -msgstr "無法以 %s 登入" - -#: ../coreapi/proxy.c:1522 -#, c-format -msgid "Refreshing on %s..." -msgstr "" - -#: ../coreapi/callbacks.c:415 -msgid "Remote ringing." -msgstr "遠端響鈴。" - -#: ../coreapi/callbacks.c:427 -msgid "Remote ringing..." -msgstr "遠端響鈴..." - -#: ../coreapi/callbacks.c:450 -msgid "Early media." -msgstr "早期媒體。" - -#: ../coreapi/callbacks.c:480 -#, c-format -msgid "Call answered by %s" -msgstr "" - -#: ../coreapi/callbacks.c:522 -msgid "Call resumed." -msgstr "通話已繼續。" - -#: ../coreapi/callbacks.c:577 -msgid "Incompatible, check codecs or security settings..." -msgstr "" - -#: ../coreapi/callbacks.c:582 ../coreapi/callbacks.c:918 -msgid "Incompatible media parameters." -msgstr "" - -#: ../coreapi/callbacks.c:607 -msgid "We have been resumed." -msgstr "" - -#. we are being paused -#: ../coreapi/callbacks.c:615 -msgid "We are paused by other party." -msgstr "" - -#: ../coreapi/callbacks.c:625 -msgid "Call is updated by remote." -msgstr "" - -#: ../coreapi/callbacks.c:794 -msgid "Call terminated." -msgstr "通話已終止。" - -#: ../coreapi/callbacks.c:822 -msgid "User is busy." -msgstr "使用者現正忙碌。" - -#: ../coreapi/callbacks.c:823 -msgid "User is temporarily unavailable." -msgstr "使用者暫時無法聯繫。" - -#. char *retrymsg=_("%s. Retry after %i minute(s)."); -#: ../coreapi/callbacks.c:825 -msgid "User does not want to be disturbed." -msgstr "使用者不想要被打擾。" - -#: ../coreapi/callbacks.c:826 -msgid "Call declined." -msgstr "通話被拒接。" - -#: ../coreapi/callbacks.c:841 -msgid "Request timeout." -msgstr "" - -#: ../coreapi/callbacks.c:872 -msgid "Redirected" -msgstr "已重新導向" - -#: ../coreapi/callbacks.c:922 -msgid "Call failed." -msgstr "通話失敗。" - -#: ../coreapi/callbacks.c:1000 -#, c-format -msgid "Registration on %s successful." -msgstr "在 %s 註冊成功。" - -#: ../coreapi/callbacks.c:1001 -#, c-format -msgid "Unregistration on %s done." -msgstr "在 %s 取消註冊完成。" - -#: ../coreapi/callbacks.c:1019 -msgid "no response timeout" -msgstr "沒有回應逾時" - -#: ../coreapi/callbacks.c:1022 -#, c-format -msgid "Registration on %s failed: %s" -msgstr "在 %s 註冊失敗:%s" - -#: ../coreapi/callbacks.c:1029 -msgid "Service unavailable, retrying" -msgstr "" - -#. if encryption is DTLS, no status to be displayed -#: ../coreapi/linphonecall.c:204 -#, c-format -msgid "Authentication token is %s" -msgstr "" - -#: ../coreapi/linphonecall.c:1663 -#, c-format -msgid "Call parameters could not be modified: %s." -msgstr "" - -#: ../coreapi/linphonecall.c:1665 -msgid "Call parameters were successfully modified." -msgstr "" - -#: ../coreapi/linphonecall.c:4636 -#, c-format -msgid "You have missed %i call." -msgid_plural "You have missed %i calls." -msgstr[0] "您有 %i 通未接來電。" - -#: ../coreapi/call_log.c:223 -msgid "aborted" -msgstr "" - -#: ../coreapi/call_log.c:226 -msgid "completed" -msgstr "" - -#: ../coreapi/call_log.c:229 -msgid "missed" -msgstr "" - -#: ../coreapi/call_log.c:232 -msgid "unknown" -msgstr "" - -#: ../coreapi/call_log.c:234 -#, c-format -msgid "" -"%s at %s\n" -"From: %s\n" -"To: %s\n" -"Status: %s\n" -"Duration: %i mn %i sec\n" -msgstr "" - -#: ../coreapi/call_log.c:235 -msgid "Outgoing call" -msgstr "" - -#: ../gtk/videowindow.c:72 -#, c-format -msgid "Cannot play %s." -msgstr "" - -#: ../gtk/videowindow.c:252 -msgid "Take screenshot" -msgstr "" diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index b5f53099b..7413074a0 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -42,6 +42,15 @@ if(ENABLE_ROOTCA_DOWNLOAD) ) endif() +set(GRAMMAR_FILES + cpim_grammar +) + +install(FILES ${GRAMMAR_FILES} + DESTINATION ${PACKAGE_GRAMMAR_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ +) + set(SOUND_FILES hello16000.wav hello8000.wav diff --git a/share/cpim_grammar b/share/cpim_grammar new file mode 100644 index 000000000..c89e4f87f Binary files /dev/null and b/share/cpim_grammar differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73b539a37..cdb539969 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,73 +20,469 @@ # ############################################################################ +set(LIBS + ${BCTOOLBOX_CORE_LIBRARIES} + ${BELLESIP_LIBRARIES} + ${MEDIASTREAMER2_LIBRARIES} + ${ORTP_LIBRARIES} + ${XML2_LIBRARIES} + ${BELR_LIBRARIES} + ${LIBXSD_LIBRARIES} +) +if(WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + list(APPEND LIBS "Ws2_32") +endif() +if(ENABLE_LIME) + list(APPEND LIBS ${BZRTP_LIBRARIES}) +endif() +if(ZLIB_FOUND) + list(APPEND LIBS ${ZLIB_LIBRARIES}) +endif() +if(SOCI_FOUND) + list(APPEND LIBS ${SOCI_LIBRARIES}) +endif() +if(SQLITE3_FOUND) + list(APPEND LIBS ${SQLITE3_LIBRARIES}) +endif() +if(ICONV_FOUND) + list(APPEND LIBS ${ICONV_LIBRARIES}) +endif() +if(ENABLE_TUNNEL) + list(APPEND LIBS ${TUNNEL_LIBRARIES}) +endif() +if(MSVC AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + list(APPEND LIBS ${LIBGCC} ${LIBMINGWEX}) +endif() +if(WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + list(APPEND LIBS shlwapi) +endif() +if(INTL_FOUND) + list(APPEND LIBS ${INTL_LIBRARIES}) +endif() +if(BELCARD_FOUND) + list(APPEND LIBS ${BELCARD_LIBRARIES}) +endif() +if(ENABLE_TUNNEL) + add_definitions(-DTUNNEL_ENABLED) +endif() + set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES - c-wrapper/c-tools.h - c-wrapper/c-types.h + address/address-p.h + address/address.h + address/identity-address.h + c-wrapper/c-wrapper.h + c-wrapper/internal/c-sal.h + c-wrapper/internal/c-tools.h + call/call-p.h + call/call.h + call/local-conference-call-p.h + call/local-conference-call.h + call/remote-conference-call-p.h + call/remote-conference-call.h + chat/chat-message/chat-message-p.h + chat/chat-message/chat-message.h + chat/chat-message/imdn-message.h + chat/chat-message/imdn-message-p.h + chat/chat-message/is-composing-message.h + chat/chat-message/notification-message.h + chat/chat-message/notification-message-p.h + chat/chat-room/abstract-chat-room-p.h + chat/chat-room/abstract-chat-room.h + chat/chat-room/basic-chat-room-p.h + chat/chat-room/basic-chat-room.h + chat/chat-room/basic-to-client-group-chat-room.h + chat/chat-room/chat-room-id.h + chat/chat-room/chat-room-listener.h + chat/chat-room/chat-room-p.h + chat/chat-room/chat-room.h + chat/chat-room/client-group-chat-room-p.h + chat/chat-room/client-group-chat-room.h + chat/chat-room/client-group-to-basic-chat-room.h + chat/chat-room/proxy-chat-room-p.h + chat/chat-room/proxy-chat-room.h + chat/chat-room/real-time-text-chat-room-p.h + chat/chat-room/real-time-text-chat-room.h + chat/chat-room/server-group-chat-room-p.h + chat/chat-room/server-group-chat-room.h + chat/cpim/cpim.h + chat/cpim/header/cpim-core-headers.h + chat/cpim/header/cpim-generic-header.h + chat/cpim/header/cpim-header-p.h + chat/cpim/header/cpim-header.h + chat/cpim/message/cpim-message.h + chat/cpim/parser/cpim-parser.h + chat/modifier/chat-message-modifier.h + chat/modifier/cpim-chat-message-modifier.h + chat/modifier/encryption-chat-message-modifier.h + chat/modifier/file-transfer-chat-message-modifier.h + chat/modifier/multipart-chat-message-modifier.h + chat/notification/imdn.h + chat/notification/is-composing-listener.h + chat/notification/is-composing.h + conference/conference-listener.h + conference/conference-p.h + conference/conference.h + conference/handlers/local-conference-event-handler-p.h + conference/handlers/local-conference-event-handler.h + conference/handlers/local-conference-list-event-handler.h + conference/handlers/remote-conference-event-handler-p.h + conference/handlers/remote-conference-event-handler.h + conference/handlers/remote-conference-list-event-handler.h + conference/local-conference-p.h + conference/local-conference.h + conference/params/call-session-params-p.h + conference/params/call-session-params.h + conference/params/media-session-params-p.h + conference/params/media-session-params.h + conference/participant-device.h + conference/participant-imdn-state.h + conference/participant-imdn-state-p.h + conference/participant-p.h + conference/participant.h + conference/remote-conference-p.h + conference/remote-conference.h + conference/session/call-session-listener.h + conference/session/call-session-p.h + conference/session/call-session.h + conference/session/media-session.h + conference/session/port-config.h + containers/lru-cache.h + content/content-disposition.h + content/content-manager.h + content/content-p.h + content/content-type.h content/content.h + content/file-content.h + content/file-transfer-content.h + content/header/header.h + content/header/header-p.h + content/header/header-param.h + core/core-accessor.h + core/core-listener.h + core/core-p.h core/core.h - cpim/cpim.h - cpim/header/cpim-core-headers.h - cpim/header/cpim-generic-header.h - cpim/header/cpim-header-p.h - cpim/header/cpim-header.h - cpim/message/cpim-message.h - cpim/parser/cpim-grammar.h - cpim/parser/cpim-parser.h + core/paths/paths.h + core/platform-helpers/platform-helpers.h + db/abstract/abstract-db-p.h + db/abstract/abstract-db.h + db/internal/db-transaction.h + db/internal/statements.h + db/main-db-chat-message-key.h + db/main-db-event-key.h + db/main-db-key-p.h + db/main-db-key.h + db/main-db-p.h + db/main-db.h + db/session/db-session.h + dial-plan/dial-plan-p.h + dial-plan/dial-plan.h + enums.h + event-log/conference/conference-call-event.h + event-log/conference/conference-event-p.h + event-log/conference/conference-event.h + event-log/conference/conference-notified-event-p.h + event-log/conference/conference-notified-event.h + event-log/conference/conference-participant-device-event.h + event-log/conference/conference-participant-event-p.h + event-log/conference/conference-participant-event.h + event-log/conference/conference-subject-event.h + event-log/event-log-p.h + event-log/event-log.h + event-log/events.h + hacks/hacks.h logger/logger.h - message/message.h + nat/ice-agent.h + nat/stun-client.h + object/app-data-container.h + object/base-object-p.h + object/base-object.h object/clonable-object-p.h object/clonable-object.h + object/clonable-shared-pointer.h + object/object-head-p.h + object/object-head.h object/object-p.h object/object.h + object/property-container.h object/singleton.h - utils/enum-generator.h - utils/general.h - utils/utils.h + sal/sal.h + search/magic-search-p.h + search/magic-search.h + search/search-result.h + utils/background-task.h + utils/general-internal.h + utils/payload-type-handler.h + variant/variant.h + xml/conference-info.h + xml/imdn.h + xml/is-composing.h + xml/linphone-imdn.h + xml/resource-lists.h + xml/rlmi.h + xml/xml.h ) set(LINPHONE_CXX_OBJECTS_SOURCE_FILES + address/address.cpp + address/identity-address.cpp + c-wrapper/api/c-address.cpp + c-wrapper/api/c-call-cbs.cpp + c-wrapper/api/c-call-params.cpp + c-wrapper/api/c-call-stats.cpp + c-wrapper/api/c-call.cpp + c-wrapper/api/c-chat-message-cbs.cpp + c-wrapper/api/c-chat-message.cpp + c-wrapper/api/c-chat-room-cbs.cpp + c-wrapper/api/c-chat-room.cpp + c-wrapper/api/c-core.cpp + c-wrapper/api/c-content.cpp + c-wrapper/api/c-dial-plan.cpp + c-wrapper/api/c-event-log.cpp + c-wrapper/api/c-magic-search.cpp + c-wrapper/api/c-participant.cpp + c-wrapper/api/c-participant-imdn-state.cpp + c-wrapper/api/c-search-result.cpp + c-wrapper/internal/c-sal.cpp + c-wrapper/internal/c-tools.cpp + call/call.cpp + call/local-conference-call.cpp + call/remote-conference-call.cpp + chat/chat-message/chat-message.cpp + chat/chat-message/imdn-message.cpp + chat/chat-message/is-composing-message.cpp + chat/chat-message/notification-message.cpp + chat/chat-room/abstract-chat-room.cpp + chat/chat-room/basic-chat-room.cpp + chat/chat-room/basic-to-client-group-chat-room.cpp + chat/chat-room/chat-room-id.cpp + chat/chat-room/chat-room.cpp + chat/chat-room/client-group-chat-room.cpp + chat/chat-room/client-group-to-basic-chat-room.cpp + chat/chat-room/proxy-chat-room.cpp + chat/chat-room/real-time-text-chat-room.cpp + chat/chat-room/server-group-chat-room-stub.cpp + chat/cpim/header/cpim-core-headers.cpp + chat/cpim/header/cpim-generic-header.cpp + chat/cpim/header/cpim-header.cpp + chat/cpim/message/cpim-message.cpp + chat/cpim/parser/cpim-parser.cpp + chat/modifier/cpim-chat-message-modifier.cpp + chat/modifier/encryption-chat-message-modifier.cpp + chat/modifier/file-transfer-chat-message-modifier.cpp + chat/modifier/multipart-chat-message-modifier.cpp + chat/notification/imdn.cpp + chat/notification/is-composing.cpp + conference/conference.cpp + conference/handlers/local-conference-event-handler.cpp + conference/handlers/local-conference-list-event-handler.cpp + conference/handlers/remote-conference-event-handler.cpp + conference/handlers/remote-conference-list-event-handler.cpp + conference/local-conference.cpp + conference/params/call-session-params.cpp + conference/params/media-session-params.cpp + conference/participant-device.cpp + conference/participant-imdn-state.cpp + conference/participant.cpp + conference/remote-conference.cpp + conference/session/call-session.cpp + conference/session/media-session.cpp + content/content-disposition.cpp + content/content-manager.cpp + content/content-type.cpp content/content.cpp + content/file-content.cpp + content/file-transfer-content.cpp + content/header/header.cpp + content/header/header-param.cpp + core/core-accessor.cpp + core/core-call.cpp + core/core-chat-room.cpp core/core.cpp - cpim/header/cpim-core-headers.cpp - cpim/header/cpim-generic-header.cpp - cpim/header/cpim-header.cpp - cpim/message/cpim-message.cpp - cpim/parser/cpim-grammar.cpp - cpim/parser/cpim-parser.cpp + core/paths/paths.cpp + core/platform-helpers/platform-helpers.cpp + db/abstract/abstract-db.cpp + db/internal/statements.cpp + db/main-db-chat-message-key.cpp + db/main-db-event-key.cpp + db/main-db-key.cpp + db/main-db.cpp + db/session/db-session.cpp + dial-plan/dial-plan.cpp + event-log/conference/conference-call-event.cpp + event-log/conference/conference-chat-message-event.cpp + event-log/conference/conference-event.cpp + event-log/conference/conference-notified-event.cpp + event-log/conference/conference-participant-device-event.cpp + event-log/conference/conference-participant-event.cpp + event-log/conference/conference-subject-event.cpp + event-log/event-log.cpp + hacks/hacks.cpp logger/logger.cpp - message/message.cpp + nat/ice-agent.cpp + nat/stun-client.cpp + object/app-data-container.cpp + object/base-object.cpp object/clonable-object.cpp object/object.cpp + object/property-container.cpp + sal/call-op.cpp + sal/event-op.cpp + sal/message-op.cpp + sal/op.cpp + sal/presence-op.cpp + sal/refer-op.cpp + sal/register-op.cpp + sal/sal.cpp + search/magic-search.cpp + search/search-result.cpp + utils/background-task.cpp + utils/fs.cpp utils/general.cpp + utils/payload-type-handler.cpp utils/utils.cpp + variant/variant.cpp + xml/conference-info.cpp + xml/imdn.cpp + xml/is-composing.cpp + xml/linphone-imdn.cpp + xml/resource-lists.cpp + xml/rlmi.cpp + xml/xml.cpp ) -set(LINPHONE_CXX_OBJECTS_DEFINITIONS "-DLIBLINPHONE_EXPORTS") +set(LINPHONE_OBJC_SOURCE_FILES) +if (APPLE) + list(APPEND LINPHONE_OBJC_SOURCE_FILES core/paths/paths-apple.mm) + list(APPEND LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES core/paths/paths-apple.h) + list(APPEND LINPHONE_CXX_OBJECTS_SOURCE_FILES core/platform-helpers/ios-platform-helpers.cpp) +elseif (ANDROID) + list(APPEND LINPHONE_CXX_OBJECTS_SOURCE_FILES core/paths/paths-android.cpp core/platform-helpers/android-platform-helpers.cpp) + list(APPEND LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES core/paths/paths-android.h) +elseif (WIN32) + list(APPEND LINPHONE_CXX_OBJECTS_SOURCE_FILES core/paths/paths-windows.cpp) + list(APPEND LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES core/paths/paths-windows.h) +elseif (UNIX) + list(APPEND LINPHONE_CXX_OBJECTS_SOURCE_FILES core/paths/paths-linux.cpp) + list(APPEND LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES core/paths/paths-linux.h) +endif () + +set(LINPHONE_CXX_OBJECTS_INCLUDE_DIRS + ${BELR_INCLUDE_DIRS} + ${LIBXSD_INCLUDE_DIRS} + ${SOCI_INCLUDE_DIRS} + ${SOCI_MYSQL_INCLUDES} +) +set(LINPHONE_CXX_OBJECTS_DEFINITIONS "-DLINPHONE_EXPORTS") set(LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${BELR_INCLUDE_DIRS}) -if(SOCI_FOUND) - list(APPEND LINPHONE_CXX_OBJECTS_INCLUDE_DIRS ${SOCI_INCLUDE_DIRS} ${SOCI_MYSQL_INCLUDES}) - add_definitions(-DSOCI_ENABLED) -endif() - set(LINPHONE_PRIVATE_HEADER_FILES) -foreach(header ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES}) +foreach (header ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES}) list(APPEND LINPHONE_PRIVATE_HEADER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${header}") -endforeach() +endforeach () set(LINPHONE_PRIVATE_HEADER_FILES ${LINPHONE_PRIVATE_HEADER_FILES} PARENT_SCOPE) +if (ANDROID AND CMAKE_C_COMPILER_ID STREQUAL "GNU") + list(APPEND STRICT_OPTIONS_CXX "-Wno-attributes") +endif() bc_apply_compile_flags(LINPHONE_CXX_OBJECTS_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX) +bc_apply_compile_flags(LINPHONE_OBJC_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC) + if(ENABLE_STATIC) - add_library(linphone-cxx-objects-static OBJECT ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_SOURCE_FILES}) - target_compile_definitions(linphone-cxx-objects-static PRIVATE ${LINPHONE_CXX_OBJECTS_DEFINITIONS}) - target_include_directories(linphone-cxx-objects-static SYSTEM PRIVATE ${LINPHONE_CXX_OBJECTS_INCLUDE_DIRS} ${LINPHONE_INCLUDE_DIRS}) + add_library(linphone-static STATIC ${LINPHONE_HEADER_FILES} + ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_SOURCE_FILES} ${LINPHONE_OBJC_SOURCE_FILES} + $ + ) + set_target_properties(linphone-static PROPERTIES OUTPUT_NAME linphone) + target_include_directories(linphone-static PUBLIC ${LINPHONE_INCLUDE_DIRS}) + target_link_libraries(linphone-static INTERFACE ${LIBS}) + if(APPLE) + target_link_libraries(linphone-static INTERFACE "-framework Foundation" "-framework AVFoundation") + endif() + install(TARGETS linphone-static EXPORT ${EXPORT_TARGETS_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + ) endif() - if(ENABLE_SHARED) - add_library(linphone-cxx-objects OBJECT ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_SOURCE_FILES}) - target_compile_definitions(linphone-cxx-objects PRIVATE ${LINPHONE_CXX_OBJECTS_DEFINITIONS}) - target_include_directories(linphone-cxx-objects SYSTEM PRIVATE ${LINPHONE_CXX_OBJECTS_INCLUDE_DIRS} ${LINPHONE_INCLUDE_DIRS}) - target_compile_options(linphone-cxx-objects PRIVATE "-fPIC") + set(LINPHONE_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/../share/cpim_grammar") #keep it relative to current dir to allow CMakeList inclusion + add_library(linphone SHARED ${LINPHONE_RESOURCES} ${LINPHONE_HEADER_FILES} + ${LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES} ${LINPHONE_CXX_OBJECTS_SOURCE_FILES} ${LINPHONE_OBJC_SOURCE_FILES} + $ + ) + #TODO: replace by if(APPLE) when we want to make apple framework on linphone-desktop too + if(IOS) + if(IOS) + set(MIN_OS ${LINPHONE_IOS_DEPLOYMENT_TARGET}) + else() + set(MIN_OS ${CMAKE_OSX_DEPLOYMENT_TARGET}) + endif() + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/build/osx/") + set_target_properties(linphone PROPERTIES + FRAMEWORK TRUE + MACOSX_FRAMEWORK_IDENTIFIER org.linphone.linphone + MACOSX_FRAMEWORK_INFO_PLIST Info.plist.in + RESOURCE ${LINPHONE_RESOURCES} + ) + endif() + if(BELCARD_FOUND) + if(APPLE) + set_target_properties(linphone PROPERTIES LINK_FLAGS "-stdlib=libc++") + endif() + endif() + + set_target_properties(linphone PROPERTIES LINKER_LANGUAGE CXX) + if(NOT ANDROID) + # Do not version shared library on Android + set_target_properties(linphone PROPERTIES SOVERSION ${LINPHONE_SO_VERSION}) + endif() + target_include_directories(linphone PUBLIC ${LINPHONE_INCLUDE_DIRS}) + target_link_libraries(linphone PRIVATE ${LIBS}) + if(APPLE) + target_link_libraries(linphone PRIVATE "-framework Foundation" "-framework AVFoundation") + endif() + if(WIN32) + # Export Xerces and Soci symbols. + list(APPEND LINPHONE_CXX_OBJECTS_DEFINITIONS "-DDLL_EXPORT" "-DSOCI_DLL") + if(CMAKE_SYSTEM_NAME STREQUAL "WindowsPhone" AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") + set_target_properties(linphone PROPERTIES PREFIX "lib") + endif() + elseif(ANDROID) + target_link_libraries(linphone PUBLIC "log" ${SUPPORT_LIBRARIES} ${CPUFEATURES_LIBRARIES}) + endif() + if(MSVC) + if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/linphone.pdb + DESTINATION ${CMAKE_INSTALL_BINDIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + ) + endif() + endif() + install(TARGETS linphone EXPORT ${EXPORT_TARGETS_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + FRAMEWORK DESTINATION Frameworks + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE + ) +endif() +target_compile_definitions(linphone PRIVATE ${LINPHONE_CXX_OBJECTS_DEFINITIONS}) + +if(ICONV_FOUND) + if(APPLE) + # Prevent conflict between the system iconv.h header and the one from macports. + if(ENABLE_STATIC) + target_compile_options(linphone-static PRIVATE "-include" "${ICONV_INCLUDE_DIRS}/iconv.h") + endif() + if(ENABLE_SHARED) + target_compile_options(linphone PRIVATE "-include" "${ICONV_INCLUDE_DIRS}/iconv.h") + endif() + else() + if(ENABLE_STATIC) + target_include_directories(linphone-static PRIVATE ${ICONV_INCLUDE_DIRS}) + endif() + if(ENABLE_SHARED) + target_include_directories(linphone PRIVATE ${ICONV_INCLUDE_DIRS}) + endif() + endif() endif() diff --git a/src/address/address-p.h b/src/address/address-p.h new file mode 100644 index 000000000..64d7d1ccf --- /dev/null +++ b/src/address/address-p.h @@ -0,0 +1,65 @@ +/* + * address-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ADDRESS_P_H_ +#define _L_ADDRESS_P_H_ + +#include + +#include "address.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +struct SalAddress; + +LINPHONE_BEGIN_NAMESPACE + +class AddressPrivate : public ClonableObjectPrivate { +public: + inline const SalAddress *getInternalAddress () const { + return internalAddress; + } + void setInternalAddress (const SalAddress *value); + + static void clearSipAddressesCache (); + +private: + struct AddressCache { + std::string scheme; + std::string displayName; + std::string username; + std::string domain; + std::string methodParam; + std::string password; + + std::unordered_map headers; + std::unordered_map params; + std::unordered_map uriParams; + }; + + SalAddress *internalAddress = nullptr; + mutable AddressCache cache; + + L_DECLARE_PUBLIC(Address); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ADDRESS_P_H_ diff --git a/src/address/address.cpp b/src/address/address.cpp new file mode 100644 index 000000000..bd875f7a2 --- /dev/null +++ b/src/address/address.cpp @@ -0,0 +1,483 @@ +/* + * address.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "address-p.h" +#include "address/identity-address.h" +#include "c-wrapper/c-wrapper.h" +#include "containers/lru-cache.h" +#include "logger/logger.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +namespace { + class SalAddressWrap { + public: + explicit SalAddressWrap (SalAddress *salAddress = nullptr) : mSalAddress(salAddress) {} + + SalAddressWrap (const SalAddressWrap &other) : mSalAddress(other.mSalAddress) { + if (mSalAddress) + sal_address_ref(mSalAddress); + } + + SalAddressWrap (SalAddressWrap &&other) : mSalAddress(other.mSalAddress) { + other.mSalAddress = nullptr; + } + + ~SalAddressWrap () { + if (mSalAddress) + sal_address_unref(mSalAddress); + } + + const SalAddress *get () { + return mSalAddress; + } + + private: + SalAddress *mSalAddress; + }; + LruCache addressesCache; +} + +static SalAddress *getSalAddressFromCache (const string &uri) { + SalAddressWrap *wrap = addressesCache[uri]; + if (wrap) + return sal_address_clone(wrap->get()); + + SalAddress *address = sal_address_new(L_STRING_TO_C(uri)); + if (address) { + addressesCache.insert(uri, SalAddressWrap(address)); + return sal_address_clone(address); + } + + return nullptr; +} + +// ----------------------------------------------------------------------------- + +void AddressPrivate::setInternalAddress (const SalAddress *addr) { + if (internalAddress) + sal_address_unref(internalAddress); + internalAddress = sal_address_clone(addr); +} + +void AddressPrivate::clearSipAddressesCache () { + addressesCache.clear(); +} + +// ----------------------------------------------------------------------------- + +Address::Address (const string &address) : ClonableObject(*new AddressPrivate) { + L_D(); + + if (!(d->internalAddress = getSalAddressFromCache(address))) { + lWarning() << "Cannot create Address, bad uri [" << address << "]"; + } +} + +Address::Address (const IdentityAddress &identityAddress) : ClonableObject(*new AddressPrivate) { + L_D(); + + const string &username = identityAddress.getUsername(); + if (username.empty()) + return; + const string &domain = identityAddress.getDomain(); + if (domain.empty()) + return; + + string uri = identityAddress.getScheme() + ":" + username + "@" + ( + domain.find(':') != string::npos ? "[" + domain + "]" : domain + ); + + if (identityAddress.hasGruu()) + uri += ";gr=" + identityAddress.getGruu(); + + d->internalAddress = getSalAddressFromCache(uri); +} + +Address::Address (const Address &other) : ClonableObject(*new AddressPrivate) { + L_D(); + SalAddress *salAddress = other.getPrivate()->internalAddress; + if (salAddress) + d->internalAddress = sal_address_clone(salAddress); +} + +Address::~Address () { + L_D(); + if (d->internalAddress) + sal_address_destroy(d->internalAddress); +} + +Address &Address::operator= (const Address &other) { + L_D(); + if (this != &other) { + if (d->internalAddress) + sal_address_destroy(d->internalAddress); + SalAddress *salAddress = other.getPrivate()->internalAddress; + d->internalAddress = salAddress ? sal_address_clone(salAddress) : nullptr; + } + + return *this; +} + +bool Address::operator== (const Address &other) const { + return asString() == other.asString(); +} + +bool Address::operator!= (const Address &other) const { + return !(*this == other); +} + +bool Address::operator< (const Address &other) const { + return asString() < other.asString(); +} + +bool Address::isValid () const { + L_D(); + return !!d->internalAddress; +} + +const string &Address::getScheme () const { + L_D(); + + if (!d->internalAddress) + return Utils::getEmptyConstRefObject(); + + string scheme(L_C_TO_STRING(sal_address_get_scheme(d->internalAddress))); + if (scheme != d->cache.scheme) + d->cache.scheme = scheme; + return d->cache.scheme; +} + +const string &Address::getDisplayName () const { + L_D(); + + if (!d->internalAddress) + return Utils::getEmptyConstRefObject(); + + string displayName(L_C_TO_STRING(sal_address_get_display_name(d->internalAddress))); + if (displayName != d->cache.displayName) + d->cache.displayName = displayName; + return d->cache.displayName; +} + +bool Address::setDisplayName (const string &displayName) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_display_name(d->internalAddress, L_STRING_TO_C(displayName)); + return true; +} + +const string &Address::getUsername () const { + L_D(); + + if (!d->internalAddress) + return Utils::getEmptyConstRefObject(); + + string username(L_C_TO_STRING(sal_address_get_username(d->internalAddress))); + if (username != d->cache.username) + d->cache.username = username; + return d->cache.username; +} + +bool Address::setUsername (const string &username) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_username(d->internalAddress, L_STRING_TO_C(username)); + return true; +} + +const string &Address::getDomain () const { + L_D(); + + if (!d->internalAddress) + return Utils::getEmptyConstRefObject(); + + string domain(L_C_TO_STRING(sal_address_get_domain(d->internalAddress))); + if (domain != d->cache.domain) + d->cache.domain = domain; + return d->cache.domain; +} + +bool Address::setDomain (const string &domain) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_domain(d->internalAddress, L_STRING_TO_C(domain)); + return true; +} + +int Address::getPort () const { + L_D(); + return d->internalAddress ? sal_address_get_port(d->internalAddress) : 0; +} + +bool Address::setPort (int port) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_port(d->internalAddress, port); + return true; +} + +Transport Address::getTransport () const { + L_D(); + return d->internalAddress ? static_cast(sal_address_get_transport(d->internalAddress)) : Transport::Udp; +} + +bool Address::setTransport (Transport transport) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_transport(d->internalAddress, static_cast(transport)); + return true; +} + +bool Address::getSecure () const { + L_D(); + return d->internalAddress && sal_address_is_secure(d->internalAddress); +} + +bool Address::setSecure (bool enabled) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_secure(d->internalAddress, enabled); + return true; +} + +bool Address::isSip () const { + L_D(); + return d->internalAddress && sal_address_is_sip(d->internalAddress); +} + +const string &Address::getMethodParam () const { + L_D(); + + if (!d->internalAddress) + return Utils::getEmptyConstRefObject(); + + string methodParam(L_C_TO_STRING(sal_address_get_method_param(d->internalAddress))); + if (methodParam != d->cache.methodParam) + d->cache.methodParam = methodParam; + return d->cache.methodParam; +} + +bool Address::setMethodParam (const string &methodParam) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_method_param(d->internalAddress, L_STRING_TO_C(methodParam)); + return true; +} + +const string &Address::getPassword () const { + L_D(); + + if (!d->internalAddress) + return Utils::getEmptyConstRefObject(); + + string password(L_C_TO_STRING(sal_address_get_password(d->internalAddress))); + if (password != d->cache.password) + d->cache.password = password; + return d->cache.password; +} + +bool Address::setPassword (const string &password) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_password(d->internalAddress, L_STRING_TO_C(password)); + return true; +} + +bool Address::clean () { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_clean(d->internalAddress); + return true; +} + +string Address::asString () const { + L_D(); + + if (!d->internalAddress) + return ""; + + char *buf = sal_address_as_string(d->internalAddress); + string out = buf; + ms_free(buf); + return out; +} + +string Address::asStringUriOnly () const { + L_D(); + + if (!d->internalAddress) + return ""; + + char *buf = sal_address_as_string_uri_only(d->internalAddress); + string out = buf; + ms_free(buf); + return out; +} + +bool Address::weakEqual (const Address &address) const { + return getUsername() == address.getUsername() && + getDomain() == address.getDomain() && + getPort() == address.getPort(); +} + +const string &Address::getHeaderValue (const string &headerName) const { + L_D(); + + if (d->internalAddress) { + const char *value = sal_address_get_header(d->internalAddress, L_STRING_TO_C(headerName)); + if (value) { + d->cache.headers[headerName] = value; + return d->cache.headers[headerName]; + } + } + + return Utils::getEmptyConstRefObject(); +} + +bool Address::setHeader (const string &headerName, const string &headerValue) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_header(d->internalAddress, L_STRING_TO_C(headerName), L_STRING_TO_C(headerValue)); + return true; +} + +bool Address::hasParam (const string ¶mName) const { + L_D(); + return d->internalAddress && !!sal_address_has_param(d->internalAddress, L_STRING_TO_C(paramName)); +} + +const string &Address::getParamValue (const string ¶mName) const { + L_D(); + + if (d->internalAddress) { + const char *value = sal_address_get_param(d->internalAddress, L_STRING_TO_C(paramName)); + if (value) { + d->cache.params[paramName] = value; + return d->cache.params[paramName]; + } + } + + return Utils::getEmptyConstRefObject(); +} + +bool Address::setParam (const string ¶mName, const string ¶mValue) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_param(d->internalAddress, L_STRING_TO_C(paramName), L_STRING_TO_C(paramValue)); + return true; +} + +bool Address::setParams (const string ¶ms) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_params(d->internalAddress, L_STRING_TO_C(params)); + return true; +} + +bool Address::hasUriParam (const string &uriParamName) const { + L_D(); + return d->internalAddress && !!sal_address_has_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); +} + +const string &Address::getUriParamValue (const string &uriParamName) const { + L_D(); + + if (d->internalAddress) { + const char *value = sal_address_get_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); + if (value) { + d->cache.uriParams[uriParamName] = value; + return d->cache.uriParams[uriParamName]; + } + } + + return Utils::getEmptyConstRefObject(); +} + +bool Address::setUriParam (const string &uriParamName, const string &uriParamValue) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName), L_STRING_TO_C(uriParamValue)); + return true; +} + +bool Address::setUriParams (const string &uriParams) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_set_uri_params(d->internalAddress, L_STRING_TO_C(uriParams)); + return true; +} + +bool Address::removeUriParam (const string &uriParamName) { + L_D(); + + if (!d->internalAddress) + return false; + + sal_address_remove_uri_param(d->internalAddress, L_STRING_TO_C(uriParamName)); + return true; +} + +LINPHONE_END_NAMESPACE diff --git a/src/address/address.h b/src/address/address.h new file mode 100644 index 000000000..f92300277 --- /dev/null +++ b/src/address/address.h @@ -0,0 +1,119 @@ +/* + * address.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ADDRESS_H_ +#define _L_ADDRESS_H_ + +#include + +#include "enums.h" +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class AddressPrivate; +class IdentityAddress; + +class LINPHONE_PUBLIC Address : public ClonableObject { + // TODO: Remove me later. + friend class CallSession; + friend class ClientGroupChatRoom; + friend class ClientGroupChatRoomPrivate; + friend class ServerGroupChatRoom; + friend class ServerGroupChatRoomPrivate; + friend class IdentityAddress; + +public: + explicit Address (const std::string &address = ""); + Address (const IdentityAddress &identityAddress); + Address (const Address &other); + ~Address (); + + Address &operator= (const Address &other); + + bool operator== (const Address &other) const; + bool operator!= (const Address &other) const; + + bool operator< (const Address &other) const; + + bool isValid () const; + + const std::string &getScheme () const; + + const std::string &getDisplayName () const; + bool setDisplayName (const std::string &displayName); + + const std::string &getUsername () const; + bool setUsername (const std::string &username); + + const std::string &getDomain () const; + bool setDomain (const std::string &domain); + + int getPort () const; + bool setPort (int port); + + Transport getTransport () const; + bool setTransport (Transport transport); + + bool getSecure () const; + bool setSecure (bool enabled); + + bool isSip () const; + + const std::string &getMethodParam () const; + bool setMethodParam (const std::string &methodParam); + + const std::string &getPassword () const; + bool setPassword (const std::string &password); + + bool clean (); + + std::string asString () const; + std::string asStringUriOnly () const; + + bool weakEqual (const Address &address) const; + + const std::string &getHeaderValue (const std::string &headerName) const; + bool setHeader (const std::string &headerName, const std::string &headerValue); + + bool hasParam (const std::string ¶mName) const; + const std::string &getParamValue (const std::string ¶mName) const; + bool setParam (const std::string ¶mName, const std::string ¶mValue = ""); + bool setParams (const std::string ¶ms); + + bool hasUriParam (const std::string &uriParamName) const; + const std::string &getUriParamValue (const std::string &uriParamName) const; + bool setUriParam (const std::string &uriParamName, const std::string &uriParamValue = ""); + bool setUriParams (const std::string &uriParams); + bool removeUriParam (const std::string &uriParamName); + +private: + L_DECLARE_PRIVATE(Address); +}; + +inline std::ostream &operator<< (std::ostream &os, const Address &address) { + os << "Address(" << address.asString() << ")"; + return os; +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ADDRESS_H_ diff --git a/src/address/identity-address.cpp b/src/address/identity-address.cpp new file mode 100644 index 000000000..f20590e16 --- /dev/null +++ b/src/address/identity-address.cpp @@ -0,0 +1,156 @@ +/* + * identity-address.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "address.h" +#include "c-wrapper/c-wrapper.h" +#include "identity-address.h" +#include "logger/logger.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class IdentityAddressPrivate : public ClonableObjectPrivate { +public: + std::string scheme; + std::string username; + std::string domain; + std::string gruu; +}; + +// ----------------------------------------------------------------------------- + +IdentityAddress::IdentityAddress (const string &address) : ClonableObject(*new IdentityAddressPrivate) { + L_D(); + Address tmpAddress(address); + if (tmpAddress.isValid() && ((tmpAddress.getScheme() == "sip") || (tmpAddress.getScheme() == "sips"))) { + d->scheme = tmpAddress.getScheme(); + d->username = tmpAddress.getUsername(); + d->domain = tmpAddress.getDomain(); + d->gruu = tmpAddress.getUriParamValue("gr"); + } +} + +IdentityAddress::IdentityAddress (const Address &address) : ClonableObject(*new IdentityAddressPrivate) { + L_D(); + d->scheme = address.getScheme(); + d->username = address.getUsername(); + d->domain = address.getDomain(); + if (address.hasUriParam("gr")) + d->gruu = address.getUriParamValue("gr"); +} + +IdentityAddress::IdentityAddress (const IdentityAddress &other) : ClonableObject(*new IdentityAddressPrivate) { + L_D(); + d->scheme = other.getScheme(); + d->username = other.getUsername(); + d->domain = other.getDomain(); + d->gruu = other.getGruu(); +} + +IdentityAddress &IdentityAddress::operator= (const IdentityAddress &other) { + L_D(); + if (this != &other) { + d->scheme = other.getScheme(); + d->username = other.getUsername(); + d->domain = other.getDomain(); + d->gruu = other.getGruu(); + } + return *this; +} + +bool IdentityAddress::operator== (const IdentityAddress &other) const { + return asString() == other.asString(); +} + +bool IdentityAddress::operator!= (const IdentityAddress &other) const { + return !(*this == other); +} + +bool IdentityAddress::operator< (const IdentityAddress &other) const { + return asString() < other.asString(); +} + +bool IdentityAddress::isValid () const { + Address tmpAddress(*this); + return tmpAddress.isValid(); +} + +const string &IdentityAddress::getScheme () const { + L_D(); + return d->scheme; +} + +const string &IdentityAddress::getUsername () const { + L_D(); + return d->username; +} + +bool IdentityAddress::setUsername (const string &username) { + L_D(); + d->username = username; + return true; +} + +const string &IdentityAddress::getDomain () const { + L_D(); + return d->domain; +} + +bool IdentityAddress::setDomain (const string &domain) { + L_D(); + d->domain = domain; + return true; +} + +bool IdentityAddress::hasGruu () const { + L_D(); + return !d->gruu.empty(); +} + +const string &IdentityAddress::getGruu () const { + L_D(); + return d->gruu; +} + +bool IdentityAddress::setGruu (const string &gruu) { + L_D(); + d->gruu = gruu; + return true; +} + +IdentityAddress IdentityAddress::getAddressWithoutGruu () const { + IdentityAddress address(*this); + address.setGruu(""); + return address; +} + +string IdentityAddress::asString () const { + Address tmpAddress(*this); + return tmpAddress.asStringUriOnly(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/address/identity-address.h b/src/address/identity-address.h new file mode 100644 index 000000000..2e39b959b --- /dev/null +++ b/src/address/identity-address.h @@ -0,0 +1,77 @@ +/* + * identity-address.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_IDENTITY_ADDRESS_H_ +#define _L_IDENTITY_ADDRESS_H_ + +#include + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Address; +class IdentityAddressPrivate; + +class LINPHONE_PUBLIC IdentityAddress : public ClonableObject { +public: + explicit IdentityAddress (const std::string &address = ""); + IdentityAddress (const Address &address); + IdentityAddress (const IdentityAddress &other); + ~IdentityAddress () = default; + + IdentityAddress &operator= (const IdentityAddress &other); + + bool operator== (const IdentityAddress &other) const; + bool operator!= (const IdentityAddress &other) const; + + bool operator< (const IdentityAddress &other) const; + + bool isValid () const; + + const std::string &getScheme () const; + + const std::string &getUsername () const; + bool setUsername (const std::string &username); + + const std::string &getDomain () const; + bool setDomain (const std::string &domain); + + bool hasGruu () const; + const std::string &getGruu () const; + bool setGruu (const std::string &gruu); + + IdentityAddress getAddressWithoutGruu () const; + + virtual std::string asString () const; + +private: + L_DECLARE_PRIVATE(IdentityAddress); +}; + +inline std::ostream &operator<< (std::ostream &os, const IdentityAddress &identityAddress) { + os << "IdentityAddress(" << identityAddress.asString() << ")"; + return os; +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_IDENTITY_ADDRESS_H_ diff --git a/src/c-wrapper/api/c-address.cpp b/src/c-wrapper/api/c-address.cpp new file mode 100644 index 000000000..dbbe793bc --- /dev/null +++ b/src/c-wrapper/api/c-address.cpp @@ -0,0 +1,199 @@ +/* + * c-address.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +L_DECLARE_C_CLONABLE_OBJECT_IMPL(Address); + +using namespace std; + +// ============================================================================= + +LinphoneAddress *linphone_address_new (const char *address) { + LinphonePrivate::Address *cppPtr = new LinphonePrivate::Address(L_C_TO_STRING(address)); + if (!cppPtr->isValid()) { + delete cppPtr; + return nullptr; + } + + LinphoneAddress *object = L_INIT(Address); + L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); + + return object; +} + +LinphoneAddress *linphone_address_clone (const LinphoneAddress *address) { + return reinterpret_cast(belle_sip_object_clone(BELLE_SIP_OBJECT(address))); +} + +LinphoneAddress *linphone_address_ref (LinphoneAddress *address) { + belle_sip_object_ref(address); + return address; +} + +void linphone_address_unref (LinphoneAddress *address) { + belle_sip_object_unref(address); +} + +const char *linphone_address_get_scheme (const LinphoneAddress *address) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getScheme()); +} + +const char *linphone_address_get_display_name (const LinphoneAddress *address) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getDisplayName()); +} + +LinphoneStatus linphone_address_set_display_name (LinphoneAddress *address, const char *display_name) { + return !L_GET_CPP_PTR_FROM_C_OBJECT(address)->setDisplayName(L_C_TO_STRING(display_name)); +} + +const char *linphone_address_get_username (const LinphoneAddress *address) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getUsername()); +} + +LinphoneStatus linphone_address_set_username (LinphoneAddress *address, const char *username) { + return !L_GET_CPP_PTR_FROM_C_OBJECT(address)->setUsername(L_C_TO_STRING(username)); +} + +const char *linphone_address_get_domain (const LinphoneAddress *address) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getDomain()); +} + +LinphoneStatus linphone_address_set_domain (LinphoneAddress *address, const char *domain) { + return !L_GET_CPP_PTR_FROM_C_OBJECT(address)->setDomain(L_C_TO_STRING(domain)); +} + +int linphone_address_get_port (const LinphoneAddress *address) { + return L_GET_CPP_PTR_FROM_C_OBJECT(address)->getPort(); +} + +LinphoneStatus linphone_address_set_port (LinphoneAddress *address, int port) { + return !L_GET_CPP_PTR_FROM_C_OBJECT(address)->setPort(port); +} + +LinphoneTransportType linphone_address_get_transport (const LinphoneAddress *address) { + return static_cast(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getTransport()); +} + +LinphoneStatus linphone_address_set_transport (LinphoneAddress *address, LinphoneTransportType transport) { + return !L_GET_CPP_PTR_FROM_C_OBJECT(address)->setTransport(static_cast(transport)); +} + +bool_t linphone_address_get_secure (const LinphoneAddress *address) { + return L_GET_CPP_PTR_FROM_C_OBJECT(address)->getSecure(); +} + +void linphone_address_set_secure (LinphoneAddress *address, bool_t enabled) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setSecure(!!enabled); +} + +bool_t linphone_address_is_sip (const LinphoneAddress *address) { + return L_GET_CPP_PTR_FROM_C_OBJECT(address)->isSip(); +} + +const char *linphone_address_get_method_param (const LinphoneAddress *address) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getMethodParam()); +} + +void linphone_address_set_method_param (LinphoneAddress *address, const char *method_param) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setMethodParam(L_C_TO_STRING(method_param)); +} + +const char *linphone_address_get_password (const LinphoneAddress *address) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getPassword()); +} + +void linphone_address_set_password (LinphoneAddress *address, const char *password) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setPassword(L_C_TO_STRING(password)); +} + +void linphone_address_clean (LinphoneAddress *address) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->clean(); +} + +char *linphone_address_as_string (const LinphoneAddress *address) { + return bctbx_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(address)->asString().c_str()); +} + +char *linphone_address_as_string_uri_only (const LinphoneAddress *address) { + return bctbx_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(address)->asStringUriOnly().c_str()); +} + +bool_t linphone_address_weak_equal (const LinphoneAddress *address1, const LinphoneAddress *address2) { + return L_GET_CPP_PTR_FROM_C_OBJECT(address1)->weakEqual(*L_GET_CPP_PTR_FROM_C_OBJECT(address2)); +} + +bool_t linphone_address_equal (const LinphoneAddress *address1, const LinphoneAddress *address2) { + return *L_GET_CPP_PTR_FROM_C_OBJECT(address1) == *L_GET_CPP_PTR_FROM_C_OBJECT(address2); +} + +const char *linphone_address_get_header (const LinphoneAddress *address, const char *header_name) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getHeaderValue(L_C_TO_STRING(header_name))); +} + +void linphone_address_set_header (LinphoneAddress *address, const char *header_name, const char *header_value) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setHeader(L_C_TO_STRING(header_name), L_C_TO_STRING(header_value)); +} + +bool_t linphone_address_has_param (const LinphoneAddress *address, const char *param_name) { + return L_GET_CPP_PTR_FROM_C_OBJECT(address)->hasParam(L_C_TO_STRING(param_name)); +} + +const char *linphone_address_get_param (const LinphoneAddress *address, const char *param_name) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getParamValue(L_C_TO_STRING(param_name))); +} + +void linphone_address_set_param (LinphoneAddress *address, const char *param_name, const char *param_value) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setParam(L_C_TO_STRING(param_name), L_C_TO_STRING(param_value)); +} + +void linphone_address_set_params (LinphoneAddress *address, const char *params) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setParams(L_C_TO_STRING(params)); +} + +bool_t linphone_address_has_uri_param (const LinphoneAddress *address, const char *uri_param_name) { + return L_GET_CPP_PTR_FROM_C_OBJECT(address)->hasUriParam(L_C_TO_STRING(uri_param_name)); +} + +const char *linphone_address_get_uri_param (const LinphoneAddress *address, const char *uri_param_name) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(address)->getUriParamValue(L_C_TO_STRING(uri_param_name))); +} + +void linphone_address_set_uri_param (LinphoneAddress *address, const char *uri_param_name, const char *uri_param_value) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setUriParam(L_C_TO_STRING(uri_param_name), L_C_TO_STRING(uri_param_value)); +} + +void linphone_address_set_uri_params (LinphoneAddress *address, const char *params) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->setUriParams(L_C_TO_STRING(params)); +} + +void linphone_address_remove_uri_param (LinphoneAddress *address, const char *uri_param_name) { + L_GET_CPP_PTR_FROM_C_OBJECT(address)->removeUriParam(L_C_TO_STRING(uri_param_name)); +} + +void linphone_address_destroy (LinphoneAddress *address) { + belle_sip_object_unref(address); +} + +bool_t linphone_address_is_secure (const LinphoneAddress *address) { + return L_GET_CPP_PTR_FROM_C_OBJECT(address)->getSecure(); +} diff --git a/src/c-wrapper/api/c-call-cbs.cpp b/src/c-wrapper/api/c-call-cbs.cpp new file mode 100644 index 000000000..8db00054c --- /dev/null +++ b/src/c-wrapper/api/c-call-cbs.cpp @@ -0,0 +1,153 @@ +/* + * c-call-cbs.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-call-cbs.h" + +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +struct _LinphoneCallCbs { + belle_sip_object_t base; + void *userData; + LinphoneCallCbsDtmfReceivedCb dtmfReceivedCb; + LinphoneCallCbsEncryptionChangedCb encryptionChangedCb; + LinphoneCallCbsInfoMessageReceivedCb infoMessageReceivedCb; + LinphoneCallCbsStateChangedCb stateChangedCb; + LinphoneCallCbsStatsUpdatedCb statsUpdatedCb; + LinphoneCallCbsTransferStateChangedCb transferStateChangedCb; + LinphoneCallCbsAckProcessingCb ackProcessing; + LinphoneCallCbsTmmbrReceivedCb tmmbrReceivedCb; + LinphoneCallCbsSnapshotTakenCb snapshotTakenCb; + LinphoneCallCbsNextVideoFrameDecodedCb nextVideoFrameDecodedCb; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCallCbs); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneCallCbs); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneCallCbs, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +// ============================================================================= + +LinphoneCallCbs *_linphone_call_cbs_new (void) { + return belle_sip_object_new(LinphoneCallCbs); +} + +LinphoneCallCbs *linphone_call_cbs_ref (LinphoneCallCbs *cbs) { + belle_sip_object_ref(cbs); + return cbs; +} + +void linphone_call_cbs_unref (LinphoneCallCbs *cbs) { + belle_sip_object_unref(cbs); +} + +void *linphone_call_cbs_get_user_data (const LinphoneCallCbs *cbs) { + return cbs->userData; +} + +void linphone_call_cbs_set_user_data (LinphoneCallCbs *cbs, void *ud) { + cbs->userData = ud; +} + +LinphoneCallCbsDtmfReceivedCb linphone_call_cbs_get_dtmf_received (LinphoneCallCbs *cbs) { + return cbs->dtmfReceivedCb; +} + +void linphone_call_cbs_set_dtmf_received (LinphoneCallCbs *cbs, LinphoneCallCbsDtmfReceivedCb cb) { + cbs->dtmfReceivedCb = cb; +} + +LinphoneCallCbsEncryptionChangedCb linphone_call_cbs_get_encryption_changed (LinphoneCallCbs *cbs) { + return cbs->encryptionChangedCb; +} + +void linphone_call_cbs_set_encryption_changed (LinphoneCallCbs *cbs, LinphoneCallCbsEncryptionChangedCb cb) { + cbs->encryptionChangedCb = cb; +} + +LinphoneCallCbsInfoMessageReceivedCb linphone_call_cbs_get_info_message_received (LinphoneCallCbs *cbs) { + return cbs->infoMessageReceivedCb; +} + +void linphone_call_cbs_set_info_message_received (LinphoneCallCbs *cbs, LinphoneCallCbsInfoMessageReceivedCb cb) { + cbs->infoMessageReceivedCb = cb; +} + +LinphoneCallCbsStateChangedCb linphone_call_cbs_get_state_changed (LinphoneCallCbs *cbs) { + return cbs->stateChangedCb; +} + +void linphone_call_cbs_set_state_changed (LinphoneCallCbs *cbs, LinphoneCallCbsStateChangedCb cb) { + cbs->stateChangedCb = cb; +} + +LinphoneCallCbsStatsUpdatedCb linphone_call_cbs_get_stats_updated (LinphoneCallCbs *cbs) { + return cbs->statsUpdatedCb; +} + +void linphone_call_cbs_set_stats_updated (LinphoneCallCbs *cbs, LinphoneCallCbsStatsUpdatedCb cb) { + cbs->statsUpdatedCb = cb; +} + +LinphoneCallCbsTransferStateChangedCb linphone_call_cbs_get_transfer_state_changed (LinphoneCallCbs *cbs) { + return cbs->transferStateChangedCb; +} + +void linphone_call_cbs_set_transfer_state_changed (LinphoneCallCbs *cbs, LinphoneCallCbsTransferStateChangedCb cb) { + cbs->transferStateChangedCb = cb; +} + +LinphoneCallCbsAckProcessingCb linphone_call_cbs_get_ack_processing (LinphoneCallCbs *cbs){ + return cbs->ackProcessing; +} + +void linphone_call_cbs_set_ack_processing (LinphoneCallCbs *cbs, LinphoneCallCbsAckProcessingCb cb){ + cbs->ackProcessing = cb; +} + +LinphoneCallCbsTmmbrReceivedCb linphone_call_cbs_get_tmmbr_received (LinphoneCallCbs *cbs) { + return cbs->tmmbrReceivedCb; +} + +void linphone_call_cbs_set_tmmbr_received (LinphoneCallCbs *cbs, LinphoneCallCbsTmmbrReceivedCb cb) { + cbs->tmmbrReceivedCb = cb; +} + +LinphoneCallCbsSnapshotTakenCb linphone_call_cbs_get_snapshot_taken(LinphoneCallCbs *cbs) { + return cbs->snapshotTakenCb; +} + +void linphone_call_cbs_set_snapshot_taken(LinphoneCallCbs *cbs, LinphoneCallCbsSnapshotTakenCb cb) { + cbs->snapshotTakenCb = cb; +} + +LinphoneCallCbsNextVideoFrameDecodedCb linphone_call_cbs_get_next_video_frame_decoded(LinphoneCallCbs *cbs) { + return cbs->nextVideoFrameDecodedCb; +} + +void linphone_call_cbs_set_next_video_frame_decoded(LinphoneCallCbs *cbs, LinphoneCallCbsNextVideoFrameDecodedCb cb) { + cbs->nextVideoFrameDecodedCb = cb; +} diff --git a/src/c-wrapper/api/c-call-params.cpp b/src/c-wrapper/api/c-call-params.cpp new file mode 100644 index 000000000..cf614024a --- /dev/null +++ b/src/c-wrapper/api/c-call-params.cpp @@ -0,0 +1,527 @@ +/* + * c-call-params.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "core/core.h" +#include "conference/params/call-session-params-p.h" +#include "conference/params/media-session-params-p.h" +#include "conference/session/call-session.h" + +#include "linphone/call_params.h" + +// ============================================================================= + +L_DECLARE_C_CLONABLE_OBJECT_IMPL(CallParams) + +using namespace std; + +// ============================================================================= +// Internal functions. +// ============================================================================= + +SalMediaProto get_proto_from_call_params (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getMediaProto(); +} + +SalStreamDir sal_dir_from_call_params_dir (LinphoneMediaDirection cpdir) { + switch (cpdir) { + case LinphoneMediaDirectionInactive: + return SalStreamInactive; + case LinphoneMediaDirectionSendOnly: + return SalStreamSendOnly; + case LinphoneMediaDirectionRecvOnly: + return SalStreamRecvOnly; + case LinphoneMediaDirectionSendRecv: + return SalStreamSendRecv; + case LinphoneMediaDirectionInvalid: + ms_error("LinphoneMediaDirectionInvalid shall not be used."); + return SalStreamInactive; + } + return SalStreamSendRecv; +} + +LinphoneMediaDirection media_direction_from_sal_stream_dir (SalStreamDir dir) { + switch (dir) { + case SalStreamInactive: + return LinphoneMediaDirectionInactive; + case SalStreamSendOnly: + return LinphoneMediaDirectionSendOnly; + case SalStreamRecvOnly: + return LinphoneMediaDirectionRecvOnly; + case SalStreamSendRecv: + return LinphoneMediaDirectionSendRecv; + } + return LinphoneMediaDirectionSendRecv; +} + +SalStreamDir get_audio_dir_from_call_params (const LinphoneCallParams *params) { + return sal_dir_from_call_params_dir(linphone_call_params_get_audio_direction(params)); +} + +SalStreamDir get_video_dir_from_call_params (const LinphoneCallParams *params) { + return sal_dir_from_call_params_dir(linphone_call_params_get_video_direction(params)); +} + +void linphone_call_params_set_custom_headers (LinphoneCallParams *params, const SalCustomHeader *ch) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setCustomHeaders(ch); +} + +void linphone_call_params_set_custom_sdp_attributes (LinphoneCallParams *params, const SalCustomSdpAttribute *csa) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setCustomSdpAttributes(csa); +} + +void linphone_call_params_set_custom_sdp_media_attributes (LinphoneCallParams *params, LinphoneStreamType type, const SalCustomSdpAttribute *csa) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setCustomSdpMediaAttributes(type, csa); +} + +// ============================================================================= +// Public functions. +// ============================================================================= + +void linphone_call_params_add_custom_header (LinphoneCallParams *params, const char *header_name, const char *header_value) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->addCustomHeader(header_name, L_C_TO_STRING(header_value)); +} + +void linphone_call_params_add_custom_sdp_attribute (LinphoneCallParams *params, const char *attribute_name, const char *attribute_value) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->addCustomSdpAttribute(attribute_name, L_C_TO_STRING(attribute_value)); +} + +void linphone_call_params_add_custom_sdp_media_attribute (LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name, const char *attribute_value) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->addCustomSdpMediaAttribute(type, attribute_name, L_C_TO_STRING(attribute_value)); +} + +void linphone_call_params_clear_custom_sdp_attributes (LinphoneCallParams *params) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->clearCustomSdpAttributes(); +} + +void linphone_call_params_clear_custom_sdp_media_attributes (LinphoneCallParams *params, LinphoneStreamType type) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->clearCustomSdpMediaAttributes(type); +} + +LinphoneCallParams *linphone_call_params_copy (const LinphoneCallParams *params) { + return (LinphoneCallParams *)belle_sip_object_clone((const belle_sip_object_t *)params); +} + +bool_t linphone_call_params_early_media_sending_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->earlyMediaSendingEnabled(); +} + +void linphone_call_params_enable_early_media_sending (LinphoneCallParams *params, bool_t enabled) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableEarlyMediaSending(!!enabled); +} + +void linphone_call_params_enable_low_bandwidth (LinphoneCallParams *params, bool_t enabled) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableLowBandwidth(!!enabled); +} + +void linphone_call_params_enable_audio (LinphoneCallParams *params, bool_t enabled) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableAudio(!!enabled); +} + +LinphoneStatus linphone_call_params_enable_realtime_text (LinphoneCallParams *params, bool_t yesno) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableRealtimeText(!!yesno); + return 0; +} + +void linphone_call_params_enable_video (LinphoneCallParams *params, bool_t enabled) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableVideo(!!enabled); +} + +const char *linphone_call_params_get_custom_header (const LinphoneCallParams *params, const char *header_name) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getCustomHeader(header_name); +} + +const char *linphone_call_params_get_custom_sdp_attribute (const LinphoneCallParams *params, const char *attribute_name) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getCustomSdpAttribute(attribute_name); +} + +const char *linphone_call_params_get_custom_sdp_media_attribute (const LinphoneCallParams *params, LinphoneStreamType type, const char *attribute_name) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getCustomSdpMediaAttribute(type, attribute_name); +} + +bool_t linphone_call_params_get_local_conference_mode (const LinphoneCallParams *params) { + return linphone_call_params_get_in_conference(params); +} + +LinphoneMediaEncryption linphone_call_params_get_media_encryption (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getMediaEncryption(); +} + +LinphonePrivacyMask linphone_call_params_get_privacy (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getPrivacy(); +} + +float linphone_call_params_get_received_framerate (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getReceivedFps(); +} + +MSVideoSize linphone_call_params_get_received_video_size (const LinphoneCallParams *params) { + MSVideoSize vsize; + LinphoneVideoDefinition *vdef = L_GET_CPP_PTR_FROM_C_OBJECT(params)->getReceivedVideoDefinition(); + if (vdef) { + vsize.width = static_cast(linphone_video_definition_get_width(vdef)); + vsize.height = static_cast(linphone_video_definition_get_height(vdef)); + } else { + vsize.width = MS_VIDEO_SIZE_UNKNOWN_W; + vsize.height = MS_VIDEO_SIZE_UNKNOWN_H; + } + return vsize; +} + +const LinphoneVideoDefinition *linphone_call_params_get_received_video_definition (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getReceivedVideoDefinition(); +} + +const char *linphone_call_params_get_record_file (const LinphoneCallParams *params) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(params)->getRecordFilePath()); +} + +const char *linphone_call_params_get_rtp_profile (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getRtpProfile(); +} + +float linphone_call_params_get_sent_framerate (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getSentFps(); +} + +MSVideoSize linphone_call_params_get_sent_video_size (const LinphoneCallParams *params) { + MSVideoSize vsize; + LinphoneVideoDefinition *vdef = L_GET_CPP_PTR_FROM_C_OBJECT(params)->getSentVideoDefinition(); + if (vdef) { + vsize.width = static_cast(linphone_video_definition_get_width(vdef)); + vsize.height = static_cast(linphone_video_definition_get_height(vdef)); + } else { + vsize.width = MS_VIDEO_SIZE_UNKNOWN_W; + vsize.height = MS_VIDEO_SIZE_UNKNOWN_H; + } + return vsize; +} + +const LinphoneVideoDefinition *linphone_call_params_get_sent_video_definition (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getSentVideoDefinition(); +} + +const char *linphone_call_params_get_session_name (const LinphoneCallParams *params) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(params)->getSessionName()); +} + +LinphonePayloadType *linphone_call_params_get_used_audio_payload_type (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedAudioPayloadType(); +} + +LinphonePayloadType *linphone_call_params_get_used_video_payload_type (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedVideoPayloadType(); +} + +LinphonePayloadType *linphone_call_params_get_used_text_payload_type (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedRealtimeTextPayloadType(); +} + +const OrtpPayloadType *linphone_call_params_get_used_audio_codec (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedAudioCodec(); +} + +void linphone_call_params_set_used_audio_codec (LinphoneCallParams *params, OrtpPayloadType *codec) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setUsedAudioCodec(codec); +} + +const OrtpPayloadType *linphone_call_params_get_used_video_codec (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedVideoCodec(); +} + +void linphone_call_params_set_used_video_codec (LinphoneCallParams *params, OrtpPayloadType *codec) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setUsedVideoCodec(codec); +} + +const OrtpPayloadType *linphone_call_params_get_used_text_codec (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getUsedRealtimeTextCodec(); +} + +void linphone_call_params_set_used_text_codec (LinphoneCallParams *params, OrtpPayloadType *codec) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setUsedRealtimeTextCodec(codec); +} + +bool_t linphone_call_params_low_bandwidth_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->lowBandwidthEnabled(); +} + +int linphone_call_params_get_audio_bandwidth_limit (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getAudioBandwidthLimit(); +} + +void linphone_call_params_set_audio_bandwidth_limit (LinphoneCallParams *params, int bandwidth) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setAudioBandwidthLimit(bandwidth); +} + +void linphone_call_params_set_media_encryption (LinphoneCallParams *params, LinphoneMediaEncryption encryption) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setMediaEncryption(encryption); +} + +void linphone_call_params_set_privacy (LinphoneCallParams *params, LinphonePrivacyMask privacy) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setPrivacy(privacy); +} + +void linphone_call_params_set_record_file (LinphoneCallParams *params, const char *path) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setRecordFilePath(L_C_TO_STRING(path)); +} + +void linphone_call_params_set_session_name (LinphoneCallParams *params, const char *name) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setSessionName(L_C_TO_STRING(name)); +} + +bool_t linphone_call_params_audio_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->audioEnabled(); +} + +bool_t linphone_call_params_realtime_text_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->realtimeTextEnabled(); +} + +bool_t linphone_call_params_video_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->videoEnabled(); +} + +LinphoneMediaDirection linphone_call_params_get_audio_direction (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getAudioDirection(); +} + +LinphoneMediaDirection linphone_call_params_get_video_direction (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getVideoDirection(); +} + +void linphone_call_params_set_audio_direction (LinphoneCallParams *params, LinphoneMediaDirection dir) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setAudioDirection(dir); +} + +void linphone_call_params_set_video_direction (LinphoneCallParams *params, LinphoneMediaDirection dir) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setVideoDirection(dir); +} + +void linphone_call_params_enable_audio_multicast (LinphoneCallParams *params, bool_t yesno) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableAudioMulticast(!!yesno); +} + +bool_t linphone_call_params_audio_multicast_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->audioMulticastEnabled(); +} + +void linphone_call_params_enable_video_multicast (LinphoneCallParams *params, bool_t yesno) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableVideoMulticast(!!yesno); +} + +bool_t linphone_call_params_video_multicast_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->videoMulticastEnabled(); +} + +bool_t linphone_call_params_real_early_media_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->earlyMediaSendingEnabled(); +} + +bool_t linphone_call_params_avpf_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->avpfEnabled(); +} + +void linphone_call_params_enable_avpf (LinphoneCallParams *params, bool_t enable) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableAvpf(!!enable); +} + +bool_t linphone_call_params_mandatory_media_encryption_enabled (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->mandatoryMediaEncryptionEnabled(); +} + +void linphone_call_params_enable_mandatory_media_encryption (LinphoneCallParams *params, bool_t value) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->enableMandatoryMediaEncryption(!!value); +} + +uint16_t linphone_call_params_get_avpf_rr_interval (const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(params)->getAvpfRrInterval(); +} + +void linphone_call_params_set_avpf_rr_interval (LinphoneCallParams *params, uint16_t value) { + L_GET_CPP_PTR_FROM_C_OBJECT(params)->setAvpfRrInterval(value); +} + +void linphone_call_params_set_sent_fps (LinphoneCallParams *params, float value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setSentFps(value); +} + +void linphone_call_params_set_received_fps (LinphoneCallParams *params, float value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setReceivedFps(value); +} + +// ============================================================================= +// Private functions. +// ============================================================================= + +bool_t linphone_call_params_get_in_conference (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getInConference(); +} + +void linphone_call_params_set_in_conference (LinphoneCallParams *params, bool_t value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setInConference(!!value); +} + +bool_t linphone_call_params_get_internal_call_update (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getInternalCallUpdate(); +} + +void linphone_call_params_set_internal_call_update (LinphoneCallParams *params, bool_t value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setInternalCallUpdate(!!value); +} + +bool_t linphone_call_params_implicit_rtcp_fb_enabled (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->implicitRtcpFbEnabled(); +} + +void linphone_call_params_enable_implicit_rtcp_fb (LinphoneCallParams *params, bool_t value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->enableImplicitRtcpFb(!!value); +} + +int linphone_call_params_get_down_bandwidth (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getDownBandwidth(); +} + +void linphone_call_params_set_down_bandwidth (LinphoneCallParams *params, int value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setDownBandwidth(value); +} + +int linphone_call_params_get_up_bandwidth (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getUpBandwidth(); +} + +void linphone_call_params_set_up_bandwidth (LinphoneCallParams *params, int value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setUpBandwidth(value); +} + +int linphone_call_params_get_down_ptime (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getDownPtime(); +} + +void linphone_call_params_set_down_ptime (LinphoneCallParams *params, int value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setDownPtime(value); +} + +int linphone_call_params_get_up_ptime (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getUpPtime(); +} + +void linphone_call_params_set_up_ptime (LinphoneCallParams *params, int value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setUpPtime(value); +} + +SalCustomHeader *linphone_call_params_get_custom_headers (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getCustomHeaders(); +} + +SalCustomSdpAttribute *linphone_call_params_get_custom_sdp_attributes (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getCustomSdpAttributes(); +} + +SalCustomSdpAttribute *linphone_call_params_get_custom_sdp_media_attributes (const LinphoneCallParams *params, LinphoneStreamType type) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getCustomSdpMediaAttributes(type); +} + +LinphoneCall *linphone_call_params_get_referer (const LinphoneCallParams *params) { + shared_ptr session = L_GET_PRIVATE_FROM_C_OBJECT(params)->getReferer(); + if (!session) + return nullptr; + for (const auto &call : session->getCore()->getCalls()) { + if (L_GET_PRIVATE(call)->getActiveSession() == session) + return L_GET_C_BACK_PTR(call); + } + return nullptr; +} + +void linphone_call_params_set_referer (LinphoneCallParams *params, LinphoneCall *referer) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setReferer(L_GET_PRIVATE_FROM_C_OBJECT(referer)->getActiveSession()); +} + +bool_t linphone_call_params_get_update_call_when_ice_completed (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getUpdateCallWhenIceCompleted(); +} + +void linphone_call_params_set_update_call_when_ice_completed (LinphoneCallParams *params, bool_t value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setUpdateCallWhenIceCompleted(!!value); +} + +void linphone_call_params_set_sent_vsize (LinphoneCallParams *params, MSVideoSize vsize) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setSentVideoDefinition(linphone_video_definition_new(static_cast(vsize.width), static_cast(vsize.height), nullptr)); +} + +void linphone_call_params_set_recv_vsize (LinphoneCallParams *params, MSVideoSize vsize) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setReceivedVideoDefinition(linphone_video_definition_new(static_cast(vsize.width), static_cast(vsize.height), nullptr)); +} + +void linphone_call_params_set_sent_video_definition (LinphoneCallParams *params, LinphoneVideoDefinition *vdef) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setSentVideoDefinition(vdef); +} + +void linphone_call_params_set_received_video_definition (LinphoneCallParams *params, LinphoneVideoDefinition *vdef) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setReceivedVideoDefinition(vdef); +} + +bool_t linphone_call_params_get_no_user_consent (const LinphoneCallParams *params) { + return L_GET_PRIVATE_FROM_C_OBJECT(params)->getNoUserConsent(); +} + +void linphone_call_params_set_no_user_consent (LinphoneCallParams *params, bool_t value) { + L_GET_PRIVATE_FROM_C_OBJECT(params)->setNoUserConsent(!!value); +} + +// ============================================================================= +// Reference and user data handling functions. +// ============================================================================= + +void *linphone_call_params_get_user_data (const LinphoneCallParams *cp) { + return L_GET_USER_DATA_FROM_C_OBJECT(cp); +} + +void linphone_call_params_set_user_data (LinphoneCallParams *cp, void *ud) { + L_SET_USER_DATA_FROM_C_OBJECT(cp, 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. +// ============================================================================= + +LinphoneCallParams *linphone_call_params_new (LinphoneCore *core) { + LinphoneCallParams *params = L_INIT(CallParams); + L_SET_CPP_PTR_FROM_C_OBJECT(params, new LinphonePrivate::MediaSessionParams()); + L_GET_CPP_PTR_FROM_C_OBJECT(params)->initDefault(L_GET_CPP_PTR_FROM_C_OBJECT(core)); + return params; +} + +LinphoneCallParams *linphone_call_params_new_for_wrapper (void) { + return _linphone_CallParams_init(); +} + +/* DEPRECATED */ +void linphone_call_params_destroy (LinphoneCallParams *cp) { + linphone_call_params_unref(cp); +} diff --git a/src/c-wrapper/api/c-call-stats.cpp b/src/c-wrapper/api/c-call-stats.cpp new file mode 100644 index 000000000..0b207c528 --- /dev/null +++ b/src/c-wrapper/api/c-call-stats.cpp @@ -0,0 +1,366 @@ +/* + * c-call-stats.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-call-stats.h" + +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +void _linphone_call_stats_clone (LinphoneCallStats *dst, const LinphoneCallStats *src); + +/** + * The LinphoneCallStats objects carries various statistic informations regarding quality of audio or video streams. + * + * To receive these informations periodically and as soon as they are computed, the application is invited to place a #LinphoneCoreCallStatsUpdatedCb callback in the LinphoneCoreVTable structure + * it passes for instantiating the LinphoneCore object (see linphone_core_new() ). + * + * At any time, the application can access last computed statistics using linphone_call_get_audio_stats() or linphone_call_get_video_stats(). +**/ +struct _LinphoneCallStats { + belle_sip_object_t base; + void *user_data; + LinphoneStreamType type; /**< Type of the stream which the stats refer to */ + jitter_stats_t jitter_stats; /**received_rtcp) { + freemsg(stats->received_rtcp); + stats->received_rtcp=NULL; + } + if (stats->sent_rtcp){ + freemsg(stats->sent_rtcp); + stats->sent_rtcp=NULL; + } +} + +void _linphone_call_stats_clone (LinphoneCallStats *dst, const LinphoneCallStats *src) { + /* + * Save the belle_sip_object_t part, copy the entire structure and restore the belle_sip_object_t part + */ + belle_sip_object_t tmp = dst->base; + memcpy(dst, src, sizeof(LinphoneCallStats)); + dst->base = tmp; + + dst->received_rtcp = NULL; + dst->sent_rtcp = NULL; +} + +void _linphone_call_stats_set_ice_state (LinphoneCallStats *stats, LinphoneIceState state) { + stats->ice_state = state; +} + +void _linphone_call_stats_set_type (LinphoneCallStats *stats, LinphoneStreamType type) { + stats->type = type; +} + +mblk_t *_linphone_call_stats_get_received_rtcp (const LinphoneCallStats *stats) { + return stats->received_rtcp; +} + +void _linphone_call_stats_set_received_rtcp (LinphoneCallStats *stats, mblk_t *m) { + stats->received_rtcp = m; +} + +mblk_t *_linphone_call_stats_get_sent_rtcp (const LinphoneCallStats *stats) { + return stats->sent_rtcp; +} + +void _linphone_call_stats_set_sent_rtcp (LinphoneCallStats *stats, mblk_t *m) { + stats->sent_rtcp = m; +} + +int _linphone_call_stats_get_updated (const LinphoneCallStats *stats) { + return stats->updated; +} + +void _linphone_call_stats_set_updated (LinphoneCallStats *stats, int updated) { + stats->updated = updated; +} + +void _linphone_call_stats_set_rtp_stats (LinphoneCallStats *stats, const rtp_stats_t *rtpStats) { + memcpy(&(stats->rtp_stats), rtpStats, sizeof(*rtpStats)); +} + +void _linphone_call_stats_set_download_bandwidth (LinphoneCallStats *stats, float bandwidth) { + stats->download_bandwidth = bandwidth; +} + +void _linphone_call_stats_set_upload_bandwidth (LinphoneCallStats *stats, float bandwidth) { + stats->upload_bandwidth = bandwidth; +} + +void _linphone_call_stats_set_rtcp_download_bandwidth (LinphoneCallStats *stats, float bandwidth) { + stats->rtcp_download_bandwidth = bandwidth; +} + +void _linphone_call_stats_set_rtcp_upload_bandwidth (LinphoneCallStats *stats, float bandwidth) { + stats->rtcp_upload_bandwidth = bandwidth; +} + +void _linphone_call_stats_set_ip_family_of_remote (LinphoneCallStats *stats, LinphoneAddressFamily family) { + stats->rtp_remote_family = family; +} + +bool_t _linphone_call_stats_rtcp_received_via_mux (const LinphoneCallStats *stats) { + return stats->rtcp_received_via_mux; +} + +// ============================================================================= +// Public functions +// ============================================================================= + +LinphoneCallStats *linphone_call_stats_ref (LinphoneCallStats* stats) { + belle_sip_object_ref(stats); + return stats; +} + +void linphone_call_stats_unref (LinphoneCallStats* stats) { + belle_sip_object_unref(stats); +} + +void *linphone_call_stats_get_user_data (const LinphoneCallStats *stats) { + return stats->user_data; +} + +void linphone_call_stats_set_user_data (LinphoneCallStats *stats, void *data) { + stats->user_data = data; +} + +void linphone_call_stats_update (LinphoneCallStats *stats, MediaStream *stream) { + PayloadType *pt; + RtpSession *session = stream->sessions.rtp_session; + const MSQualityIndicator *qi = media_stream_get_quality_indicator(stream); + if (qi) { + stats->local_late_rate=ms_quality_indicator_get_local_late_rate(qi); + stats->local_loss_rate=ms_quality_indicator_get_local_loss_rate(qi); + } + media_stream_get_local_rtp_stats(stream, &stats->rtp_stats); + pt = rtp_profile_get_payload(rtp_session_get_profile(session), rtp_session_get_send_payload_type(session)); + stats->clockrate = pt ? pt->clock_rate : 8000; +} + +/*do not change the prototype of this function, it is also used internally in linphone-daemon.*/ +void linphone_call_stats_fill (LinphoneCallStats *stats, MediaStream *ms, OrtpEvent *ev) { + OrtpEventType evt=ortp_event_get_type(ev); + OrtpEventData *evd=ortp_event_get_data(ev); + + if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { + stats->round_trip_delay = rtp_session_get_round_trip_propagation(ms->sessions.rtp_session); + if(stats->received_rtcp != NULL) + freemsg(stats->received_rtcp); + stats->received_rtcp = evd->packet; + stats->rtcp_received_via_mux = evd->info.socket_type == OrtpRTPSocket; + evd->packet = NULL; + stats->updated = LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE; + linphone_call_stats_update(stats,ms); + } else if (evt == ORTP_EVENT_RTCP_PACKET_EMITTED) { + memcpy(&stats->jitter_stats, rtp_session_get_jitter_stats(ms->sessions.rtp_session), sizeof(jitter_stats_t)); + if (stats->sent_rtcp != NULL) + freemsg(stats->sent_rtcp); + stats->sent_rtcp = evd->packet; + evd->packet = NULL; + stats->updated = LINPHONE_CALL_STATS_SENT_RTCP_UPDATE; + linphone_call_stats_update(stats,ms); + } +} + +LinphoneStreamType linphone_call_stats_get_type (const LinphoneCallStats *stats) { + return stats->type; +} + +float linphone_call_stats_get_sender_loss_rate (const LinphoneCallStats *stats) { + const report_block_t *srb = NULL; + + if (!stats || !stats->sent_rtcp) + return 0.0; + /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ + if (stats->sent_rtcp->b_cont != NULL) + msgpullup(stats->sent_rtcp, (size_t)-1); + + do{ + if (rtcp_is_SR(stats->sent_rtcp)) + srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0); + else if (rtcp_is_RR(stats->sent_rtcp)) + srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0); + if (srb) break; + }while (rtcp_next_packet(stats->sent_rtcp)); + rtcp_rewind(stats->sent_rtcp); + if (!srb) + return 0.0; + return 100.0f * (float)report_block_get_fraction_lost(srb) / 256.0f; +} + +float linphone_call_stats_get_receiver_loss_rate (const LinphoneCallStats *stats) { + const report_block_t *rrb = NULL; + + if (!stats || !stats->received_rtcp) + return 0.0; + /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ + if (stats->received_rtcp->b_cont != NULL) + msgpullup(stats->received_rtcp, (size_t)-1); + + do{ + if (rtcp_is_RR(stats->received_rtcp)) + rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0); + else if (rtcp_is_SR(stats->received_rtcp)) + rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0); + if (rrb) break; + }while (rtcp_next_packet(stats->received_rtcp)); + rtcp_rewind(stats->received_rtcp); + if (!rrb) + return 0.0; + return 100.0f * (float)report_block_get_fraction_lost(rrb) / 256.0f; +} + +float linphone_call_stats_get_local_loss_rate (const LinphoneCallStats *stats) { + return stats->local_loss_rate; +} + +float linphone_call_stats_get_local_late_rate (const LinphoneCallStats *stats) { + return stats->local_late_rate; +} + +float linphone_call_stats_get_sender_interarrival_jitter (const LinphoneCallStats *stats) { + const report_block_t *srb = NULL; + + if (!stats || !stats->sent_rtcp) + return 0.0; + /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ + if (stats->sent_rtcp->b_cont != NULL) + msgpullup(stats->sent_rtcp, (size_t)-1); + if (rtcp_is_SR(stats->sent_rtcp)) + srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0); + else if (rtcp_is_RR(stats->sent_rtcp)) + srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0); + if (!srb) + return 0.0; + if (stats->clockrate == 0) + return 0.0; + return (float)report_block_get_interarrival_jitter(srb) / (float)stats->clockrate; +} + +float linphone_call_stats_get_receiver_interarrival_jitter (const LinphoneCallStats *stats) { + const report_block_t *rrb = NULL; + + if (!stats || !stats->received_rtcp) + return 0.0; + /* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */ + if (stats->received_rtcp->b_cont != NULL) + msgpullup(stats->received_rtcp, (size_t)-1); + if (rtcp_is_SR(stats->received_rtcp)) + rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0); + else if (rtcp_is_RR(stats->received_rtcp)) + rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0); + if (!rrb) + return 0.0; + if (stats->clockrate == 0) + return 0.0; + return (float)report_block_get_interarrival_jitter(rrb) / (float)stats->clockrate; +} + +const rtp_stats_t *linphone_call_stats_get_rtp_stats (const LinphoneCallStats *stats) { + return &stats->rtp_stats; +} + +uint64_t linphone_call_stats_get_late_packets_cumulative_number (const LinphoneCallStats *stats) { + return linphone_call_stats_get_rtp_stats(stats)->outoftime; +} + +float linphone_call_stats_get_download_bandwidth (const LinphoneCallStats *stats) { + return stats->download_bandwidth; +} + +float linphone_call_stats_get_upload_bandwidth (const LinphoneCallStats *stats) { + return stats->upload_bandwidth; +} + +float linphone_call_stats_get_rtcp_download_bandwidth (const LinphoneCallStats *stats) { + return stats->rtcp_download_bandwidth; +} + +float linphone_call_stats_get_rtcp_upload_bandwidth (const LinphoneCallStats *stats) { + return stats->rtcp_upload_bandwidth; +} + +LinphoneIceState linphone_call_stats_get_ice_state (const LinphoneCallStats *stats) { + return stats->ice_state; +} + +LinphoneUpnpState linphone_call_stats_get_upnp_state (const LinphoneCallStats *stats) { + return stats->upnp_state; +} + +LinphoneAddressFamily linphone_call_stats_get_ip_family_of_remote (const LinphoneCallStats *stats) { + return (LinphoneAddressFamily)stats->rtp_remote_family; +} + +float linphone_call_stats_get_jitter_buffer_size_ms (const LinphoneCallStats *stats) { + return stats->jitter_stats.jitter_buffer_size_ms; +} + +float linphone_call_stats_get_round_trip_delay (const LinphoneCallStats *stats) { + return stats->round_trip_delay; +} + +float linphone_call_stats_get_estimated_download_bandwidth(const LinphoneCallStats *stats) { + return stats->estimated_download_bandwidth; +} + +void linphone_call_stats_set_estimated_download_bandwidth(LinphoneCallStats *stats, float estimated_value) { + stats->estimated_download_bandwidth = estimated_value; +} diff --git a/src/c-wrapper/api/c-call.cpp b/src/c-wrapper/api/c-call.cpp new file mode 100644 index 000000000..724c38066 --- /dev/null +++ b/src/c-wrapper/api/c-call.cpp @@ -0,0 +1,685 @@ +/* + * c-call.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-call.h" +#include "linphone/api/c-call-cbs.h" +#include "linphone/api/c-call-stats.h" +#include "linphone/wrapper_utils.h" + +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "call/call.h" +#include "call/local-conference-call.h" +#include "call/remote-conference-call.h" +#include "chat/chat-room/real-time-text-chat-room.h" +#include "conference/params/media-session-params-p.h" +#include "core/core-p.h" + +// ============================================================================= + +using namespace std; + +static void _linphone_call_constructor (LinphoneCall *call); +static void _linphone_call_destructor (LinphoneCall *call); + +L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(Call, + _linphone_call_constructor, _linphone_call_destructor, + bctbx_list_t *callbacks; /* A list of LinphoneCallCbs object */ + LinphoneCallCbs *currentCbs; /* The current LinphoneCallCbs object used to call a callback */ + char *authenticationTokenCache; + mutable char *referToCache; + char *remoteContactCache; + char *remoteUserAgentCache; + mutable char *toHeaderCache; + /* TODO: all the fields need to be removed */ + LinphoneConference *confRef; /**> Point on the associated conference if this call is part of a conference. NULL instead. */ + MSAudioEndpoint *endpoint; /*used for conferencing*/ + LinphoneChatRoom *chat_room; +) + +static void _linphone_call_constructor (LinphoneCall *call) {} + +static void _linphone_call_destructor (LinphoneCall *call) { + if (call->referToCache) + bctbx_free(call->referToCache); + if (call->remoteContactCache) + bctbx_free(call->remoteContactCache); + if (call->remoteUserAgentCache) + bctbx_free(call->remoteUserAgentCache); + if (call->toHeaderCache) + bctbx_free(call->toHeaderCache); + bctbx_list_free_with_data(call->callbacks, (bctbx_list_free_func)linphone_call_cbs_unref); +} + +// ============================================================================= +// TODO: To remove! +// ============================================================================= + +void linphone_call_init_media_streams (LinphoneCall *call) { + L_GET_PRIVATE_FROM_C_OBJECT(call)->initializeMediaStreams(); +} + +/*This function is not static because used internally in linphone-daemon project*/ +void _post_configure_audio_stream (AudioStream *st, LinphoneCore *lc, bool_t muted) { + L_GET_PRIVATE_FROM_C_OBJECT(lc)->postConfigureAudioStream(st, !!muted); +} + +void linphone_call_stop_media_streams (LinphoneCall *call) { + L_GET_PRIVATE_FROM_C_OBJECT(call)->stopMediaStreams(); +} + +/* Internal version that does not play tone indication*/ +int _linphone_call_pause (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->pause(); +} + + +// ============================================================================= +// Private functions. +// ============================================================================= + +void _linphone_call_set_conf_ref (LinphoneCall *call, LinphoneConference *ref) { + call->confRef = ref; +} + +MSAudioEndpoint *_linphone_call_get_endpoint (const LinphoneCall *call) { + return call->endpoint; +} + +void _linphone_call_set_endpoint (LinphoneCall *call, MSAudioEndpoint *endpoint) { + call->endpoint = endpoint; +} + +MediaStream *linphone_call_get_stream (LinphoneCall *call, LinphoneStreamType type) { + return L_GET_PRIVATE_FROM_C_OBJECT(call)->getMediaStream(type); +} + +LinphonePrivate::SalCallOp * linphone_call_get_op (const LinphoneCall *call) { + return L_GET_PRIVATE_FROM_C_OBJECT(call)->getOp(); +} + +LinphoneProxyConfig * linphone_call_get_dest_proxy (const LinphoneCall *call) { + return L_GET_PRIVATE_FROM_C_OBJECT(call)->getDestProxy(); +} + +LinphoneCallLog * linphone_call_get_log (const LinphoneCall *call) { + return linphone_call_get_call_log(call); +} + +IceSession * linphone_call_get_ice_session (const LinphoneCall *call) { + return L_GET_PRIVATE_FROM_C_OBJECT(call)->getIceSession(); +} + +bool_t linphone_call_get_audio_muted (const LinphoneCall *call) { + return L_GET_PRIVATE_FROM_C_OBJECT(call)->getAudioMuted(); +} + +void linphone_call_set_audio_muted (LinphoneCall *call, bool_t value) { + L_GET_PRIVATE_FROM_C_OBJECT(call)->setAudioMuted(!!value); +} + +bool_t linphone_call_get_all_muted (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getAllMuted(); +} + +#define NOTIFY_IF_EXIST(cbName, functionName, ...) \ + for (bctbx_list_t *it = call->callbacks; it; it = bctbx_list_next(it)) { \ + call->currentCbs = reinterpret_cast(bctbx_list_get_data(it)); \ + LinphoneCallCbs ## cbName ## Cb cb = linphone_call_cbs_get_ ## functionName (call->currentCbs); \ + if (cb) \ + cb(__VA_ARGS__); \ + } + +void linphone_call_notify_state_changed (LinphoneCall *call, LinphoneCallState cstate, const char *message) { + NOTIFY_IF_EXIST(StateChanged, state_changed, call, cstate, message) + linphone_core_notify_call_state_changed(linphone_call_get_core(call), call, cstate, message); +} + +void linphone_call_notify_dtmf_received (LinphoneCall *call, int dtmf) { + NOTIFY_IF_EXIST(DtmfReceived, dtmf_received, call, dtmf) + linphone_core_notify_dtmf_received(linphone_call_get_core(call), call, dtmf); +} + +void linphone_call_notify_encryption_changed (LinphoneCall *call, bool_t on, const char *authentication_token) { + NOTIFY_IF_EXIST(EncryptionChanged, encryption_changed, call, on, authentication_token) + linphone_core_notify_call_encryption_changed(linphone_call_get_core(call), call, on, authentication_token); +} + +void linphone_call_notify_transfer_state_changed (LinphoneCall *call, LinphoneCallState cstate) { + NOTIFY_IF_EXIST(TransferStateChanged, transfer_state_changed, call, cstate) + linphone_core_notify_transfer_state_changed(linphone_call_get_core(call), call, cstate); +} + +void linphone_call_notify_stats_updated (LinphoneCall *call, const LinphoneCallStats *stats) { + NOTIFY_IF_EXIST(StatsUpdated, stats_updated, call, stats) + linphone_core_notify_call_stats_updated(linphone_call_get_core(call), call, stats); +} + +void linphone_call_notify_info_message_received (LinphoneCall *call, const LinphoneInfoMessage *msg) { + NOTIFY_IF_EXIST(InfoMessageReceived, info_message_received, call, msg) + linphone_core_notify_info_received(linphone_call_get_core(call), call, msg); +} + +void linphone_call_notify_ack_processing (LinphoneCall *call, LinphoneHeaders *msg, bool_t is_received) { + NOTIFY_IF_EXIST(AckProcessing, ack_processing, call, msg, is_received) +} + +void linphone_call_notify_tmmbr_received (LinphoneCall *call, int stream_index, int tmmbr) { + NOTIFY_IF_EXIST(TmmbrReceived, tmmbr_received, call, stream_index, tmmbr) +} + +void linphone_call_notify_snapshot_taken(LinphoneCall *call, const char *file_path) { + NOTIFY_IF_EXIST(SnapshotTaken, snapshot_taken, call, file_path) +} + +void linphone_call_notify_next_video_frame_decoded(LinphoneCall *call) { + NOTIFY_IF_EXIST(NextVideoFrameDecoded, next_video_frame_decoded, call) +} + +// ============================================================================= +// Public functions. +// ============================================================================= + +LinphoneCore *linphone_call_get_core (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getCore()->getCCore(); +} + +LinphoneCallState linphone_call_get_state (const LinphoneCall *call) { + return static_cast(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getState()); +} + +bool_t linphone_call_asked_to_autoanswer (LinphoneCall *call) { + //return TRUE if the unique(for the moment) incoming call asked to be autoanswered + if (call) + return linphone_call_get_op(call)->autoAnswerAsked(); + return FALSE; +} + +const LinphoneAddress *linphone_call_get_remote_address (const LinphoneCall *call) { + return L_GET_C_BACK_PTR(&L_GET_CPP_PTR_FROM_C_OBJECT(call)->getRemoteAddress()); +} + +const LinphoneAddress *linphone_call_get_to_address (const LinphoneCall *call) { + return L_GET_C_BACK_PTR(&L_GET_CPP_PTR_FROM_C_OBJECT(call)->getToAddress()); +} + +const char *linphone_call_get_to_header (const LinphoneCall *call, const char *name) { + string header = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getToHeader(name); + if (header.empty()) + return nullptr; + if (call->toHeaderCache) + bctbx_free(call->toHeaderCache); + call->toHeaderCache = bctbx_strdup(header.c_str()); + return call->toHeaderCache; +} + +char *linphone_call_get_remote_address_as_string (const LinphoneCall *call) { + return ms_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getRemoteAddress().asString().c_str()); +} + +const LinphoneAddress *linphone_call_get_diversion_address (const LinphoneCall *call) { + const LinphonePrivate::Address &diversionAddress = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getDiversionAddress(); + return diversionAddress.isValid() ? L_GET_C_BACK_PTR(&diversionAddress) : nullptr; +} + +LinphoneCallDir linphone_call_get_dir (const LinphoneCall *call) { + return linphone_call_log_get_dir(linphone_call_get_log(call)); +} + +LinphoneCallLog *linphone_call_get_call_log (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getLog(); +} + +const char *linphone_call_get_refer_to (const LinphoneCall *call) { + string referTo = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getReferTo(); + if (referTo.empty()) + return nullptr; + if (call->referToCache) + bctbx_free(call->referToCache); + call->referToCache = bctbx_strdup(referTo.c_str()); + return call->referToCache; +} + +bool_t linphone_call_has_transfer_pending (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->hasTransferPending(); +} + +LinphoneCall *linphone_call_get_transferer_call (const LinphoneCall *call) { + shared_ptr referer = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getReferer(); + if (!referer) + return nullptr; + return L_GET_C_BACK_PTR(referer); +} + +LinphoneCall *linphone_call_get_transfer_target_call (const LinphoneCall *call) { + shared_ptr transferTarget = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getTransferTarget(); + if (!transferTarget) + return nullptr; + return L_GET_C_BACK_PTR(transferTarget); +} + +LinphoneCall *linphone_call_get_replaced_call (LinphoneCall *call) { + shared_ptr replacedCall = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getReplacedCall(); + if (!replacedCall) + return nullptr; + return L_GET_C_BACK_PTR(replacedCall); +} + +int linphone_call_get_duration (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getDuration(); +} + +const LinphoneCallParams *linphone_call_get_current_params (LinphoneCall *call) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getCurrentParams()); +} + +const LinphoneCallParams *linphone_call_get_remote_params(LinphoneCall *call) { + const LinphonePrivate::MediaSessionParams *remoteParams = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getRemoteParams(); + return remoteParams ? L_GET_C_BACK_PTR(remoteParams) : nullptr; +} + +void linphone_call_enable_camera (LinphoneCall *call, bool_t enable) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->enableCamera(!!enable); +} + +bool_t linphone_call_camera_enabled (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->cameraEnabled(); +} + +LinphoneStatus linphone_call_take_video_snapshot (LinphoneCall *call, const char *file) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->takeVideoSnapshot(L_C_TO_STRING(file)); +} + +LinphoneStatus linphone_call_take_preview_snapshot (LinphoneCall *call, const char *file) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->takePreviewSnapshot(L_C_TO_STRING(file)); +} + +LinphoneReason linphone_call_get_reason (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getReason(); +} + +const LinphoneErrorInfo *linphone_call_get_error_info (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getErrorInfo(); +} + +const char *linphone_call_get_remote_user_agent (LinphoneCall *call) { + string ua = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getRemoteUserAgent(); + if (ua.empty()) + return nullptr; + if (call->remoteUserAgentCache) + bctbx_free(call->remoteUserAgentCache); + call->remoteUserAgentCache = bctbx_strdup(ua.c_str()); + return call->remoteUserAgentCache; +} + +const char * linphone_call_get_remote_contact (LinphoneCall *call) { + string contact = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getRemoteContact(); + if (contact.empty()) + return nullptr; + if (call->remoteContactCache) + bctbx_free(call->remoteContactCache); + call->remoteContactCache = bctbx_strdup(contact.c_str()); + return call->remoteContactCache; +} + +const char *linphone_call_get_authentication_token (LinphoneCall *call) { + string token = L_GET_CPP_PTR_FROM_C_OBJECT(call)->getAuthenticationToken(); + if (token.empty()) + return nullptr; + if (call->authenticationTokenCache) + bctbx_free(call->authenticationTokenCache); + call->authenticationTokenCache = bctbx_strdup(token.c_str()); + return call->authenticationTokenCache; +} + +bool_t linphone_call_get_authentication_token_verified (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getAuthenticationTokenVerified(); +} + +void linphone_call_set_authentication_token_verified (LinphoneCall *call, bool_t verified) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setAuthenticationTokenVerified(!!verified); +} + +void linphone_call_send_vfu_request (LinphoneCall *call) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->sendVfuRequest(); +} + +void linphone_call_set_next_video_frame_decoded_callback (LinphoneCall *call, LinphoneCallCbFunc cb, void *ud) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setNextVideoFrameDecodedCallback(cb, ud); +} + +void linphone_call_request_notify_next_video_frame_decoded(LinphoneCall *call){ + L_GET_CPP_PTR_FROM_C_OBJECT(call)->requestNotifyNextVideoFrameDecoded(); +} + +LinphoneCallState linphone_call_get_transfer_state (LinphoneCall *call) { + return static_cast(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getTransferState()); +} + +void linphone_call_zoom_video (LinphoneCall* call, float zoom_factor, float* cx, float* cy) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->zoomVideo(zoom_factor, cx, cy); +} + +void linphone_call_zoom (LinphoneCall *call, float zoom_factor, float cx, float cy) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->zoomVideo(zoom_factor, cx, cy); +} + +LinphoneStatus linphone_call_send_dtmf (LinphoneCall *call, char dtmf) { + if (!call) { + ms_warning("linphone_call_send_dtmf(): invalid call, canceling DTMF"); + return -1; + } + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->sendDtmf(dtmf); +} + +LinphoneStatus linphone_call_send_dtmfs (LinphoneCall *call, const char *dtmfs) { + if (!call) { + ms_warning("linphone_call_send_dtmfs(): invalid call, canceling DTMF sequence"); + return -1; + } + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->sendDtmfs(dtmfs); +} + +void linphone_call_cancel_dtmfs (LinphoneCall *call) { + if (!call) + return; + L_GET_CPP_PTR_FROM_C_OBJECT(call)->cancelDtmfs(); +} + +bool_t linphone_call_is_in_conference (const LinphoneCall *call) { + return !!L_GET_CPP_PTR_FROM_C_OBJECT(call)->isInConference(); +} + +LinphoneConference *linphone_call_get_conference (const LinphoneCall *call) { + return call->confRef; +} + +void linphone_call_set_audio_route (LinphoneCall *call, LinphoneAudioRoute route) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setAudioRoute(route); +} + +int linphone_call_get_stream_count (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getStreamCount(); +} + +MSFormatType linphone_call_get_stream_type (const LinphoneCall *call, int stream_index) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getStreamType(stream_index); +} + +RtpTransport *linphone_call_get_meta_rtp_transport (const LinphoneCall *call, int stream_index) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getMetaRtpTransport(stream_index); +} + +RtpTransport *linphone_call_get_meta_rtcp_transport (const LinphoneCall *call, int stream_index) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getMetaRtcpTransport(stream_index); +} + +LinphoneStatus linphone_call_pause (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->pause(); +} + +LinphoneStatus linphone_call_resume (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->resume(); +} + +LinphoneStatus linphone_call_terminate (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->terminate(); +} + +LinphoneStatus linphone_call_terminate_with_error_info (LinphoneCall *call , const LinphoneErrorInfo *ei) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->terminate(ei); +} + +LinphoneStatus linphone_call_redirect (LinphoneCall *call, const char *redirect_uri) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->redirect(redirect_uri); +} + +LinphoneStatus linphone_call_decline (LinphoneCall *call, LinphoneReason reason) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->decline(reason); +} + +LinphoneStatus linphone_call_decline_with_error_info (LinphoneCall *call, const LinphoneErrorInfo *ei) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->decline(ei); +} + +LinphoneStatus linphone_call_accept (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->accept(nullptr); +} + +LinphoneStatus linphone_call_accept_with_params (LinphoneCall *call, const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->accept(params ? L_GET_CPP_PTR_FROM_C_OBJECT(params) : nullptr); +} + +LinphoneStatus linphone_call_accept_early_media (LinphoneCall* call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->acceptEarlyMedia(); +} + +LinphoneStatus linphone_call_accept_early_media_with_params (LinphoneCall *call, const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->acceptEarlyMedia(params ? L_GET_CPP_PTR_FROM_C_OBJECT(params) : nullptr); +} + +LinphoneStatus linphone_call_update (LinphoneCall *call, const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->update(params ? L_GET_CPP_PTR_FROM_C_OBJECT(params) : nullptr); +} + +LinphoneStatus linphone_call_defer_update (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->deferUpdate(); +} + +LinphoneStatus linphone_call_accept_update (LinphoneCall *call, const LinphoneCallParams *params) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->acceptUpdate(params ? L_GET_CPP_PTR_FROM_C_OBJECT(params) : nullptr); +} + +LinphoneStatus linphone_call_transfer (LinphoneCall *call, const char *referTo) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->transfer(referTo); +} + +LinphoneStatus linphone_call_transfer_to_another (LinphoneCall *call, LinphoneCall *dest) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->transfer(L_GET_CPP_PTR_FROM_C_OBJECT(dest)); +} + +void *linphone_call_get_native_video_window_id (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getNativeVideoWindowId(); +} + +void linphone_call_set_native_video_window_id (LinphoneCall *call, void *id) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setNativeVideoWindowId(id); +} + +void linphone_call_enable_echo_cancellation (LinphoneCall *call, bool_t enable) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->enableEchoCancellation(!!enable); +} + +bool_t linphone_call_echo_cancellation_enabled (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->echoCancellationEnabled(); +} + +void linphone_call_enable_echo_limiter (LinphoneCall *call, bool_t val) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->enableEchoLimiter(!!val); +} + +bool_t linphone_call_echo_limiter_enabled (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->echoLimiterEnabled(); +} + +LinphoneChatRoom *linphone_call_get_chat_room (LinphoneCall *call) { + shared_ptr acr = L_GET_PRIVATE_FROM_C_OBJECT(call)->getChatRoom(); + if (acr) + return L_GET_C_BACK_PTR(acr); + return nullptr; +} + +float linphone_call_get_play_volume (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getPlayVolume(); +} + +float linphone_call_get_record_volume (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getRecordVolume(); +} + +float linphone_call_get_speaker_volume_gain (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getSpeakerVolumeGain(); +} + +void linphone_call_set_speaker_volume_gain( LinphoneCall *call, float volume) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setSpeakerVolumeGain(volume); +} + +float linphone_call_get_microphone_volume_gain (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getMicrophoneVolumeGain(); +} + +void linphone_call_set_microphone_volume_gain (LinphoneCall *call, float volume) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setMicrophoneVolumeGain(volume); +} + +float linphone_call_get_current_quality (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getCurrentQuality(); +} + +float linphone_call_get_average_quality (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getAverageQuality(); +} + +void linphone_call_start_recording (LinphoneCall *call) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->startRecording(); +} + +void linphone_call_stop_recording (LinphoneCall *call) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->stopRecording(); +} + +LinphonePlayer *linphone_call_get_player (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getPlayer(); +} + +bool_t linphone_call_media_in_progress (const LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->mediaInProgress(); +} + +void linphone_call_ogl_render (const LinphoneCall *call) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->oglRender(); +} + +LinphoneStatus linphone_call_send_info_message (LinphoneCall *call, const LinphoneInfoMessage *info) { + SalBodyHandler *body_handler = sal_body_handler_from_content(linphone_info_message_get_content(info)); + linphone_call_get_op(call)->setSentCustomHeaders(linphone_info_message_get_headers(info)); + return linphone_call_get_op(call)->sendInfo(body_handler); +} + +LinphoneCallStats *linphone_call_get_stats (LinphoneCall *call, LinphoneStreamType type) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getStats(type); +} + +LinphoneCallStats *linphone_call_get_audio_stats (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getAudioStats(); +} + +LinphoneCallStats *linphone_call_get_video_stats (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getVideoStats(); +} + +LinphoneCallStats *linphone_call_get_text_stats (LinphoneCall *call) { + return L_GET_CPP_PTR_FROM_C_OBJECT(call)->getTextStats(); +} + +void linphone_call_add_callbacks (LinphoneCall *call, LinphoneCallCbs *cbs) { + call->callbacks = bctbx_list_append(call->callbacks, linphone_call_cbs_ref(cbs)); +} + +void linphone_call_remove_callbacks (LinphoneCall *call, LinphoneCallCbs *cbs) { + call->callbacks = bctbx_list_remove(call->callbacks, cbs); + linphone_call_cbs_unref(cbs); +} + +LinphoneCallCbs *linphone_call_get_current_callbacks (const LinphoneCall *call) { + return call->currentCbs; +} + +const bctbx_list_t *linphone_call_get_callbacks_list(const LinphoneCall *call) { + return call->callbacks; +} + +void linphone_call_set_params (LinphoneCall *call, const LinphoneCallParams *params) { + L_GET_CPP_PTR_FROM_C_OBJECT(call)->setParams(L_GET_CPP_PTR_FROM_C_OBJECT(params)); +} + +const LinphoneCallParams *linphone_call_get_params (LinphoneCall *call) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(call)->getParams()); +} + +// ============================================================================= +// Reference and user data handling functions. +// ============================================================================= + +LinphoneCall *linphone_call_ref (LinphoneCall *call) { + belle_sip_object_ref(call); + return call; +} + +void linphone_call_unref (LinphoneCall *call) { + belle_sip_object_unref(call); +} + +void *linphone_call_get_user_data (const LinphoneCall *call) { + return L_GET_USER_DATA_FROM_C_OBJECT(call); +} + +void linphone_call_set_user_data (LinphoneCall *call, void *ud) { + L_SET_USER_DATA_FROM_C_OBJECT(call, ud); +} + +// ============================================================================= +// Constructor and destructor functions. +// ============================================================================= + +LinphoneCall *linphone_call_new_outgoing (LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg) { + LinphoneCall *lcall = L_INIT(Call); + shared_ptr call; + string confType = lp_config_get_string(linphone_core_get_config(lc), "misc", "conference_type", "local"); + if (confType == "remote") { + call = make_shared(L_GET_CPP_PTR_FROM_C_OBJECT(lc), LinphoneCallOutgoing, + *L_GET_CPP_PTR_FROM_C_OBJECT(from), *L_GET_CPP_PTR_FROM_C_OBJECT(to), + cfg, nullptr, L_GET_CPP_PTR_FROM_C_OBJECT(params)); + } else { + call = make_shared(L_GET_CPP_PTR_FROM_C_OBJECT(lc), LinphoneCallOutgoing, + *L_GET_CPP_PTR_FROM_C_OBJECT(from), *L_GET_CPP_PTR_FROM_C_OBJECT(to), + cfg, nullptr, L_GET_CPP_PTR_FROM_C_OBJECT(params)); + } + L_SET_CPP_PTR_FROM_C_OBJECT(lcall, call); + return lcall; +} + +LinphoneCall *linphone_call_new_incoming (LinphoneCore *lc, const LinphoneAddress *from, const LinphoneAddress *to, LinphonePrivate::SalCallOp *op) { + LinphoneCall *lcall = L_INIT(Call); + shared_ptr call; + string confType = lp_config_get_string(linphone_core_get_config(lc), "misc", "conference_type", "local"); + if (confType == "remote") { + call = make_shared(L_GET_CPP_PTR_FROM_C_OBJECT(lc), LinphoneCallIncoming, + *L_GET_CPP_PTR_FROM_C_OBJECT(from), *L_GET_CPP_PTR_FROM_C_OBJECT(to), + nullptr, op, nullptr); + } else { + call = make_shared(L_GET_CPP_PTR_FROM_C_OBJECT(lc), LinphoneCallIncoming, + *L_GET_CPP_PTR_FROM_C_OBJECT(from), *L_GET_CPP_PTR_FROM_C_OBJECT(to), + nullptr, op, nullptr); + } + L_SET_CPP_PTR_FROM_C_OBJECT(lcall, call); + L_GET_PRIVATE_FROM_C_OBJECT(lcall)->initiateIncoming(); + return lcall; +} diff --git a/src/c-wrapper/api/c-chat-message-cbs.cpp b/src/c-wrapper/api/c-chat-message-cbs.cpp new file mode 100644 index 000000000..aced7c8bb --- /dev/null +++ b/src/c-wrapper/api/c-chat-message-cbs.cpp @@ -0,0 +1,133 @@ +/* + * c-chat-message-cbs.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-chat-message-cbs.h" + +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +struct _LinphoneChatMessageCbs { + belle_sip_object_t base; + void *userData; + LinphoneChatMessageCbsMsgStateChangedCb msg_state_changed; + LinphoneChatMessageCbsFileTransferRecvCb file_transfer_recv; + LinphoneChatMessageCbsFileTransferSendCb file_transfer_send; + LinphoneChatMessageCbsFileTransferProgressIndicationCb file_transfer_progress_indication; + LinphoneChatMessageCbsParticipantImdnStateChangedCb participant_imdn_state_changed; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatMessageCbs); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatMessageCbs); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatMessageCbs, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +// ============================================================================= + +LinphoneChatMessageCbs * linphone_chat_message_cbs_new (void) { + return belle_sip_object_new(LinphoneChatMessageCbs); +} + +LinphoneChatMessageCbs * linphone_chat_message_cbs_ref (LinphoneChatMessageCbs *cbs) { + belle_sip_object_ref(cbs); + return cbs; +} + +void linphone_chat_message_cbs_unref (LinphoneChatMessageCbs *cbs) { + belle_sip_object_unref(cbs); +} + +void * linphone_chat_message_cbs_get_user_data (const LinphoneChatMessageCbs *cbs) { + return cbs->userData; +} + +void linphone_chat_message_cbs_set_user_data (LinphoneChatMessageCbs *cbs, void *ud) { + cbs->userData = ud; +} + +LinphoneChatMessageCbsMsgStateChangedCb linphone_chat_message_cbs_get_msg_state_changed ( + const LinphoneChatMessageCbs *cbs +) { + return cbs->msg_state_changed; +} + +void linphone_chat_message_cbs_set_msg_state_changed ( + LinphoneChatMessageCbs *cbs, + LinphoneChatMessageCbsMsgStateChangedCb cb +) { + cbs->msg_state_changed = cb; +} + +LinphoneChatMessageCbsFileTransferRecvCb linphone_chat_message_cbs_get_file_transfer_recv ( + const LinphoneChatMessageCbs *cbs +) { + return cbs->file_transfer_recv; +} + +void linphone_chat_message_cbs_set_file_transfer_recv ( + LinphoneChatMessageCbs *cbs, + LinphoneChatMessageCbsFileTransferRecvCb cb +) { + cbs->file_transfer_recv = cb; +} + +LinphoneChatMessageCbsFileTransferSendCb linphone_chat_message_cbs_get_file_transfer_send ( + const LinphoneChatMessageCbs *cbs +) { + return cbs->file_transfer_send; +} + +void linphone_chat_message_cbs_set_file_transfer_send ( + LinphoneChatMessageCbs *cbs, + LinphoneChatMessageCbsFileTransferSendCb cb +) { + cbs->file_transfer_send = cb; +} + +LinphoneChatMessageCbsFileTransferProgressIndicationCb linphone_chat_message_cbs_get_file_transfer_progress_indication ( + const LinphoneChatMessageCbs *cbs +) { + return cbs->file_transfer_progress_indication; +} + +void linphone_chat_message_cbs_set_file_transfer_progress_indication ( + LinphoneChatMessageCbs *cbs, + LinphoneChatMessageCbsFileTransferProgressIndicationCb cb +) { + cbs->file_transfer_progress_indication = cb; +} + +LinphoneChatMessageCbsParticipantImdnStateChangedCb linphone_chat_message_cbs_get_participant_imdn_state_changed ( + const LinphoneChatMessageCbs *cbs +) { + return cbs->participant_imdn_state_changed; +} + +void linphone_chat_message_cbs_set_participant_imdn_state_changed ( + LinphoneChatMessageCbs *cbs, + LinphoneChatMessageCbsParticipantImdnStateChangedCb cb +) { + cbs->participant_imdn_state_changed = cb; +} diff --git a/src/c-wrapper/api/c-chat-message.cpp b/src/c-wrapper/api/c-chat-message.cpp new file mode 100644 index 000000000..c2582bc11 --- /dev/null +++ b/src/c-wrapper/api/c-chat-message.cpp @@ -0,0 +1,363 @@ +/* + * c-chat-message.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-chat-message.h" +#include "linphone/api/c-content.h" +#include "linphone/utils/utils.h" +#include "linphone/wrapper_utils.h" + +#include "ortp/b64.h" + +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "chat/chat-room/real-time-text-chat-room-p.h" +#include "chat/notification/imdn.h" +#include "content/content-type.h" +#include "content/content.h" +#include "conference/participant.h" +#include "conference/participant-imdn-state.h" + +// ============================================================================= + +using namespace std; + +static void _linphone_chat_message_constructor (LinphoneChatMessage *msg); +static void _linphone_chat_message_destructor (LinphoneChatMessage *msg); + +L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(ChatMessage, + _linphone_chat_message_constructor, + _linphone_chat_message_destructor, + + LinphoneChatMessageCbs *cbs; + LinphoneAddress *from; // cache for shared_ptr
+ LinphoneAddress *to; // cache for shared_ptr
+ LinphoneChatMessageStateChangedCb message_state_changed_cb; + void *message_state_changed_user_data; + + struct Cache { + string contentType; + string textContentBody; + string customHeaderValue; + } mutable cache; +) + +static void _linphone_chat_message_constructor (LinphoneChatMessage *msg) { + msg->cbs = linphone_chat_message_cbs_new(); + new(&msg->cache) LinphoneChatMessage::Cache(); +} + +static void _linphone_chat_message_destructor (LinphoneChatMessage *msg) { + linphone_chat_message_cbs_unref(msg->cbs); + msg->cbs = nullptr; + if (msg->from) + linphone_address_unref(msg->from); + if (msg->to) + linphone_address_unref(msg->to); + + msg->cache.~Cache(); +} + +// ============================================================================= +// Reference and user data handling functions. +// ============================================================================= + +LinphoneChatMessage *linphone_chat_message_ref (LinphoneChatMessage *msg) { + belle_sip_object_ref(msg); + return msg; +} + +void linphone_chat_message_unref (LinphoneChatMessage *msg) { + belle_sip_object_unref(msg); +} + +void * linphone_chat_message_get_user_data (const LinphoneChatMessage *msg) { + return L_GET_USER_DATA_FROM_C_OBJECT(msg); +} + +void linphone_chat_message_set_user_data (LinphoneChatMessage *msg, void *ud) { + L_SET_USER_DATA_FROM_C_OBJECT(msg, ud); +} + +LinphoneChatMessageCbs *linphone_chat_message_get_callbacks(const LinphoneChatMessage *msg) { + return msg->cbs; +} + +// ============================================================================= +// Getter and setters +// ============================================================================= + +LinphoneChatRoom *linphone_chat_message_get_chat_room (const LinphoneChatMessage *msg) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getChatRoom()); +} + +const char *linphone_chat_message_get_external_body_url (const LinphoneChatMessage *msg) { + return L_STRING_TO_C(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getExternalBodyUrl()); +} + +void linphone_chat_message_set_external_body_url (LinphoneChatMessage *msg, const char *url) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->setExternalBodyUrl(L_C_TO_STRING(url)); +} + +time_t linphone_chat_message_get_time (const LinphoneChatMessage *msg) { + return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getTime(); +} + +bool_t linphone_chat_message_is_secured (LinphoneChatMessage *msg) { + return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->isSecured(); +} + +bool_t linphone_chat_message_is_outgoing (LinphoneChatMessage *msg) { + return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getDirection() == LinphonePrivate::ChatMessage::Direction::Outgoing; +} + +LinphoneChatMessageState linphone_chat_message_get_state (const LinphoneChatMessage *msg) { + return ((LinphoneChatMessageState)L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getState()); +} + +const char* linphone_chat_message_get_message_id (const LinphoneChatMessage *msg) { + return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getImdnMessageId().c_str(); +} + +bool_t linphone_chat_message_is_read (LinphoneChatMessage *msg) { + return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->isRead(); +} + +const char *linphone_chat_message_get_appdata (const LinphoneChatMessage *msg) { + return L_STRING_TO_C(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getAppdata()); +} + +void linphone_chat_message_set_appdata (LinphoneChatMessage *msg, const char *data) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->setAppdata(L_C_TO_STRING(data)); +} + +const LinphoneAddress *linphone_chat_message_get_from_address (LinphoneChatMessage *msg) { + if (msg->from) + linphone_address_unref(msg->from); + msg->from = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getFromAddress().asString().c_str()); + return msg->from; +} + +const LinphoneAddress *linphone_chat_message_get_to_address (LinphoneChatMessage *msg) { + if (msg->to) + linphone_address_unref(msg->to); + msg->to = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getToAddress().asString().c_str()); + return msg->to; +} + +const char *linphone_chat_message_get_file_transfer_filepath (LinphoneChatMessage *msg) { + return L_STRING_TO_C(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferFilepath()); +} + +void linphone_chat_message_set_file_transfer_filepath (LinphoneChatMessage *msg, const char *filepath) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->setFileTransferFilepath(L_C_TO_STRING(filepath)); +} + +void linphone_chat_message_add_custom_header( + LinphoneChatMessage *msg, + const char *header_name, + const char *header_value +) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->addSalCustomHeader(L_C_TO_STRING(header_name), L_C_TO_STRING(header_value)); +} + +void linphone_chat_message_remove_custom_header (LinphoneChatMessage *msg, const char *header_name) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->removeSalCustomHeader(L_C_TO_STRING(header_name)); +} + +const char *linphone_chat_message_get_custom_header (LinphoneChatMessage *msg, const char *header_name) { + msg->cache.customHeaderValue = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getSalCustomHeaderValue(L_C_TO_STRING(header_name)); + return L_STRING_TO_C(msg->cache.customHeaderValue); +} + +const LinphoneErrorInfo *linphone_chat_message_get_error_info (const LinphoneChatMessage *msg) { + return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getErrorInfo(); +} + +bool_t linphone_chat_message_get_to_be_stored (const LinphoneChatMessage *message) { + return L_GET_CPP_PTR_FROM_C_OBJECT(message)->getToBeStored(); +} + +void linphone_chat_message_set_to_be_stored (LinphoneChatMessage *message, bool_t to_be_stored) { + L_GET_CPP_PTR_FROM_C_OBJECT(message)->setToBeStored(!!to_be_stored); +} + +// ============================================================================= +// Methods +// ============================================================================= + +bool_t linphone_chat_message_download_file (LinphoneChatMessage *msg) { + return !!L_GET_PRIVATE_FROM_C_OBJECT(msg)->downloadFile(); +} + +void linphone_chat_message_cancel_file_transfer (LinphoneChatMessage *msg) { + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->cancelFileTransfer(); +} + +void linphone_chat_message_send (LinphoneChatMessage *msg) { + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->send(); +} + +void linphone_chat_message_resend (LinphoneChatMessage *msg) { + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->send(); +} + +void linphone_chat_message_resend_2 (LinphoneChatMessage *msg) { + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->send(); +} + +LinphoneStatus linphone_chat_message_put_char (LinphoneChatMessage *msg, uint32_t character) { + return ((LinphoneStatus)L_GET_CPP_PTR_FROM_C_OBJECT(msg)->putCharacter(character)); +} + +void linphone_chat_message_add_text_content (LinphoneChatMessage *msg, const char *c_content) { + LinphonePrivate::Content *content = new LinphonePrivate::Content(); + LinphonePrivate::ContentType contentType = LinphonePrivate::ContentType::PlainText; + content->setContentType(contentType); + content->setBody(L_C_TO_STRING(c_content)); + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->addContent(content); +} + +bool_t linphone_chat_message_has_text_content (const LinphoneChatMessage *msg) { + return L_GET_PRIVATE_FROM_C_OBJECT(msg)->hasTextContent(); +} + +const char *linphone_chat_message_get_text_content (const LinphoneChatMessage *msg) { + const LinphonePrivate::Content *content = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getTextContent(); + if (content->isEmpty()) + return nullptr; + msg->cache.textContentBody = content->getBodyAsString(); + return L_STRING_TO_C(msg->cache.textContentBody); +} + +bool_t linphone_chat_message_is_file_transfer_in_progress (LinphoneChatMessage *msg) { + return L_GET_CPP_PTR_FROM_C_OBJECT(msg)->isFileTransferInProgress(); +} + +bctbx_list_t *linphone_chat_message_get_participants_by_imdn_state (const LinphoneChatMessage *msg, LinphoneChatMessageState state) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getParticipantsByImdnState(LinphonePrivate::ChatMessage::State(state))); +} + + +// ============================================================================= +// Old listener +// ============================================================================= + +LinphoneChatMessageStateChangedCb linphone_chat_message_get_message_state_changed_cb(LinphoneChatMessage* msg) { + return msg->message_state_changed_cb; +} + +void linphone_chat_message_set_message_state_changed_cb (LinphoneChatMessage* msg, LinphoneChatMessageStateChangedCb cb) { + msg->message_state_changed_cb = cb; +} + +void linphone_chat_message_set_message_state_changed_cb_user_data (LinphoneChatMessage* msg, void *user_data) { + msg->message_state_changed_user_data = user_data; +} + +void * linphone_chat_message_get_message_state_changed_cb_user_data (LinphoneChatMessage* msg) { + return msg->message_state_changed_user_data; +} + +// ============================================================================= +// Structure has changed, hard to keep the behavior +// ============================================================================= + +const char *linphone_chat_message_get_content_type (LinphoneChatMessage *msg) { + msg->cache.contentType = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getContentType().asString(); + return L_STRING_TO_C(msg->cache.contentType); +} + +void linphone_chat_message_set_content_type (LinphoneChatMessage *msg, const char *content_type) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->setContentType(LinphonePrivate::ContentType(L_C_TO_STRING(content_type))); +} + +const char *linphone_chat_message_get_text (LinphoneChatMessage *msg) { + return L_STRING_TO_C(L_GET_PRIVATE_FROM_C_OBJECT(msg)->getText()); +} + +int linphone_chat_message_set_text (LinphoneChatMessage *msg, const char* text) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->setText(L_C_TO_STRING(text)); + return 0; +} + +LinphoneContent *linphone_chat_message_get_file_transfer_information (LinphoneChatMessage *msg) { + const LinphonePrivate::Content *content = L_GET_PRIVATE_FROM_C_OBJECT(msg)->getFileTransferInformation(); + if (content) return L_GET_C_BACK_PTR(content); + return NULL; +} + +// ============================================================================= +// Nothing to do, they call other C API methods +// ============================================================================= + +const LinphoneAddress *linphone_chat_message_get_peer_address (LinphoneChatMessage *msg) { + return linphone_chat_room_get_peer_address(linphone_chat_message_get_chat_room(msg)); +} + +const LinphoneAddress *linphone_chat_message_get_local_address (LinphoneChatMessage *msg) { + if (L_GET_CPP_PTR_FROM_C_OBJECT(msg)->getDirection() == LinphonePrivate::ChatMessage::Direction::Outgoing) + return linphone_chat_message_get_from_address(msg); + return linphone_chat_message_get_to_address(msg); +} + +LinphoneReason linphone_chat_message_get_reason (LinphoneChatMessage *msg) { + return linphone_error_info_get_reason(linphone_chat_message_get_error_info(msg)); +} + +bool_t linphone_chat_message_is_file_transfer (LinphoneChatMessage *msg) { + return L_GET_PRIVATE_FROM_C_OBJECT(msg)->hasFileTransferContent(); +} + +bool_t linphone_chat_message_is_text (LinphoneChatMessage *msg) { + return L_GET_PRIVATE_FROM_C_OBJECT(msg)->hasTextContent(); +} + +const char *linphone_chat_message_state_to_string (const LinphoneChatMessageState state) { + switch (state) { + case LinphoneChatMessageStateIdle: + return "LinphoneChatMessageStateIdle"; + case LinphoneChatMessageStateInProgress: + return "LinphoneChatMessageStateInProgress"; + case LinphoneChatMessageStateDelivered: + return "LinphoneChatMessageStateDelivered"; + case LinphoneChatMessageStateNotDelivered: + return "LinphoneChatMessageStateNotDelivered"; + case LinphoneChatMessageStateFileTransferError: + return "LinphoneChatMessageStateFileTransferError"; + case LinphoneChatMessageStateFileTransferDone: + return "LinphoneChatMessageStateFileTransferDone "; + case LinphoneChatMessageStateDeliveredToUser: + return "LinphoneChatMessageStateDeliveredToUser"; + case LinphoneChatMessageStateDisplayed: + return "LinphoneChatMessageStateDisplayed"; + } + return NULL; +} + +void linphone_chat_message_start_file_download ( + LinphoneChatMessage *msg, + LinphoneChatMessageStateChangedCb status_cb, + void *ud +) { + msg->message_state_changed_cb = status_cb; + msg->message_state_changed_user_data = ud; + linphone_chat_message_download_file(msg); +} diff --git a/src/c-wrapper/api/c-chat-room-cbs.cpp b/src/c-wrapper/api/c-chat-room-cbs.cpp new file mode 100644 index 000000000..0927d1b97 --- /dev/null +++ b/src/c-wrapper/api/c-chat-room-cbs.cpp @@ -0,0 +1,243 @@ +/* + * c-chat-room-cbs.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-chat-room-cbs.h" + +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +struct _LinphoneChatRoomCbs { + belle_sip_object_t base; + void *userData; + LinphoneChatRoomCbsIsComposingReceivedCb isComposingReceivedCb; + LinphoneChatRoomCbsMessageReceivedCb messageReceivedCb; + LinphoneChatRoomCbsParticipantAddedCb participantAddedCb; + LinphoneChatRoomCbsParticipantRemovedCb participantRemovedCb; + LinphoneChatRoomCbsParticipantDeviceAddedCb participantDeviceAddedCb; + LinphoneChatRoomCbsParticipantDeviceRemovedCb participantDeviceRemovedCb; + LinphoneChatRoomCbsParticipantAdminStatusChangedCb participantAdminStatusChangedCb; + LinphoneChatRoomCbsStateChangedCb stateChangedCb; + LinphoneChatRoomCbsSubjectChangedCb subjectChangedCb; + LinphoneChatRoomCbsConferenceJoinedCb conferenceJoinedCb; + LinphoneChatRoomCbsConferenceLeftCb conferenceLeftCb; + LinphoneChatRoomCbsUndecryptableMessageReceivedCb undecryptableMessageReceivedCb; + LinphoneChatRoomCbsChatMessageReceivedCb chatMessageReceivedCb; + LinphoneChatRoomCbsChatMessageSentCb chatMessageSentCb; + LinphoneChatRoomCbsConferenceAddressGenerationCb conferenceAddressGenerationCb; + LinphoneChatRoomCbsParticipantDeviceFetchRequestedCb participantDeviceFetchRequestedCb; + LinphoneChatRoomCbsParticipantsCapabilitiesCheckedCb participantsCapabilitiesChecked; + LinphoneChatRoomCbsParticipantRegistrationSubscriptionRequestedCb participantRegistrationSubscriptionRequestedCb; + LinphoneChatRoomCbsParticipantRegistrationUnsubscriptionRequestedCb participantRegistrationUnsubscriptionRequestedCb; + LinphoneChatRoomCbsShouldChatMessageBeStoredCb shouldMessageBeStoredCb; +}; + +BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneChatRoomCbs); + +BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphoneChatRoomCbs); + +BELLE_SIP_INSTANCIATE_VPTR(LinphoneChatRoomCbs, belle_sip_object_t, + NULL, // destroy + NULL, // clone + NULL, // marshal + FALSE +); + +// ============================================================================= + +LinphoneChatRoomCbs * _linphone_chat_room_cbs_new (void) { + return belle_sip_object_new(LinphoneChatRoomCbs); +} + +LinphoneChatRoomCbs * linphone_chat_room_cbs_ref (LinphoneChatRoomCbs *cbs) { + belle_sip_object_ref(cbs); + return cbs; +} + +void linphone_chat_room_cbs_unref (LinphoneChatRoomCbs *cbs) { + belle_sip_object_unref(cbs); +} + +void * linphone_chat_room_cbs_get_user_data (const LinphoneChatRoomCbs *cbs) { + return cbs->userData; +} + +void linphone_chat_room_cbs_set_user_data (LinphoneChatRoomCbs *cbs, void *ud) { + cbs->userData = ud; +} + +LinphoneChatRoomCbsIsComposingReceivedCb linphone_chat_room_cbs_get_is_composing_received (const LinphoneChatRoomCbs *cbs) { + return cbs->isComposingReceivedCb; +} + +void linphone_chat_room_cbs_set_is_composing_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsIsComposingReceivedCb cb) { + cbs->isComposingReceivedCb = cb; +} + +LinphoneChatRoomCbsMessageReceivedCb linphone_chat_room_cbs_get_message_received (const LinphoneChatRoomCbs *cbs) { + return cbs->messageReceivedCb; +} + +void linphone_chat_room_cbs_set_message_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsMessageReceivedCb cb) { + cbs->messageReceivedCb = cb; +} + +LinphoneChatRoomCbsChatMessageReceivedCb linphone_chat_room_cbs_get_chat_message_received (const LinphoneChatRoomCbs *cbs) { + return cbs->chatMessageReceivedCb; +} + +void linphone_chat_room_cbs_set_chat_message_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsChatMessageReceivedCb cb) { + cbs->chatMessageReceivedCb = cb; +} + +LinphoneChatRoomCbsChatMessageSentCb linphone_chat_room_cbs_get_chat_message_sent (const LinphoneChatRoomCbs *cbs) { + return cbs->chatMessageSentCb; +} + +void linphone_chat_room_cbs_set_chat_message_sent (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsChatMessageSentCb cb) { + cbs->chatMessageSentCb = cb; +} + +LinphoneChatRoomCbsParticipantAddedCb linphone_chat_room_cbs_get_participant_added (const LinphoneChatRoomCbs *cbs) { + return cbs->participantAddedCb; +} + +void linphone_chat_room_cbs_set_participant_added (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantAddedCb cb) { + cbs->participantAddedCb = cb; +} + +LinphoneChatRoomCbsParticipantRemovedCb linphone_chat_room_cbs_get_participant_removed (const LinphoneChatRoomCbs *cbs) { + return cbs->participantRemovedCb; +} + +void linphone_chat_room_cbs_set_participant_removed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantRemovedCb cb) { + cbs->participantRemovedCb = cb; +} + +LinphoneChatRoomCbsParticipantAdminStatusChangedCb linphone_chat_room_cbs_get_participant_admin_status_changed (const LinphoneChatRoomCbs *cbs) { + return cbs->participantAdminStatusChangedCb; +} + +void linphone_chat_room_cbs_set_participant_admin_status_changed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantAdminStatusChangedCb cb) { + cbs->participantAdminStatusChangedCb = cb; +} + +LinphoneChatRoomCbsStateChangedCb linphone_chat_room_cbs_get_state_changed (const LinphoneChatRoomCbs *cbs) { + return cbs->stateChangedCb; +} + +void linphone_chat_room_cbs_set_state_changed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsStateChangedCb cb) { + cbs->stateChangedCb = cb; +} + +LinphoneChatRoomCbsSubjectChangedCb linphone_chat_room_cbs_get_subject_changed (const LinphoneChatRoomCbs *cbs) { + return cbs->subjectChangedCb; +} + +void linphone_chat_room_cbs_set_subject_changed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsSubjectChangedCb cb) { + cbs->subjectChangedCb = cb; +} + +LinphoneChatRoomCbsUndecryptableMessageReceivedCb linphone_chat_room_cbs_get_undecryptable_message_received (const LinphoneChatRoomCbs *cbs) { + return cbs->undecryptableMessageReceivedCb; +} + +void linphone_chat_room_cbs_set_undecryptable_message_received (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsUndecryptableMessageReceivedCb cb) { + cbs->undecryptableMessageReceivedCb = cb; +} + +LinphoneChatRoomCbsParticipantDeviceAddedCb linphone_chat_room_cbs_get_participant_device_added (const LinphoneChatRoomCbs *cbs) { + return cbs->participantDeviceAddedCb; +} + +void linphone_chat_room_cbs_set_participant_device_added (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantDeviceAddedCb cb) { + cbs->participantDeviceAddedCb = cb; +} + +LinphoneChatRoomCbsParticipantDeviceRemovedCb linphone_chat_room_cbs_get_participant_device_removed (const LinphoneChatRoomCbs *cbs) { + return cbs->participantDeviceRemovedCb; +} + +void linphone_chat_room_cbs_set_participant_device_removed (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantDeviceRemovedCb cb) { + cbs->participantDeviceRemovedCb = cb; +} + +LinphoneChatRoomCbsConferenceJoinedCb linphone_chat_room_cbs_get_conference_joined (const LinphoneChatRoomCbs *cbs) { + return cbs->conferenceJoinedCb; +} + +void linphone_chat_room_cbs_set_conference_joined (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsConferenceJoinedCb cb) { + cbs->conferenceJoinedCb = cb; +} + +LinphoneChatRoomCbsConferenceLeftCb linphone_chat_room_cbs_get_conference_left (const LinphoneChatRoomCbs *cbs) { + return cbs->conferenceLeftCb; +} + +void linphone_chat_room_cbs_set_conference_left (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsConferenceLeftCb cb) { + cbs->conferenceLeftCb = cb; +} + +LinphoneChatRoomCbsConferenceAddressGenerationCb linphone_chat_room_cbs_get_conference_address_generation (const LinphoneChatRoomCbs *cbs) { + return cbs->conferenceAddressGenerationCb; +} + +void linphone_chat_room_cbs_set_conference_address_generation (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsConferenceAddressGenerationCb cb) { + cbs->conferenceAddressGenerationCb = cb; +} + +LinphoneChatRoomCbsParticipantDeviceFetchRequestedCb linphone_chat_room_cbs_get_participant_device_fetch_requested (const LinphoneChatRoomCbs *cbs) { + return cbs->participantDeviceFetchRequestedCb; +} + +void linphone_chat_room_cbs_set_participant_device_fetch_requested (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantDeviceFetchRequestedCb cb) { + cbs->participantDeviceFetchRequestedCb = cb; +} + +LinphoneChatRoomCbsParticipantsCapabilitiesCheckedCb linphone_chat_room_cbs_get_participants_capabilities_checked (const LinphoneChatRoomCbs *cbs) { + return cbs->participantsCapabilitiesChecked; +} + +void linphone_chat_room_cbs_set_participants_capabilities_checked (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantsCapabilitiesCheckedCb cb) { + cbs->participantsCapabilitiesChecked = cb; +} + +LinphoneChatRoomCbsParticipantRegistrationSubscriptionRequestedCb linphone_chat_room_cbs_get_participant_registration_subscription_requested (const LinphoneChatRoomCbs *cbs) { + return cbs->participantRegistrationSubscriptionRequestedCb; +} + +void linphone_chat_room_cbs_set_participant_registration_subscription_requested (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantRegistrationSubscriptionRequestedCb cb) { + cbs->participantRegistrationSubscriptionRequestedCb = cb; +} + +LinphoneChatRoomCbsParticipantRegistrationUnsubscriptionRequestedCb linphone_chat_room_cbs_get_participant_registration_unsubscription_requested (const LinphoneChatRoomCbs *cbs) { + return cbs->participantRegistrationUnsubscriptionRequestedCb; +} + +void linphone_chat_room_cbs_set_participant_registration_unsubscription_requested (LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsParticipantRegistrationUnsubscriptionRequestedCb cb) { + cbs->participantRegistrationUnsubscriptionRequestedCb = cb; +} + +LinphoneChatRoomCbsShouldChatMessageBeStoredCb linphone_chat_room_cbs_get_chat_message_should_be_stored( LinphoneChatRoomCbs *cbs) { + return cbs->shouldMessageBeStoredCb; +} + +void linphone_chat_room_cbs_set_chat_message_should_be_stored( LinphoneChatRoomCbs *cbs, LinphoneChatRoomCbsShouldChatMessageBeStoredCb cb) { + cbs->shouldMessageBeStoredCb = cb; +} diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp new file mode 100644 index 000000000..0832910e4 --- /dev/null +++ b/src/c-wrapper/api/c-chat-room.cpp @@ -0,0 +1,561 @@ +/* + * c-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +// TODO: Remove me later. +#include "linphone/chat.h" + +#include "linphone/api/c-chat-room.h" +#include "linphone/wrapper_utils.h" + +#include "address/identity-address.h" +#include "c-wrapper/c-wrapper.h" +#include "call/call.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-room/real-time-text-chat-room-p.h" +#include "chat/chat-room/server-group-chat-room-p.h" +#include "conference/participant.h" +#include "core/core-p.h" +#include "event-log/event-log.h" + +// ============================================================================= + +using namespace std; + +static void _linphone_chat_room_constructor (LinphoneChatRoom *cr); +static void _linphone_chat_room_destructor (LinphoneChatRoom *cr); + +L_DECLARE_C_OBJECT_IMPL_WITH_XTORS( + ChatRoom, + _linphone_chat_room_constructor, _linphone_chat_room_destructor, + bctbx_list_t *callbacks; /* A list of LinphoneCallCbs object */ + LinphoneChatRoomCbs *currentCbs; /* The current LinphoneCallCbs object used to call a callback */ + mutable LinphoneAddress *conferenceAddressCache; + mutable LinphoneAddress *peerAddressCache; + mutable LinphoneAddress *localAddressCache; + mutable bctbx_list_t *composingAddresses; +) + +static void _linphone_chat_room_constructor (LinphoneChatRoom *cr) {} + +static void _linphone_chat_room_destructor (LinphoneChatRoom *cr) { + if (cr->conferenceAddressCache) + linphone_address_unref(cr->conferenceAddressCache); + if (cr->peerAddressCache) + linphone_address_unref(cr->peerAddressCache); + if (cr->localAddressCache) + linphone_address_unref(cr->localAddressCache); + if (cr->composingAddresses) + bctbx_list_free_with_data(cr->composingAddresses, (bctbx_list_free_func)linphone_address_unref); + _linphone_chat_room_clear_callbacks(cr); +} + +static list _get_identity_address_list_from_address_list(list addressList) { + list lIdent; + for (const auto &addr : addressList) + lIdent.push_back(LinphonePrivate::IdentityAddress(addr)); + return lIdent; +} + +// ============================================================================= +// Public functions. +// ============================================================================= + +void linphone_chat_room_send_message (LinphoneChatRoom *cr, const char *msg) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createChatMessage(msg)->send(); +} + +bool_t linphone_chat_room_is_remote_composing (const LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->isRemoteComposing(); +} + +LinphoneCore *linphone_chat_room_get_lc (const LinphoneChatRoom *cr) { + return linphone_chat_room_get_core(cr); +} + +LinphoneCore *linphone_chat_room_get_core (const LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCore()->getCCore(); +} + +const LinphoneAddress *linphone_chat_room_get_peer_address (LinphoneChatRoom *cr) { + if (cr->peerAddressCache) { + linphone_address_unref(cr->peerAddressCache); + } + + cr->peerAddressCache = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getPeerAddress().asString().c_str()); + return cr->peerAddressCache; +} + +const LinphoneAddress *linphone_chat_room_get_local_address (LinphoneChatRoom *cr) { + if (cr->localAddressCache) { + linphone_address_unref(cr->localAddressCache); + } + + cr->localAddressCache = linphone_address_new(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getLocalAddress().asString().c_str()); + return cr->localAddressCache; +} + +LinphoneChatMessage *linphone_chat_room_create_message (LinphoneChatRoom *cr, const char *message) { + shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createChatMessage(L_C_TO_STRING(message)); + LinphoneChatMessage *object = L_INIT(ChatMessage); + L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); + return object; +} + +LinphoneChatMessage *linphone_chat_room_create_message_2 ( + LinphoneChatRoom *cr, + const char *message, + const char *external_body_url, + LinphoneChatMessageState state, + time_t time, + bool_t is_read, + bool_t is_incoming +) { + LinphoneChatMessage *msg = linphone_chat_room_create_message(cr, message); + + linphone_chat_message_set_external_body_url(msg, external_body_url ? ms_strdup(external_body_url) : NULL); + + LinphonePrivate::ChatMessagePrivate *dMsg = L_GET_PRIVATE_FROM_C_OBJECT(msg); + dMsg->setTime(time); + dMsg->setState(static_cast(state)); + + return msg; +} + +void linphone_chat_room_send_chat_message_2 (LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + linphone_chat_message_ref(msg); + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->send(); +} + +void linphone_chat_room_send_chat_message (LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + L_GET_CPP_PTR_FROM_C_OBJECT(msg)->send(); +} + +void linphone_chat_room_receive_chat_message (LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + L_GET_PRIVATE_FROM_C_OBJECT(msg)->receive(); +} + +uint32_t linphone_chat_room_get_char (const LinphoneChatRoom *cr) { + if (!(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities() & LinphonePrivate::ChatRoom::Capabilities::RealTimeText)) + return 0; + return L_GET_CPP_PTR_FROM_C_OBJECT(cr, RealTimeTextChatRoom)->getChar(); +} + +void linphone_chat_room_compose (LinphoneChatRoom *cr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->compose(); +} + +LinphoneCall *linphone_chat_room_get_call (const LinphoneChatRoom *cr) { + if (!(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities() & LinphonePrivate::ChatRoom::Capabilities::RealTimeText)) + return nullptr; + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr, RealTimeTextChatRoom)->getCall()); +} + +void linphone_chat_room_set_call (LinphoneChatRoom *cr, LinphoneCall *call) { + if (!(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities() & LinphonePrivate::ChatRoom::Capabilities::RealTimeText)) + return; + L_GET_PRIVATE_FROM_C_OBJECT(cr, RealTimeTextChatRoom)->call = L_GET_CPP_PTR_FROM_C_OBJECT(call); +} + +void linphone_chat_room_mark_as_read (LinphoneChatRoom *cr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->markAsRead(); +} + +int linphone_chat_room_get_unread_messages_count (LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getUnreadChatMessageCount(); +} + +int linphone_chat_room_get_history_size (LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getChatMessageCount(); +} + +void linphone_chat_room_delete_message (LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + shared_ptr event = LinphonePrivate::MainDb::getEventFromKey( + L_GET_PRIVATE_FROM_C_OBJECT(msg)->dbKey + ); + if (event) + LinphonePrivate::EventLog::deleteFromDatabase(event); +} + +void linphone_chat_room_delete_history (LinphoneChatRoom *cr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->deleteHistory(); +} + +bctbx_list_t *linphone_chat_room_get_history_range (LinphoneChatRoom *cr, int startm, int endm) { + list> chatMessages; + for (auto &event : L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getMessageHistoryRange(startm, endm)) + chatMessages.push_back(static_pointer_cast(event)->getChatMessage()); + + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(chatMessages); +} + +bctbx_list_t *linphone_chat_room_get_history (LinphoneChatRoom *cr, int nb_message) { + return linphone_chat_room_get_history_range(cr, 0, nb_message); +} + +bctbx_list_t *linphone_chat_room_get_history_range_message_events (LinphoneChatRoom *cr, int startm, int endm) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getMessageHistoryRange(startm, endm)); +} + +bctbx_list_t *linphone_chat_room_get_history_message_events (LinphoneChatRoom *cr, int nb_events) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getMessageHistory(nb_events)); +} + +bctbx_list_t *linphone_chat_room_get_history_events (LinphoneChatRoom *cr, int nb_events) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getHistory(nb_events)); +} + +bctbx_list_t *linphone_chat_room_get_history_range_events (LinphoneChatRoom *cr, int begin, int end) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getHistoryRange(begin, end)); +} + +int linphone_chat_room_get_history_events_size(LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getHistorySize(); +} + +LinphoneChatMessage *linphone_chat_room_get_last_message_in_history(LinphoneChatRoom *cr) { + shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getLastChatMessageInHistory(); + if (!cppPtr) + return nullptr; + + return linphone_chat_message_ref(L_GET_C_BACK_PTR(cppPtr)); +} + +LinphoneChatMessage *linphone_chat_room_find_message (LinphoneChatRoom *cr, const char *message_id) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findChatMessage(message_id)); +} + +LinphoneChatRoomState linphone_chat_room_get_state (const LinphoneChatRoom *cr) { + return (LinphoneChatRoomState)L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getState(); +} + +bool_t linphone_chat_room_has_been_left (const LinphoneChatRoom *cr) { + return (bool_t)L_GET_CPP_PTR_FROM_C_OBJECT(cr)->hasBeenLeft(); +} + +time_t linphone_chat_room_get_last_update_time(const LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getLastUpdateTime(); +} + +void linphone_chat_room_add_participant (LinphoneChatRoom *cr, const LinphoneAddress *addr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->addParticipant( + LinphonePrivate::IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(addr)), nullptr, false + ); +} + +void linphone_chat_room_add_participants (LinphoneChatRoom *cr, const bctbx_list_t *addresses) { + list lAddr = L_GET_RESOLVED_CPP_LIST_FROM_C_LIST(addresses, Address); + list lIdentAddr; + for (const auto &addr : lAddr) + lIdentAddr.push_back(LinphonePrivate::IdentityAddress(addr)); + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->addParticipants(lIdentAddr, nullptr, false); +} + +bool_t linphone_chat_room_can_handle_participants (const LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->canHandleParticipants(); +} + +LinphoneParticipant *linphone_chat_room_find_participant (const LinphoneChatRoom *cr, const LinphoneAddress *addr) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->findParticipant( + LinphonePrivate::IdentityAddress(*L_GET_CPP_PTR_FROM_C_OBJECT(addr)) + )); +} + +LinphoneChatRoomCapabilitiesMask linphone_chat_room_get_capabilities (const LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities(); +} + +bool_t linphone_chat_room_has_capability(const LinphoneChatRoom *cr, int mask) { + if (L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getCapabilities() & mask) return true; + return false; +} + +const LinphoneAddress *linphone_chat_room_get_conference_address (const LinphoneChatRoom *cr) { + if (cr->conferenceAddressCache) + linphone_address_unref(cr->conferenceAddressCache); + + const LinphonePrivate::IdentityAddress &address = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getConferenceAddress(); + if (address.isValid()) + cr->conferenceAddressCache = linphone_address_new(address.asString().c_str()); + else + cr->conferenceAddressCache = nullptr; + return cr->conferenceAddressCache; +} + +LinphoneParticipant *linphone_chat_room_get_me (const LinphoneChatRoom *cr) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getMe()); +} + +int linphone_chat_room_get_nb_participants (const LinphoneChatRoom *cr) { + return L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getParticipantCount(); +} + +bctbx_list_t *linphone_chat_room_get_participants (const LinphoneChatRoom *cr) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getParticipants()); +} + +const char * linphone_chat_room_get_subject (const LinphoneChatRoom *cr) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getSubject()); +} + +void linphone_chat_room_leave (LinphoneChatRoom *cr) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->leave(); +} + +void linphone_chat_room_remove_participant (LinphoneChatRoom *cr, LinphoneParticipant *participant) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->removeParticipant(L_GET_CPP_PTR_FROM_C_OBJECT(participant)); +} + +void linphone_chat_room_remove_participants (LinphoneChatRoom *cr, const bctbx_list_t *participants) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->removeParticipants(L_GET_RESOLVED_CPP_LIST_FROM_C_LIST(participants, Participant)); +} + +void linphone_chat_room_set_participant_admin_status (LinphoneChatRoom *cr, LinphoneParticipant *participant, bool_t isAdmin) { + shared_ptr p = L_GET_CPP_PTR_FROM_C_OBJECT(participant); + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->setParticipantAdminStatus(p, !!isAdmin); +} + +void linphone_chat_room_set_subject (LinphoneChatRoom *cr, const char *subject) { + L_GET_CPP_PTR_FROM_C_OBJECT(cr)->setSubject(L_C_TO_STRING(subject)); +} + +const bctbx_list_t *linphone_chat_room_get_composing_addresses (LinphoneChatRoom *cr) { + bctbx_list_free_with_data(cr->composingAddresses, (bctbx_list_free_func)linphone_address_unref); + list composingAddresses; + // TODO: Improve perf or algorithm? + { + list addresses = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getComposingAddresses(); + transform( + addresses.cbegin(), addresses.cend(), + back_inserter(composingAddresses), [](const LinphonePrivate::Address &address) { + return LinphonePrivate::IdentityAddress(address); + } + ); + } + cr->composingAddresses = L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(composingAddresses); + return cr->composingAddresses; +} + +LinphoneChatMessage *linphone_chat_room_create_file_transfer_message(LinphoneChatRoom *cr, LinphoneContent *initial_content) { + shared_ptr cppPtr = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->createFileTransferMessage(L_GET_CPP_PTR_FROM_C_OBJECT(initial_content)); + LinphoneChatMessage *object = L_INIT(ChatMessage); + L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); + return object; +} + +void linphone_chat_room_set_conference_address (LinphoneChatRoom *cr, const LinphoneAddress *confAddr) { + char *addrStr = linphone_address_as_string(confAddr); + LinphonePrivate::ServerGroupChatRoomPrivate *sgcr = dynamic_cast(L_GET_PRIVATE_FROM_C_OBJECT(cr)); + if (sgcr) + sgcr->setConferenceAddress(LinphonePrivate::IdentityAddress(addrStr)); + bctbx_free(addrStr); +} + +void linphone_chat_room_set_participant_devices (LinphoneChatRoom *cr, const LinphoneAddress *partAddr, const bctbx_list_t *partDevices) { + char *addrStr = linphone_address_as_string(partAddr); + list lDevices = L_GET_RESOLVED_CPP_LIST_FROM_C_LIST(partDevices, Address); + list lIdentAddr; + for (const auto &addr : lDevices) + lIdentAddr.push_back(LinphonePrivate::IdentityAddress(addr)); + LinphonePrivate::ServerGroupChatRoomPrivate *sgcr = dynamic_cast(L_GET_PRIVATE_FROM_C_OBJECT(cr)); + if (sgcr) + sgcr->setParticipantDevices(LinphonePrivate::IdentityAddress(addrStr), lIdentAddr); + bctbx_free(addrStr); +} + +void linphone_chat_room_add_participant_device (LinphoneChatRoom *cr, const LinphoneAddress *participantAddress, const LinphoneAddress *deviceAddress) { + char *participantAddressStr = linphone_address_as_string(participantAddress); + char *deviceAddressStr = linphone_address_as_string(deviceAddress); + LinphonePrivate::ServerGroupChatRoomPrivate *sgcr = dynamic_cast(L_GET_PRIVATE_FROM_C_OBJECT(cr)); + if (sgcr) + sgcr->addParticipantDevice(LinphonePrivate::IdentityAddress(participantAddressStr), LinphonePrivate::IdentityAddress(deviceAddressStr)); + bctbx_free(participantAddressStr); + bctbx_free(deviceAddressStr); +} + +void linphone_chat_room_add_compatible_participants (LinphoneChatRoom *cr, const LinphoneAddress *deviceAddr, const bctbx_list_t *participantsCompatible) { + list lPartsComp = L_GET_RESOLVED_CPP_LIST_FROM_C_LIST(participantsCompatible, Address); + LinphonePrivate::ServerGroupChatRoomPrivate *sgcr = dynamic_cast(L_GET_PRIVATE_FROM_C_OBJECT(cr)); + if (sgcr) { + char *deviceAddrStr = linphone_address_as_string_uri_only(deviceAddr); + sgcr->addCompatibleParticipants(LinphonePrivate::IdentityAddress(deviceAddrStr), + _get_identity_address_list_from_address_list(lPartsComp) + ); + bctbx_free(deviceAddrStr); + } +} + +// ============================================================================= +// Callbacks +// ============================================================================= + +void _linphone_chat_room_clear_callbacks (LinphoneChatRoom *cr) { + bctbx_list_free_with_data(cr->callbacks, (bctbx_list_free_func)linphone_chat_room_cbs_unref); + cr->callbacks = nullptr; +} + +void linphone_chat_room_add_callbacks (LinphoneChatRoom *cr, LinphoneChatRoomCbs *cbs) { + cr->callbacks = bctbx_list_append(cr->callbacks, linphone_chat_room_cbs_ref(cbs)); +} + +void linphone_chat_room_remove_callbacks (LinphoneChatRoom *cr, LinphoneChatRoomCbs *cbs) { + cr->callbacks = bctbx_list_remove(cr->callbacks, cbs); + linphone_chat_room_cbs_unref(cbs); +} + +LinphoneChatRoomCbs *linphone_chat_room_get_current_callbacks (const LinphoneChatRoom *cr) { + return cr->currentCbs; +} + +void linphone_chat_room_set_current_callbacks(LinphoneChatRoom *cr, LinphoneChatRoomCbs *cbs) { + cr->currentCbs = cbs; +} + +const bctbx_list_t *linphone_chat_room_get_callbacks_list(const LinphoneChatRoom *cr) { + return cr->callbacks; +} + +#define NOTIFY_IF_EXIST(cbName, functionName, ...) \ + bctbx_list_t *callbacksCopy = bctbx_list_copy(linphone_chat_room_get_callbacks_list(cr)); \ + for (bctbx_list_t *it = callbacksCopy; it; it = bctbx_list_next(it)) { \ + linphone_chat_room_set_current_callbacks(cr, reinterpret_cast(bctbx_list_get_data(it))); \ + LinphoneChatRoomCbs ## cbName ## Cb cb = linphone_chat_room_cbs_get_ ## functionName (linphone_chat_room_get_current_callbacks(cr)); \ + if (cb) \ + cb(__VA_ARGS__); \ + } \ + linphone_chat_room_set_current_callbacks(cr, nullptr); \ + bctbx_list_free(callbacksCopy); + +void _linphone_chat_room_notify_is_composing_received(LinphoneChatRoom *cr, const LinphoneAddress *remoteAddr, bool_t isComposing) { + NOTIFY_IF_EXIST(IsComposingReceived, is_composing_received, cr, remoteAddr, isComposing) +} + +void _linphone_chat_room_notify_message_received(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + NOTIFY_IF_EXIST(MessageReceived, message_received, cr, msg) +} + +void _linphone_chat_room_notify_participant_added(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(ParticipantAdded, participant_added, cr, event_log) +} + +void _linphone_chat_room_notify_participant_removed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(ParticipantRemoved, participant_removed, cr, event_log) +} + +void _linphone_chat_room_notify_participant_device_added(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(ParticipantDeviceAdded, participant_device_added, cr, event_log) +} + +void _linphone_chat_room_notify_participant_device_removed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(ParticipantDeviceRemoved, participant_device_removed, cr, event_log) +} + +void _linphone_chat_room_notify_participant_admin_status_changed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(ParticipantAdminStatusChanged, participant_admin_status_changed, cr, event_log) +} + +void _linphone_chat_room_notify_state_changed(LinphoneChatRoom *cr, LinphoneChatRoomState newState) { + NOTIFY_IF_EXIST(StateChanged, state_changed, cr, newState) +} + +void _linphone_chat_room_notify_subject_changed(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(SubjectChanged, subject_changed, cr, event_log) +} + +void _linphone_chat_room_notify_conference_joined(LinphoneChatRoom *cr, const LinphoneEventLog *eventLog) { + NOTIFY_IF_EXIST(ConferenceJoined, conference_joined, cr, eventLog) +} + +void _linphone_chat_room_notify_conference_left(LinphoneChatRoom *cr, const LinphoneEventLog *eventLog) { + NOTIFY_IF_EXIST(ConferenceLeft, conference_left, cr, eventLog) +} + +void _linphone_chat_room_notify_undecryptable_message_received(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + NOTIFY_IF_EXIST(UndecryptableMessageReceived, undecryptable_message_received, cr, msg) +} + +void _linphone_chat_room_notify_chat_message_received(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(ChatMessageReceived, chat_message_received, cr, event_log) +} + +void _linphone_chat_room_notify_chat_message_sent(LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + NOTIFY_IF_EXIST(ChatMessageSent, chat_message_sent, cr, event_log) +} + +void _linphone_chat_room_notify_conference_address_generation(LinphoneChatRoom *cr) { + NOTIFY_IF_EXIST(ConferenceAddressGeneration, conference_address_generation, cr) +} + +void _linphone_chat_room_notify_participant_device_fetch_requested(LinphoneChatRoom *cr, const LinphoneAddress *participantAddr) { + NOTIFY_IF_EXIST(ParticipantDeviceFetchRequested, participant_device_fetch_requested, cr, participantAddr) +} + +void _linphone_chat_room_notify_participants_capabilities_checked(LinphoneChatRoom *cr, const LinphoneAddress *deviceAddr, const bctbx_list_t *participantsAddr) { + NOTIFY_IF_EXIST(ParticipantsCapabilitiesChecked, participants_capabilities_checked, cr, deviceAddr, participantsAddr) +} + +void _linphone_chat_room_notify_participant_registration_subscription_requested(LinphoneChatRoom *cr, const LinphoneAddress *participantAddr) { + NOTIFY_IF_EXIST(ParticipantRegistrationSubscriptionRequested, participant_registration_subscription_requested, cr, participantAddr) +} + +void _linphone_chat_room_notify_participant_registration_unsubscription_requested(LinphoneChatRoom *cr, const LinphoneAddress *participantAddr) { + NOTIFY_IF_EXIST(ParticipantRegistrationUnsubscriptionRequested, participant_registration_unsubscription_requested, cr, participantAddr) +} + +void _linphone_chat_room_notify_chat_message_should_be_stored(LinphoneChatRoom *cr, LinphoneChatMessage *msg) { + NOTIFY_IF_EXIST(ShouldChatMessageBeStored, chat_message_should_be_stored, cr, msg) +} + +// ============================================================================= +// Reference and user data handling functions. +// ============================================================================= + +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 L_GET_USER_DATA_FROM_C_OBJECT(cr); +} + +void linphone_chat_room_set_user_data (LinphoneChatRoom *cr, void *ud) { + L_SET_USER_DATA_FROM_C_OBJECT(cr, ud); +} + +// ============================================================================= +// Constructor and destructor functions. +// ============================================================================= + +LinphoneChatRoom *_linphone_server_group_chat_room_new (LinphoneCore *core, LinphonePrivate::SalCallOp *op) { + LinphoneChatRoom *cr = L_INIT(ChatRoom); + L_SET_CPP_PTR_FROM_C_OBJECT(cr, make_shared( + L_GET_CPP_PTR_FROM_C_OBJECT(core), + op + )); + L_GET_PRIVATE_FROM_C_OBJECT(cr)->setState(LinphonePrivate::ChatRoom::State::Instantiated); + L_GET_PRIVATE_FROM_C_OBJECT(cr, ServerGroupChatRoom)->confirmCreation(); + return cr; +} diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp new file mode 100644 index 000000000..6dbbd81ec --- /dev/null +++ b/src/c-wrapper/api/c-content.cpp @@ -0,0 +1,345 @@ +/* + * c-content.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-content.h" +#include "linphone/wrapper_utils.h" + +#include "c-wrapper/c-wrapper.h" +#include "content/content-type.h" +#include "content/file-content.h" +#include "content/file-transfer-content.h" +#include "content/header/header-param.h" + +// ============================================================================= + +using namespace std; + +static void _linphone_content_constructor (LinphoneContent *content); +static void _linphone_content_destructor (LinphoneContent *content); +static void _linphone_content_c_clone (LinphoneContent *dest, const LinphoneContent *src); + +L_DECLARE_C_CLONABLE_OBJECT_IMPL_WITH_XTORS(Content, + _linphone_content_constructor, + _linphone_content_destructor, + _linphone_content_c_clone, + + void *cryptoContext; // Used to encrypt file for RCS file transfer. + + mutable size_t size; + + struct Cache { + string name; + string type; + string subtype; + string buffer; + } mutable cache; +) + +static void _linphone_content_constructor (LinphoneContent *content) { + new(&content->cache) LinphoneContent::Cache(); +} + +static void _linphone_content_destructor (LinphoneContent *content) { + content->cache.~Cache(); +} + +static void _linphone_content_c_clone (LinphoneContent *dest, const LinphoneContent *src) { + new(&dest->cache) LinphoneContent::Cache(); + dest->size = src->size; + dest->cache = src->cache; +} + +// ============================================================================= +// Reference and user data handling functions. +// ============================================================================= + +LinphoneContent *linphone_content_ref (LinphoneContent *content) { + belle_sip_object_ref(content); + return content; +} + +void linphone_content_unref (LinphoneContent *content) { + belle_sip_object_unref(content); +} + +void *linphone_content_get_user_data (const LinphoneContent *content) { + return L_GET_USER_DATA_FROM_C_OBJECT(content); +} + +void linphone_content_set_user_data (LinphoneContent *content, void *user_data) { + return L_SET_USER_DATA_FROM_C_OBJECT(content, user_data); +} + +// ============================================================================= + +const char *linphone_content_get_type (const LinphoneContent *content) { + return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getType().c_str(); +} + +void linphone_content_set_type (LinphoneContent *content, const char *type) { + LinphonePrivate::ContentType contentType = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + contentType.setType(L_C_TO_STRING(type)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(contentType); +} + +const char *linphone_content_get_subtype (const LinphoneContent *content) { + return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().getSubType().c_str(); +} + +void linphone_content_set_subtype (LinphoneContent *content, const char *subtype) { + LinphonePrivate::ContentType contentType = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + contentType.setSubType(L_C_TO_STRING(subtype)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(contentType); +} + +void linphone_content_add_content_type_parameter (LinphoneContent *content, const char *name, const char *value) { + LinphonePrivate::ContentType contentType = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + contentType.addParameter(L_C_TO_STRING(name), L_C_TO_STRING(value)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentType(contentType); +} + +const uint8_t *linphone_content_get_buffer (const LinphoneContent *content) { + return reinterpret_cast(linphone_content_get_string_buffer(content)); +} + +void linphone_content_set_buffer (LinphoneContent *content, const uint8_t *buffer, size_t size) { + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBody(buffer, size); +} + +const char *linphone_content_get_string_buffer (const LinphoneContent *content) { + content->cache.buffer = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String(); + return content->cache.buffer.c_str(); +} + +void linphone_content_set_string_buffer (LinphoneContent *content, const char *buffer) { + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setBodyFromUtf8(L_C_TO_STRING(buffer)); +} + +size_t linphone_content_get_file_size(const LinphoneContent *content) { + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + size_t size = 0; + if (c->isFile()) + size = static_cast(c)->getFileSize(); + else if (c->isFileTransfer()) + size = static_cast(c)->getFileSize(); + return size; +} + +size_t linphone_content_get_size (const LinphoneContent *content) { + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + size_t size = c->getSize(); + if (size == 0) { + size = content->size; + } + return size; +} + +void linphone_content_set_size (LinphoneContent *content, size_t size) { + content->size = size; +} + +const char *linphone_content_get_encoding (const LinphoneContent *content) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentEncoding()); +} + +void linphone_content_set_encoding (LinphoneContent *content, const char *encoding) { + L_GET_CPP_PTR_FROM_C_OBJECT(content)->setContentEncoding(L_C_TO_STRING(encoding)); +} + +const char *linphone_content_get_name (const LinphoneContent *content) { + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFile()) + return static_cast(c)->getFileName().c_str(); + if (c->isFileTransfer()) + return static_cast(c)->getFileName().c_str(); + return content->cache.name.c_str(); +} + +void linphone_content_set_name (LinphoneContent *content, const char *name) { + LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFile()) + static_cast(c)->setFileName(L_C_TO_STRING(name)); + else if (c->isFileTransfer()) + static_cast(c)->setFileName(L_C_TO_STRING(name)); + else + content->cache.name = L_C_TO_STRING(name); +} + +bool_t linphone_content_is_multipart (const LinphoneContent *content) { + return L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType().isMultipart(); +} + +LinphoneContent *linphone_content_get_part (const LinphoneContent *content, int idx) { + SalBodyHandler *bodyHandler = sal_body_handler_from_content(content); + if (!sal_body_handler_is_multipart(bodyHandler)) { + sal_body_handler_unref(bodyHandler); + return nullptr; + } + SalBodyHandler *partBodyHandler = sal_body_handler_get_part(bodyHandler, idx); + LinphoneContent *result = linphone_content_from_sal_body_handler(partBodyHandler); + sal_body_handler_unref(bodyHandler); + return result; +} + +LinphoneContent *linphone_content_find_part_by_header (const LinphoneContent *content, const char *headerName, const char *headerValue) { + SalBodyHandler *bodyHandler = sal_body_handler_from_content(content); + if (!sal_body_handler_is_multipart(bodyHandler)) { + sal_body_handler_unref(bodyHandler); + return nullptr; + } + SalBodyHandler *partBodyHandler = sal_body_handler_find_part_by_header(bodyHandler, headerName, headerValue); + LinphoneContent *result = linphone_content_from_sal_body_handler(partBodyHandler); + sal_body_handler_unref(bodyHandler); + return result; +} + +const char *linphone_content_get_custom_header (const LinphoneContent *content, const char *headerName) { + SalBodyHandler *bodyHandler = sal_body_handler_from_content(content); + const char *header = sal_body_handler_get_header(bodyHandler, headerName); + sal_body_handler_unref(bodyHandler); + return header; +} + +const char *linphone_content_get_key (const LinphoneContent *content) { + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFileTransfer()) { + const LinphonePrivate::FileTransferContent *ftc = static_cast(c); + return ftc->getFileKey().data(); + } + return nullptr; +} + +size_t linphone_content_get_key_size (const LinphoneContent *content) { + const LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFileTransfer()) { + const LinphonePrivate::FileTransferContent *ftc = static_cast(c); + return ftc->getFileKeySize(); + } + return 0; +} + +void linphone_content_set_key (LinphoneContent *content, const char *key, const size_t keyLength) { + LinphonePrivate::Content *c = L_GET_CPP_PTR_FROM_C_OBJECT(content); + if (c->isFileTransfer()) { + LinphonePrivate::FileTransferContent *ftc = static_cast(c); + ftc->setFileKey(key, keyLength); + } +} + +// ============================================================================= +// Private functions. +// ============================================================================= + +static LinphoneContent *linphone_content_new_with_body_handler (const SalBodyHandler *bodyHandler, bool parseMultipart) { + LinphoneContent *content = L_INIT(Content); + content->cryptoContext = nullptr; + LinphonePrivate::Content *c = new LinphonePrivate::Content(); + L_SET_CPP_PTR_FROM_C_OBJECT(content, c); + + if (!bodyHandler) + return content; + + linphone_content_set_type(content, sal_body_handler_get_type(bodyHandler)); + linphone_content_set_subtype(content, sal_body_handler_get_subtype(bodyHandler)); + for (const belle_sip_list_t *params = sal_body_handler_get_content_type_parameters_names(bodyHandler); params; params = params->next) { + const char *paramName = reinterpret_cast(params->data); + const char *paramValue = sal_body_handler_get_content_type_parameter(bodyHandler, paramName); + linphone_content_add_content_type_parameter(content, paramName, paramValue); + } + + if (linphone_content_is_multipart(content) && parseMultipart) { + belle_sip_multipart_body_handler_t *mpbh = BELLE_SIP_MULTIPART_BODY_HANDLER(bodyHandler); + char *body = belle_sip_object_to_string(mpbh); + linphone_content_set_string_buffer(content, body); + belle_sip_free(body); + } else { + linphone_content_set_string_buffer(content, reinterpret_cast(sal_body_handler_get_data(bodyHandler))); + } + + const belle_sip_list_t *headers = reinterpret_cast(sal_body_handler_get_headers(bodyHandler)); + while (headers) { + belle_sip_header_t *cHeader = BELLE_SIP_HEADER(headers->data); + LinphonePrivate::Header header = LinphonePrivate::Header(belle_sip_header_get_name(cHeader), belle_sip_header_get_unparsed_value(cHeader)); + L_GET_CPP_PTR_FROM_C_OBJECT(content)->addHeader(header); + headers = headers->next; + } + if (sal_body_handler_get_encoding(bodyHandler)) + linphone_content_set_encoding(content, sal_body_handler_get_encoding(bodyHandler)); + + return content; +} + +LinphoneContent *linphone_content_new (void) { + return linphone_content_new_with_body_handler(nullptr, true); +} + +LinphoneContent *linphone_content_copy (const LinphoneContent *ref) { + return reinterpret_cast(belle_sip_object_clone(BELLE_SIP_OBJECT(ref))); +} + +LinphoneContent *linphone_core_create_content (LinphoneCore *lc) { + return linphone_content_new(); +} + +// Crypto context is managed(allocated/freed) by the encryption function, +// so provide the address of field in the private structure. +void **linphone_content_get_cryptoContext_address (LinphoneContent *content) { + return &content->cryptoContext; +} + +LinphoneContent *linphone_content_from_sal_body_handler (const SalBodyHandler *bodyHandler, bool parseMultipart) { + if (!bodyHandler) + return nullptr; + return linphone_content_new_with_body_handler(bodyHandler, parseMultipart); +} + +SalBodyHandler *sal_body_handler_from_content (const LinphoneContent *content, bool parseMultipart) { + if (!content) + return nullptr; + + SalBodyHandler *bodyHandler; + LinphonePrivate::ContentType contentType = L_GET_CPP_PTR_FROM_C_OBJECT(content)->getContentType(); + if (contentType.isMultipart() && parseMultipart) { + size_t size = linphone_content_get_size(content); + char *buffer = bctbx_strdup(L_GET_CPP_PTR_FROM_C_OBJECT(content)->getBodyAsUtf8String().c_str()); + const char *boundary = L_STRING_TO_C(contentType.getParameter("boundary").getValue()); + belle_sip_multipart_body_handler_t *bh = belle_sip_multipart_body_handler_new_from_buffer(buffer, size, boundary); + bodyHandler = reinterpret_cast(BELLE_SIP_BODY_HANDLER(bh)); + bctbx_free(buffer); + } else { + bodyHandler = sal_body_handler_new(); + sal_body_handler_set_data(bodyHandler, belle_sip_strdup(linphone_content_get_string_buffer(content))); + } + + for (const auto &header : L_GET_CPP_PTR_FROM_C_OBJECT(content)->getHeaders()) { + belle_sip_header_t *additionalHeader = belle_sip_header_parse(header.asString().c_str()); + belle_sip_body_handler_add_header(BELLE_SIP_BODY_HANDLER(bodyHandler), additionalHeader); + } + + sal_body_handler_set_type(bodyHandler, contentType.getType().c_str()); + sal_body_handler_set_subtype(bodyHandler, contentType.getSubType().c_str()); + sal_body_handler_set_size(bodyHandler, linphone_content_get_size(content)); + for (const auto ¶m : contentType.getParameters()) + sal_body_handler_set_content_type_parameter(bodyHandler, param.getName().c_str(), param.getValue().c_str()); + + if (linphone_content_get_encoding(content)) + sal_body_handler_set_encoding(bodyHandler, linphone_content_get_encoding(content)); + + return bodyHandler; +} diff --git a/src/c-wrapper/api/c-core.cpp b/src/c-wrapper/api/c-core.cpp new file mode 100644 index 000000000..eb5bb3195 --- /dev/null +++ b/src/c-wrapper/api/c-core.cpp @@ -0,0 +1,47 @@ +/* + * c-core.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/wrapper_utils.h" + +#include "c-wrapper/c-wrapper.h" +#include "core/core.h" + +#include "private_structs.h" + +// ============================================================================= + +using namespace std; + +static void _linphone_core_constructor (LinphoneCore *lc); +static void _linphone_core_destructor (LinphoneCore *lc); + +L_DECLARE_C_OBJECT_IMPL_WITH_XTORS( + Core, + _linphone_core_constructor, _linphone_core_destructor, + LINPHONE_CORE_STRUCT_FIELDS +) + +static void _linphone_core_constructor (LinphoneCore *lc) { +} + +static void _linphone_core_destructor (LinphoneCore *lc) { + if (lc->callsCache) + bctbx_list_free_with_data(lc->callsCache, (bctbx_list_free_func)linphone_call_unref); + _linphone_core_uninit(lc); +} diff --git a/src/c-wrapper/api/c-dial-plan.cpp b/src/c-wrapper/api/c-dial-plan.cpp new file mode 100644 index 000000000..f063b4ab3 --- /dev/null +++ b/src/c-wrapper/api/c-dial-plan.cpp @@ -0,0 +1,85 @@ +/* + * c-dial-plan.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-dial-plan.h" +#include "linphone/wrapper_utils.h" + +#include "c-wrapper/c-wrapper.h" +#include "dial-plan/dial-plan.h" + +// ============================================================================= + +using namespace std; + +L_DECLARE_C_CLONABLE_OBJECT_IMPL(DialPlan); + +// TODO: Remove me later. Ugly workaround for C++ wrapper. +LinphoneDialPlan *linphone_dial_plan_ref (LinphoneDialPlan *dp) { + return dp; +} + +void linphone_dial_plan_unref (LinphoneDialPlan *) {} + +const char *linphone_dial_plan_get_country (const LinphoneDialPlan *dp) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(dp)->getCountry()); +} + +const char *linphone_dial_plan_get_iso_country_code (const LinphoneDialPlan *dp) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(dp)->getIsoCountryCode()); +} + +const char *linphone_dial_plan_get_country_calling_code (const LinphoneDialPlan *dp) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(dp)->getCountryCallingCode()); +} + +int linphone_dial_plan_get_national_number_length (const LinphoneDialPlan *dp) { + return L_GET_CPP_PTR_FROM_C_OBJECT(dp)->getNationalNumberLength(); +} + +const char *linphone_dial_plan_get_international_call_prefix (const LinphoneDialPlan *dp) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(dp)->getInternationalCallPrefix()); +} + +int linphone_dial_plan_lookup_ccc_from_e164 (const char *e164) { + return LinphonePrivate::DialPlan::lookupCccFromE164(L_C_TO_STRING(e164)); +} + +int linphone_dial_plan_lookup_ccc_from_iso (const char *iso) { + return LinphonePrivate::DialPlan::lookupCccFromIso(L_C_TO_STRING(iso)); +} + +const LinphoneDialPlan *linphone_dial_plan_by_ccc_as_int (int ccc) { + const LinphonePrivate::DialPlan &dp = LinphonePrivate::DialPlan::findByCcc(ccc); + return L_GET_C_BACK_PTR(&dp); +} + +const LinphoneDialPlan *linphone_dial_plan_by_ccc (const char *ccc) { + const LinphonePrivate::DialPlan &dp = LinphonePrivate::DialPlan::findByCcc(L_C_TO_STRING(ccc)); + return L_GET_C_BACK_PTR(&dp); +} + +const bctbx_list_t *linphone_dial_plan_get_all_list () { + static const list &dps = LinphonePrivate::DialPlan::getAllDialPlans(); + static const bctbx_list_t *list = L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(dps); + return list; +} + +bool_t linphone_dial_plan_is_generic (const LinphoneDialPlan *ccc) { + return L_GET_CPP_PTR_FROM_C_OBJECT(ccc)->isGeneric(); +} diff --git a/src/c-wrapper/api/c-event-log.cpp b/src/c-wrapper/api/c-event-log.cpp index 2404b5418..4b5beba33 100644 --- a/src/c-wrapper/api/c-event-log.cpp +++ b/src/c-wrapper/api/c-event-log.cpp @@ -1,11 +1,11 @@ /* * c-event-log.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,103 +13,309 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "c-wrapper/c-tools.h" +#include "linphone/api/c-event-log.h" -#include "c-event-log.h" - -#include "event-log/call-event.h" -#include "event-log/conference-participant-event.h" -#include "event-log/message-event.h" +#include "c-wrapper/c-wrapper.h" +#include "call/call.h" +#include "chat/chat-message/chat-message.h" +#include "chat/chat-room/chat-room-id.h" +#include "event-log/events.h" // ============================================================================= using namespace std; -extern "C" { -// ----------------------------------------------------------------------------- -// Event log. -// ----------------------------------------------------------------------------- +static void _linphone_event_log_constructor (LinphoneEventLog *event_log); +static void _linphone_event_log_destructor (LinphoneEventLog *event_log); -L_DECLARE_C_STRUCT_IMPL(EventLog, event_log); -L_DECLARE_C_STRUCT_NEW_DEFAULT(EventLog, event_log); +L_DECLARE_C_OBJECT_IMPL_WITH_XTORS( + EventLog, + _linphone_event_log_constructor, + _linphone_event_log_destructor, + mutable LinphoneAddress *peerAddressCache; + mutable LinphoneAddress *localAddressCache; + mutable LinphoneAddress *participantAddressCache; + mutable LinphoneAddress *deviceAddressCache; +); -LinphoneEventLogType linphone_event_log_get_type (const LinphoneEventLog *eventLog) { - return static_cast(eventLog->cppPtr->getType()); +void _linphone_event_log_constructor (LinphoneEventLog *) {} + +void _linphone_event_log_destructor (LinphoneEventLog *event_log) { + if (event_log->peerAddressCache) + linphone_address_unref(event_log->peerAddressCache); + if (event_log->localAddressCache) + linphone_address_unref(event_log->localAddressCache); + if (event_log->participantAddressCache) + linphone_address_unref(event_log->participantAddressCache); + if (event_log->deviceAddressCache) + linphone_address_unref(event_log->deviceAddressCache); } // ----------------------------------------------------------------------------- -// Message event. +// Helpers. // ----------------------------------------------------------------------------- -L_DECLARE_C_STRUCT_IMPL(MessageEvent, message_event); +static bool isConferenceType (LinphoneEventLogType type) { + switch (type) { + case LinphoneEventLogTypeConferenceCallEnd: + case LinphoneEventLogTypeConferenceCallStart: + case LinphoneEventLogTypeConferenceChatMessage: + case LinphoneEventLogTypeConferenceCreated: + case LinphoneEventLogTypeConferenceTerminated: + case LinphoneEventLogTypeConferenceParticipantAdded: + case LinphoneEventLogTypeConferenceParticipantDeviceAdded: + case LinphoneEventLogTypeConferenceParticipantDeviceRemoved: + case LinphoneEventLogTypeConferenceParticipantRemoved: + case LinphoneEventLogTypeConferenceParticipantSetAdmin: + case LinphoneEventLogTypeConferenceParticipantUnsetAdmin: + case LinphoneEventLogTypeConferenceSubjectChanged: + return true; -LinphoneMessageEvent *linphone_message_event_new (LinphoneMessage *message) { - LinphoneMessageEvent *object = _linphone_message_event_init(); - // TODO: call make_shared with cppPtr. - object->cppPtr = make_shared(nullptr); - return object; + default: + break; + } + + return false; } -LinphoneMessage *linphone_message_event_get_message (const LinphoneMessageEvent *messageEvent) { - // TODO. - return nullptr; +static bool isConferenceCallType (LinphoneEventLogType type) { + switch (type) { + case LinphoneEventLogTypeConferenceCallEnd: + case LinphoneEventLogTypeConferenceCallStart: + return true; + + default: + break; + } + + return false; +} + +static bool isConferenceChatMessageType (LinphoneEventLogType type) { + switch (type) { + case LinphoneEventLogTypeConferenceChatMessage: + return true; + + default: + break; + } + + return false; +} + +static bool isConferenceNotifiedType (LinphoneEventLogType type) { + switch (type) { + case LinphoneEventLogTypeConferenceParticipantAdded: + case LinphoneEventLogTypeConferenceParticipantDeviceAdded: + case LinphoneEventLogTypeConferenceParticipantDeviceRemoved: + case LinphoneEventLogTypeConferenceParticipantRemoved: + case LinphoneEventLogTypeConferenceParticipantSetAdmin: + case LinphoneEventLogTypeConferenceParticipantUnsetAdmin: + case LinphoneEventLogTypeConferenceSubjectChanged: + return true; + + default: + break; + } + + return false; +} + +static bool isConferenceParticipantType (LinphoneEventLogType type) { + switch (type) { + case LinphoneEventLogTypeConferenceParticipantAdded: + case LinphoneEventLogTypeConferenceParticipantDeviceAdded: + case LinphoneEventLogTypeConferenceParticipantDeviceRemoved: + case LinphoneEventLogTypeConferenceParticipantRemoved: + case LinphoneEventLogTypeConferenceParticipantSetAdmin: + case LinphoneEventLogTypeConferenceParticipantUnsetAdmin: + return true; + + default: + break; + } + + return false; +} + +static bool isConferenceParticipantDeviceType (LinphoneEventLogType type) { + switch (type) { + case LinphoneEventLogTypeConferenceParticipantDeviceAdded: + case LinphoneEventLogTypeConferenceParticipantDeviceRemoved: + return true; + + default: + break; + } + + return false; +} + +static bool isConferenceSubjectType (LinphoneEventLogType type) { + switch (type) { + case LinphoneEventLogTypeConferenceSubjectChanged: + return true; + + default: + break; + } + + return false; } // ----------------------------------------------------------------------------- -// Call event. +// EventLog. // ----------------------------------------------------------------------------- -// L_DECLARE_C_STRUCT_IMPL(CallEvent, call_event); - -LinphoneCallEvent *linphone_call_event_new (LinphoneEventLogType type, LinphoneCall *call) { - // TODO. - return nullptr; +LinphoneEventLog *linphone_event_log_ref (LinphoneEventLog *event_log) { + belle_sip_object_ref(event_log); + return event_log; } -LinphoneCall *linphone_call_event_get_call (const LinphoneCallEvent *call_event) { - // TODO. - return nullptr; +void linphone_event_log_unref (LinphoneEventLog *event_log) { + belle_sip_object_unref(event_log); +} + +LinphoneEventLogType linphone_event_log_get_type (const LinphoneEventLog *event_log) { + return static_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log)->getType() + ); +} + +time_t linphone_event_log_get_creation_time (const LinphoneEventLog *event_log) { + return L_GET_CPP_PTR_FROM_C_OBJECT(event_log)->getCreationTime(); +} + +void linphone_event_log_delete_from_database (LinphoneEventLog *event_log) { + LinphonePrivate::EventLog::deleteFromDatabase(L_GET_CPP_PTR_FROM_C_OBJECT(event_log)); } // ----------------------------------------------------------------------------- -// Conference event. +// ConferenceEvent. // ----------------------------------------------------------------------------- -// L_DECLARE_C_STRUCT_IMPL(ConferenceEvent, conference_event); +const LinphoneAddress *linphone_event_log_get_peer_address (const LinphoneEventLog *event_log) { + if (!isConferenceType(linphone_event_log_get_type(event_log))) + return nullptr; -LinphoneConferenceEvent *linphone_conference_event_new ( - LinphoneEventLogType type, - const LinphoneAddress *address -) { - // TODO. - return nullptr; + if (!event_log->peerAddressCache) + event_log->peerAddressCache = linphone_address_new( + static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getChatRoomId().getPeerAddress().asString().c_str() + ); + + return event_log->peerAddressCache; } -const LinphoneAddress *linphone_conference_event_get_address (const LinphoneConferenceEvent *conference_event) { - // TODO. - return nullptr; +const LinphoneAddress *linphone_event_log_get_local_address (const LinphoneEventLog *event_log) { + if (!isConferenceType(linphone_event_log_get_type(event_log))) + return nullptr; + + if (!event_log->localAddressCache) + event_log->localAddressCache = linphone_address_new( + static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getChatRoomId().getLocalAddress().asString().c_str() + ); + + return event_log->localAddressCache; } // ----------------------------------------------------------------------------- -// Conference participant event. +// ConferenceNotifiedEvent. // ----------------------------------------------------------------------------- -// L_DECLARE_C_STRUCT_IMPL(ConferenceParticipantEvent, conference_participant_event); +unsigned int linphone_event_log_get_notify_id (const LinphoneEventLog *event_log) { + if (!isConferenceNotifiedType(linphone_event_log_get_type(event_log))) + return 0; -LinphoneConferenceParticipantEvent *linphone_conference_participant_event_new ( - LinphoneEventLogType type, - const LinphoneAddress *conference_address, - const LinphoneAddress *participant_address -) { - // TODO. - return nullptr; + return static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getNotifyId(); } -const LinphoneAddress *linphone_conference_participant_event_get_participant_address (const LinphoneConferenceParticipantEvent *conference_participant_event) { - // TODO. - return nullptr; +// ----------------------------------------------------------------------------- +// ConferenceCallEvent. +// ----------------------------------------------------------------------------- + +LinphoneCall *linphone_event_log_get_call (const LinphoneEventLog *event_log) { + if (!isConferenceCallType(linphone_event_log_get_type(event_log))) + return nullptr; + + return L_GET_C_BACK_PTR( + static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getCall() + ); } + +// ----------------------------------------------------------------------------- +// ConferenceChatMessageEvent. +// ----------------------------------------------------------------------------- + +LinphoneChatMessage *linphone_event_log_get_chat_message (const LinphoneEventLog *event_log) { + if (!isConferenceChatMessageType(linphone_event_log_get_type(event_log))) + return nullptr; + + return L_GET_C_BACK_PTR( + static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getChatMessage() + ); +} + +// ----------------------------------------------------------------------------- +// ConferenceParticipantEvent. +// ----------------------------------------------------------------------------- + +const LinphoneAddress *linphone_event_log_get_participant_address (const LinphoneEventLog *event_log) { + if (!isConferenceParticipantType(linphone_event_log_get_type(event_log))) + return nullptr; + + if (!event_log->participantAddressCache) + event_log->participantAddressCache = linphone_address_new( + static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getParticipantAddress().asString().c_str() + ); + + return event_log->participantAddressCache; +} + +// ----------------------------------------------------------------------------- +// ConferenceParticipantDeviceEvent. +// ----------------------------------------------------------------------------- + +const LinphoneAddress *linphone_event_log_get_device_address (const LinphoneEventLog *event_log) { + if (!isConferenceParticipantDeviceType(linphone_event_log_get_type(event_log))) + return nullptr; + + if (!event_log->deviceAddressCache) + event_log->deviceAddressCache = linphone_address_new( + static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getDeviceAddress().asString().c_str() + ); + + return event_log->deviceAddressCache; +} + +// ----------------------------------------------------------------------------- +// ConferenceSubjectEvent. +// ----------------------------------------------------------------------------- + +LINPHONE_PUBLIC const char *linphone_event_log_get_subject (const LinphoneEventLog *event_log) { + if (!isConferenceSubjectType(linphone_event_log_get_type(event_log))) + return nullptr; + + return L_STRING_TO_C( + static_pointer_cast( + L_GET_CPP_PTR_FROM_C_OBJECT(event_log) + )->getSubject() + ); } diff --git a/src/c-wrapper/api/c-event-log.h b/src/c-wrapper/api/c-event-log.h deleted file mode 100644 index a33edbabb..000000000 --- a/src/c-wrapper/api/c-event-log.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * c-event-log.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _C_EVENT_LOG_H_ -#define _C_EVENT_LOG_H_ - -#include "c-wrapper/c-types.h" - -// ============================================================================= - -#ifdef __cplusplus - extern "C" { -#endif - -LINPHONE_PUBLIC LinphoneEventLog *linphone_event_log_new (); -LINPHONE_PUBLIC LinphoneEventLogType linphone_event_log_get_type (const LinphoneEventLog *event_log); - -LINPHONE_PUBLIC LinphoneCallEvent *linphone_call_event_new (LinphoneEventLogType type, LinphoneCall *call); -LINPHONE_PUBLIC LinphoneCall *linphone_call_event_get_call (const LinphoneCallEvent *call_event); - -LINPHONE_PUBLIC LinphoneConferenceEvent *linphone_conference_event_new ( - LinphoneEventLogType type, - const LinphoneAddress *address -); - -LINPHONE_PUBLIC const LinphoneAddress *linphone_conference_event_get_address (const LinphoneConferenceEvent *conference_event); - -LINPHONE_PUBLIC LinphoneConferenceParticipantEvent *linphone_conference_participant_event_new ( - LinphoneEventLogType type, - const LinphoneAddress *conferenceAddress, - const LinphoneAddress *participantAddress -); - -LINPHONE_PUBLIC const LinphoneAddress *linphone_conference_participant_event_get_participant_address (const LinphoneConferenceParticipantEvent *conference_participant_event); - -LINPHONE_PUBLIC LinphoneMessageEvent *linphone_message_event_new (LinphoneMessage *message); -LINPHONE_PUBLIC LinphoneMessage *linphone_message_event_get_message (const LinphoneMessageEvent *message_event); - -#ifdef __cplusplus - } -#endif - -#endif // ifndef _C_EVENT_LOG_H_ diff --git a/src/c-wrapper/api/c-magic-search.cpp b/src/c-wrapper/api/c-magic-search.cpp new file mode 100644 index 000000000..cceae6be7 --- /dev/null +++ b/src/c-wrapper/api/c-magic-search.cpp @@ -0,0 +1,112 @@ +/* + * c-magic-search.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "c-wrapper/c-wrapper.h" +#include "search/magic-search.h" + +// ============================================================================= + +using namespace std; + +L_DECLARE_C_OBJECT_IMPL(MagicSearch); + +LinphoneMagicSearch *linphone_core_create_magic_search(LinphoneCore *lc) { + shared_ptr cppPtr = make_shared( + L_GET_CPP_PTR_FROM_C_OBJECT(lc) + ); + + LinphoneMagicSearch *object = L_INIT(MagicSearch); + L_SET_CPP_PTR_FROM_C_OBJECT(object, cppPtr); + return object; +} + +LinphoneMagicSearch *linphone_magic_search_new(LinphoneCore *lc) { + return linphone_core_create_magic_search(lc); +} + +LinphoneMagicSearch *linphone_magic_search_ref (LinphoneMagicSearch *magic_search) { + belle_sip_object_ref(magic_search); + return magic_search; +} + +void linphone_magic_search_unref (LinphoneMagicSearch *magic_search) { + belle_sip_object_unref(magic_search); +} + +void linphone_magic_search_set_min_weight (LinphoneMagicSearch *magic_search, unsigned int weight) { + L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->setMinWeight(weight); +} + +unsigned int linphone_magic_search_get_min_weight (const LinphoneMagicSearch *magic_search) { + return L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->getMinWeight(); +} + +void linphone_magic_search_set_max_weight (LinphoneMagicSearch *magic_search, unsigned int weight) { + L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->setMaxWeight(weight); +} + +unsigned int linphone_magic_search_get_max_weight (const LinphoneMagicSearch *magic_search) { + return L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->getMaxWeight(); +} + +const char *linphone_magic_search_get_delimiter (const LinphoneMagicSearch *magic_search) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->getDelimiter()); +} + +void linphone_magic_search_set_delimiter (LinphoneMagicSearch *magic_search, const char *delimiter) { + L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->setDelimiter(L_C_TO_STRING(delimiter)); +} + +bool_t linphone_magic_search_get_use_delimiter (LinphoneMagicSearch *magic_search) { + return L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->getUseDelimiter(); +} + +void linphone_magic_search_set_use_delimiter (LinphoneMagicSearch *magic_search, bool_t enable) { + L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->setUseDelimiter(!!enable); +} + +unsigned int linphone_magic_search_get_search_limit (const LinphoneMagicSearch *magic_search) { + return L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->getSearchLimit(); +} + +void linphone_magic_search_set_search_limit (LinphoneMagicSearch *magic_search, unsigned int limit) { + L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->setSearchLimit(limit); +} + +bool_t linphone_magic_search_get_limited_search (const LinphoneMagicSearch *magic_search) { + return L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->getLimitedSearch(); +} + +void linphone_magic_search_set_limited_search (LinphoneMagicSearch *magic_search, bool_t limited) { + L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->setLimitedSearch(!!limited); +} + +void linphone_magic_search_reset_search_cache (LinphoneMagicSearch *magic_search) { + L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->resetSearchCache(); +} + +bctbx_list_t* linphone_magic_search_get_contact_list_from_filter ( + LinphoneMagicSearch *magic_search, + const char *filter, + const char *domain +) { + return L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(L_GET_CPP_PTR_FROM_C_OBJECT(magic_search)->getContactListFromFilter( + L_C_TO_STRING(filter), L_C_TO_STRING(domain) + )); +} diff --git a/src/c-wrapper/api/c-participant-imdn-state.cpp b/src/c-wrapper/api/c-participant-imdn-state.cpp new file mode 100644 index 000000000..85dc5e74a --- /dev/null +++ b/src/c-wrapper/api/c-participant-imdn-state.cpp @@ -0,0 +1,63 @@ +/* + * c-participant-imdn-state.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-participant-imdn-state.h" + +#include "c-wrapper/c-wrapper.h" +#include "conference/participant.h" +#include "conference/participant-imdn-state.h" + +// ============================================================================= + +using namespace std; + +L_DECLARE_C_CLONABLE_OBJECT_IMPL(ParticipantImdnState); + +LinphoneParticipantImdnState *linphone_participant_imdn_state_ref (LinphoneParticipantImdnState *state) { + belle_sip_object_ref(state); + return state; +} + +void linphone_participant_imdn_state_unref (LinphoneParticipantImdnState *state) { + belle_sip_object_unref(state); +} + +void *linphone_participant_imdn_state_get_user_data(const LinphoneParticipantImdnState *state) { + return L_GET_USER_DATA_FROM_C_OBJECT(state); +} + +void linphone_participant_imdn_state_set_user_data(LinphoneParticipantImdnState *state, void *ud) { + L_SET_USER_DATA_FROM_C_OBJECT(state, ud); +} + +const LinphoneParticipant *linphone_participant_imdn_state_get_participant (const LinphoneParticipantImdnState *state) { + return L_GET_C_BACK_PTR(L_GET_CPP_PTR_FROM_C_OBJECT(state)->getParticipant()); +} + +LinphoneChatMessageState linphone_participant_imdn_state_get_state (const LinphoneParticipantImdnState *state) { + return (LinphoneChatMessageState)L_GET_CPP_PTR_FROM_C_OBJECT(state)->getState(); +} + +time_t linphone_participant_imdn_state_get_state_change_time (const LinphoneParticipantImdnState *state) { + return L_GET_CPP_PTR_FROM_C_OBJECT(state)->getStateChangeTime(); +} + +const LinphoneParticipantImdnState *_linphone_participant_imdn_state_from_cpp_obj (const LinphonePrivate::ParticipantImdnState &state) { + return L_GET_C_BACK_PTR(&state); +} \ No newline at end of file diff --git a/src/c-wrapper/api/c-participant.cpp b/src/c-wrapper/api/c-participant.cpp new file mode 100644 index 000000000..9cc2b7f88 --- /dev/null +++ b/src/c-wrapper/api/c-participant.cpp @@ -0,0 +1,61 @@ +/* + * c-participant.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-participant.h" + +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" +#include "conference/participant.h" + +// ============================================================================= + +using namespace std; + +L_DECLARE_C_OBJECT_IMPL(Participant, + mutable LinphoneAddress *addressCache; +); + +LinphoneParticipant *linphone_participant_ref (LinphoneParticipant *participant) { + belle_sip_object_ref(participant); + return participant; +} + +void linphone_participant_unref (LinphoneParticipant *participant) { + belle_sip_object_unref(participant); +} + +void *linphone_participant_get_user_data(const LinphoneParticipant *participant) { + return L_GET_USER_DATA_FROM_C_OBJECT(participant); +} + +void linphone_participant_set_user_data(LinphoneParticipant *participant, void *ud) { + L_SET_USER_DATA_FROM_C_OBJECT(participant, ud); +} + +const LinphoneAddress *linphone_participant_get_address (const LinphoneParticipant *participant) { + LinphonePrivate::Address addr(L_GET_CPP_PTR_FROM_C_OBJECT(participant)->getAddress()); + if (participant->addressCache) + linphone_address_unref(participant->addressCache); + participant->addressCache = linphone_address_new(addr.asString().c_str()); + return participant->addressCache; +} + +bool_t linphone_participant_is_admin (const LinphoneParticipant *participant) { + return L_GET_CPP_PTR_FROM_C_OBJECT(participant)->isAdmin(); +} diff --git a/src/c-wrapper/api/c-search-result.cpp b/src/c-wrapper/api/c-search-result.cpp new file mode 100644 index 000000000..295c0edeb --- /dev/null +++ b/src/c-wrapper/api/c-search-result.cpp @@ -0,0 +1,48 @@ +/* + * c-search-result.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "search/search-result.h" +#include "c-wrapper/c-wrapper.h" + +L_DECLARE_C_CLONABLE_OBJECT_IMPL(SearchResult); + +LinphoneSearchResult *linphone_search_result_ref(LinphoneSearchResult *searchResult) { + belle_sip_object_ref(searchResult); + return searchResult; +} + +void linphone_search_result_unref(LinphoneSearchResult *searchResult) { + belle_sip_object_unref(searchResult); +} + +const LinphoneFriend* linphone_search_result_get_friend(const LinphoneSearchResult *searchResult) { + return L_GET_CPP_PTR_FROM_C_OBJECT(searchResult)->getFriend(); +} + +const LinphoneAddress* linphone_search_result_get_address(const LinphoneSearchResult *searchResult) { + return L_GET_CPP_PTR_FROM_C_OBJECT(searchResult)->getAddress(); +} + +const char* linphone_search_result_get_phone_number(const LinphoneSearchResult *searchResult) { + return L_STRING_TO_C(L_GET_CPP_PTR_FROM_C_OBJECT(searchResult)->getPhoneNumber()); +} + +unsigned int linphone_search_result_get_weight(const LinphoneSearchResult *searchResult) { + return L_GET_CPP_PTR_FROM_C_OBJECT(searchResult)->getWeight(); +} diff --git a/src/c-wrapper/c-tools.h b/src/c-wrapper/c-tools.h deleted file mode 100644 index a63eef594..000000000 --- a/src/c-wrapper/c-tools.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * c-tools.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _C_TOOLS_H_ -#define _C_TOOLS_H_ - -// From coreapi. -#include "private.h" - -// ============================================================================= - -#define L_DECLARE_C_STRUCT_IMPL(STRUCT, C_NAME) \ - struct _Linphone ## STRUCT { \ - belle_sip_object_t base; \ - shared_ptr cppPtr; \ - }; \ - BELLE_SIP_DECLARE_VPTR_NO_EXPORT(Linphone ## STRUCT); \ - static Linphone ## STRUCT *_linphone_ ## C_NAME ## _init() { \ - Linphone ## STRUCT * object = belle_sip_object_new(Linphone ## STRUCT); \ - new(&object->cppPtr) shared_ptr(); \ - return object; \ - } \ - static void _linphone_ ## C_NAME ## _uninit(Linphone ## STRUCT * object) { \ - object->cppPtr.reset(); \ - object->cppPtr->~STRUCT (); \ - } \ - static void _linphone_ ## C_NAME ## _clone(Linphone ## STRUCT * dest, const Linphone ## STRUCT * src) { \ - new(&dest->cppPtr) shared_ptr(); \ - dest->cppPtr = make_shared(*src->cppPtr.get()); \ - } \ - BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(Linphone ## STRUCT); \ - BELLE_SIP_INSTANCIATE_VPTR(Linphone ## STRUCT, belle_sip_object_t, \ - _linphone_ ## C_NAME ## _uninit, \ - _linphone_ ## C_NAME ## _clone, \ - NULL, \ - FALSE \ - ); - -#define L_DECLARE_C_STRUCT_NEW_DEFAULT(STRUCT, C_NAME) \ - Linphone ## STRUCT * linphone_ ## C_NAME ## _new() { \ - Linphone ## STRUCT * object = _linphone_ ## C_NAME ## _init(); \ - object->cppPtr = make_shared(); \ - return object; \ - } - -#endif // ifndef _C_TOOLS_H_ diff --git a/src/c-wrapper/c-types.h b/src/c-wrapper/c-types.h deleted file mode 100644 index 933b067b6..000000000 --- a/src/c-wrapper/c-types.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * c-types.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _C_TYPES_H_ -#define _C_TYPES_H_ - -// Do not move this define. -// Enable C enums. -#define L_USE_C_ENUM - -#include "event-log/event-log-enums.h" - -#define L_DECLARE_C_ENUM(CLASS, ENUM, VALUES) enum Linphone ## CLASS ## ENUM { VALUES } -#define L_DECLARE_C_STRUCT(STRUCT) typedef struct _Linphone ## STRUCT Linphone ## STRUCT; - -// ============================================================================= - -#ifdef __cplusplus - extern "C" { -#endif - -// ============================================================================= -// C Structures. -// ============================================================================= - -L_DECLARE_C_STRUCT(Call); -L_DECLARE_C_STRUCT(CallEvent); -L_DECLARE_C_STRUCT(ConferenceEvent); -L_DECLARE_C_STRUCT(ConferenceParticipantEvent); -L_DECLARE_C_STRUCT(EventLog); -L_DECLARE_C_STRUCT(Message); -L_DECLARE_C_STRUCT(MessageEvent); - -// TODO: Remove me in the future. -typedef struct SalAddress LinphoneAddress; - -// ============================================================================= -// C Enums. -// ============================================================================= - -L_DECLARE_C_ENUM(EventLog, Type, L_ENUM_VALUES_EVENT_LOG_TYPE); - -#ifdef __cplusplus - } -#endif - -#endif // ifndef _C_TYPES_H_ diff --git a/src/c-wrapper/c-wrapper.h b/src/c-wrapper/c-wrapper.h new file mode 100644 index 000000000..11d1b2033 --- /dev/null +++ b/src/c-wrapper/c-wrapper.h @@ -0,0 +1,140 @@ +/* + * c-wrapper.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_WRAPPER_H_ +#define _L_C_WRAPPER_H_ + +#include "linphone/api/c-types.h" + +#include "internal/c-tools.h" + +// TODO: From coreapi. Remove me later. +#include "private_functions.h" + +// ============================================================================= +// Declare exported C types. +// ============================================================================= + +#define L_REGISTER_TYPES(F) \ + F(Address, Address) \ + F(Call, Call) \ + F(ChatMessage, ChatMessage) \ + F(AbstractChatRoom, ChatRoom) \ + F(Core, Core) \ + F(Content, Content) \ + F(DialPlan, DialPlan) \ + F(EventLog, EventLog) \ + F(MagicSearch, MagicSearch) \ + F(MediaSessionParams, CallParams) \ + F(Participant, Participant) \ + F(ParticipantImdnState, ParticipantImdnState) \ + F(SearchResult, SearchResult) + +#define L_REGISTER_SUBTYPES(F) \ + F(AbstractChatRoom, BasicChatRoom) \ + F(AbstractChatRoom, BasicToClientGroupChatRoom) \ + F(AbstractChatRoom, ChatRoom) \ + F(AbstractChatRoom, ClientGroupChatRoom) \ + F(AbstractChatRoom, ClientGroupToBasicChatRoom) \ + F(AbstractChatRoom, RealTimeTextChatRoom) \ + F(AbstractChatRoom, ServerGroupChatRoom) \ + F(Call, LocalConferenceCall) \ + F(Call, RemoteConferenceCall) \ + F(EventLog, ConferenceCallEvent) \ + F(EventLog, ConferenceChatMessageEvent) \ + F(EventLog, ConferenceEvent) \ + F(EventLog, ConferenceNotifiedEvent) \ + F(EventLog, ConferenceParticipantDeviceEvent) \ + F(EventLog, ConferenceParticipantEvent) \ + F(EventLog, ConferenceSubjectEvent) + +// ============================================================================= +// Register belle-sip ID. +// ============================================================================= + +#define L_REGISTER_ID(CPP_TYPE, C_TYPE) BELLE_SIP_TYPE_ID(Linphone ## C_TYPE), + +BELLE_SIP_DECLARE_TYPES_BEGIN(linphone, 10000) +L_REGISTER_TYPES(L_REGISTER_ID) +BELLE_SIP_TYPE_ID(LinphoneAccountCreator), +BELLE_SIP_TYPE_ID(LinphoneAccountCreatorCbs), +BELLE_SIP_TYPE_ID(LinphoneAccountCreatorService), +BELLE_SIP_TYPE_ID(LinphoneAuthInfo), +BELLE_SIP_TYPE_ID(LinphoneBuffer), +BELLE_SIP_TYPE_ID(LinphoneCallCbs), +BELLE_SIP_TYPE_ID(LinphoneCallLog), +BELLE_SIP_TYPE_ID(LinphoneCallStats), +BELLE_SIP_TYPE_ID(LinphoneChatMessageCbs), +BELLE_SIP_TYPE_ID(LinphoneChatRoomCbs), +BELLE_SIP_TYPE_ID(LinphoneConference), +BELLE_SIP_TYPE_ID(LinphoneConferenceParams), +BELLE_SIP_TYPE_ID(LinphoneConfig), +BELLE_SIP_TYPE_ID(LinphoneContactProvider), +BELLE_SIP_TYPE_ID(LinphoneContactSearch), +BELLE_SIP_TYPE_ID(LinphoneCoreCbs), +BELLE_SIP_TYPE_ID(LinphoneErrorInfo), +BELLE_SIP_TYPE_ID(LinphoneEvent), +BELLE_SIP_TYPE_ID(LinphoneEventCbs), +BELLE_SIP_TYPE_ID(LinphoneFactory), +BELLE_SIP_TYPE_ID(LinphoneFriend), +BELLE_SIP_TYPE_ID(LinphoneFriendList), +BELLE_SIP_TYPE_ID(LinphoneFriendListCbs), +BELLE_SIP_TYPE_ID(LinphoneImEncryptionEngine), +BELLE_SIP_TYPE_ID(LinphoneImEncryptionEngineCbs), +BELLE_SIP_TYPE_ID(LinphoneImNotifPolicy), +BELLE_SIP_TYPE_ID(LinphoneInfoMessage), +BELLE_SIP_TYPE_ID(LinphoneLDAPContactProvider), +BELLE_SIP_TYPE_ID(LinphoneLDAPContactSearch), +BELLE_SIP_TYPE_ID(LinphoneLoggingService), +BELLE_SIP_TYPE_ID(LinphoneLoggingServiceCbs), +BELLE_SIP_TYPE_ID(LinphoneNatPolicy), +BELLE_SIP_TYPE_ID(LinphonePayloadType), +BELLE_SIP_TYPE_ID(LinphonePlayer), +BELLE_SIP_TYPE_ID(LinphonePlayerCbs), +BELLE_SIP_TYPE_ID(LinphonePresenceActivity), +BELLE_SIP_TYPE_ID(LinphonePresenceModel), +BELLE_SIP_TYPE_ID(LinphonePresenceNote), +BELLE_SIP_TYPE_ID(LinphonePresencePerson), +BELLE_SIP_TYPE_ID(LinphonePresenceService), +BELLE_SIP_TYPE_ID(LinphoneProxyConfig), +BELLE_SIP_TYPE_ID(LinphoneRange), +BELLE_SIP_TYPE_ID(LinphoneTransports), +BELLE_SIP_TYPE_ID(LinphoneTunnel), +BELLE_SIP_TYPE_ID(LinphoneTunnelConfig), +BELLE_SIP_TYPE_ID(LinphoneVcard), +BELLE_SIP_TYPE_ID(LinphoneVideoActivationPolicy), +BELLE_SIP_TYPE_ID(LinphoneVideoDefinition), +BELLE_SIP_TYPE_ID(LinphoneXmlRpcRequest), +BELLE_SIP_TYPE_ID(LinphoneXmlRpcRequestCbs), +BELLE_SIP_TYPE_ID(LinphoneXmlRpcSession) +BELLE_SIP_DECLARE_TYPES_END + +#undef L_REGISTER_ID + +// ============================================================================= +// Register C types. +// ============================================================================= + +L_REGISTER_TYPES(L_REGISTER_TYPE); +L_REGISTER_SUBTYPES(L_REGISTER_SUBTYPE); + +#undef L_REGISTER_SUBTYPES +#undef L_REGISTER_TYPES + +#endif // ifndef _L_C_WRAPPER_H_ diff --git a/coreapi/sal.c b/src/c-wrapper/internal/c-sal.cpp similarity index 94% rename from coreapi/sal.c rename to src/c-wrapper/internal/c-sal.cpp index c749877f4..ae0ed5a2d 100644 --- a/coreapi/sal.c +++ b/src/c-wrapper/internal/c-sal.cpp @@ -1,21 +1,21 @@ /* -linphone -Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr) - -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + * c-sal.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ /** This file contains SAL API functions that do not depend on the underlying implementation (like belle-sip). @@ -23,7 +23,7 @@ This file contains SAL API functions that do not depend on the underlying implem #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "sal/sal.h" +#include "c-wrapper/internal/c-sal.h" #include @@ -426,6 +426,7 @@ int sal_stream_description_equals(const SalStreamDescription *sd1, const SalStre if (strcmp(sd1->ice_ufrag, sd2->ice_ufrag) != 0 && sd2->ice_ufrag[0] != '\0') result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED; if (strcmp(sd1->ice_pwd, sd2->ice_pwd) != 0 && sd2->ice_pwd[0] != '\0') result |= SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED; + /*DTLS*/ if (sd1->dtls_role != sd2->dtls_role) result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; if (strcmp(sd1->dtls_fingerprint, sd2->dtls_fingerprint) != 0) result |= SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED; @@ -495,6 +496,7 @@ int sal_media_description_equals(const SalMediaDescription *md1, const SalMediaD return result; } +#if 0 static void assign_address(SalAddress** address, const char *value){ if (*address){ sal_address_destroy(*address); @@ -518,17 +520,6 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress *address){ ((SalOpBase*)op)->contact_address=address?sal_address_clone(address):NULL; } -void sal_op_set_and_clean_contact_address(SalOp *op, SalAddress *contact) { - if (contact && !sal_address_get_uri_param(contact, "gr")) { /*in case of gruu, nothing to do*/ - SalTransport tport = sal_address_get_transport((SalAddress*)contact); - sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/ - sal_address_set_transport((SalAddress*)contact,tport); - } - sal_op_set_contact_address(op, contact); - if (contact) - sal_address_unref(contact); -} - const SalAddress* sal_op_get_contact_address(const SalOp *op) { return ((SalOpBase*)op)->contact_address; } @@ -563,9 +554,11 @@ void sal_op_set_route(SalOp *op, const char *route){ assign_string(&op_base->route,route_string); \ if(route_string) ms_free(route_string); } + const bctbx_list_t* sal_op_get_route_addresses(const SalOp *op) { return ((SalOpBase*)op)->route_addresses; } + void sal_op_set_route_address(SalOp *op, const SalAddress *address){ char* address_string=sal_address_as_string(address); /*can probably be optimized*/ sal_op_set_route(op,address_string); @@ -617,6 +610,7 @@ Sal *sal_op_get_sal(const SalOp *op){ const char *sal_op_get_from(const SalOp *op){ return ((SalOpBase*)op)->from; } + const SalAddress *sal_op_get_from_address(const SalOp *op){ return ((SalOpBase*)op)->from_address; } @@ -648,6 +642,7 @@ const char *sal_op_get_proxy(const SalOp *op){ const char *sal_op_get_network_origin(const SalOp *op){ return ((SalOpBase*)op)->origin; } + const char* sal_op_get_call_id(const SalOp *op) { return ((SalOpBase*)op)->call_id; } @@ -732,6 +727,9 @@ void __sal_op_free(SalOp *op){ sal_media_description_unref(b->local_media); if (b->remote_media) sal_media_description_unref(b->remote_media); + if (b->custom_body) { + sal_custom_body_unref(b->custom_body); + } if (b->call_id) ms_free((void*)b->call_id); if (b->service_route) { @@ -752,6 +750,7 @@ void __sal_op_free(SalOp *op){ } ms_free(op); } +#endif SalAuthInfo* sal_auth_info_new() { return ms_new0(SalAuthInfo,1); @@ -764,6 +763,7 @@ SalAuthInfo* sal_auth_info_clone(const SalAuthInfo* auth_info) { new_auth_info->realm=auth_info->realm?ms_strdup(auth_info->realm):NULL; new_auth_info->domain=auth_info->realm?ms_strdup(auth_info->domain):NULL; new_auth_info->password=auth_info->password?ms_strdup(auth_info->password):NULL; + new_auth_info->algorithm=auth_info->algorithm?ms_strdup(auth_info->algorithm):NULL; return new_auth_info; } @@ -776,6 +776,7 @@ void sal_auth_info_delete(SalAuthInfo* auth_info) { if (auth_info->ha1) ms_free(auth_info->ha1); if (auth_info->certificates) sal_certificates_chain_delete(auth_info->certificates); if (auth_info->key) sal_signing_key_delete(auth_info->key); + if (auth_info->algorithm) ms_free(auth_info->algorithm); ms_free(auth_info); } @@ -840,15 +841,18 @@ const char* sal_reason_to_string(const SalReason reason) { default: return "Unkown reason"; } } +#if 0 const SalAddress* sal_op_get_service_route(const SalOp *op) { return ((SalOpBase*)op)->service_route; } + void sal_op_set_service_route(SalOp *op,const SalAddress* service_route) { if (((SalOpBase*)op)->service_route) sal_address_destroy(((SalOpBase*)op)->service_route); ((SalOpBase*)op)->service_route=service_route?sal_address_clone(service_route):NULL; } +#endif const char* sal_presence_status_to_string(const SalPresenceStatus status) { switch (status) { @@ -886,7 +890,7 @@ static int line_get_value(const char *input, const char *key, char *value, size_ size_t len; if (!end) len = strlen(input); - else len = end + 1 - input; + else len = (size_t)(end + 1 - input); *read = len; strncpy(line, input, MIN(len, sizeof(line))); @@ -913,20 +917,3 @@ int sal_lines_get_value(const char *data, const char *key, char *value, size_t v } while (read != 0); return FALSE; } - -const char *sal_op_get_entity_tag(const SalOp* op) { - SalOpBase* op_base = (SalOpBase*)op; - return op_base->entity_tag; -} - - -void sal_op_set_entity_tag(SalOp *op, const char* entity_tag) { - SalOpBase* op_base = (SalOpBase*)op; - if (op_base->entity_tag != NULL){ - ms_free(op_base->entity_tag); - } - if (entity_tag) - op_base->entity_tag = ms_strdup(entity_tag); - else - op_base->entity_tag = NULL; -} diff --git a/include/sal/sal.h b/src/c-wrapper/internal/c-sal.h similarity index 51% rename from include/sal/sal.h rename to src/c-wrapper/internal/c-sal.h index 241b94a4f..77cd79a01 100644 --- a/include/sal/sal.h +++ b/src/c-wrapper/internal/c-sal.h @@ -1,21 +1,21 @@ /* -linphone -Copyright (C) 2010 Simon MORLAT (simon.morlat@free.fr) - -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ + * c-sal.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ /** This header files defines the Signaling Abstraction Layer. @@ -23,11 +23,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. protocols and implementations under linphone, for example SIP, JINGLE... **/ -#ifndef sal_h -#define sal_h +#ifndef _L_C_SAL_H_ +#define _L_C_SAL_H_ #ifdef HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif #include "mediastreamer2/mediastream.h" @@ -47,22 +47,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #endif #endif -#ifdef __cplusplus -extern "C" { -#endif - /*Dirty hack, keep in sync with mediastreamer2/include/mediastream.h */ #ifndef PAYLOAD_TYPE_FLAG_CAN_RECV #define PAYLOAD_TYPE_FLAG_CAN_RECV PAYLOAD_TYPE_USER_FLAG_1 #define PAYLOAD_TYPE_FLAG_CAN_SEND PAYLOAD_TYPE_USER_FLAG_2 #endif -struct Sal; - -typedef struct Sal Sal; - -struct SalOp; - -typedef struct SalOp SalOp; struct SalAddress; @@ -99,15 +88,17 @@ typedef enum { #define SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION (1<<6) /* use force graph reconstruction*/ #define SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED (1<<7) - +#ifdef __cplusplus +extern "C" { +#endif const char* sal_transport_to_string(SalTransport transport); SalTransport sal_transport_parse(const char*); /* Address manipulation API*/ -SalAddress * sal_address_new(const char *uri); +LINPHONE_PUBLIC SalAddress * sal_address_new(const char *uri); SalAddress * sal_address_clone(const SalAddress *addr); SalAddress * sal_address_ref(SalAddress *addr); -void sal_address_unref(SalAddress *addr); +LINPHONE_PUBLIC void sal_address_unref(SalAddress *addr); const char *sal_address_get_scheme(const SalAddress *addr); const char *sal_address_get_display_name(const SalAddress* addr); const char *sal_address_get_display_name_unquoted(const SalAddress *addr); @@ -129,7 +120,7 @@ void sal_address_clean(SalAddress *addr); char *sal_address_as_string(const SalAddress *u); char *sal_address_as_string_uri_only(const SalAddress *u); void sal_address_destroy(SalAddress *u); -void sal_address_set_param(SalAddress *u,const char* name,const char* value); +LINPHONE_PUBLIC void sal_address_set_param(SalAddress *u,const char* name,const char* value); void sal_address_set_transport(SalAddress* addr,SalTransport transport); void sal_address_set_transport_name(SalAddress* addr,const char* transport); void sal_address_set_method_param(SalAddress *addr, const char *method); @@ -148,12 +139,12 @@ const char *sal_address_get_password(const SalAddress *addr); void sal_address_set_header(SalAddress *addr, const char *header_name, const char *header_value); const char *sal_address_get_header(const SalAddress *addr, const char *name); -LINPHONE_PUBLIC Sal * sal_init(MSFactory *factory); -LINPHONE_PUBLIC void sal_uninit(Sal* sal); void sal_set_log_handler(BctbxLogFunc log_handler); -void sal_set_user_pointer(Sal *sal, void *user_data); -void *sal_get_user_pointer(const Sal *sal); + +#ifdef __cplusplus +} +#endif typedef enum { @@ -162,7 +153,7 @@ typedef enum { SalText, SalOther } SalStreamType; -const char* sal_stream_type_to_string(SalStreamType type); + typedef enum{ SalProtoRtpAvp, @@ -173,7 +164,6 @@ typedef enum{ SalProtoUdpTlsRtpSavpf, SalProtoOther }SalMediaProto; -const char* sal_media_proto_to_string(SalMediaProto type); typedef enum{ SalStreamSendRecv, @@ -181,8 +171,18 @@ typedef enum{ SalStreamRecvOnly, SalStreamInactive }SalStreamDir; + +#ifdef __cplusplus +extern "C" { +#endif + +const char* sal_stream_type_to_string(SalStreamType type); +const char* sal_media_proto_to_string(SalMediaProto type); const char* sal_stream_dir_to_string(SalStreamDir type); +#ifdef __cplusplus +} +#endif #define SAL_ENDPOINT_CANDIDATE_MAX 2 @@ -256,15 +256,15 @@ typedef struct SalStreamDescription{ char rtcp_cname[256]; int rtp_port; int rtcp_port; - MSList *payloads; /*user_data=(void*)((intptr_t)n); -#define payload_type_get_number(pt) ((int)(intptr_t)(pt)->user_data) +#define payload_type_set_number(pt,n) (pt)->user_data=(void*)((intptr_t)n); +#define payload_type_get_number(pt) ((int)(intptr_t)(pt)->user_data) -/*misc*/ -void sal_get_default_local_ip(Sal *sal, int address_family, char *ip, size_t iplen); +#ifdef __cplusplus +extern "C" { +#endif -LINPHONE_PUBLIC belle_sip_resolver_context_t * sal_resolve_a(Sal* sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data); -LINPHONE_PUBLIC belle_sip_resolver_context_t * sal_resolve(Sal *sal, const char *service, const char *transport, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data); - SalCustomHeader *sal_custom_header_ref(SalCustomHeader *ch); void sal_custom_header_unref(SalCustomHeader *ch); SalCustomHeader *sal_custom_header_append(SalCustomHeader *ch, const char *name, const char *value); @@ -866,9 +608,6 @@ SalCustomHeader *sal_custom_header_remove(SalCustomHeader *ch, const char *name) void sal_custom_header_free(SalCustomHeader *ch); SalCustomHeader *sal_custom_header_clone(const SalCustomHeader *ch); -const SalCustomHeader *sal_op_get_recv_custom_header(SalOp *op); - -void sal_op_set_sent_custom_header(SalOp *op, SalCustomHeader* ch); SalCustomSdpAttribute * sal_custom_sdp_attribute_append(SalCustomSdpAttribute *csa, const char *name, const char *value); @@ -882,50 +621,13 @@ void sal_enable_log(void); void sal_disable_log(void); void sal_set_log_level(OrtpLogLevel level); -/*internal API */ -void __sal_op_init(SalOp *b, Sal *sal); -void __sal_op_set_network_origin(SalOp *op, const char *origin /*a sip uri*/); -void __sal_op_set_network_origin_address(SalOp *op, SalAddress *origin); -void __sal_op_set_remote_contact(SalOp *op, const char *ct); -void __sal_op_free(SalOp *b); - -/*test api*/ -/*0 for no error*/ -LINPHONE_PUBLIC void sal_set_send_error(Sal *sal,int value); -/*1 for no error*/ -LINPHONE_PUBLIC void sal_set_recv_error(Sal *sal,int value); - -/*always answer 480 if value=true*/ -LINPHONE_PUBLIC void sal_enable_unconditional_answer(Sal *sal,int value); - -LINPHONE_PUBLIC bool_t sal_pending_trans_checking_enabled(const Sal *sal) ; -LINPHONE_PUBLIC int sal_enable_pending_trans_checking(Sal *sal, bool_t value) ; - - - -/*refresher retry after value in ms*/ -LINPHONE_PUBLIC void sal_set_refresher_retry_after(Sal *sal,int value); -LINPHONE_PUBLIC int sal_get_refresher_retry_after(const Sal *sal); -/*enable contact fixing*/ -void sal_nat_helper_enable(Sal *sal,bool_t enable); -bool_t sal_nat_helper_enabled(Sal *sal); - -LINPHONE_PUBLIC void sal_set_dns_timeout(Sal* sal,int timeout); -LINPHONE_PUBLIC int sal_get_dns_timeout(const Sal* sal); -LINPHONE_PUBLIC void sal_set_transport_timeout(Sal* sal,int timeout); -LINPHONE_PUBLIC int sal_get_transport_timeout(const Sal* sal); -void sal_set_dns_servers(Sal *sal, const MSList *servers); -LINPHONE_PUBLIC void sal_enable_dns_srv(Sal *sal, bool_t enable); -LINPHONE_PUBLIC bool_t sal_dns_srv_enabled(const Sal *sal); -LINPHONE_PUBLIC void sal_enable_dns_search(Sal *sal, bool_t enable); -LINPHONE_PUBLIC bool_t sal_dns_search_enabled(const Sal *sal); -LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file); -LINPHONE_PUBLIC const char *sal_get_dns_user_hosts_file(const Sal *sal); unsigned int sal_get_random(void); LINPHONE_PUBLIC char *sal_get_random_token(int size); unsigned char * sal_get_random_bytes(unsigned char *ret, size_t size); +#if 0 belle_sip_source_t * sal_create_timer(Sal *sal, belle_sip_source_func_t func, void *data, unsigned int timeout_value_ms, const char* timer_name); void sal_cancel_timer(Sal *sal, belle_sip_source_t *timer); +#endif //SalBodyHandler * sal_body_handler_new(const char *type, const char *subtype, void *data, size_t size, const char *encoding); SalBodyHandler * sal_body_handler_new(void); @@ -935,6 +637,9 @@ const char * sal_body_handler_get_type(const SalBodyHandler *body_handler); void sal_body_handler_set_type(SalBodyHandler *body_handler, const char *type); const char * sal_body_handler_get_subtype(const SalBodyHandler *body_handler); void sal_body_handler_set_subtype(SalBodyHandler *body_handler, const char *subtype); +const belle_sip_list_t * sal_body_handler_get_content_type_parameters_names(const SalBodyHandler *body_handler); +const char * sal_body_handler_get_content_type_parameter(const SalBodyHandler *body_handler, const char *name); +void sal_body_handler_set_content_type_parameter(SalBodyHandler *body_handler, const char *paramName, const char *paramValue); const char * sal_body_handler_get_encoding(const SalBodyHandler *body_handler); void sal_body_handler_set_encoding(SalBodyHandler *body_handler, const char *encoding); void * sal_body_handler_get_data(const SalBodyHandler *body_handler); @@ -943,27 +648,19 @@ size_t sal_body_handler_get_size(const SalBodyHandler *body_handler); void sal_body_handler_set_size(SalBodyHandler *body_handler, size_t size); bool_t sal_body_handler_is_multipart(const SalBodyHandler *body_handler); SalBodyHandler * sal_body_handler_get_part(const SalBodyHandler *body_handler, int idx); +const belle_sip_list_t * sal_body_handler_get_parts(const SalBodyHandler *body_handler); SalBodyHandler * sal_body_handler_find_part_by_header(const SalBodyHandler *body_handler, const char *header_name, const char *header_value); const char * sal_body_handler_get_header(const SalBodyHandler *body_handler, const char *header_name); +const belle_sip_list_t* sal_body_handler_get_headers(const SalBodyHandler *body_handler); /*this function parses a document with key=value pairs separated by new lines, and extracts the value for a given key*/ int sal_lines_get_value(const char *data, const char *key, char *value, size_t value_size); -LINPHONE_PUBLIC void *sal_get_stack_impl(Sal *sal); -const char* sal_op_get_public_address(SalOp *sal, int *port); -const char* sal_op_get_local_address(SalOp *sal, int *port); unsigned long sal_begin_background_task(const char *name, void (*max_time_reached)(void *), void *data); void sal_end_background_task(unsigned long id); /*Some old equipment may not only rely on attribute sendonly/recvonly/sendrecv/inative*/ -void sal_op_cnx_ip_to_0000_if_sendonly_enable(SalOp *sal,bool_t yesno); -bool_t sal_op_cnx_ip_to_0000_if_sendonly_enabled(SalOp *sal); - -void sal_set_http_proxy_host(Sal *sal, const char *host) ; -void sal_set_http_proxy_port(Sal *sal, int port) ; -const char *sal_get_http_proxy_host(const Sal *sal); -int sal_get_http_proxy_port(const Sal *sal); #ifdef __cplusplus } diff --git a/src/c-wrapper/internal/c-tools.cpp b/src/c-wrapper/internal/c-tools.cpp new file mode 100644 index 000000000..32fb869b4 --- /dev/null +++ b/src/c-wrapper/internal/c-tools.cpp @@ -0,0 +1,42 @@ +/* + * c-tools.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifdef DEBUG + #include +#endif + +#include "c-tools.h" +#include "object/base-object.h" +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +#ifdef DEBUG + void Wrapper::setName (belle_sip_object_t *cObject, const BaseObject *cppObject) { + belle_sip_object_set_name(cObject, typeid(*cppObject).name()); + } + + void Wrapper::setName (belle_sip_object_t *cObject, const ClonableObject *cppObject) { + belle_sip_object_set_name(cObject, typeid(*cppObject).name()); + } +#endif + +LINPHONE_END_NAMESPACE diff --git a/src/c-wrapper/internal/c-tools.h b/src/c-wrapper/internal/c-tools.h new file mode 100644 index 000000000..e2520dcc3 --- /dev/null +++ b/src/c-wrapper/internal/c-tools.h @@ -0,0 +1,856 @@ +/* + * c-tools.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_C_TOOLS_H_ +#define _L_C_TOOLS_H_ + +#include + +#include + +#include "linphone/utils/utils.h" + +#include "object/property-container.h" + +// ============================================================================= +// Internal. +// ============================================================================= + +#ifdef DEBUG + #define L_INTERNAL_WRAPPER_CONSTEXPR +#else + #define L_INTERNAL_WRAPPER_CONSTEXPR constexpr +#endif + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- +// MetaInfo. +// ----------------------------------------------------------------------------- + +template +struct CppTypeMetaInfo { + enum { + defined = false, + isSubtype = false + }; + typedef void cType; +}; + +template +struct CTypeMetaInfo { + enum { + defined = false + }; + typedef void cppType; +}; + +// --------------------------------------------------------------------------- +// IsCppObject traits. +// --------------------------------------------------------------------------- + +template +struct IsCppObject { + enum { + value = std::is_base_of::value || std::is_base_of::value + }; +}; + +template +struct IsPrivateCppObject { + enum { + value = std::is_base_of::value || + std::is_base_of::value + }; +}; + +template +struct IsRegisteredCppObject { + enum { + value = CppTypeMetaInfo::defined && ( + !CppTypeMetaInfo::isSubtype || + std::is_base_of::cType>::cppType, CppType>::value + ) + }; +}; + +// --------------------------------------------------------------------------- +// IsDefined traits. +// --------------------------------------------------------------------------- + +template +struct IsDefinedBaseCppObject { + enum { + value = IsRegisteredCppObject::value && std::is_base_of::value + }; +}; + +template +struct IsDefinedCppObject { + enum { + value = IsDefinedBaseCppObject::value && std::is_base_of::value + }; +}; + +template +struct IsDefinedClonableCppObject { + enum { + value = IsRegisteredCppObject::value && std::is_base_of::value + }; +}; + +class Wrapper { +private: + // --------------------------------------------------------------------------- + // Wrapped Objects. + // --------------------------------------------------------------------------- + + enum class WrappedObjectOwner : int { + External, + Internal + }; + + template + struct WrappedBaseObject { + belle_sip_object_t base; + std::shared_ptr cppPtr; + std::weak_ptr weakCppPtr; + + // By default: External. + WrappedObjectOwner owner; + }; + + template + struct WrappedClonableObject { + belle_sip_object_t base; + CppType *cppPtr; + + // By default: External. + WrappedObjectOwner owner; + }; + + // --------------------------------------------------------------------------- + // Debug tools. + // --------------------------------------------------------------------------- + + #ifdef DEBUG + static void setName (belle_sip_object_t *cObject, const BaseObject *cppObject); + static void setName (belle_sip_object_t *cObject, const ClonableObject *cppObject); + #endif + + // --------------------------------------------------------------------------- + // Runtime checker. + // --------------------------------------------------------------------------- + + [[noreturn]] static inline void abort (const char *message) { + std::cerr << "[FATAL C-WRAPPER]" << message << std::endl; + std::terminate(); + } + + // --------------------------------------------------------------------------- + // Get cpp ptr (shared if BaseObject, not shared if ClonableObject) + // from cpp object. + // --------------------------------------------------------------------------- + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline std::shared_ptr getResolvedCppPtr (const CppType *cppObject) { + if (L_UNLIKELY(!cppObject)) + return nullptr; + + try { + typedef typename std::decaygetSharedFromThis())>::type SharedFromThisType; + + return std::static_pointer_cast( + std::const_pointer_cast(cppObject->getSharedFromThis()) + ); + } catch (const std::bad_weak_ptr &e) { + abort(e.what()); + } + + L_ASSERT(false); + return nullptr; + } + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static constexpr const CppType *getResolvedCppPtr (const CppType *cppObject) { + return cppObject; + } + + // --------------------------------------------------------------------------- + // Casts. + // --------------------------------------------------------------------------- + + template< + typename CppDerivedPrivateType, + typename CppBasePrivateType, + typename = typename std::enable_if::value, CppDerivedPrivateType>::type + > + static L_INTERNAL_WRAPPER_CONSTEXPR CppDerivedPrivateType *cast (CppBasePrivateType *base) { + #ifdef DEBUG + if (!base) + return static_cast(base); + + CppDerivedPrivateType *derived = dynamic_cast(base); + if (!derived) + abort("Invalid cast."); + return derived; + #else + return static_cast(base); + #endif + } + +public: + // --------------------------------------------------------------------------- + // Back ptr reset, used by uninit c object function. + // --------------------------------------------------------------------------- + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static void uninitBaseCppObject (CType *cObject) { + WrappedBaseObject *wrappedObject = reinterpret_cast *>(cObject); + + std::shared_ptr cppObject = wrappedObject->owner == WrappedObjectOwner::Internal + ? wrappedObject->weakCppPtr.lock() + : wrappedObject->cppPtr; + + if (cppObject) + cppObject->setCBackPtr(nullptr); + + wrappedObject->cppPtr.~shared_ptr(); + wrappedObject->weakCppPtr.~weak_ptr(); + } + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static void uninitClonableCppObject (CType *cObject) { + WrappedClonableObject *wrappedObject = reinterpret_cast *>(cObject); + if (wrappedObject->owner == WrappedObjectOwner::External) + delete wrappedObject->cppPtr; + } + + // --------------------------------------------------------------------------- + // Belle sip handlers. + // Deal with floating references. + // --------------------------------------------------------------------------- + + static void onBelleSipFirstRef (belle_sip_object_t *base) { + WrappedBaseObject *wrappedObject = reinterpret_cast *>(base); + if (wrappedObject->owner == WrappedObjectOwner::Internal) + wrappedObject->cppPtr = wrappedObject->weakCppPtr.lock(); + } + + static void onBelleSipLastRef (belle_sip_object_t *base) { + WrappedBaseObject *wrappedObject = reinterpret_cast *>(base); + if (wrappedObject->owner == WrappedObjectOwner::Internal) + wrappedObject->cppPtr.reset(); + } + + // --------------------------------------------------------------------------- + // Get private data of cpp Object. + // --------------------------------------------------------------------------- + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static constexpr decltype(std::declval().getPrivate()) getPrivate (CppType *cppObject) { + return cppObject->getPrivate(); + } + + // --------------------------------------------------------------------------- + // Deal with cpp ptr destruction. + // --------------------------------------------------------------------------- + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static void handleObjectDestruction (CppType *cppObject) { + void *value = cppObject->getCBackPtr(); + if (value && static_cast *>(value)->owner == WrappedObjectOwner::Internal) + belle_sip_object_unref(value); + } + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static void handleClonableObjectDestruction (CppType *cppObject) { + void *value = cppObject->getCBackPtr(); + if (value && static_cast *>(value)->owner == WrappedObjectOwner::Internal) + belle_sip_object_unref(value); + } + + // --------------------------------------------------------------------------- + // Get c/cpp ptr helpers. + // --------------------------------------------------------------------------- + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline std::shared_ptr getCppPtrFromC (CType *cObject) { + #ifdef DEBUG + typedef typename CTypeMetaInfo::cppType BaseType; + typedef CppType DerivedType; + + std::shared_ptr cppObject; + { + WrappedBaseObject *wrappedObject = reinterpret_cast *>(cObject); + cppObject = wrappedObject->owner == WrappedObjectOwner::Internal + ? wrappedObject->weakCppPtr.lock() + : wrappedObject->cppPtr; + } + + if (!cppObject) + abort("Cpp Object is null."); + + std::shared_ptr derivedCppObject = std::static_pointer_cast(cppObject); + if (!derivedCppObject) + abort("Invalid derived cpp object."); + + return derivedCppObject; + #else + WrappedBaseObject *wrappedObject = reinterpret_cast *>(cObject); + return wrappedObject->owner == WrappedObjectOwner::Internal + ? wrappedObject->weakCppPtr.lock() + : wrappedObject->cppPtr; + #endif + } + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline std::shared_ptr getCppPtrFromC (const CType *cObject) { + return getCppPtrFromC::type, CppType>(const_cast(cObject)); + } + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static L_INTERNAL_WRAPPER_CONSTEXPR CppType *getCppPtrFromC (CType *cObject) { + #ifdef DEBUG + typedef typename CTypeMetaInfo::cppType BaseType; + typedef CppType DerivedType; + + BaseType *cppObject = reinterpret_cast *>(cObject)->cppPtr; + if (!cppObject) + abort("Cpp Object is null."); + + DerivedType *derivedCppObject = dynamic_cast(cppObject); + if (!derivedCppObject) + abort("Invalid derived cpp object."); + + return derivedCppObject; + #else + return reinterpret_cast *>(cObject)->cppPtr; + #endif + } + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static L_INTERNAL_WRAPPER_CONSTEXPR const CppType *getCppPtrFromC (const CType *cObject) { + return getCppPtrFromC(const_cast(cObject)); + } + + // --------------------------------------------------------------------------- + // Set c/cpp ptr helpers. + // --------------------------------------------------------------------------- + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline void setCppPtrFromC (CType *cObject, const std::shared_ptr &cppObject) { + WrappedBaseObject *wrappedObject = reinterpret_cast *>(cObject); + std::shared_ptr oldCppObject; + + if (wrappedObject->owner == WrappedObjectOwner::Internal) { + oldCppObject = wrappedObject->weakCppPtr.lock(); + wrappedObject->weakCppPtr = cppObject; + if (reinterpret_cast(cObject)->ref > 1) + wrappedObject->cppPtr = cppObject; + else + wrappedObject->cppPtr.reset(); + } else { + oldCppObject = wrappedObject->cppPtr; + wrappedObject->cppPtr = cppObject; + } + + if (oldCppObject) + oldCppObject->setCBackPtr(nullptr); + cppObject->setCBackPtr(cObject); + + #ifdef DEBUG + setName(reinterpret_cast(cObject), cppObject.get()); + #endif + } + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline void setCppPtrFromC (CType *cObject, CppType *cppObject) { + CppType **cppObjectAddr = &reinterpret_cast *>(cObject)->cppPtr; + if (*cppObjectAddr == cppObject) + return; + + if (reinterpret_cast *>(cObject)->owner == WrappedObjectOwner::External) + delete *cppObjectAddr; + + *cppObjectAddr = cppObject; + (*cppObjectAddr)->setCBackPtr(cObject); + + #ifdef DEBUG + setName(reinterpret_cast(cObject), cppObject); + #endif + } + + // --------------------------------------------------------------------------- + // Get c back ptr resolver helpers. + // --------------------------------------------------------------------------- + +private: + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline typename CppTypeMetaInfo::cType *getCBackPtrResolver (const std::shared_ptr &cppObject) { + return getCBackPtr(cppObject); + } + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline typename CppTypeMetaInfo::cType *getCBackPtrResolver (const CppType *cppObject) { + if (L_UNLIKELY(!cppObject)) + return nullptr; + + typedef typename CppTypeMetaInfo::cType RetType; + + void *value = cppObject->getCBackPtr(); + if (value) + return static_cast(value); + + RetType *cObject = CppTypeMetaInfo::init(); + reinterpret_cast *>(cObject)->owner = WrappedObjectOwner::Internal; + setCppPtrFromC(cObject, const_cast(cppObject)); + + return cObject; + } + + // --------------------------------------------------------------------------- + // Get c back ptr helpers. + // --------------------------------------------------------------------------- + +public: + template< + typename CppType, + typename = typename std::enable_if< + IsDefinedCppObject::value || IsDefinedClonableCppObject::value, CppType + >::type + > + static inline typename CppTypeMetaInfo::cType *getCBackPtr (const CppType *cppObject) { + return getCBackPtrResolver(getResolvedCppPtr(cppObject)); + } + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline typename CppTypeMetaInfo::cType *getCBackPtr (const std::shared_ptr &cppObject) { + if (L_UNLIKELY(!cppObject)) + return nullptr; + + typedef typename CppTypeMetaInfo::cType RetType; + + void *value = cppObject->getCBackPtr(); + if (value) + return static_cast(value); + + RetType *cObject = CppTypeMetaInfo::init(); + reinterpret_cast *>(cObject)->owner = WrappedObjectOwner::Internal; + setCppPtrFromC(cObject, cppObject); + + return cObject; + } + + // --------------------------------------------------------------------------- + // Get/set user data. + // --------------------------------------------------------------------------- + + static inline void *getUserData (const PropertyContainer *propertyContainer) { + L_ASSERT(propertyContainer); + return propertyContainer->getProperty("LinphonePrivate::Wrapper::userData").getValue(); + } + + static inline void setUserData (PropertyContainer *propertyContainer, void *value) { + L_ASSERT(propertyContainer); + propertyContainer->setProperty("LinphonePrivate::Wrapper::userData", value); + } + + // --------------------------------------------------------------------------- + // List conversions. + // --------------------------------------------------------------------------- + + template + static inline bctbx_list_t *getCListFromCppList (const std::list &cppList) { + bctbx_list_t *result = nullptr; + for (const auto &value : cppList) + result = bctbx_list_append(result, value); + return result; + } + + template + static inline std::list getCppListFromCList (const bctbx_list_t *cList) { + std::list result; + for (auto it = cList; it; it = bctbx_list_next(it)) + result.push_back(static_cast(bctbx_list_get_data(it))); + return result; + } + + // --------------------------------------------------------------------------- + // Resolved list conversions. + // --------------------------------------------------------------------------- + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline bctbx_list_t *getResolvedCListFromCppList (const std::list> &cppList) { + bctbx_list_t *result = nullptr; + for (const auto &value : cppList) + result = bctbx_list_append(result, belle_sip_object_ref(getCBackPtr(value))); + return result; + } + + template< + typename CppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline bctbx_list_t *getResolvedCListFromCppList (const std::list &cppList) { + bctbx_list_t *result = nullptr; + for (const auto &value : cppList) { + auto cValue = getCBackPtr(new CppType(value)); + reinterpret_cast *>(cValue)->owner = WrappedObjectOwner::External; + result = bctbx_list_append(result, cValue); + } + return result; + } + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline std::list> getResolvedCppListFromCList (const bctbx_list_t *cList) { + std::list> result; + for (auto it = cList; it; it = bctbx_list_next(it)) + result.push_back(getCppPtrFromC(static_cast(bctbx_list_get_data(it)))); + return result; + } + + template< + typename CType, + typename CppType = typename CTypeMetaInfo::cppType, + typename = typename std::enable_if::value, CppType>::type + > + static inline std::list getResolvedCppListFromCList (const bctbx_list_t *cList) { + std::list result; + for (auto it = cList; it; it = bctbx_list_next(it)) + result.push_back(*getCppPtrFromC(static_cast(bctbx_list_get_data(it)))); + return result; + } + +private: + Wrapper (); + + L_DISABLE_COPY(Wrapper); +}; + +LINPHONE_END_NAMESPACE + +#undef L_INTERNAL_WRAPPER_CONSTEXPR + +#define L_INTERNAL_C_NO_XTOR(C_OBJECT) +#define L_INTERNAL_C_NO_CLONE_C(C_DEST_OBJECT, C_SRC_OBJECT) + +#define L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, ...) \ + static_assert(LinphonePrivate::CTypeMetaInfo::defined, "Type is not defined."); \ + static_assert( \ + LinphonePrivate::IsDefinedBaseCppObject< \ + LinphonePrivate::CTypeMetaInfo::cppType \ + >::value, \ + "Type is not declared as base object." \ + ); \ + struct _Linphone ## C_TYPE { \ + belle_sip_object_t base; \ + std::shared_ptr cppPtr; \ + std::weak_ptr weakCppPtr; \ + int owner; \ + __VA_ARGS__ \ + }; + +#define L_INTERNAL_DECLARE_C_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR) \ + BELLE_SIP_DECLARE_VPTR_NO_EXPORT(Linphone ## C_TYPE); \ + Linphone ## C_TYPE *_linphone_ ## C_TYPE ## _init () { \ + Linphone ## C_TYPE *object = belle_sip_object_new(Linphone ## C_TYPE); \ + new(&object->cppPtr) std::shared_ptr(); \ + new(&object->weakCppPtr) std::weak_ptr(); \ + CONSTRUCTOR(object); \ + return object; \ + } \ + static void _linphone_ ## C_TYPE ## _uninit (Linphone ## C_TYPE *object) { \ + DESTRUCTOR(object); \ + LinphonePrivate::Wrapper::uninitBaseCppObject(object); \ + } \ + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(Linphone ## C_TYPE); \ + BELLE_SIP_INSTANCIATE_VPTR2( \ + Linphone ## C_TYPE, \ + belle_sip_object_t, \ + _linphone_ ## C_TYPE ## _uninit, \ + NULL, \ + NULL, \ + LinphonePrivate::Wrapper::onBelleSipFirstRef, \ + LinphonePrivate::Wrapper::onBelleSipLastRef, \ + FALSE \ + ); + +#define L_INTERNAL_DECLARE_C_CLONABLE_OBJECT(C_TYPE, ...) \ + static_assert(LinphonePrivate::CTypeMetaInfo::defined, "Type is not defined."); \ + static_assert( \ + LinphonePrivate::IsDefinedClonableCppObject< \ + LinphonePrivate::CTypeMetaInfo::cppType \ + >::value, \ + "Type is not declared as clonable object." \ + ); \ + struct _Linphone ## C_TYPE { \ + belle_sip_object_t base; \ + L_CPP_TYPE_OF_C_TYPE(C_TYPE) *cppPtr; \ + int owner; \ + __VA_ARGS__ \ + }; \ + +#define L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, CLONE_C) \ + BELLE_SIP_DECLARE_VPTR_NO_EXPORT(Linphone ## C_TYPE); \ + Linphone ## C_TYPE *_linphone_ ## C_TYPE ## _init () { \ + Linphone ## C_TYPE *object = belle_sip_object_new(Linphone ## C_TYPE); \ + CONSTRUCTOR(object); \ + return object; \ + } \ + static void _linphone_ ## C_TYPE ## _uninit (Linphone ## C_TYPE * object) { \ + DESTRUCTOR(object); \ + LinphonePrivate::Wrapper::uninitClonableCppObject(object); \ + } \ + static void _linphone_ ## C_TYPE ## _clone (Linphone ## C_TYPE *dest, const Linphone ## C_TYPE *src) { \ + L_ASSERT(src->cppPtr); \ + dest->cppPtr = new L_CPP_TYPE_OF_C_TYPE(C_TYPE)(*src->cppPtr); \ + CLONE_C(dest, src); \ + } \ + BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(Linphone ## C_TYPE); \ + BELLE_SIP_INSTANCIATE_VPTR( \ + Linphone ## C_TYPE, belle_sip_object_t, \ + _linphone_ ## C_TYPE ## _uninit, \ + _linphone_ ## C_TYPE ## _clone, \ + NULL, \ + FALSE \ + ); + +// ============================================================================= +// Public Wrapper API. +// ============================================================================= + +// ----------------------------------------------------------------------------- +// Register type. +// ----------------------------------------------------------------------------- + +#define L_REGISTER_TYPE(CPP_TYPE, C_TYPE) \ + extern Linphone ## C_TYPE *_linphone_ ## C_TYPE ## _init (); \ + LINPHONE_BEGIN_NAMESPACE \ + class CPP_TYPE; \ + template<> \ + struct CppTypeMetaInfo { \ + enum { \ + defined = true, \ + isSubtype = false \ + }; \ + typedef Linphone ## C_TYPE cType; \ + static inline Linphone ## C_TYPE *init () { \ + return _linphone_ ## C_TYPE ## _init(); \ + } \ + }; \ + template<> \ + struct CTypeMetaInfo { \ + enum { defined = true }; \ + typedef CPP_TYPE cppType; \ + }; \ + LINPHONE_END_NAMESPACE + +#define L_REGISTER_SUBTYPE(CPP_TYPE, CPP_SUBTYPE) \ + LINPHONE_BEGIN_NAMESPACE \ + class CPP_SUBTYPE; \ + static_assert(CppTypeMetaInfo::defined, "Base type is not defined"); \ + template<> \ + struct CppTypeMetaInfo { \ + enum { \ + defined = true, \ + isSubtype = true \ + }; \ + typedef CppTypeMetaInfo::cType cType; \ + static inline typename CppTypeMetaInfo::cType *init () { \ + return CppTypeMetaInfo::init(); \ + } \ + }; \ + LINPHONE_END_NAMESPACE + +#define L_CPP_TYPE_OF_C_TYPE(C_TYPE) \ + LinphonePrivate::CTypeMetaInfo::cppType + +#define L_CPP_TYPE_OF_C_OBJECT(C_OBJECT) \ + LinphonePrivate::CTypeMetaInfo::type>::type>::cppType + +// ----------------------------------------------------------------------------- +// C object declaration. +// ----------------------------------------------------------------------------- + +// Declare wrapped C object with constructor/destructor. +#define L_DECLARE_C_OBJECT_IMPL_WITH_XTORS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, ...) \ + L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, __VA_ARGS__) \ + L_INTERNAL_DECLARE_C_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR) + +// Declare wrapped C object. +#define L_DECLARE_C_OBJECT_IMPL(C_TYPE, ...) \ + L_INTERNAL_DECLARE_C_OBJECT(C_TYPE, __VA_ARGS__) \ + L_INTERNAL_DECLARE_C_OBJECT_FUNCTIONS(C_TYPE, L_INTERNAL_C_NO_XTOR, L_INTERNAL_C_NO_XTOR) + +// Declare clonable wrapped C object with constructor/destructor and clone_c. +#define L_DECLARE_C_CLONABLE_OBJECT_IMPL_WITH_XTORS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, CLONE_C, ...) \ + L_INTERNAL_DECLARE_C_CLONABLE_OBJECT(C_TYPE, __VA_ARGS__) \ + L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, CONSTRUCTOR, DESTRUCTOR, CLONE_C) + +// Declare clonable wrapped C object. +#define L_DECLARE_C_CLONABLE_OBJECT_IMPL(C_TYPE, ...) \ + L_INTERNAL_DECLARE_C_CLONABLE_OBJECT(C_TYPE, __VA_ARGS__) \ + L_INTERNAL_DECLARE_C_CLONABLE_OBJECT_FUNCTIONS(C_TYPE, L_INTERNAL_C_NO_XTOR, L_INTERNAL_C_NO_XTOR, L_INTERNAL_C_NO_CLONE_C) + +// ----------------------------------------------------------------------------- +// Helpers. +// ----------------------------------------------------------------------------- + +// String conversions between C/C++. +#define L_STRING_TO_C(STR) ((STR).empty() ? NULL : (STR).c_str()) +#define L_C_TO_STRING(STR) ((STR) == NULL ? std::string() : (STR)) + +// Call the init function of wrapped C object. +#define L_INIT(C_TYPE) _linphone_ ## C_TYPE ## _init() + +// Get/set the cpp-ptr of a wrapped C object. +#define L_GET_CPP_PTR_FROM_C_OBJECT_1_ARGS(C_OBJECT) \ + LinphonePrivate::Wrapper::getCppPtrFromC(C_OBJECT) +#define L_GET_CPP_PTR_FROM_C_OBJECT_2_ARGS(C_OBJECT, CPP_TYPE) \ + LinphonePrivate::Wrapper::getCppPtrFromC< \ + std::remove_pointer::type, \ + LinphonePrivate::CPP_TYPE \ + >(C_OBJECT) + +#define L_GET_CPP_PTR_FROM_C_OBJECT_MACRO_CHOOSER(...) \ + L_EXPAND(L_GET_ARG_3(__VA_ARGS__, L_GET_CPP_PTR_FROM_C_OBJECT_2_ARGS, L_GET_CPP_PTR_FROM_C_OBJECT_1_ARGS)) + +#define L_GET_CPP_PTR_FROM_C_OBJECT(...) \ + L_EXPAND(L_GET_CPP_PTR_FROM_C_OBJECT_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)) + +// Set the cpp-ptr of a wrapped C object. +#define L_SET_CPP_PTR_FROM_C_OBJECT(C_OBJECT, CPP_OBJECT) \ + LinphonePrivate::Wrapper::setCppPtrFromC(C_OBJECT, CPP_OBJECT) + +// Get the private data of a shared or simple cpp-ptr. +#define L_GET_PRIVATE_1_ARGS(CPP_OBJECT) \ + LinphonePrivate::Wrapper::getPrivate(LinphonePrivate::Utils::getPtr(CPP_OBJECT)) +#define L_GET_PRIVATE_2_ARGS(CPP_OBJECT, CPP_TYPE) \ + LinphonePrivate::Wrapper::cast(L_GET_PRIVATE_1_ARGS(CPP_OBJECT)) + +#define L_GET_PRIVATE_MACRO_CHOOSER(...) \ + L_EXPAND(L_GET_ARG_3(__VA_ARGS__, L_GET_PRIVATE_2_ARGS, L_GET_PRIVATE_1_ARGS)) + +#define L_GET_PRIVATE(...) \ + L_EXPAND(L_GET_PRIVATE_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)) + +// Get the private data of a shared or simple cpp-ptr of a wrapped C object. +#define L_GET_PRIVATE_FROM_C_OBJECT_1_ARGS(C_OBJECT) \ + L_GET_PRIVATE_1_ARGS(LinphonePrivate::Utils::getPtr(L_GET_CPP_PTR_FROM_C_OBJECT_1_ARGS(C_OBJECT))) +#define L_GET_PRIVATE_FROM_C_OBJECT_2_ARGS(C_OBJECT, CPP_TYPE) \ + L_GET_PRIVATE_1_ARGS(LinphonePrivate::Utils::getPtr(L_GET_CPP_PTR_FROM_C_OBJECT_2_ARGS(C_OBJECT, CPP_TYPE))) + +#define L_GET_PRIVATE_FROM_C_OBJECT_MACRO_CHOOSER(...) \ + L_EXPAND(L_GET_ARG_3(__VA_ARGS__, L_GET_PRIVATE_FROM_C_OBJECT_2_ARGS, L_GET_PRIVATE_FROM_C_OBJECT_1_ARGS)) + +#define L_GET_PRIVATE_FROM_C_OBJECT(...) \ + L_EXPAND(L_GET_PRIVATE_FROM_C_OBJECT_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)) + +// Get the wrapped C object of a C++ object. +#define L_GET_C_BACK_PTR(CPP_OBJECT) \ + LinphonePrivate::Wrapper::getCBackPtr(CPP_OBJECT) + +// Get/set user data on a wrapped C object. +#define L_GET_USER_DATA_FROM_C_OBJECT(C_OBJECT) \ + LinphonePrivate::Wrapper::getUserData( \ + LinphonePrivate::Utils::getPtr(L_GET_CPP_PTR_FROM_C_OBJECT(C_OBJECT)) \ + ) +#define L_SET_USER_DATA_FROM_C_OBJECT(C_OBJECT, VALUE) \ + LinphonePrivate::Wrapper::setUserData( \ + LinphonePrivate::Utils::getPtr(L_GET_CPP_PTR_FROM_C_OBJECT(C_OBJECT)), \ + VALUE \ + ) + +// Transforms cpp list and c list. +#define L_GET_C_LIST_FROM_CPP_LIST(CPP_LIST) \ + LinphonePrivate::Wrapper::getCListFromCppList(CPP_LIST) +#define L_GET_CPP_LIST_FROM_C_LIST(C_LIST, TYPE) \ + LinphonePrivate::Wrapper::getCppListFromCList(C_LIST) + +// Transforms cpp list and c list and convert cpp object to c object. +#define L_GET_RESOLVED_C_LIST_FROM_CPP_LIST(CPP_LIST) \ + LinphonePrivate::Wrapper::getResolvedCListFromCppList(CPP_LIST) +#define L_GET_RESOLVED_CPP_LIST_FROM_C_LIST(C_LIST, C_TYPE) \ + LinphonePrivate::Wrapper::getResolvedCppListFromCList(C_LIST) + +#endif // ifndef _L_C_TOOLS_H_ diff --git a/src/call/call-p.h b/src/call/call-p.h new file mode 100644 index 000000000..d75942501 --- /dev/null +++ b/src/call/call-p.h @@ -0,0 +1,132 @@ +/* + * call-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_P_H_ +#define _L_CALL_P_H_ + +#include "call.h" +#include "conference/conference.h" +#include "conference/session/call-session-listener.h" +#include "object/object-p.h" +#include "utils/background-task.h" + +// TODO: Remove me later. +#include "private.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSession; +class RealTimeTextChatRoom; + +class CallPrivate : public ObjectPrivate, public CallSessionListener { +public: + void initiateIncoming (); + bool initiateOutgoing (); + void iterate (time_t currentRealTime, bool oneSecondElapsed); + void startIncomingNotification (); + + void pauseForTransfer (); + int startInvite (const Address *destination); + std::shared_ptr startReferredCall (const MediaSessionParams *params); + + virtual std::shared_ptr getActiveSession () const { return nullptr; } + bool getAudioMuted () const; + std::shared_ptr getChatRoom (); + + LinphoneProxyConfig *getDestProxy () const; + IceSession *getIceSession () const; + unsigned int getMediaStartCount () const; + MediaStream *getMediaStream (LinphoneStreamType type) const; + SalCallOp *getOp () const; + bool getRingingBeep () const { return ringingBeep; } + void setAudioMuted (bool value); + void setRingingBeep (bool value) { ringingBeep = value; } + LinphoneCallStats *getStats (LinphoneStreamType type) const; + + void createPlayer () const; + + void initializeMediaStreams (); + void stopMediaStreams (); + +private: + void requestNotifyNextVideoFrameDecoded (); + void startRemoteRing (); + void terminateBecauseOfLostMedia (); + + /* CallSessionListener */ + void onAckBeingSent (const std::shared_ptr &session, LinphoneHeaders *headers) override; + void onAckReceived (const std::shared_ptr &session, LinphoneHeaders *headers) override; + void onBackgroundTaskToBeStarted (const std::shared_ptr &session) override; + void onBackgroundTaskToBeStopped (const std::shared_ptr &session) override; + bool onCallSessionAccepted (const std::shared_ptr &session) override; + void onCallSessionConferenceStreamStarting (const std::shared_ptr &session, bool mute) override; + void onCallSessionConferenceStreamStopping (const std::shared_ptr &session) override; + void onCallSessionEarlyFailed (const std::shared_ptr &session, LinphoneErrorInfo *ei) override; + void onCallSessionSetReleased (const std::shared_ptr &session) override; + void onCallSessionSetTerminated (const std::shared_ptr &session) override; + void onCallSessionStartReferred (const std::shared_ptr &session) override; + void onCallSessionStateChanged (const std::shared_ptr &session, CallSession::State state, const std::string &message) override; + void onCallSessionTransferStateChanged (const std::shared_ptr &session, CallSession::State state) override; + void onCheckForAcceptation (const std::shared_ptr &session) override; + void onDtmfReceived (const std::shared_ptr &session, char dtmf) override; + void onIncomingCallSessionNotified (const std::shared_ptr &session) override; + void onIncomingCallSessionStarted (const std::shared_ptr &session) override; + void onIncomingCallSessionTimeoutCheck (const std::shared_ptr &session, int elapsed, bool oneSecondElapsed) override; + void onInfoReceived (const std::shared_ptr &session, const LinphoneInfoMessage *im) override; + void onNoMediaTimeoutCheck (const std::shared_ptr &session, bool oneSecondElapsed) override; + void onEncryptionChanged (const std::shared_ptr &session, bool activated, const std::string &authToken) override; + void onCallSessionStateChangedForReporting (const std::shared_ptr &session) override; + void onRtcpUpdateForReporting (const std::shared_ptr &session, SalStreamType type) override; + void onStatsUpdated (const std::shared_ptr &session, const LinphoneCallStats *stats) override; + void onUpdateMediaInfoForReporting (const std::shared_ptr &session, int statsType) override; + void onResetCurrentSession (const std::shared_ptr &session) override; + void onSetCurrentSession (const std::shared_ptr &session) override; + void onFirstVideoFrameDecoded (const std::shared_ptr &session) override; + void onResetFirstVideoFrameDecoded (const std::shared_ptr &session) override; + void onPlayErrorTone (const std::shared_ptr &session, LinphoneReason reason) override; + void onRingbackToneRequested (const std::shared_ptr &session, bool requested) override; + void onStartRinging (const std::shared_ptr &session) override; + void onStopRinging (const std::shared_ptr &session) override; + void onStopRingingIfInCall (const std::shared_ptr &session) override; + void onStopRingingIfNeeded (const std::shared_ptr &session) override; + bool areSoundResourcesAvailable (const std::shared_ptr &session) override; + bool isPlayingRingbackTone (const std::shared_ptr &session) override; + void onRealTimeTextCharacterReceived (const std::shared_ptr &session, RealtimeTextReceivedCharacter *character) override; + void onTmmbrReceived(const std::shared_ptr &session, int streamIndex, int tmmbr) override; + void onSnapshotTaken(const std::shared_ptr &session, const char *file_path) override; + + mutable LinphonePlayer *player = nullptr; + + CallCallbackObj nextVideoFrameDecoded; + + bool ringingBeep = false; + bool playingRingbackTone = false; + + BackgroundTask bgTask; + + mutable std::shared_ptr chatRoom; + + L_DECLARE_PUBLIC(Call); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CALL_P_H_ diff --git a/src/call/call.cpp b/src/call/call.cpp new file mode 100644 index 000000000..e7d0348f2 --- /dev/null +++ b/src/call/call.cpp @@ -0,0 +1,949 @@ +/* + * call.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "c-wrapper/c-wrapper.h" +#include "call-p.h" +#include "chat/chat-room/real-time-text-chat-room-p.h" +#include "conference/params/media-session-params-p.h" +#include "conference/session/call-session-p.h" +#include "conference/session/media-session-p.h" +#include "core/core-p.h" +#include "logger/logger.h" + +#include "conference_private.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +bool CallPrivate::getAudioMuted () const { + return static_pointer_cast(getActiveSession())->getPrivate()->getAudioMuted(); +} + +shared_ptr CallPrivate::getChatRoom () { + L_Q(); + if (!chatRoom && (q->getState() != CallSession::State::End) && (q->getState() != CallSession::State::Released)) { + chatRoom = static_pointer_cast(q->getCore()->getOrCreateBasicChatRoom(q->getRemoteAddress(), true)); + chatRoom->getPrivate()->setCall(q->getSharedFromThis()); + } + return chatRoom; +} + +LinphoneProxyConfig *CallPrivate::getDestProxy () const { + return getActiveSession()->getPrivate()->getDestProxy(); +} + +IceSession *CallPrivate::getIceSession () const { + return static_pointer_cast(getActiveSession())->getPrivate()->getIceSession(); +} + +unsigned int CallPrivate::getMediaStartCount () const { + return static_pointer_cast(getActiveSession())->getPrivate()->getMediaStartCount(); +} + +MediaStream *CallPrivate::getMediaStream (LinphoneStreamType type) const { + return static_pointer_cast(getActiveSession())->getPrivate()->getMediaStream(type); +} + +SalCallOp * CallPrivate::getOp () const { + return getActiveSession()->getPrivate()->getOp(); +} + +void CallPrivate::setAudioMuted (bool value) { + static_pointer_cast(getActiveSession())->getPrivate()->setAudioMuted(value); +} + +LinphoneCallStats *CallPrivate::getStats (LinphoneStreamType type) const { + return static_pointer_cast(getActiveSession())->getPrivate()->getStats(type); +} + +// ----------------------------------------------------------------------------- + +void CallPrivate::initiateIncoming () { + getActiveSession()->initiateIncoming(); +} + +bool CallPrivate::initiateOutgoing () { + shared_ptr session = getActiveSession(); + bool defer = session->initiateOutgoing(); + session->getPrivate()->createOp(); + return defer; +} + +void CallPrivate::iterate (time_t currentRealTime, bool oneSecondElapsed) { + getActiveSession()->iterate(currentRealTime, oneSecondElapsed); +} + +void CallPrivate::startIncomingNotification () { + getActiveSession()->startIncomingNotification(); +} + +void CallPrivate::pauseForTransfer () { + static_pointer_cast(getActiveSession())->getPrivate()->pauseForTransfer(); +} + +int CallPrivate::startInvite (const Address *destination) { + return getActiveSession()->startInvite(destination, ""); +} + +shared_ptr CallPrivate::startReferredCall (const MediaSessionParams *params) { + L_Q(); + if (q->getState() != CallSession::State::Paused) { + pauseForTransfer(); + } + MediaSessionParams msp; + if (params) + msp = *params; + else { + msp.initDefault(q->getCore()); + msp.enableAudio(q->getCurrentParams()->audioEnabled()); + msp.enableVideo(q->getCurrentParams()->videoEnabled()); + } + lInfo() << "Starting new call to referred address " << q->getReferTo(); + L_GET_PRIVATE(&msp)->setReferer(getActiveSession()); + L_GET_PRIVATE(getActiveSession())->setReferPending(false); + LinphoneCallParams *lcp = L_GET_C_BACK_PTR(&msp); + LinphoneCall *newCall = linphone_core_invite_with_params(q->getCore()->getCCore(), q->getReferTo().c_str(), lcp); + if (newCall) { + getActiveSession()->getPrivate()->setTransferTarget(L_GET_PRIVATE_FROM_C_OBJECT(newCall)->getActiveSession()); + L_GET_PRIVATE_FROM_C_OBJECT(newCall)->getActiveSession()->getPrivate()->notifyReferState(); + } + return L_GET_CPP_PTR_FROM_C_OBJECT(newCall); +} + +// ----------------------------------------------------------------------------- + +void CallPrivate::createPlayer () const { + L_Q(); + player = linphone_call_build_player(L_GET_C_BACK_PTR(q)); +} + +// ----------------------------------------------------------------------------- + +void CallPrivate::initializeMediaStreams () { + static_pointer_cast(getActiveSession())->getPrivate()->initializeStreams(); +} + +void CallPrivate::stopMediaStreams () { + static_pointer_cast(getActiveSession())->getPrivate()->stopStreams(); +} + +// ----------------------------------------------------------------------------- + + +void CallPrivate::startRemoteRing () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + if (!lc->sound_conf.play_sndcard) + return; + + MSSndCard *ringCard = lc->sound_conf.lsd_card ? lc->sound_conf.lsd_card : lc->sound_conf.play_sndcard; + int maxRate = static_pointer_cast(getActiveSession())->getPrivate()->getLocalDesc()->streams[0].max_rate; + if (maxRate > 0) + ms_snd_card_set_preferred_sample_rate(ringCard, maxRate); + // We release sound before playing ringback tone + AudioStream *as = reinterpret_cast(getMediaStream(LinphoneStreamTypeAudio)); + if (as) + audio_stream_unprepare_sound(as); + if (lc->sound_conf.remote_ring) { + ms_snd_card_set_stream_type(ringCard, MS_SND_CARD_STREAM_VOICE); + lc->ringstream = ring_start(lc->factory, lc->sound_conf.remote_ring, 2000, ringCard); + } +} + +void CallPrivate::terminateBecauseOfLostMedia () { + L_Q(); + lInfo() << "Call [" << q << "]: Media connectivity with " << q->getRemoteAddress().asString() + << " is lost, call is going to be terminated"; + static_pointer_cast(getActiveSession())->terminateBecauseOfLostMedia(); + linphone_core_play_named_tone(q->getCore()->getCCore(), LinphoneToneCallLost); +} + +// ----------------------------------------------------------------------------- + +void CallPrivate::onAckBeingSent (const shared_ptr &session, LinphoneHeaders *headers) { + L_Q(); + linphone_call_notify_ack_processing(L_GET_C_BACK_PTR(q), headers, false); +} + +void CallPrivate::onAckReceived (const shared_ptr &session, LinphoneHeaders *headers) { + L_Q(); + linphone_call_notify_ack_processing(L_GET_C_BACK_PTR(q), headers, true); +} + +void CallPrivate::onBackgroundTaskToBeStarted (const shared_ptr &session) { + L_Q(); + bgTask.start(q->getCore(),30); +} + +void CallPrivate::onBackgroundTaskToBeStopped (const shared_ptr &session) { + bgTask.stop(); +} + +bool CallPrivate::onCallSessionAccepted (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + bool wasRinging = false; + + if (q->getCore()->getCurrentCall() != q->getSharedFromThis()) + linphone_core_preempt_sound_resources(lc); + + // Stop ringing + if (linphone_ringtoneplayer_is_started(lc->ringtoneplayer)) { + lInfo() << "Stop ringing"; + linphone_core_stop_ringing(lc); + wasRinging = true; + } + if (ringingBeep) { + linphone_core_stop_dtmf(lc); + ringingBeep = false; + } + return wasRinging; +} + +void CallPrivate::onCallSessionConferenceStreamStarting (const shared_ptr &session, bool mute) { + L_Q(); + if (q->getCore()->getCCore()->conf_ctx) { + linphone_conference_on_call_stream_starting(q->getCore()->getCCore()->conf_ctx, L_GET_C_BACK_PTR(q), mute); + } +} + +void CallPrivate::onCallSessionConferenceStreamStopping (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + if (lc->conf_ctx && _linphone_call_get_endpoint(L_GET_C_BACK_PTR(q))) + linphone_conference_on_call_stream_stopping(lc->conf_ctx, L_GET_C_BACK_PTR(q)); +} + +void CallPrivate::onCallSessionEarlyFailed (const shared_ptr &session, LinphoneErrorInfo *ei) { + L_Q(); + LinphoneCallLog *log = session->getLog(); + linphone_core_report_early_failed_call(q->getCore()->getCCore(), + linphone_call_log_get_dir(log), + linphone_address_clone(linphone_call_log_get_from(log)), + linphone_address_clone(linphone_call_log_get_to(log)), + ei); + linphone_call_unref(L_GET_C_BACK_PTR(q)); +} + +void CallPrivate::onCallSessionSetReleased (const shared_ptr &session) { + L_Q(); + linphone_call_unref(L_GET_C_BACK_PTR(q)); +} + +void CallPrivate::onCallSessionSetTerminated (const shared_ptr &session) { + L_Q(); + LinphoneCore *core = q->getCore()->getCCore(); + if (q->getSharedFromThis() == q->getCore()->getCurrentCall()) { + lInfo() << "Resetting the current call"; + q->getCore()->getPrivate()->setCurrentCall(nullptr); + } + if (q->getCore()->getPrivate()->removeCall(q->getSharedFromThis()) != 0) + lError() << "Could not remove the call from the list!!!"; + if (core->conf_ctx) + linphone_conference_on_call_terminating(core->conf_ctx, L_GET_C_BACK_PTR(q)); + if (ringingBeep) { + linphone_core_stop_dtmf(core); + ringingBeep = false; + } +#if 0 + if (lcall->chat_room) + linphone_chat_room_set_call(lcall->chat_room, nullptr); +#endif // if 0 + if (!q->getCore()->getPrivate()->hasCalls()) + ms_bandwidth_controller_reset_state(core->bw_controller); +} + +void CallPrivate::onCallSessionStartReferred (const shared_ptr &session) { + startReferredCall(nullptr); +} + +void CallPrivate::onCallSessionStateChanged (const shared_ptr &session, CallSession::State state, const string &message) { + L_Q(); + switch(state){ + case CallSession::State::OutgoingInit: + case CallSession::State::IncomingReceived: + getPlatformHelpers(q->getCore()->getCCore())->acquireWifiLock(); + getPlatformHelpers(q->getCore()->getCCore())->acquireMcastLock(); + getPlatformHelpers(q->getCore()->getCCore())->acquireCpuLock(); + break; + case CallSession::State::Released: + getPlatformHelpers(q->getCore()->getCCore())->releaseWifiLock(); + getPlatformHelpers(q->getCore()->getCCore())->releaseMcastLock(); + getPlatformHelpers(q->getCore()->getCCore())->releaseCpuLock(); + break; + default: + break; + } + linphone_call_notify_state_changed(L_GET_C_BACK_PTR(q), static_cast(state), message.c_str()); +} + +void CallPrivate::onCallSessionTransferStateChanged (const shared_ptr &session, CallSession::State state) { + L_Q(); + linphone_call_notify_transfer_state_changed(L_GET_C_BACK_PTR(q), static_cast(state)); +} + +void CallPrivate::onCheckForAcceptation (const shared_ptr &session) { + L_Q(); + list> calls = q->getCore()->getCalls(); + shared_ptr currentCall = q->getSharedFromThis(); + for (const auto &call : calls) { + if (call == currentCall) + continue; + switch (call->getState()) { + case CallSession::State::OutgoingInit: + case CallSession::State::OutgoingProgress: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + lInfo() << "Already existing call [" << call << "] in state [" << Utils::toString(call->getState()) + << "], canceling it before accepting new call [" << currentCall << "]"; + call->terminate(); + break; + default: + break; // Nothing to do + } + } +} + +void CallPrivate::onDtmfReceived (const shared_ptr &session, char dtmf) { + L_Q(); + linphone_call_notify_dtmf_received(L_GET_C_BACK_PTR(q), dtmf); +} + +void CallPrivate::onIncomingCallSessionNotified (const shared_ptr &session) { + L_Q(); + /* The call is acceptable so we can now add it to our list */ + q->getCore()->getPrivate()->addCall(q->getSharedFromThis()); +} + +void CallPrivate::onIncomingCallSessionStarted (const shared_ptr &session) { + L_Q(); + linphone_core_notify_incoming_call(q->getCore()->getCCore(), L_GET_C_BACK_PTR(q)); +} + +void CallPrivate::onIncomingCallSessionTimeoutCheck (const shared_ptr &session, int elapsed, bool oneSecondElapsed) { + L_Q(); + if (oneSecondElapsed) + lInfo() << "Incoming call ringing for " << elapsed << " seconds"; + if (elapsed > q->getCore()->getCCore()->sip_conf.inc_timeout) { + lInfo() << "Incoming call timeout (" << q->getCore()->getCCore()->sip_conf.inc_timeout << ")"; + auto config = linphone_core_get_config(q->getCore()->getCCore()); + int statusCode = linphone_config_get_int(config, "sip", "inc_timeout_status_code", 486); + getActiveSession()->declineNotAnswered(linphone_error_code_to_reason(statusCode)); + } +} + +void CallPrivate::onInfoReceived (const shared_ptr &session, const LinphoneInfoMessage *im) { + L_Q(); + linphone_call_notify_info_message_received(L_GET_C_BACK_PTR(q), im); +} + +void CallPrivate::onNoMediaTimeoutCheck (const shared_ptr &session, bool oneSecondElapsed) { + L_Q(); + int disconnectTimeout = linphone_core_get_nortp_timeout(q->getCore()->getCCore()); + bool disconnected = false; + AudioStream *as = reinterpret_cast(getMediaStream(LinphoneStreamTypeAudio)); + if (((q->getState() == CallSession::State::StreamsRunning) || (q->getState() == CallSession::State::PausedByRemote)) + && oneSecondElapsed && as && (as->ms.state == MSStreamStarted) && (disconnectTimeout > 0)) + disconnected = !audio_stream_alive(as, disconnectTimeout); + if (disconnected) + terminateBecauseOfLostMedia(); +} + +void CallPrivate::onEncryptionChanged (const shared_ptr &session, bool activated, const string &authToken) { + L_Q(); + linphone_call_notify_encryption_changed(L_GET_C_BACK_PTR(q), activated, authToken.empty() ? nullptr : authToken.c_str()); +} + +void CallPrivate::onCallSessionStateChangedForReporting (const shared_ptr &session) { + L_Q(); + linphone_reporting_call_state_updated(L_GET_C_BACK_PTR(q)); +} + +void CallPrivate::onRtcpUpdateForReporting (const shared_ptr &session, SalStreamType type) { + L_Q(); + linphone_reporting_on_rtcp_update(L_GET_C_BACK_PTR(q), type); +} + +void CallPrivate::onStatsUpdated (const shared_ptr &session, const LinphoneCallStats *stats) { + L_Q(); + linphone_call_notify_stats_updated(L_GET_C_BACK_PTR(q), stats); +} + +void CallPrivate::onUpdateMediaInfoForReporting (const shared_ptr &session, int statsType) { + L_Q(); + linphone_reporting_update_media_info(L_GET_C_BACK_PTR(q), statsType); +} + +void CallPrivate::onResetCurrentSession (const shared_ptr &session) { + L_Q(); + q->getCore()->getPrivate()->setCurrentCall(nullptr); +} + +void CallPrivate::onSetCurrentSession (const shared_ptr &session) { + L_Q(); + q->getCore()->getPrivate()->setCurrentCall(q->getSharedFromThis()); +} + +void CallPrivate::onFirstVideoFrameDecoded (const shared_ptr &session) { + L_Q(); + if (nextVideoFrameDecoded._func) { + nextVideoFrameDecoded._func(L_GET_C_BACK_PTR(q), nextVideoFrameDecoded._user_data); + nextVideoFrameDecoded._func = nullptr; + nextVideoFrameDecoded._user_data = nullptr; + } + linphone_call_notify_next_video_frame_decoded(L_GET_C_BACK_PTR(q)); +} + +void CallPrivate::onResetFirstVideoFrameDecoded (const shared_ptr &session) { + /*we are called here by the MediaSession when the stream start to know whether there is the deprecated nextVideoFrameDecoded callback set, + * so that we can request the notification of the next frame decoded.*/ +#ifdef VIDEO_ENABLED + if (nextVideoFrameDecoded._func) + requestNotifyNextVideoFrameDecoded(); +#endif // ifdef VIDEO_ENABLED +} + +void CallPrivate::requestNotifyNextVideoFrameDecoded(){ + static_pointer_cast(getActiveSession())->requestNotifyNextVideoFrameDecoded(); +} + +void CallPrivate::onPlayErrorTone (const shared_ptr &session, LinphoneReason reason) { + L_Q(); + linphone_core_play_call_error_tone(q->getCore()->getCCore(), reason); +} + +void CallPrivate::onRingbackToneRequested (const shared_ptr &session, bool requested) { + L_Q(); + if (requested && linphone_core_get_remote_ringback_tone(q->getCore()->getCCore())) + playingRingbackTone = true; + else if (!requested) + playingRingbackTone = false; +} + +void CallPrivate::onStartRinging (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + if (lc->ringstream) + return; // Already ringing! + startRemoteRing(); +} + +void CallPrivate::onStopRinging (const shared_ptr &session) { + L_Q(); + linphone_core_stop_ringing(q->getCore()->getCCore()); +} + +void CallPrivate::onStopRingingIfInCall (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + // We stop the ring only if we have this current call or if we are in call + if ((q->getCore()->getCallCount() == 1) || linphone_core_in_call(lc)) { + linphone_core_stop_ringing(lc); + } +} + +void CallPrivate::onStopRingingIfNeeded (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + bool stopRinging = true; + bool ringDuringEarlyMedia = !!linphone_core_get_ring_during_incoming_early_media(lc); + for (const auto &call : q->getCore()->getCalls()) { + if ((call->getState() == CallSession::State::IncomingReceived) + || (ringDuringEarlyMedia && call->getState() == CallSession::State::IncomingEarlyMedia)) { + stopRinging = false; + break; + } + } + if (stopRinging) + linphone_core_stop_ringing(lc); +} + +bool CallPrivate::areSoundResourcesAvailable (const shared_ptr &session) { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + shared_ptr currentCall = q->getCore()->getCurrentCall(); + return !linphone_core_is_in_conference(lc) && (!currentCall || (currentCall == q->getSharedFromThis())); +} + +bool CallPrivate::isPlayingRingbackTone (const shared_ptr &session) { + return playingRingbackTone; +} + +void CallPrivate::onRealTimeTextCharacterReceived (const shared_ptr &session, RealtimeTextReceivedCharacter *data) { + L_Q(); + getChatRoom()->getPrivate()->realtimeTextReceived(data->character, q->getSharedFromThis()); +} + +void CallPrivate::onTmmbrReceived (const shared_ptr &session, int streamIndex, int tmmbr) { + L_Q(); + linphone_call_notify_tmmbr_received(L_GET_C_BACK_PTR(q), streamIndex, tmmbr); +} + +void CallPrivate::onSnapshotTaken(const shared_ptr &session, const char *file_path) { + L_Q(); + linphone_call_notify_snapshot_taken(L_GET_C_BACK_PTR(q), file_path); +} + +// ============================================================================= + +Call::Call (CallPrivate &p, shared_ptr core) : Object(p), CoreAccessor(core) { + L_D(); + d->nextVideoFrameDecoded._func = nullptr; + d->nextVideoFrameDecoded._user_data = nullptr; + + d->bgTask.setName("Liblinphone call notification"); +} + +// ----------------------------------------------------------------------------- + +LinphoneStatus Call::accept (const MediaSessionParams *msp) { + L_D(); + return static_pointer_cast(d->getActiveSession())->accept(msp); +} + +LinphoneStatus Call::acceptEarlyMedia (const MediaSessionParams *msp) { + L_D(); + return static_pointer_cast(d->getActiveSession())->acceptEarlyMedia(msp); +} + +LinphoneStatus Call::acceptUpdate (const MediaSessionParams *msp) { + L_D(); + return static_pointer_cast(d->getActiveSession())->acceptUpdate(msp); +} + +void Call::cancelDtmfs () { + L_D(); + static_pointer_cast(d->getActiveSession())->cancelDtmfs(); +} + +LinphoneStatus Call::decline (LinphoneReason reason) { + L_D(); + return d->getActiveSession()->decline(reason); +} + +LinphoneStatus Call::decline (const LinphoneErrorInfo *ei) { + L_D(); + return d->getActiveSession()->decline(ei); +} + +LinphoneStatus Call::deferUpdate () { + L_D(); + return d->getActiveSession()->deferUpdate(); +} + +bool Call::hasTransferPending () const { + L_D(); + return d->getActiveSession()->hasTransferPending(); +} + +void Call::oglRender () const { + L_D(); + static_pointer_cast(d->getActiveSession())->getPrivate()->oglRender(); +} + +LinphoneStatus Call::pause () { + L_D(); + return static_pointer_cast(d->getActiveSession())->pause(); +} + +LinphoneStatus Call::redirect (const string &redirectUri) { + L_D(); + return d->getActiveSession()->redirect(redirectUri); +} + +LinphoneStatus Call::resume () { + L_D(); + return static_pointer_cast(d->getActiveSession())->resume(); +} + +LinphoneStatus Call::sendDtmf (char dtmf) { + L_D(); + return static_pointer_cast(d->getActiveSession())->sendDtmf(dtmf); +} + +LinphoneStatus Call::sendDtmfs (const string &dtmfs) { + L_D(); + return static_pointer_cast(d->getActiveSession())->sendDtmfs(dtmfs); +} + +void Call::sendVfuRequest () { + L_D(); + static_pointer_cast(d->getActiveSession())->sendVfuRequest(); +} + +void Call::startRecording () { + L_D(); + static_pointer_cast(d->getActiveSession())->startRecording(); +} + +void Call::stopRecording () { + L_D(); + static_pointer_cast(d->getActiveSession())->stopRecording(); +} + +LinphoneStatus Call::takePreviewSnapshot (const string &file) { + L_D(); + return static_pointer_cast(d->getActiveSession())->takePreviewSnapshot(file); +} + +LinphoneStatus Call::takeVideoSnapshot (const string &file) { + L_D(); + return static_pointer_cast(d->getActiveSession())->takeVideoSnapshot(file); +} + +LinphoneStatus Call::terminate (const LinphoneErrorInfo *ei) { + L_D(); + return d->getActiveSession()->terminate(ei); +} + +LinphoneStatus Call::transfer (const shared_ptr &dest) { + L_D(); + return d->getActiveSession()->transfer(dest->getPrivate()->getActiveSession()); +} + +LinphoneStatus Call::transfer (const string &dest) { + L_D(); + return d->getActiveSession()->transfer(dest); +} + +LinphoneStatus Call::update (const MediaSessionParams *msp) { + L_D(); + return static_pointer_cast(d->getActiveSession())->update(msp); +} + +void Call::zoomVideo (float zoomFactor, float *cx, float *cy) { + zoomVideo(zoomFactor, *cx, *cy); +} + +void Call::zoomVideo (float zoomFactor, float cx, float cy) { + L_D(); + static_pointer_cast(d->getActiveSession())->zoomVideo(zoomFactor, cx, cy); +} + +// ----------------------------------------------------------------------------- + +bool Call::cameraEnabled () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->cameraEnabled(); +} + +bool Call::echoCancellationEnabled () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->echoCancellationEnabled(); +} + +bool Call::echoLimiterEnabled () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->echoLimiterEnabled(); +} + +void Call::enableCamera (bool value) { + L_D(); + static_pointer_cast(d->getActiveSession())->enableCamera(value); +} + +void Call::enableEchoCancellation (bool value) { + L_D(); + static_pointer_cast(d->getActiveSession())->enableEchoCancellation(value); +} + +void Call::enableEchoLimiter (bool value) { + L_D(); + static_pointer_cast(d->getActiveSession())->enableEchoLimiter(value); +} + +bool Call::getAllMuted () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getAllMuted(); +} + +LinphoneCallStats *Call::getAudioStats () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getAudioStats(); +} + +string Call::getAuthenticationToken () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getAuthenticationToken(); +} + +bool Call::getAuthenticationTokenVerified () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getAuthenticationTokenVerified(); +} + +float Call::getAverageQuality () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getAverageQuality(); +} + +const MediaSessionParams *Call::getCurrentParams () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getCurrentParams(); +} + +float Call::getCurrentQuality () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getCurrentQuality(); +} + +LinphoneCallDir Call::getDirection () const { + L_D(); + return d->getActiveSession()->getDirection(); +} + +const Address &Call::getDiversionAddress () const { + L_D(); + return d->getActiveSession()->getDiversionAddress(); +} + +int Call::getDuration () const { + L_D(); + return d->getActiveSession()->getDuration(); +} + +const LinphoneErrorInfo *Call::getErrorInfo () const { + L_D(); + return d->getActiveSession()->getErrorInfo(); +} + +const Address &Call::getLocalAddress () const { + L_D(); + return d->getActiveSession()->getLocalAddress(); +} + +LinphoneCallLog *Call::getLog () const { + L_D(); + return d->getActiveSession()->getLog(); +} + +RtpTransport *Call::getMetaRtcpTransport (int streamIndex) const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getMetaRtcpTransport(streamIndex); +} + +RtpTransport *Call::getMetaRtpTransport (int streamIndex) const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getMetaRtpTransport(streamIndex); +} + +float Call::getMicrophoneVolumeGain () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getMicrophoneVolumeGain(); +} + +void *Call::getNativeVideoWindowId () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getNativeVideoWindowId(); +} + +const MediaSessionParams *Call::getParams () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getMediaParams(); +} + +LinphonePlayer *Call::getPlayer () const { + L_D(); + if (!d->player) + d->createPlayer(); + return d->player; +} + +float Call::getPlayVolume () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getPlayVolume(); +} + +LinphoneReason Call::getReason () const { + L_D(); + return d->getActiveSession()->getReason(); +} + +float Call::getRecordVolume () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getRecordVolume(); +} + +shared_ptr Call::getReferer () const { + L_D(); + shared_ptr referer = d->getActiveSession()->getReferer(); + if (!referer) + return nullptr; + for (const auto &call : getCore()->getCalls()) { + if (call->getPrivate()->getActiveSession() == referer) + return call; + } + return nullptr; +} + +string Call::getReferTo () const { + L_D(); + return d->getActiveSession()->getReferTo(); +} + +const Address &Call::getRemoteAddress () const { + L_D(); + return d->getActiveSession()->getRemoteAddress(); +} + +string Call::getRemoteContact () const { + L_D(); + return d->getActiveSession()->getRemoteContact(); +} + +const MediaSessionParams *Call::getRemoteParams () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getRemoteParams(); +} + +string Call::getRemoteUserAgent () const { + L_D(); + return d->getActiveSession()->getRemoteUserAgent(); +} + +shared_ptr Call::getReplacedCall () const { + L_D(); + shared_ptr replacedCallSession = d->getActiveSession()->getReplacedCallSession(); + if (!replacedCallSession) + return nullptr; + for (const auto &call : getCore()->getCalls()) { + if (call->getPrivate()->getActiveSession() == replacedCallSession) + return call; + } + return nullptr; +} + +float Call::getSpeakerVolumeGain () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getSpeakerVolumeGain(); +} + +CallSession::State Call::getState () const { + L_D(); + return d->getActiveSession()->getState(); +} + +LinphoneCallStats *Call::getStats (LinphoneStreamType type) const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getStats(type); +} + +int Call::getStreamCount () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getStreamCount(); +} + +MSFormatType Call::getStreamType (int streamIndex) const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getStreamType(streamIndex); +} + +LinphoneCallStats *Call::getTextStats () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getTextStats(); +} + +const Address &Call::getToAddress () const { + L_D(); + return d->getActiveSession()->getToAddress(); +} + +string Call::getToHeader (const string &name) const { + L_D(); + return d->getActiveSession()->getToHeader(name); +} + +CallSession::State Call::getTransferState () const { + L_D(); + return d->getActiveSession()->getTransferState(); +} + +shared_ptr Call::getTransferTarget () const { + L_D(); + shared_ptr transferTarget = d->getActiveSession()->getTransferTarget(); + if (!transferTarget) + return nullptr; + for (const auto &call : getCore()->getCalls()) { + if (call->getPrivate()->getActiveSession() == transferTarget) + return call; + } + return nullptr; +} + +LinphoneCallStats *Call::getVideoStats () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->getVideoStats(); +} + +bool Call::isInConference () const { + L_D(); + return d->getActiveSession()->getPrivate()->isInConference(); +} + +bool Call::mediaInProgress () const { + L_D(); + return static_pointer_cast(d->getActiveSession())->mediaInProgress(); +} + +void Call::setAudioRoute (LinphoneAudioRoute route) { + L_D(); + static_pointer_cast(d->getActiveSession())->setAudioRoute(route); +} + +void Call::setAuthenticationTokenVerified (bool value) { + L_D(); + static_pointer_cast(d->getActiveSession())->setAuthenticationTokenVerified(value); +} + +void Call::setMicrophoneVolumeGain (float value) { + L_D(); + static_pointer_cast(d->getActiveSession())->setMicrophoneVolumeGain(value); +} + +void Call::setNativeVideoWindowId (void *id) { + L_D(); + static_pointer_cast(d->getActiveSession())->setNativeVideoWindowId(id); +} + +void Call::setNextVideoFrameDecodedCallback (LinphoneCallCbFunc cb, void *user_data) { + L_D(); + d->nextVideoFrameDecoded._func = cb; + d->nextVideoFrameDecoded._user_data = user_data; + d->requestNotifyNextVideoFrameDecoded(); +} + +void Call::requestNotifyNextVideoFrameDecoded (){ + L_D(); + d->requestNotifyNextVideoFrameDecoded(); +} + +void Call::setParams (const MediaSessionParams *msp) { + L_D(); + static_pointer_cast(d->getActiveSession())->setParams(msp); +} + +void Call::setSpeakerVolumeGain (float value) { + L_D(); + static_pointer_cast(d->getActiveSession())->setSpeakerVolumeGain(value); +} + +LINPHONE_END_NAMESPACE diff --git a/src/call/call.h b/src/call/call.h new file mode 100644 index 000000000..49315d9f9 --- /dev/null +++ b/src/call/call.h @@ -0,0 +1,140 @@ +/* + * call.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_CALL_H_ +#define _L_CALL_CALL_H_ + +#include "conference/params/media-session-params.h" +#include "conference/session/call-session.h" +#include "core/core-accessor.h" +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Address; +class CallPrivate; +class CallSessionPrivate; +class MediaSessionPrivate; + +class LINPHONE_PUBLIC Call : public Object, public CoreAccessor { + friend class CallSessionPrivate; + friend class ChatMessage; + friend class ChatMessagePrivate; + friend class CorePrivate; + friend class MediaSessionPrivate; + +public: + L_OVERRIDE_SHARED_FROM_THIS(Call); + + LinphoneStatus accept (const MediaSessionParams *msp = nullptr); + LinphoneStatus acceptEarlyMedia (const MediaSessionParams *msp = nullptr); + LinphoneStatus acceptUpdate (const MediaSessionParams *msp); + void cancelDtmfs (); + LinphoneStatus decline (LinphoneReason reason); + LinphoneStatus decline (const LinphoneErrorInfo *ei); + LinphoneStatus deferUpdate (); + bool hasTransferPending () const; + void oglRender () const; + LinphoneStatus pause (); + LinphoneStatus redirect (const std::string &redirectUri); + LinphoneStatus resume (); + LinphoneStatus sendDtmf (char dtmf); + LinphoneStatus sendDtmfs (const std::string &dtmfs); + void sendVfuRequest (); + void startRecording (); + void stopRecording (); + LinphoneStatus takePreviewSnapshot (const std::string &file); + LinphoneStatus takeVideoSnapshot (const std::string &file); + LinphoneStatus terminate (const LinphoneErrorInfo *ei = nullptr); + LinphoneStatus transfer (const std::shared_ptr &dest); + LinphoneStatus transfer (const std::string &dest); + LinphoneStatus update (const MediaSessionParams *msp = nullptr); + void zoomVideo (float zoomFactor, float *cx, float *cy); + void zoomVideo (float zoomFactor, float cx, float cy); + + bool cameraEnabled () const; + bool echoCancellationEnabled () const; + bool echoLimiterEnabled () const; + void enableCamera (bool value); + void enableEchoCancellation (bool value); + void enableEchoLimiter (bool value); + bool getAllMuted () const; + LinphoneCallStats *getAudioStats () const; + std::string getAuthenticationToken () const; + bool getAuthenticationTokenVerified () const; + float getAverageQuality () const; + const MediaSessionParams *getCurrentParams () const; + float getCurrentQuality () const; + LinphoneCallDir getDirection () const; + const Address &getDiversionAddress () const; + int getDuration () const; + const LinphoneErrorInfo *getErrorInfo () const; + const Address &getLocalAddress () const; + LinphoneCallLog *getLog () const; + RtpTransport *getMetaRtcpTransport (int streamIndex) const; + RtpTransport *getMetaRtpTransport (int streamIndex) const; + float getMicrophoneVolumeGain () const; + void *getNativeVideoWindowId () const; + const MediaSessionParams *getParams () const; + LinphonePlayer *getPlayer () const; + float getPlayVolume () const; + LinphoneReason getReason () const; + float getRecordVolume () const; + std::shared_ptr getReferer () const; + std::string getReferTo () const; + const Address &getRemoteAddress () const; + std::string getRemoteContact () const; + const MediaSessionParams *getRemoteParams () const; + std::string getRemoteUserAgent () const; + std::shared_ptr getReplacedCall () const; + float getSpeakerVolumeGain () const; + CallSession::State getState () const; + LinphoneCallStats *getStats (LinphoneStreamType type) const; + int getStreamCount () const; + MSFormatType getStreamType (int streamIndex) const; + LinphoneCallStats *getTextStats () const; + const Address &getToAddress () const; + std::string getToHeader (const std::string &name) const; + CallSession::State getTransferState () const; + std::shared_ptr getTransferTarget () const; + LinphoneCallStats *getVideoStats () const; + bool isInConference () const; + bool mediaInProgress () const; + void setAudioRoute (LinphoneAudioRoute route); + void setAuthenticationTokenVerified (bool value); + void setMicrophoneVolumeGain (float value); + void setNativeVideoWindowId (void *id); + void setNextVideoFrameDecodedCallback (LinphoneCallCbFunc cb, void *user_data); + void requestNotifyNextVideoFrameDecoded(); + void setParams (const MediaSessionParams *msp); + void setSpeakerVolumeGain (float value); + +protected: + Call (CallPrivate &p, std::shared_ptr core); + +private: + L_DECLARE_PRIVATE(Call); + L_DISABLE_COPY(Call); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CALL_CALL_H_ diff --git a/src/call/local-conference-call-p.h b/src/call/local-conference-call-p.h new file mode 100644 index 000000000..89e4a1971 --- /dev/null +++ b/src/call/local-conference-call-p.h @@ -0,0 +1,40 @@ +/* + * local-conference-call-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LOCAL_CONFERENCE_CALL_P_H_ +#define _L_LOCAL_CONFERENCE_CALL_P_H_ + +#include "call-p.h" +#include "local-conference-call.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class LocalConferenceCallPrivate : public CallPrivate { +public: + std::shared_ptr getActiveSession () const override; + +private: + L_DECLARE_PUBLIC(LocalConferenceCall); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LOCAL_CONFERENCE_CALL_P_H_ diff --git a/src/call/local-conference-call.cpp b/src/call/local-conference-call.cpp new file mode 100644 index 000000000..de9e349ac --- /dev/null +++ b/src/call/local-conference-call.cpp @@ -0,0 +1,65 @@ +/* + * local-conference-call.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference/local-conference-p.h" +#include "conference/participant-p.h" +#include "conference/session/media-session-p.h" +#include "local-conference-call-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +shared_ptr LocalConferenceCallPrivate::getActiveSession () const { + L_Q(); + return q->getActiveParticipant()->getPrivate()->getSession(); +} + +// ============================================================================= + +LocalConferenceCall::LocalConferenceCall ( + shared_ptr core, + LinphoneCallDir direction, + const Address &from, + const Address &to, + LinphoneProxyConfig *cfg, + SalCallOp *op, + const MediaSessionParams *msp + ) + : Call(*new LocalConferenceCallPrivate(), core), + LocalConference(getCore(), IdentityAddress((direction == LinphoneCallIncoming) ? to : from), getPrivate()) { + addParticipant((direction == LinphoneCallIncoming) ? from : to, msp, true); + shared_ptr participant = getParticipants().front(); + participant->getPrivate()->getSession()->configure(direction, cfg, op, from, to); +} + +LocalConferenceCall::~LocalConferenceCall () { + L_D(); + auto session = d->getActiveSession(); + if (session) + session->getPrivate()->setCallSessionListener(nullptr); +} + +shared_ptr LocalConferenceCall::getCore () const { + return Call::getCore(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/call/local-conference-call.h b/src/call/local-conference-call.h new file mode 100644 index 000000000..66f9ae084 --- /dev/null +++ b/src/call/local-conference-call.h @@ -0,0 +1,61 @@ +/* + * local-conference-call.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LOCAL_CONFERENCE_CALL_H_ +#define _L_LOCAL_CONFERENCE_CALL_H_ + +// From coreapi +#include "private.h" + +#include "call/call.h" +#include "conference/local-conference.h" + +#include "linphone/types.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Core; +class LocalConferenceCallPrivate; + +class LocalConferenceCall : public Call, public LocalConference { +public: + // TODO: Make me private! + LocalConferenceCall ( + std::shared_ptr core, + LinphoneCallDir direction, + const Address &from, + const Address &to, + LinphoneProxyConfig *cfg, + SalCallOp *op, + const MediaSessionParams *msp + ); + virtual ~LocalConferenceCall (); + + std::shared_ptr getCore () const; + +private: + L_DECLARE_PRIVATE(LocalConferenceCall); + L_DISABLE_COPY(LocalConferenceCall); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LOCAL_CONFERENCE_CALL_H_ diff --git a/src/call/remote-conference-call-p.h b/src/call/remote-conference-call-p.h new file mode 100644 index 000000000..8f9cda90b --- /dev/null +++ b/src/call/remote-conference-call-p.h @@ -0,0 +1,40 @@ +/* + * remote-conference-call-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REMOTE_CONFERENCE_CALL_P_H_ +#define _L_REMOTE_CONFERENCE_CALL_P_H_ + +#include "call/call-p.h" +#include "remote-conference-call.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class RemoteConferenceCallPrivate : public CallPrivate { +public: + std::shared_ptr getActiveSession () const override; + +private: + L_DECLARE_PUBLIC(RemoteConferenceCall); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REMOTE_CONFERENCE_CALL_P_H_ diff --git a/src/call/remote-conference-call.cpp b/src/call/remote-conference-call.cpp new file mode 100644 index 000000000..aadd39ed9 --- /dev/null +++ b/src/call/remote-conference-call.cpp @@ -0,0 +1,65 @@ +/* + * remote-conference-call.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference/remote-conference-p.h" +#include "conference/participant-p.h" +#include "conference/session/media-session-p.h" +#include "remote-conference-call-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +shared_ptr RemoteConferenceCallPrivate::getActiveSession () const { + L_Q(); + return q->getActiveParticipant()->getPrivate()->getSession(); +} + +// ============================================================================= + +RemoteConferenceCall::RemoteConferenceCall ( + shared_ptr core, + LinphoneCallDir direction, + const Address &from, + const Address &to, + LinphoneProxyConfig *cfg, + SalCallOp *op, + const MediaSessionParams *msp + ) + : Call(*new RemoteConferenceCallPrivate, core), + RemoteConference(core, IdentityAddress((direction == LinphoneCallIncoming) ? to : from), getPrivate()) { + addParticipant((direction == LinphoneCallIncoming) ? from : to, msp, true); + shared_ptr participant = getParticipants().front(); + participant->getPrivate()->getSession()->configure(direction, cfg, op, from, to); +} + +RemoteConferenceCall::~RemoteConferenceCall () { + L_D(); + auto session = d->getActiveSession(); + if (session) + session->getPrivate()->setCallSessionListener(nullptr); +} + +shared_ptr RemoteConferenceCall::getCore () const { + return Call::getCore(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/call/remote-conference-call.h b/src/call/remote-conference-call.h new file mode 100644 index 000000000..9360b2c11 --- /dev/null +++ b/src/call/remote-conference-call.h @@ -0,0 +1,56 @@ +/* + * remote-conference-call.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REMOTE_CONFERENCE_CALL_H_ +#define _L_REMOTE_CONFERENCE_CALL_H_ + +#include "call/call.h" +#include "conference/remote-conference.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Core; +class RemoteConferenceCallPrivate; + +class LINPHONE_PUBLIC RemoteConferenceCall : public Call, public RemoteConference { +public: + // TODO: Make me private. + RemoteConferenceCall ( + std::shared_ptr core, + LinphoneCallDir direction, + const Address &from, + const Address &to, + LinphoneProxyConfig *cfg, + SalCallOp *op, + const MediaSessionParams *msp + ); + ~RemoteConferenceCall (); + + std::shared_ptr getCore () const; + +private: + L_DECLARE_PRIVATE(RemoteConferenceCall); + L_DISABLE_COPY(RemoteConferenceCall); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REMOTE_CONFERENCE_CALL_H_ diff --git a/src/chat/chat-message/chat-message-p.h b/src/chat/chat-message/chat-message-p.h new file mode 100644 index 000000000..86bdff7e1 --- /dev/null +++ b/src/chat/chat-message/chat-message-p.h @@ -0,0 +1,224 @@ +/* + * chat-message-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_MESSAGE_P_H_ +#define _L_CHAT_MESSAGE_P_H_ + +#include + +#include "chat/chat-message/chat-message.h" +#include "chat/chat-room/chat-room-id.h" +#include "chat/modifier/file-transfer-chat-message-modifier.h" +#include "chat/notification/imdn.h" +#include "content/content.h" +#include "content/content-type.h" +#include "content/file-content.h" +#include "content/file-transfer-content.h" +#include "db/main-db.h" +#include "db/main-db-chat-message-key.h" +#include "event-log/conference/conference-chat-message-event.h" +#include "object/object-p.h" +#include "sal/sal.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatMessagePrivate : public ObjectPrivate { + friend class CpimChatMessageModifier; + friend class EncryptionChatMessageModifier; + friend class MultipartChatMessageModifier; + friend class NotificationMessagePrivate; + +public: + enum Step { + None = 1 << 0, + FileUpload = 1 << 1, + Multipart = 1 << 2, + Encryption = 1 << 3, + Cpim = 1 << 4, + Started = 1 << 5, + }; + + void setApplyModifiers (bool value) { applyModifiers = value; } + + void setDirection (ChatMessage::Direction dir); + + void setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState, time_t stateChangeTime); + virtual void setState (ChatMessage::State newState, bool force = false); + + void setTime (time_t time); + + void setIsReadOnly (bool readOnly); + + void setImdnMessageId (const std::string &imdnMessageId); + + void forceFromAddress (const IdentityAddress &fromAddress) { + this->fromAddress = fromAddress; + } + + void forceToAddress (const IdentityAddress &toAddress) { + this->toAddress = toAddress; + } + + void markContentsAsNotLoaded () { + contentsNotLoadedFromDatabase = true; + } + + void loadContentsFromDatabase () const; + + std::list &getContents () { + loadContentsFromDatabase(); + return contents; + } + + const std::list &getContents () const { + loadContentsFromDatabase(); + return contents; + } + + belle_http_request_t *getHttpRequest () const; + void setHttpRequest (belle_http_request_t *request); + + SalOp *getSalOp () const; + void setSalOp (SalOp *op); + + bool getDisplayNotificationRequired () const { return displayNotificationRequired; } + bool getNegativeDeliveryNotificationRequired () const { return negativeDeliveryNotificationRequired; } + bool getPositiveDeliveryNotificationRequired () const { return positiveDeliveryNotificationRequired; } + virtual void setDisplayNotificationRequired (bool value) { displayNotificationRequired = value; } + virtual void setNegativeDeliveryNotificationRequired (bool value) { negativeDeliveryNotificationRequired = value; } + virtual void setPositiveDeliveryNotificationRequired (bool value) { positiveDeliveryNotificationRequired = value; } + + SalCustomHeader *getSalCustomHeaders () const; + void setSalCustomHeaders (SalCustomHeader *headers); + + void addSalCustomHeader (const std::string &name, const std::string &value); + void removeSalCustomHeader (const std::string &name); + std::string getSalCustomHeaderValue (const std::string &name); + + void loadFileTransferUrlFromBodyToContent (); + std::string createFakeFileTransferFromUrl(const std::string &url); + + void setChatRoom (const std::shared_ptr &chatRoom); + + void setEncryptionPrevented (bool value) { encryptionPrevented = value; } + + // ----------------------------------------------------------------------------- + // Deprecated methods only used for C wrapper, to be removed some day... + // ----------------------------------------------------------------------------- + + const ContentType &getContentType (); + void setContentType (const ContentType &contentType); + + const std::string &getText (); + void setText (const std::string &text); + + const std::string &getFileTransferFilepath () const; + void setFileTransferFilepath (const std::string &path); + + const std::string &getAppdata () const; + void setAppdata (const std::string &appData); + + const std::string &getExternalBodyUrl () const; + void setExternalBodyUrl (const std::string &url); + + bool hasTextContent () const; + const Content* getTextContent () const; + + bool hasFileTransferContent () const; + const Content* getFileTransferContent () const; + + const Content* getFileTransferInformation () const; + void setFileTransferInformation (Content *content); + + void addContent (Content *content); + void removeContent (Content *content); + + bool downloadFile (); + + void notifyReceiving (); + LinphoneReason receive (); + void send (); + + void storeInDb (); + void updateInDb (); + +private: + ChatMessagePrivate(const std::shared_ptr &cr, ChatMessage::Direction dir); + + static bool validStateTransition (ChatMessage::State currentState, ChatMessage::State newState); + +public: + mutable MainDbChatMessageKey dbKey; + +protected: + bool displayNotificationRequired = true; + bool negativeDeliveryNotificationRequired = true; + bool positiveDeliveryNotificationRequired = true; + bool toBeStored = true; + std::string contentEncoding; + +private: + // TODO: Clean attributes. + time_t time = ::ms_time(0); // TODO: Change me in all files. + std::string imdnId; + std::string rttMessage; + std::string externalBodyUrl; + bool isSecured = false; + mutable bool isReadOnly = false; + Content internalContent; + + // TODO: to replace salCustomheaders + std::unordered_map customHeaders; + + mutable LinphoneErrorInfo * errorInfo = nullptr; + SalOp *salOp = nullptr; + SalCustomHeader *salCustomHeaders = nullptr; + unsigned char currentSendStep = Step::None; + unsigned char currentRecvStep = Step::None; + bool applyModifiers = true; + FileTransferChatMessageModifier fileTransferChatMessageModifier; + + // Cache for returned values, used for compatibility with previous C API + std::string fileTransferFilePath; + ContentType cContentType; + std::string cText; + + // TODO: Remove my comment. VARIABLES OK. + // Do not expose. + + std::weak_ptr chatRoom; + ChatRoomId chatRoomId; + IdentityAddress fromAddress; + IdentityAddress toAddress; + + ChatMessage::State state = ChatMessage::State::Idle; + ChatMessage::Direction direction = ChatMessage::Direction::Incoming; + + std::list contents; + + bool encryptionPrevented = false; + mutable bool contentsNotLoadedFromDatabase = false; + L_DECLARE_PUBLIC(ChatMessage); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CHAT_MESSAGE_P_H_ diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp new file mode 100644 index 000000000..3017bd233 --- /dev/null +++ b/src/chat/chat-message/chat-message.cpp @@ -0,0 +1,1165 @@ +/* + * chat-message.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "object/object-p.h" + +#include "linphone/api/c-content.h" +#include "linphone/core.h" +#include "linphone/lpconfig.h" +#include "linphone/utils/utils.h" + +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "chat/chat-room/client-group-to-basic-chat-room.h" +#include "chat/chat-room/real-time-text-chat-room.h" +#include "chat/modifier/cpim-chat-message-modifier.h" +#include "chat/modifier/encryption-chat-message-modifier.h" +#include "chat/modifier/multipart-chat-message-modifier.h" +#include "chat/notification/imdn.h" +#include "conference/participant.h" +#include "conference/participant-imdn-state.h" +#include "content/content-disposition.h" +#include "content/header/header-param.h" +#include "core/core.h" +#include "core/core-p.h" +#include "logger/logger.h" +#include "sip-tools/sip-headers.h" + +#include "ortp/b64.h" + +// ============================================================================= + +using namespace std; + +using namespace B64_NAMESPACE; + +LINPHONE_BEGIN_NAMESPACE + +ChatMessagePrivate::ChatMessagePrivate(const std::shared_ptr &cr, ChatMessage::Direction dir):fileTransferChatMessageModifier(cr->getCore()->getCCore()->http_provider) { + direction = dir; + setChatRoom(cr); +} + +void ChatMessagePrivate::setDirection (ChatMessage::Direction dir) { + direction = dir; +} + +void ChatMessagePrivate::setTime (time_t t) { + time = t; +} + +void ChatMessagePrivate::setIsReadOnly (bool readOnly) { + isReadOnly = readOnly; +} + +void ChatMessagePrivate::setParticipantState (const IdentityAddress &participantAddress, ChatMessage::State newState, time_t stateChangeTime) { + L_Q(); + + if (!dbKey.isValid()) + return; + + unique_ptr &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb; + shared_ptr eventLog = mainDb->getEventFromKey(dbKey); + ChatMessage::State currentState = mainDb->getChatMessageParticipantState(eventLog, participantAddress); + if (!validStateTransition(currentState, newState)) + return; + + lInfo() << "Chat message " << this << ": moving participant '" << participantAddress.asString() << "' state to " + << Utils::toString(newState); + mainDb->setChatMessageParticipantState(eventLog, participantAddress, newState, stateChangeTime); + + LinphoneChatMessage *msg = L_GET_C_BACK_PTR(q); + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + if (cbs && linphone_chat_message_cbs_get_participant_imdn_state_changed(cbs)) { + auto participant = q->getChatRoom()->findParticipant(participantAddress); + ParticipantImdnState imdnState(participant, newState, stateChangeTime); + linphone_chat_message_cbs_get_participant_imdn_state_changed(cbs)(msg, + _linphone_participant_imdn_state_from_cpp_obj(imdnState) + ); + } + + if (linphone_config_get_bool(linphone_core_get_config(q->getChatRoom()->getCore()->getCCore()), + "misc", "enable_simple_group_chat_message_state", FALSE + ) + ) { + setState(newState); + return; + } + + list states = mainDb->getChatMessageParticipantStates(eventLog); + size_t nbDisplayedStates = 0; + size_t nbDeliveredToUserStates = 0; + size_t nbNotDeliveredStates = 0; + for (const auto &state : states) { + switch (state) { + case ChatMessage::State::Displayed: + nbDisplayedStates++; + break; + case ChatMessage::State::DeliveredToUser: + nbDeliveredToUserStates++; + break; + case ChatMessage::State::NotDelivered: + nbNotDeliveredStates++; + break; + default: + break; + } + } + + if (nbNotDeliveredStates > 0) + setState(ChatMessage::State::NotDelivered); + else if (nbDisplayedStates == states.size()) + setState(ChatMessage::State::Displayed); + else if ((nbDisplayedStates + nbDeliveredToUserStates) == states.size()) + setState(ChatMessage::State::DeliveredToUser); +} + +void ChatMessagePrivate::setState (ChatMessage::State newState, bool force) { + L_Q(); + + if (force) + state = newState; + + if (!validStateTransition(state, newState)) + return; + + lInfo() << "Chat message " << this << ": moving from " << Utils::toString(state) << + " to " << Utils::toString(newState); + state = newState; + + LinphoneChatMessage *msg = L_GET_C_BACK_PTR(q); + if (linphone_chat_message_get_message_state_changed_cb(msg)) + linphone_chat_message_get_message_state_changed_cb(msg)( + msg, + (LinphoneChatMessageState)state, + linphone_chat_message_get_message_state_changed_cb_user_data(msg) + ); + + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + if (cbs && linphone_chat_message_cbs_get_msg_state_changed(cbs)) + linphone_chat_message_cbs_get_msg_state_changed(cbs)(msg, (LinphoneChatMessageState)state); + + if (state == ChatMessage::State::FileTransferDone && !hasFileTransferContent()) { + // We wait until the file has been downloaded to send the displayed IMDN + bool doNotStoreInDb = static_cast(q->getChatRoom()->getPrivate())->sendDisplayNotification(q->getSharedFromThis()); + // Force the state so it is stored directly in DB, but when the IMDN has successfully been delivered + setState(ChatMessage::State::Displayed, doNotStoreInDb); + } else { + updateInDb(); + } +} + +belle_http_request_t *ChatMessagePrivate::getHttpRequest () const { + return fileTransferChatMessageModifier.getHttpRequest(); +} + +void ChatMessagePrivate::setHttpRequest (belle_http_request_t *request) { + fileTransferChatMessageModifier.setHttpRequest(request); +} + +SalOp *ChatMessagePrivate::getSalOp () const { + return salOp; +} + +void ChatMessagePrivate::setSalOp (SalOp *op) { + salOp = op; +} + +SalCustomHeader *ChatMessagePrivate::getSalCustomHeaders () const { + return salCustomHeaders; +} + +void ChatMessagePrivate::setSalCustomHeaders (SalCustomHeader *headers) { + salCustomHeaders = headers; +} + +void ChatMessagePrivate::addSalCustomHeader (const string &name, const string &value) { + salCustomHeaders = sal_custom_header_append(salCustomHeaders, name.c_str(), value.c_str()); +} + +void ChatMessagePrivate::removeSalCustomHeader (const string &name) { + salCustomHeaders = sal_custom_header_remove(salCustomHeaders, name.c_str()); +} + +string ChatMessagePrivate::getSalCustomHeaderValue (const string &name) { + return L_C_TO_STRING(sal_custom_header_find(salCustomHeaders, name.c_str())); +} + +// ----------------------------------------------------------------------------- +// Below methods are only for C API backward compatibility... +// ----------------------------------------------------------------------------- + +bool ChatMessagePrivate::hasTextContent() const { + for (const Content *c : getContents()) { + if (c->getContentType() == ContentType::PlainText) { + return true; + } + } + return false; +} + +const Content* ChatMessagePrivate::getTextContent() const { + for (const Content *c : getContents()) { + if (c->getContentType() == ContentType::PlainText) { + return c; + } + } + return &Utils::getEmptyConstRefObject(); +} + +bool ChatMessagePrivate::hasFileTransferContent() const { + for (const Content *c : contents) { + if (c->isFileTransfer()) { + return true; + } + } + return false; +} + +const Content* ChatMessagePrivate::getFileTransferContent() const { + for (const Content *c : contents) { + if (c->isFileTransfer()) { + return c; + } + } + return &Utils::getEmptyConstRefObject(); +} + +const string &ChatMessagePrivate::getFileTransferFilepath () const { + return fileTransferFilePath; +} + +void ChatMessagePrivate::setFileTransferFilepath (const string &path) { + fileTransferFilePath = path; +} + +const string &ChatMessagePrivate::getAppdata () const { + for (const Content *c : getContents()) { + if (!c->getAppData("legacy").empty()) { + return c->getAppData("legacy"); + } + } + return Utils::getEmptyConstRefObject(); +} + +void ChatMessagePrivate::setAppdata (const string &data) { + bool contentFound = false; + for (Content *c : getContents()) { + c->setAppData("legacy", data); + contentFound = true; + break; + } + if (contentFound) { + updateInDb(); + } +} + +const string &ChatMessagePrivate::getExternalBodyUrl () const { + if (!externalBodyUrl.empty()) { + return externalBodyUrl; + } + if (hasFileTransferContent()) { + FileTransferContent *content = (FileTransferContent*) getFileTransferContent(); + return content->getFileUrl(); + } + return Utils::getEmptyConstRefObject(); +} + +void ChatMessagePrivate::setExternalBodyUrl (const string &url) { + externalBodyUrl = url; +} + +const ContentType &ChatMessagePrivate::getContentType () { + loadContentsFromDatabase(); + if (direction == ChatMessage::Direction::Incoming) { + if (contents.size() > 0) { + Content *content = contents.front(); + cContentType = content->getContentType(); + } else { + cContentType = internalContent.getContentType(); + } + } else { + if (internalContent.getContentType().isValid()) { + cContentType = internalContent.getContentType(); + } else { + if (contents.size() > 0) { + Content *content = contents.front(); + cContentType = content->getContentType(); + } + } + } + return cContentType; +} + +void ChatMessagePrivate::setContentType (const ContentType &contentType) { + loadContentsFromDatabase(); + if (contents.size() > 0 && internalContent.getContentType().isEmpty() && internalContent.isEmpty()) { + internalContent.setBody(contents.front()->getBody()); + } + internalContent.setContentType(contentType); + + if ((currentSendStep &ChatMessagePrivate::Step::Started) != ChatMessagePrivate::Step::Started) { + // if not started yet the sending also alter the first content + if (contents.size() > 0) + contents.front()->setContentType(contentType); + } +} + +const string &ChatMessagePrivate::getText () { + loadContentsFromDatabase(); + if (direction == ChatMessage::Direction::Incoming) { + if (hasTextContent()) { + cText = getTextContent()->getBodyAsString(); + } else if (contents.size() > 0) { + Content *content = contents.front(); + cText = content->getBodyAsString(); + } else { + cText = internalContent.getBodyAsString(); + } + } else { + if (!internalContent.isEmpty()) { + cText = internalContent.getBodyAsString(); + } else { + if (contents.size() > 0) { + Content *content = contents.front(); + cText = content->getBodyAsString(); + } + } + } + return cText; +} + +void ChatMessagePrivate::setText (const string &text) { + loadContentsFromDatabase(); + if (contents.size() > 0 && internalContent.getContentType().isEmpty() && internalContent.isEmpty()) { + internalContent.setContentType(contents.front()->getContentType()); + } + internalContent.setBody(text); + + if ((currentSendStep &ChatMessagePrivate::Step::Started) != ChatMessagePrivate::Step::Started) { + // if not started yet the sending also alter the first content + if (contents.size() > 0) + contents.front()->setBody(text); + } +} + +const Content *ChatMessagePrivate::getFileTransferInformation () const { + if (hasFileTransferContent()) { + return getFileTransferContent(); + } + for (const Content *c : getContents()) { + if (c->isFile()) { + FileContent *fileContent = (FileContent *)c; + return fileContent; + } + } + return nullptr; +} + +void ChatMessagePrivate::setFileTransferInformation (Content *content) { + L_Q(); + + if (content->isFile()) { + q->addContent(content); + } else { + // This scenario is more likely to happen because the caller is using the C API + LinphoneContent *c_content = L_GET_C_BACK_PTR(content); + FileContent *fileContent = new FileContent(); + fileContent->setContentType(content->getContentType()); + fileContent->setFileSize(linphone_content_get_size(c_content)); // This information is only available from C Content if it was created from C API + fileContent->setFileName(linphone_content_get_name(c_content)); // This information is only available from C Content if it was created from C API + if (!content->isEmpty()) { + fileContent->setBody(content->getBody()); + } + q->addContent(fileContent); + } +} + +bool ChatMessagePrivate::downloadFile () { + L_Q(); + + for (auto &content : getContents()) + if (content->isFileTransfer()) + return q->downloadFile(static_cast(content)); + + return false; +} + +void ChatMessagePrivate::addContent (Content *content) { + getContents().push_back(content); +} + +void ChatMessagePrivate::removeContent (Content *content) { + getContents().remove(content); +} + +void ChatMessagePrivate::loadFileTransferUrlFromBodyToContent() { + L_Q(); + int errorCode = 0; + fileTransferChatMessageModifier.decode(q->getSharedFromThis(), errorCode); +} + +std::string ChatMessagePrivate::createFakeFileTransferFromUrl(const std::string &url) { + return fileTransferChatMessageModifier.createFakeFileTransferFromUrl(url); +} + +void ChatMessagePrivate::setChatRoom (const shared_ptr &cr) { + chatRoom = cr; + chatRoomId = cr->getChatRoomId(); + if (direction == ChatMessage::Direction::Outgoing) { + fromAddress = chatRoomId.getLocalAddress(); + toAddress = chatRoomId.getPeerAddress(); + } else { + fromAddress = chatRoomId.getPeerAddress(); + toAddress = chatRoomId.getLocalAddress(); + } +} + +// ----------------------------------------------------------------------------- + +static void forceUtf8Content (Content &content) { + // TODO: Deal with other content type in the future. + ContentType contentType = content.getContentType(); + if (contentType != ContentType::PlainText) + return; + + string charset = contentType.getParameter("charset").getValue(); + if (charset.empty()) + return; + + size_t n = charset.find("charset="); + if (n == string::npos) + return; + + L_BEGIN_LOG_EXCEPTION + + size_t begin = n + sizeof("charset"); + size_t end = charset.find(";", begin); + charset = charset.substr(begin, end - begin); + + if (Utils::stringToLower(charset) != "utf-8") { + string utf8Body = Utils::convertAnyToUtf8(content.getBodyAsUtf8String(), charset); + if (!utf8Body.empty()) { + // TODO: use move operator if possible in the future! + content.setBodyFromUtf8(utf8Body); + contentType.addParameter("charset", "UTF-8"); + content.setContentType(contentType); + } + } + + L_END_LOG_EXCEPTION +} + +void ChatMessagePrivate::notifyReceiving () { + L_Q(); + + LinphoneChatRoom *chatRoom = static_pointer_cast(q->getChatRoom())->getPrivate()->getCChatRoom(); + if ((getContentType() != ContentType::Imdn) && (getContentType() != ContentType::ImIsComposing)) { + _linphone_chat_room_notify_chat_message_should_be_stored(chatRoom, L_GET_C_BACK_PTR(q->getSharedFromThis())); + if (toBeStored) + storeInDb(); + } else { + // For compatibility, when CPIM is not used + positiveDeliveryNotificationRequired = false; + negativeDeliveryNotificationRequired = false; + displayNotificationRequired = false; + } + shared_ptr event = make_shared( + ::time(nullptr), q->getSharedFromThis() + ); + _linphone_chat_room_notify_chat_message_received(chatRoom, L_GET_C_BACK_PTR(event)); + // Legacy + q->getChatRoom()->getPrivate()->notifyChatMessageReceived(q->getSharedFromThis()); + + if (getPositiveDeliveryNotificationRequired()) + static_cast(q->getChatRoom()->getPrivate())->sendDeliveryNotification(q->getSharedFromThis()); +} + +LinphoneReason ChatMessagePrivate::receive () { + L_Q(); + int errorCode = 0; + LinphoneReason reason = LinphoneReasonNone; + + shared_ptr core = q->getCore(); + shared_ptr chatRoom = q->getChatRoom(); + + // --------------------------------------- + // Start of message modification + // --------------------------------------- + + if ((currentRecvStep &ChatMessagePrivate::Step::Encryption) == ChatMessagePrivate::Step::Encryption) { + lInfo() << "Encryption step already done, skipping"; + } else { + EncryptionChatMessageModifier ecmm; + ChatMessageModifier::Result result = ecmm.decode(q->getSharedFromThis(), errorCode); + if (result == ChatMessageModifier::Result::Error) { + /* Unable to decrypt message */ + chatRoom->getPrivate()->notifyUndecryptableChatMessageReceived(q->getSharedFromThis()); + reason = linphone_error_code_to_reason(errorCode); + if (getNegativeDeliveryNotificationRequired()) { + static_cast(q->getChatRoom()->getPrivate())->sendDeliveryErrorNotification( + q->getSharedFromThis(), + reason + ); + } + return reason; + } else if (result == ChatMessageModifier::Result::Suspended) { + currentRecvStep |= ChatMessagePrivate::Step::Encryption; + return LinphoneReasonNone; + } + currentRecvStep |= ChatMessagePrivate::Step::Encryption; + } + + if ((currentRecvStep &ChatMessagePrivate::Step::Cpim) == ChatMessagePrivate::Step::Cpim) { + lInfo() << "Cpim step already done, skipping"; + } else { + if (internalContent.getContentType() == ContentType::Cpim) { + CpimChatMessageModifier ccmm; + ccmm.decode(q->getSharedFromThis(), errorCode); + } + currentRecvStep |= ChatMessagePrivate::Step::Cpim; + } + + if ((currentRecvStep &ChatMessagePrivate::Step::Multipart) == ChatMessagePrivate::Step::Multipart) { + lInfo() << "Multipart step already done, skipping"; + } else { + MultipartChatMessageModifier mcmm; + mcmm.decode(q->getSharedFromThis(), errorCode); + currentRecvStep |= ChatMessagePrivate::Step::Multipart; + } + + if ((currentRecvStep & ChatMessagePrivate::Step::FileUpload) == ChatMessagePrivate::Step::FileUpload) { + lInfo() << "File download step already done, skipping"; + } else { + // This will check if internal content is FileTransfer and make the appropriate changes + loadFileTransferUrlFromBodyToContent(); + currentRecvStep |= ChatMessagePrivate::Step::FileUpload; + } + + if (contents.size() == 0) { + // All previous modifiers only altered the internal content, let's fill the content list + contents.push_back(new Content(internalContent)); + } + + for (auto &content : contents) + forceUtf8Content(*content); + + // --------------------------------------- + // End of message modification + // --------------------------------------- + + // Remove internal content as it is not needed anymore and will confuse some old methods like getText() + internalContent.setBody(""); + internalContent.setContentType(ContentType("")); + // Also remove current step so we go through all modifiers if message is re-sent + currentRecvStep = ChatMessagePrivate::Step::None; + + setState(ChatMessage::State::Delivered); + + if (errorCode <= 0) { + bool foundSupportContentType = false; + for (Content *c : contents) { + ContentType ct(c->getContentType()); + ct.cleanParameters(); + if (linphone_core_is_content_type_supported(core->getCCore(), ct.asString().c_str())) { + foundSupportContentType = true; + break; + } else + lError() << "Unsupported content-type: " << c->getContentType(); + } + + if (!foundSupportContentType) { + errorCode = 415; + lError() << "No content-type in the contents list is supported..."; + } + } + + // Check if this is in fact an outgoing message (case where this is a message sent by us from an other device). + Address me(linphone_core_get_identity(core->getCCore())); + if (me.weakEqual(q->getFromAddress())) + setDirection(ChatMessage::Direction::Outgoing); + + // Check if this is a duplicate message. + if (chatRoom->findChatMessage(imdnId, direction)) + return core->getCCore()->chat_deny_code; + + if (errorCode > 0) { + reason = linphone_error_code_to_reason(errorCode); + if (getNegativeDeliveryNotificationRequired()) { + static_cast(q->getChatRoom()->getPrivate())->sendDeliveryErrorNotification( + q->getSharedFromThis(), + reason + ); + } + return reason; + } + + if ((getContentType() == ContentType::ImIsComposing) || (getContentType() == ContentType::Imdn)) + toBeStored = false; + + return reason; +} + +void ChatMessagePrivate::send () { + L_Q(); + SalOp *op = salOp; + LinphoneCall *lcall = nullptr; + int errorCode = 0; + + currentSendStep |= ChatMessagePrivate::Step::Started; + + if (toBeStored && currentSendStep == (ChatMessagePrivate::Step::Started | ChatMessagePrivate::Step::None)) + storeInDb(); + + if ((currentSendStep & ChatMessagePrivate::Step::FileUpload) == ChatMessagePrivate::Step::FileUpload) { + lInfo() << "File upload step already done, skipping"; + } else { + ChatMessageModifier::Result result = fileTransferChatMessageModifier.encode(q->getSharedFromThis(), errorCode); + if (result == ChatMessageModifier::Result::Error) { + setState(ChatMessage::State::NotDelivered); + return; + } else if (result == ChatMessageModifier::Result::Suspended) { + setState(ChatMessage::State::InProgress); + return; + } + currentSendStep |= ChatMessagePrivate::Step::FileUpload; + } + + shared_ptr core = q->getCore(); + if (lp_config_get_int(core->getCCore()->config, "sip", "chat_use_call_dialogs", 0) != 0) { + lcall = linphone_core_get_call_by_remote_address(core->getCCore(), q->getToAddress().asString().c_str()); + if (lcall) { + shared_ptr call = L_GET_CPP_PTR_FROM_C_OBJECT(lcall); + if ((call->getState() == CallSession::State::Connected) + || (call->getState() == CallSession::State::StreamsRunning) + || (call->getState() == CallSession::State::Paused) + || (call->getState() == CallSession::State::Pausing) + || (call->getState() == CallSession::State::PausedByRemote) + ) { + lInfo() << "Send SIP msg through the existing call"; + op = call->getPrivate()->getOp(); + string identity = linphone_core_find_best_identity(core->getCCore(), linphone_call_get_remote_address(lcall)); + if (identity.empty()) { + LinphoneAddress *addr = linphone_address_new(q->getToAddress().asString().c_str()); + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(core->getCCore(), addr); + if (proxy) { + identity = L_GET_CPP_PTR_FROM_C_OBJECT(linphone_proxy_config_get_identity_address(proxy))->asString(); + } else { + identity = linphone_core_get_primary_contact(core->getCCore()); + } + linphone_address_unref(addr); + } + } + } + } + + if (!op) { + LinphoneAddress *peer = linphone_address_new(q->getToAddress().asString().c_str()); + /* Sending out of call */ + salOp = op = new SalMessageOp(core->getCCore()->sal); + linphone_configure_op( + core->getCCore(), op, peer, getSalCustomHeaders(), + !!lp_config_get_int(core->getCCore()->config, "sip", "chat_msg_with_contact", 0) + ); + op->setUserPointer(q); /* If out of call, directly store msg */ + linphone_address_unref(peer); + } + op->setFrom(q->getFromAddress().asString().c_str()); + op->setTo(q->getToAddress().asString().c_str()); + + // --------------------------------------- + // Start of message modification + // --------------------------------------- + + if (applyModifiers) { + // Do not multipart or encapsulate with CPIM in an old ChatRoom to maintain backward compatibility + if (q->getChatRoom()->canHandleMultipart()) { + if ((currentSendStep &ChatMessagePrivate::Step::Multipart) == ChatMessagePrivate::Step::Multipart) { + lInfo() << "Multipart step already done, skipping"; + } else { + if (contents.size() > 1) { + MultipartChatMessageModifier mcmm; + mcmm.encode(q->getSharedFromThis(), errorCode); + } + currentSendStep |= ChatMessagePrivate::Step::Multipart; + } + } + + if (q->getChatRoom()->canHandleCpim()) { + if ((currentSendStep &ChatMessagePrivate::Step::Cpim) == ChatMessagePrivate::Step::Cpim) { + lInfo() << "Cpim step already done, skipping"; + } else { + CpimChatMessageModifier ccmm; + ccmm.encode(q->getSharedFromThis(), errorCode); + currentSendStep |= ChatMessagePrivate::Step::Cpim; + } + } + + if ((currentSendStep &ChatMessagePrivate::Step::Encryption) == ChatMessagePrivate::Step::Encryption) { + lInfo() << "Encryption step already done, skipping"; + } else { + if (!encryptionPrevented) { + EncryptionChatMessageModifier ecmm; + ChatMessageModifier::Result result = ecmm.encode(q->getSharedFromThis(), errorCode); + if (result == ChatMessageModifier::Result::Error) { + sal_error_info_set((SalErrorInfo *)op->getErrorInfo(), SalReasonNotAcceptable, "SIP", errorCode, "Unable to encrypt IM", nullptr); + setState(ChatMessage::State::NotDelivered); + return; + } else if (result == ChatMessageModifier::Result::Suspended) { + currentSendStep |= ChatMessagePrivate::Step::Encryption; + return; + } + } + currentSendStep |= ChatMessagePrivate::Step::Encryption; + } + } + + // --------------------------------------- + // End of message modification + // --------------------------------------- + + if (internalContent.isEmpty()) { + if (contents.size() > 0) { + internalContent = *(contents.front()); + } else if (externalBodyUrl.empty()) { // When using external body url, there is no content + lError() << "Trying to send a message without any content !"; + return; + } + } + + auto msgOp = dynamic_cast(op); + if (!externalBodyUrl.empty()) { + Content content; + ContentType contentType(ContentType::ExternalBody); + contentType.addParameter("access-type", "URL"); + contentType.addParameter("URL", "\"" + externalBodyUrl + "\""); + content.setContentType(contentType); + msgOp->sendMessage(content); + } else { + if (!internalContent.getContentType().isValid()) + internalContent.setContentType(ContentType::PlainText); + if (!contentEncoding.empty()) + internalContent.setContentEncoding(contentEncoding); + msgOp->sendMessage(internalContent); + } + + // Restore FileContents and remove FileTransferContents + list::iterator it = contents.begin(); + while (it != contents.end()) { + Content *content = *it; + if (content->isFileTransfer()) { + FileTransferContent *fileTransferContent = static_cast(content); + it = contents.erase(it); + addContent(fileTransferContent->getFileContent()); + delete fileTransferContent; + } else { + it++; + } + } + + // Remove internal content as it is not needed anymore and will confuse some old methods like getContentType() + internalContent.setBody(""); + internalContent.setContentType(ContentType("")); + // Also remove current step so we go through all modifiers if message is re-sent + currentSendStep = ChatMessagePrivate::Step::None; + + if (imdnId.empty()) + setImdnMessageId(op->getCallId()); /* must be known at that time */ + + if (lcall && linphone_call_get_op(lcall) == op) { + /* In this case, chat delivery status is not notified, so unrefing chat message right now */ + /* Might be better fixed by delivering status, but too costly for now */ + return; + } + + /* If operation failed, we should not change message state */ + if (direction == ChatMessage::Direction::Outgoing) { + setIsReadOnly(true); + setState(ChatMessage::State::InProgress); + } +} + +void ChatMessagePrivate::storeInDb () { + L_Q(); + + // TODO: store message in the future + if (linphone_core_conference_server_enabled(q->getCore()->getCCore())) return; + + if (dbKey.isValid()) { + updateInDb(); + } else { + shared_ptr eventLog = make_shared(time, q->getSharedFromThis()); + + // Avoid transaction in transaction if contents are not loaded. + loadContentsFromDatabase(); + q->getChatRoom()->getPrivate()->addEvent(eventLog); + + if (direction == ChatMessage::Direction::Incoming) { + if (hasFileTransferContent()) { + // Keep the event in the transient list, message storage can be updated in near future + q->getChatRoom()->getPrivate()->addTransientEvent(eventLog); + } + } else { + // Keep event in transient to be able to store in database state changes + q->getChatRoom()->getPrivate()->addTransientEvent(eventLog); + } + } +} + +void ChatMessagePrivate::updateInDb () { + L_Q(); + + if (!dbKey.isValid()) + return; + + unique_ptr &mainDb = q->getChatRoom()->getCore()->getPrivate()->mainDb; + shared_ptr eventLog = mainDb->getEventFromKey(dbKey); + + // Avoid transaction in transaction if contents are not loaded. + loadContentsFromDatabase(); + mainDb->updateEvent(eventLog); + + if (direction == ChatMessage::Direction::Incoming) { + if (!hasFileTransferContent()) { + // Incoming message doesn't have any download waiting anymore, we can remove it's event from the transients + q->getChatRoom()->getPrivate()->removeTransientEvent(eventLog); + } + } else { + if (state == ChatMessage::State::Delivered || state == ChatMessage::State::NotDelivered) { + // Once message has reached this state it won't change anymore so we can remove the event from the transients + q->getChatRoom()->getPrivate()->removeTransientEvent(eventLog); + } + } +} + +// ----------------------------------------------------------------------------- + +bool ChatMessagePrivate::validStateTransition (ChatMessage::State currentState, ChatMessage::State newState) { + if (newState == currentState) + return false; + + if ( + (currentState == ChatMessage::State::Displayed || currentState == ChatMessage::State::DeliveredToUser) && + ( + newState == ChatMessage::State::DeliveredToUser || + newState == ChatMessage::State::Delivered || + newState == ChatMessage::State::NotDelivered + ) + ) + return false; + return true; +} + +// ----------------------------------------------------------------------------- + +ChatMessage::ChatMessage (const shared_ptr &chatRoom, ChatMessage::Direction direction) : + Object(*new ChatMessagePrivate(chatRoom, direction)), CoreAccessor(chatRoom->getCore()) { +} + +ChatMessage::ChatMessage (ChatMessagePrivate &p) : Object(p), CoreAccessor(p.getPublic()->getChatRoom()->getCore()) { +} + +ChatMessage::~ChatMessage () { + L_D(); + + for (Content *content : d->contents) { + if (content->isFileTransfer()) { + FileTransferContent *fileTransferContent = static_cast(content); + delete fileTransferContent->getFileContent(); + } + delete content; + } + + if (d->salOp) { + d->salOp->setUserPointer(nullptr); + d->salOp->unref(); + } + if (d->salCustomHeaders) + sal_custom_header_unref(d->salCustomHeaders); +} + +shared_ptr ChatMessage::getChatRoom () const { + L_D(); + + shared_ptr chatRoom = d->chatRoom.lock(); + if (!chatRoom) { + chatRoom = getCore()->getOrCreateBasicChatRoom(d->chatRoomId); + if (!chatRoom) { + lError() << "Unable to get valid chat room instance."; + throw logic_error("Unable to get chat room of chat message."); + } + } + + return chatRoom; +} + +// ----------------------------------------------------------------------------- + +time_t ChatMessage::getTime () const { + L_D(); + return d->time; +} + +bool ChatMessage::isSecured () const { + L_D(); + return d->isSecured; +} + +void ChatMessage::setIsSecured (bool isSecured) { + L_D(); + d->isSecured = isSecured; +} + +ChatMessage::Direction ChatMessage::getDirection () const { + L_D(); + return d->direction; +} + +ChatMessage::State ChatMessage::getState () const { + L_D(); + return d->state; +} + +const string &ChatMessage::getImdnMessageId () const { + L_D(); + return d->imdnId; +} + +void ChatMessagePrivate::setImdnMessageId (const string &id) { + imdnId = id; +} + +void ChatMessagePrivate::loadContentsFromDatabase () const { + L_Q(); + if (contentsNotLoadedFromDatabase) { + isReadOnly = false; + contentsNotLoadedFromDatabase = false; + q->getChatRoom()->getCore()->getPrivate()->mainDb->loadChatMessageContents( + const_pointer_cast(q->getSharedFromThis()) + ); + isReadOnly = true; + } +} + +bool ChatMessage::isRead () const { + L_D(); + + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(getCore()->getCCore()); + if (linphone_im_notif_policy_get_recv_imdn_displayed(policy) && d->state == State::Displayed) + return true; + + if ( + linphone_im_notif_policy_get_recv_imdn_delivered(policy) && + (d->state == State::DeliveredToUser || d->state == State::Displayed) + ) + return true; + + return d->state == State::Delivered || d->state == State::Displayed || d->state == State::DeliveredToUser; +} + +const IdentityAddress &ChatMessage::getFromAddress () const { + L_D(); + return d->fromAddress; +} + +const IdentityAddress &ChatMessage::getToAddress () const { + L_D(); + return d->toAddress; +} + +bool ChatMessage::getToBeStored () const { + L_D(); + return d->toBeStored; +} + +void ChatMessage::setToBeStored (bool value) { + L_D(); + d->toBeStored = value; +} + +// ----------------------------------------------------------------------------- + +list ChatMessage::getParticipantsByImdnState (ChatMessage::State state) const { + L_D(); + + list result; + if (!(getChatRoom()->getCapabilities() & AbstractChatRoom::Capabilities::Conference) || !d->dbKey.isValid()) + return result; + + unique_ptr &mainDb = getChatRoom()->getCore()->getPrivate()->mainDb; + shared_ptr eventLog = mainDb->getEventFromKey(d->dbKey); + list dbResults = mainDb->getChatMessageParticipantsByImdnState(eventLog, state); + for (const auto &dbResult : dbResults) { + auto sender = getChatRoom()->findParticipant(getFromAddress()); + auto participant = getChatRoom()->findParticipant(dbResult.address); + if (participant && (participant != sender)) + result.emplace_back(participant, dbResult.state, dbResult.timestamp); + } + + return result; +} + +// ----------------------------------------------------------------------------- + +const LinphoneErrorInfo *ChatMessage::getErrorInfo () const { + L_D(); + if (!d->errorInfo) d->errorInfo = linphone_error_info_new(); // let's do it mutable + linphone_error_info_from_sal_op(d->errorInfo, d->salOp); + return d->errorInfo; +} + +bool ChatMessage::isReadOnly () const { + L_D(); + return d->isReadOnly; +} + +const list &ChatMessage::getContents () const { + L_D(); + return d->getContents(); +} + +void ChatMessage::addContent (Content *content) { + L_D(); + if (!d->isReadOnly) + d->addContent(content); +} + +void ChatMessage::removeContent (Content *content) { + L_D(); + if (!d->isReadOnly) + d->removeContent(content); +} + +const Content &ChatMessage::getInternalContent () const { + L_D(); + return d->internalContent; +} + +void ChatMessage::setInternalContent (const Content &content) { + L_D(); + d->internalContent = content; +} + +string ChatMessage::getCustomHeaderValue (const string &headerName) const { + L_D(); + try { + return d->customHeaders.at(headerName); + } catch (const exception &) { + // Key doesn't exist. + } + return nullptr; +} + +void ChatMessage::addCustomHeader (const string &headerName, const string &headerValue) { + L_D(); + if (d->isReadOnly) return; + + d->customHeaders[headerName] = headerValue; +} + +void ChatMessage::removeCustomHeader (const string &headerName) { + L_D(); + if (d->isReadOnly) return; + + d->customHeaders.erase(headerName); +} + +void ChatMessage::send () { + L_D(); + + // Do not allow sending a message that is already being sent or that has been correctly delivered/displayed + if ((d->state == State::InProgress) || (d->state == State::Delivered) || (d->state == State::FileTransferDone) || + (d->state == State::DeliveredToUser) || (d->state == State::Displayed)) { + lWarning() << "Cannot send chat message in state " << Utils::toString(d->state); + return; + } + + d->loadContentsFromDatabase(); + getChatRoom()->getPrivate()->sendChatMessage(getSharedFromThis()); +} + +bool ChatMessage::downloadFile(FileTransferContent *fileTransferContent) { + L_D(); + return d->fileTransferChatMessageModifier.downloadFile(getSharedFromThis(), fileTransferContent); +} + +bool ChatMessage::isFileTransferInProgress() { + L_D(); + return d->fileTransferChatMessageModifier.isFileTransferInProgressAndValid(); +} + +void ChatMessage::cancelFileTransfer () { + L_D(); + if (d->fileTransferChatMessageModifier.isFileTransferInProgressAndValid()) { + if (d->state == State::InProgress) { + d->setState(State::NotDelivered); + } + d->fileTransferChatMessageModifier.cancelFileTransfer(); + } else { + lInfo() << "No existing file transfer - nothing to cancel"; + } +} + +int ChatMessage::putCharacter (uint32_t character) { + L_D(); + + constexpr uint32_t newLine = 0x2028; + constexpr uint32_t crlf = 0x0D0A; + constexpr uint32_t lf = 0x0A; + + shared_ptr chatRoom = getChatRoom(); + if (!(chatRoom->getCapabilities() & LinphonePrivate::ChatRoom::Capabilities::RealTimeText)) + return -1; + + shared_ptr rttcr = + static_pointer_cast(chatRoom); + if (!rttcr) + return -1; + + shared_ptr call = rttcr->getCall(); + if (!call || !call->getPrivate()->getMediaStream(LinphoneStreamTypeText)) + return -1; + + if (character == newLine || character == crlf || character == lf) { + shared_ptr core = getCore(); + if (lp_config_get_int(core->getCCore()->config, "misc", "store_rtt_messages", 1) == 1) { + lInfo() << "New line sent, forge a message with content " << d->rttMessage; + d->state = State::Displayed; + d->setText(d->rttMessage); + d->storeInDb(); + d->rttMessage = ""; + } + } else { + char *value = LinphonePrivate::Utils::utf8ToChar(character); + d->rttMessage += string(value); + lDebug() << "Sent RTT character: " << value << "(" << (unsigned long)character << "), pending text is " << d->rttMessage; + delete[] value; + } + + text_stream_putchar32( + reinterpret_cast(call->getPrivate()->getMediaStream(LinphoneStreamTypeText)), + character + ); + return 0; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-message/chat-message.h b/src/chat/chat-message/chat-message.h new file mode 100644 index 000000000..ef188d8bc --- /dev/null +++ b/src/chat/chat-message/chat-message.h @@ -0,0 +1,126 @@ +/* + * chat-message.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_MESSAGE_H_ +#define _L_CHAT_MESSAGE_H_ + +#include + +#include "linphone/api/c-types.h" +#include "linphone/enums/chat-message-enums.h" + +// TODO: Remove me later? +#include "address/identity-address.h" + +#include "core/core-accessor.h" +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class AbstractChatRoom; +class Content; +class FileTransferContent; +class ChatMessagePrivate; +class Participant; +class ParticipantImdnState; + +class LINPHONE_PUBLIC ChatMessage : public Object, public CoreAccessor { + friend class BasicToClientGroupChatRoom; + friend class BasicToClientGroupChatRoomPrivate; + friend class ChatRoom; + friend class ChatRoomPrivate; + friend class CpimChatMessageModifier; + friend class FileTransferChatMessageModifier; + friend class Imdn; + friend class ImdnMessagePrivate; + friend class MainDb; + friend class MainDbPrivate; + friend class RealTimeTextChatRoomPrivate; + friend class ServerGroupChatRoomPrivate; + +public: + L_OVERRIDE_SHARED_FROM_THIS(ChatMessage); + + L_DECLARE_ENUM(State, L_ENUM_VALUES_CHAT_MESSAGE_STATE); + L_DECLARE_ENUM(Direction, L_ENUM_VALUES_CHAT_MESSAGE_DIRECTION); + + virtual ~ChatMessage (); + + // ----- TODO: Remove me. + void cancelFileTransfer (); + int putCharacter (uint32_t character); + void setIsSecured (bool isSecured); + // ----- TODO: Remove me. + + std::shared_ptr getChatRoom () const; + + void send (); + + time_t getTime () const; + + bool isSecured () const; + State getState () const; + Direction getDirection () const; + + const std::string &getImdnMessageId () const; + + const IdentityAddress &getFromAddress () const; + const IdentityAddress &getToAddress () const; + + // TODO: Return a cpp reference. + const LinphoneErrorInfo *getErrorInfo () const; + + bool isRead () const; + bool isReadOnly () const; + + bool getToBeStored () const; + virtual void setToBeStored (bool value); + + std::list getParticipantsByImdnState (State state) const; + + const std::list &getContents () const; + void addContent (Content *content); + void removeContent (Content *content); + + const Content &getInternalContent () const; + void setInternalContent (const Content &content); + + // TODO: to replace salCustomheaders + std::string getCustomHeaderValue (const std::string &headerName) const; + void addCustomHeader (const std::string &headerName, const std::string &headerValue); + void removeCustomHeader (const std::string &headerName); + + bool downloadFile (FileTransferContent *content); + bool isFileTransferInProgress(); + +protected: + explicit ChatMessage (ChatMessagePrivate &p); + +private: + ChatMessage (const std::shared_ptr &chatRoom, ChatMessage::Direction direction); + + L_DECLARE_PRIVATE(ChatMessage); + L_DISABLE_COPY(ChatMessage); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CHAT_MESSAGE_H_ diff --git a/src/chat/chat-message/imdn-message-p.h b/src/chat/chat-message/imdn-message-p.h new file mode 100644 index 000000000..57b0678e9 --- /dev/null +++ b/src/chat/chat-message/imdn-message-p.h @@ -0,0 +1,47 @@ +/* + * imdn-message-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_IMDN_MESSAGE_P_H_ +#define _L_IMDN_MESSAGE_P_H_ + +#include "chat/chat-message/imdn-message.h" +#include "chat/chat-message/notification-message-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ImdnMessagePrivate : public NotificationMessagePrivate { +public: + const ImdnMessage::Context &getContext () { return context; } + +private: + ImdnMessagePrivate (const ImdnMessage::Context &context) + : NotificationMessagePrivate(context.chatRoom, ChatMessage::Direction::Outgoing), context(context) {} + + void setState (ChatMessage::State newState, bool force = false) override; + + ImdnMessage::Context context; + + L_DECLARE_PUBLIC(ImdnMessage); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_IMDN_MESSAGE_P_H_ diff --git a/src/chat/chat-message/imdn-message.cpp b/src/chat/chat-message/imdn-message.cpp new file mode 100644 index 000000000..9e849560d --- /dev/null +++ b/src/chat/chat-message/imdn-message.cpp @@ -0,0 +1,93 @@ +/* + * imdn-message.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "chat/chat-message/imdn-message-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "content/content-disposition.h" +#include "logger/logger.h" +#include "sip-tools/sip-headers.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +void ImdnMessagePrivate::setState (ChatMessage::State newState, bool force) { + L_Q(); + + if (newState == ChatMessage::State::Delivered) { + for (const auto &message : context.deliveredMessages) + message->getPrivate()->updateInDb(); + for (const auto &message : context.displayedMessages) + message->getPrivate()->updateInDb(); + static_pointer_cast(context.chatRoom)->getPrivate()->getImdnHandler()->onImdnMessageDelivered(q->getSharedFromThis()); + } else if (newState == ChatMessage::State::NotDelivered) { + // TODO: Maybe we should retry sending the IMDN message if we get an error here + } +} + +// ----------------------------------------------------------------------------- + +ImdnMessage::ImdnMessage ( + const shared_ptr &chatRoom, + const list> &deliveredMessages, + const list> &displayedMessages +) : ImdnMessage(Context(chatRoom, deliveredMessages, displayedMessages)) {} + +ImdnMessage::ImdnMessage ( + const shared_ptr &chatRoom, + const list &nonDeliveredMessages +) : ImdnMessage(Context(chatRoom, nonDeliveredMessages)) {} + +ImdnMessage::ImdnMessage (const std::shared_ptr &message) : ImdnMessage(message->getPrivate()->context) {} + +ImdnMessage::ImdnMessage (const Context &context) : NotificationMessage(*new ImdnMessagePrivate(context)) { + L_D(); + + for (const auto &message : d->context.deliveredMessages) { + Content *content = new Content(); + content->setContentDisposition(ContentDisposition::Notification); + content->setContentType(ContentType::Imdn); + content->setBody(Imdn::createXml(message->getImdnMessageId(), message->getTime(), Imdn::Type::Delivery, LinphoneReasonNone)); + addContent(content); + } + for (const auto &message : d->context.displayedMessages) { + Content *content = new Content(); + content->setContentDisposition(ContentDisposition::Notification); + content->setContentType(ContentType::Imdn); + content->setBody(Imdn::createXml(message->getImdnMessageId(), message->getTime(), Imdn::Type::Display, LinphoneReasonNone)); + addContent(content); + } + for (const auto &mr : d->context.nonDeliveredMessages) { + Content *content = new Content(); + content->setContentDisposition(ContentDisposition::Notification); + content->setContentType(ContentType::Imdn); + content->setBody(Imdn::createXml(mr.message->getImdnMessageId(), mr.message->getTime(), Imdn::Type::Delivery, mr.reason)); + addContent(content); + } + + d->addSalCustomHeader(PriorityHeader::HeaderName, PriorityHeader::NonUrgent); + if (!d->context.nonDeliveredMessages.empty()) + d->setEncryptionPrevented(true); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-message/imdn-message.h b/src/chat/chat-message/imdn-message.h new file mode 100644 index 000000000..28ce11084 --- /dev/null +++ b/src/chat/chat-message/imdn-message.h @@ -0,0 +1,77 @@ +/* + * imdn-message.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_IMDN_MESSAGE_H_ +#define _L_IMDN_MESSAGE_H_ + +#include "chat/chat-message/notification-message.h" +#include "chat/notification/imdn.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ImdnMessagePrivate; + +class LINPHONE_PUBLIC ImdnMessage : public NotificationMessage { +public: + friend class ChatRoomPrivate; + friend class Imdn; + + L_OVERRIDE_SHARED_FROM_THIS(ImdnMessage); + + virtual ~ImdnMessage () = default; + +private: + struct Context { + Context ( + const std::shared_ptr &chatRoom, + const std::list> &deliveredMessages, + const std::list> &displayedMessages + ) : chatRoom(chatRoom), deliveredMessages(deliveredMessages), displayedMessages(displayedMessages) {} + Context ( + const std::shared_ptr &chatRoom, + const std::list &nonDeliveredMessages + ) : chatRoom(chatRoom), nonDeliveredMessages(nonDeliveredMessages) {} + + std::shared_ptr chatRoom; + std::list> deliveredMessages; + std::list> displayedMessages; + std::list nonDeliveredMessages; + }; + + ImdnMessage ( + const std::shared_ptr &chatRoom, + const std::list> &deliveredMessages, + const std::list> &displayedMessages + ); + ImdnMessage ( + const std::shared_ptr &chatRoom, + const std::list &nonDeliveredMessages + ); + ImdnMessage (const std::shared_ptr &message); + ImdnMessage (const Context &context); + + L_DECLARE_PRIVATE(ImdnMessage); + L_DISABLE_COPY(ImdnMessage); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_IMDN_MESSAGE_H_ diff --git a/src/chat/chat-message/is-composing-message.cpp b/src/chat/chat-message/is-composing-message.cpp new file mode 100644 index 000000000..9797e9e9e --- /dev/null +++ b/src/chat/chat-message/is-composing-message.cpp @@ -0,0 +1,46 @@ +/* + * is-composing-message.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "chat/chat-message/notification-message-p.h" +#include "chat/chat-message/is-composing-message.h" +#include "sip-tools/sip-headers.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +IsComposingMessage::IsComposingMessage ( + const shared_ptr &chatRoom, + IsComposing &isComposingHandler, + bool isComposing +) : NotificationMessage(*new NotificationMessagePrivate(chatRoom, ChatMessage::Direction::Outgoing)) { + L_D(); + Content *content = new Content(); + content->setContentType(ContentType::ImIsComposing); + content->setBody(isComposingHandler.createXml(isComposing)); + addContent(content); + d->addSalCustomHeader(PriorityHeader::HeaderName, PriorityHeader::NonUrgent); + d->addSalCustomHeader("Expires", "0"); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-message/is-composing-message.h b/src/chat/chat-message/is-composing-message.h new file mode 100644 index 000000000..41f2a8c7f --- /dev/null +++ b/src/chat/chat-message/is-composing-message.h @@ -0,0 +1,51 @@ +/* + * is-composing-message.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_IS_COMPOSING_MESSAGE_H_ +#define _L_IS_COMPOSING_MESSAGE_H_ + +#include "chat/chat-message/notification-message.h" +#include "chat/notification/is-composing.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class LINPHONE_PUBLIC IsComposingMessage : public NotificationMessage { +public: + friend class ChatRoomPrivate; + + L_OVERRIDE_SHARED_FROM_THIS(IsComposingMessage); + + virtual ~IsComposingMessage () = default; + +private: + IsComposingMessage ( + const std::shared_ptr &chatRoom, + IsComposing &isComposingHandler, + bool isComposing + ); + + L_DECLARE_PRIVATE(NotificationMessage); + L_DISABLE_COPY(IsComposingMessage); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_IS_COMPOSING_MESSAGE_H_ diff --git a/src/chat/chat-message/notification-message-p.h b/src/chat/chat-message/notification-message-p.h new file mode 100644 index 000000000..28e2bbb52 --- /dev/null +++ b/src/chat/chat-message/notification-message-p.h @@ -0,0 +1,50 @@ +/* + * notification-message-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_NOTIFICATION_MESSAGE_P_H_ +#define _L_NOTIFICATION_MESSAGE_P_H_ + +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-message/notification-message.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class NotificationMessagePrivate : public ChatMessagePrivate { + friend class ImdnMessage; + friend class IsComposingMessage; + +protected: + NotificationMessagePrivate(const std::shared_ptr &cr, ChatMessage::Direction dir) + : ChatMessagePrivate(cr, dir) {} + + void setState (ChatMessage::State newState, bool force = false) override {}; + +private: + void setDisplayNotificationRequired (bool value) override {} + void setNegativeDeliveryNotificationRequired (bool value) override {} + void setPositiveDeliveryNotificationRequired (bool value) override {} + + L_DECLARE_PUBLIC(NotificationMessage); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_NOTIFICATION_MESSAGE_P_H_ diff --git a/src/chat/chat-message/notification-message.cpp b/src/chat/chat-message/notification-message.cpp new file mode 100644 index 000000000..16c649d13 --- /dev/null +++ b/src/chat/chat-message/notification-message.cpp @@ -0,0 +1,46 @@ +/* + * notification-message.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "chat/chat-message/notification-message-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +NotificationMessage::NotificationMessage (const shared_ptr &chatRoom, ChatMessage::Direction direction) : + NotificationMessage(*new NotificationMessagePrivate(chatRoom, direction)) { +} + +NotificationMessage::NotificationMessage (NotificationMessagePrivate &p) : ChatMessage(p) { + L_D(); + d->displayNotificationRequired = false; + d->negativeDeliveryNotificationRequired = false; + d->positiveDeliveryNotificationRequired = false; + d->toBeStored = false; + d->contentEncoding = "deflate"; +} + +void NotificationMessage::setToBeStored (bool value) { +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-message/notification-message.h b/src/chat/chat-message/notification-message.h new file mode 100644 index 000000000..f818a009f --- /dev/null +++ b/src/chat/chat-message/notification-message.h @@ -0,0 +1,53 @@ +/* + * notification-message.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_NOTIFICATION_MESSAGE_H_ +#define _L_NOTIFICATION_MESSAGE_H_ + +#include "chat/chat-message/chat-message.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class NotificationMessagePrivate; + +class LINPHONE_PUBLIC NotificationMessage : public ChatMessage { +public: + friend class ChatRoomPrivate; + + L_OVERRIDE_SHARED_FROM_THIS(NotificationMessage); + + virtual ~NotificationMessage () = default; + + void setToBeStored (bool value) override; + +protected: + explicit NotificationMessage (NotificationMessagePrivate &p); + +private: + NotificationMessage (const std::shared_ptr &chatRoom, ChatMessage::Direction direction); + + L_DECLARE_PRIVATE(NotificationMessage); + L_DISABLE_COPY(NotificationMessage); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_NOTIFICATION_MESSAGE_H_ diff --git a/src/chat/chat-room/abstract-chat-room-p.h b/src/chat/chat-room/abstract-chat-room-p.h new file mode 100644 index 000000000..de9054965 --- /dev/null +++ b/src/chat/chat-room/abstract-chat-room-p.h @@ -0,0 +1,61 @@ +/* + * abstract-chat-room-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ABSTRACT_CHAT_ROOM_P_H_ +#define _L_ABSTRACT_CHAT_ROOM_P_H_ + +#include "abstract-chat-room.h" +#include "chat/chat-room/chat-room-listener.h" +#include "conference/session/call-session-listener.h" +#include "object/object-p.h" + +// ============================================================================= + +L_DECL_C_STRUCT_PREFIX_LESS(SalMessage); + +LINPHONE_BEGIN_NAMESPACE + +class SalOp; + +class AbstractChatRoomPrivate : public ObjectPrivate, public ChatRoomListener, public CallSessionListener { +public: + virtual void setCreationTime (time_t creationTime) = 0; + virtual void setLastUpdateTime (time_t lastUpdateTime) = 0; + + virtual void setState (AbstractChatRoom::State state) = 0; + + virtual void sendChatMessage (const std::shared_ptr &chatMessage) = 0; + + virtual void addEvent (const std::shared_ptr &eventLog) = 0; + + virtual void addTransientEvent (const std::shared_ptr &eventLog) = 0; + virtual void removeTransientEvent (const std::shared_ptr &eventLog) = 0; + + virtual void sendDeliveryNotifications () = 0; + + virtual void notifyChatMessageReceived (const std::shared_ptr &chatMessage) = 0; + virtual void notifyUndecryptableChatMessageReceived (const std::shared_ptr &chatMessage) = 0; + + virtual LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) = 0; + virtual void onChatMessageReceived (const std::shared_ptr &chatMessage) = 0; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ABSTRACT_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/abstract-chat-room.cpp b/src/chat/chat-room/abstract-chat-room.cpp new file mode 100644 index 000000000..2f6a123c9 --- /dev/null +++ b/src/chat/chat-room/abstract-chat-room.cpp @@ -0,0 +1,35 @@ +/* + * abstract-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "abstract-chat-room-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +AbstractChatRoom::AbstractChatRoom ( + AbstractChatRoomPrivate &p, + const shared_ptr &core +) : Object(p), CoreAccessor(core) {} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/abstract-chat-room.h b/src/chat/chat-room/abstract-chat-room.h new file mode 100644 index 000000000..8a259466f --- /dev/null +++ b/src/chat/chat-room/abstract-chat-room.h @@ -0,0 +1,112 @@ +/* + * abstract-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ABSTRACT_CHAT_ROOM_H_ +#define _L_ABSTRACT_CHAT_ROOM_H_ + +#include "linphone/utils/enum-mask.h" + +#include "chat/chat-message/chat-message.h" +#include "conference/conference-interface.h" +#include "core/core-accessor.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class AbstractChatRoomPrivate; +class ChatRoomId; +class EventLog; + +class LINPHONE_PUBLIC AbstractChatRoom : public Object, public CoreAccessor, public ConferenceInterface { + friend class ChatMessage; + friend class ChatMessagePrivate; + friend class ClientGroupToBasicChatRoomPrivate; + friend class Core; + friend class CorePrivate; + friend class MainDb; + friend class ProxyChatRoomPrivate; + +public: + L_OVERRIDE_SHARED_FROM_THIS(AbstractChatRoom); + + L_DECLARE_ENUM(Capabilities, L_ENUM_VALUES_CHAT_ROOM_CAPABILITIES); + L_DECLARE_ENUM(State, L_ENUM_VALUES_CHAT_ROOM_STATE); + + typedef EnumMask CapabilitiesMask; + + virtual void allowCpim (bool value) = 0; + virtual void allowMultipart (bool value) = 0; + virtual bool canHandleCpim () const = 0; + virtual bool canHandleMultipart () const = 0; + + virtual const ChatRoomId &getChatRoomId () const = 0; + + virtual const IdentityAddress &getPeerAddress () const = 0; + virtual const IdentityAddress &getLocalAddress () const = 0; + + virtual time_t getCreationTime () const = 0; + virtual time_t getLastUpdateTime () const = 0; + + virtual CapabilitiesMask getCapabilities () const = 0; + virtual State getState () const = 0; + virtual bool hasBeenLeft () const = 0; + + virtual std::list> getMessageHistory (int nLast) const = 0; + virtual std::list> getMessageHistoryRange (int begin, int end) const = 0; + virtual std::list> getHistory (int nLast) const = 0; + virtual std::list> getHistoryRange (int begin, int end) const = 0; + virtual int getHistorySize () const = 0; + + virtual void deleteFromDb () = 0; + virtual void deleteHistory () = 0; + + virtual std::shared_ptr getLastChatMessageInHistory () const = 0; + + virtual int getChatMessageCount () const = 0; + virtual int getUnreadChatMessageCount () const = 0; + + virtual void compose () = 0; + virtual bool isRemoteComposing () const = 0; + virtual std::list getComposingAddresses () const = 0; + + virtual std::shared_ptr createChatMessage () = 0; + virtual std::shared_ptr createChatMessage (const std::string &text) = 0; + + virtual std::shared_ptr createFileTransferMessage (Content *initialContent) = 0; + + virtual std::shared_ptr findChatMessage (const std::string &messageId) const = 0; + virtual std::shared_ptr findChatMessage ( + const std::string &messageId, + ChatMessage::Direction direction + ) const = 0; + + virtual void markAsRead () = 0; + +protected: + explicit AbstractChatRoom (AbstractChatRoomPrivate &p, const std::shared_ptr &core); + +private: + L_DECLARE_PRIVATE(AbstractChatRoom); + L_DISABLE_COPY(AbstractChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ABSTRACT_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/basic-chat-room-p.h b/src/chat/chat-room/basic-chat-room-p.h new file mode 100644 index 000000000..28d810955 --- /dev/null +++ b/src/chat/chat-room/basic-chat-room-p.h @@ -0,0 +1,43 @@ +/* + * basic-chat-room-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_BASIC_CHAT_ROOM_P_H_ +#define _L_BASIC_CHAT_ROOM_P_H_ + +#include "basic-chat-room.h" +#include "chat/chat-room/chat-room-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class BasicChatRoomPrivate : public ChatRoomPrivate { +private: + std::string subject; + std::shared_ptr me; + std::list> participants; + bool cpimAllowed = false; + bool multipartAllowed = false; + + L_DECLARE_PUBLIC(BasicChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_BASIC_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/basic-chat-room.cpp b/src/chat/chat-room/basic-chat-room.cpp new file mode 100644 index 000000000..63b4372ed --- /dev/null +++ b/src/chat/chat-room/basic-chat-room.cpp @@ -0,0 +1,141 @@ +/* + * basic-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "basic-chat-room-p.h" +#include "conference/participant.h" +#include "logger/logger.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +BasicChatRoom::BasicChatRoom (const shared_ptr &core, const ChatRoomId &chatRoomId) : + BasicChatRoom(*new BasicChatRoomPrivate, core, chatRoomId) {} + +BasicChatRoom::BasicChatRoom ( + BasicChatRoomPrivate &p, + const std::shared_ptr &core, + const ChatRoomId &chatRoomId +) : ChatRoom(p, core, chatRoomId) { + L_D(); + d->me = make_shared(nullptr, getLocalAddress()); + d->participants.push_back(make_shared(nullptr, getPeerAddress())); +} + +void BasicChatRoom::allowCpim (bool value) { + L_D(); + d->cpimAllowed = value; +} + +void BasicChatRoom::allowMultipart (bool value) { + L_D(); + d->multipartAllowed = value; +} + +bool BasicChatRoom::canHandleCpim () const { + L_D(); + return d->cpimAllowed; +} + +bool BasicChatRoom::canHandleMultipart () const { + L_D(); + return d->multipartAllowed; +} + +BasicChatRoom::CapabilitiesMask BasicChatRoom::getCapabilities () const { + return { Capabilities::Basic, Capabilities::OneToOne }; +} + +bool BasicChatRoom::hasBeenLeft () const { + return false; +} + +bool BasicChatRoom::canHandleParticipants () const { + return false; +} + +const IdentityAddress &BasicChatRoom::getConferenceAddress () const { + lError() << "a BasicChatRoom does not have a conference address"; + return Utils::getEmptyConstRefObject(); +} + +void BasicChatRoom::addParticipant (const IdentityAddress &, const CallSessionParams *, bool) { + lError() << "addParticipant() is not allowed on a BasicChatRoom"; +} + +void BasicChatRoom::addParticipants (const list &, const CallSessionParams *, bool) { + lError() << "addParticipants() is not allowed on a BasicChatRoom"; +} + +void BasicChatRoom::removeParticipant (const shared_ptr &) { + lError() << "removeParticipant() is not allowed on a BasicChatRoom"; +} + +void BasicChatRoom::removeParticipants (const list> &) { + lError() << "removeParticipants() is not allowed on a BasicChatRoom"; +} + +shared_ptr BasicChatRoom::findParticipant (const IdentityAddress &) const { + lError() << "findParticipant() is not allowed on a BasicChatRoom"; + return nullptr; +} + +shared_ptr BasicChatRoom::getMe () const { + L_D(); + return d->me; +} + +int BasicChatRoom::getParticipantCount () const { + return 1; +} + +const list> &BasicChatRoom::getParticipants () const { + L_D(); + return d->participants; +} + +void BasicChatRoom::setParticipantAdminStatus (const shared_ptr &, bool) { + lError() << "setParticipantAdminStatus() is not allowed on a BasicChatRoom"; +} + +const string &BasicChatRoom::getSubject () const { + L_D(); + return d->subject; +} + +void BasicChatRoom::setSubject (const string &subject) { + L_D(); + d->subject = subject; +} + +void BasicChatRoom::join () { + lError() << "join() is not allowed on a BasicChatRoom"; +} + +void BasicChatRoom::leave () { + lError() << "leave() is not allowed on a BasicChatRoom"; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/basic-chat-room.h b/src/chat/chat-room/basic-chat-room.h new file mode 100644 index 000000000..767ebaa35 --- /dev/null +++ b/src/chat/chat-room/basic-chat-room.h @@ -0,0 +1,81 @@ +/* + * basic-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_BASIC_CHAT_ROOM_H_ +#define _L_BASIC_CHAT_ROOM_H_ + +#include "chat/chat-room/chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class BasicChatRoomPrivate; + +class LINPHONE_PUBLIC BasicChatRoom : public ChatRoom { + friend class Core; + friend class CorePrivate; + +public: + void allowCpim (bool value) override; + void allowMultipart (bool value) override; + bool canHandleCpim () const override; + bool canHandleMultipart () const override; + + CapabilitiesMask getCapabilities () const override; + bool hasBeenLeft () const override; + + const IdentityAddress &getConferenceAddress () const override; + + bool canHandleParticipants () const override; + + void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override; + void addParticipants (const std::list &addresses, const CallSessionParams *params, bool hasMedia) override; + + void removeParticipant (const std::shared_ptr &participant) override; + void removeParticipants (const std::list> &participants) override; + + std::shared_ptr findParticipant (const IdentityAddress &addr) const override; + + std::shared_ptr getMe () const override; + int getParticipantCount () const override; + const std::list> &getParticipants () const override; + + void setParticipantAdminStatus (const std::shared_ptr &participant, bool isAdmin) override; + + const std::string &getSubject () const override; + void setSubject (const std::string &subject) override; + + void join () override; + void leave () override; + + +protected: + explicit BasicChatRoom (BasicChatRoomPrivate &p, const std::shared_ptr &core, const ChatRoomId &chatRoomId); + +private: + BasicChatRoom (const std::shared_ptr &core, const ChatRoomId &chatRoomId); + + L_DECLARE_PRIVATE(BasicChatRoom); + L_DISABLE_COPY(BasicChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_BASIC_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/basic-to-client-group-chat-room.cpp b/src/chat/chat-room/basic-to-client-group-chat-room.cpp new file mode 100644 index 000000000..960067b14 --- /dev/null +++ b/src/chat/chat-room/basic-to-client-group-chat-room.cpp @@ -0,0 +1,152 @@ +/* + * basic-to-client-group-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "basic-to-client-group-chat-room.h" +#include "proxy-chat-room-p.h" +#include "client-group-chat-room-p.h" +#include "chat/chat-message/chat-message-p.h" +#include "conference/participant.h" +#include "conference/session/call-session.h" +#include "core/core-p.h" +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class BasicToClientGroupChatRoomPrivate : public ProxyChatRoomPrivate { +public: + void onChatRoomInsertRequested (const shared_ptr &chatRoom) override { + L_Q(); + // Insert the client group chat room temporarily + q->getCore()->getPrivate()->insertChatRoom(chatRoom); + } + + void onChatRoomInsertInDatabaseRequested (const shared_ptr &chatRoom) override { + // Do not insert the client group chat room in database, the migration will do it + } + + void onChatRoomDeleteRequested (const shared_ptr &chatRoom) override { + L_Q(); + q->getCore()->deleteChatRoom(q->getSharedFromThis()); + setState(AbstractChatRoom::State::Deleted); + } + + void sendChatMessage (const shared_ptr &chatMessage) override { + L_Q(); + ProxyChatRoomPrivate::sendChatMessage(chatMessage); + const char *specs = linphone_core_get_linphone_specs(chatMessage->getCore()->getCCore()); + time_t currentRealTime = ms_time(nullptr); + LinphoneAddress *lAddr = linphone_address_new( + chatMessage->getChatRoom()->getChatRoomId().getLocalAddress().asString().c_str() + ); + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(q->getCore()->getCCore(), lAddr); + linphone_address_unref(lAddr); + const char *conferenceFactoryUri = nullptr; + if (proxy) + conferenceFactoryUri = linphone_proxy_config_get_conference_factory_uri(proxy); + if (!conferenceFactoryUri + || (chatRoom->getCapabilities() & ChatRoom::Capabilities::Conference) + || clientGroupChatRoom + || !specs || !strstr(specs, "groupchat") + || ((currentRealTime - migrationRealTime) < + linphone_config_get_int(linphone_core_get_config(chatMessage->getCore()->getCCore()), + "misc", "basic_to_client_group_chat_room_migration_timer", 86400) // Try migration every 24 hours + ) + ) { + return; + } + migrationRealTime = currentRealTime; + clientGroupChatRoom = static_pointer_cast( + chatRoom->getCore()->getPrivate()->createClientGroupChatRoom(chatRoom->getSubject(), "", Content(), false) + ); + clientGroupChatRoom->getPrivate()->setCallSessionListener(this); + clientGroupChatRoom->getPrivate()->setChatRoomListener(this); + clientGroupChatRoom->addParticipant(chatRoom->getPeerAddress(), nullptr, false); + } + + void onCallSessionStateChanged ( + const shared_ptr &session, + CallSession::State newState, + const string &message + ) override { + if (!clientGroupChatRoom) + return; + if ((newState == CallSession::State::Error) && (clientGroupChatRoom->getState() == ChatRoom::State::CreationPending)) { + Core::deleteChatRoom(clientGroupChatRoom); + if (session->getReason() == LinphoneReasonNotAcceptable) { + clientGroupChatRoom = nullptr; + return; + } + } + clientGroupChatRoom->getPrivate()->onCallSessionStateChanged(session, newState, message); + } + +private: + shared_ptr clientGroupChatRoom; + time_t migrationRealTime = 0; + + L_DECLARE_PUBLIC(BasicToClientGroupChatRoom); +}; + +// ============================================================================= + +BasicToClientGroupChatRoom::BasicToClientGroupChatRoom (const shared_ptr &chatRoom) : + ProxyChatRoom(*new BasicToClientGroupChatRoomPrivate, chatRoom) {} + +BasicToClientGroupChatRoom::CapabilitiesMask BasicToClientGroupChatRoom::getCapabilities () const { + L_D(); + CapabilitiesMask capabilities = d->chatRoom->getCapabilities(); + capabilities.set(Capabilities::Proxy); + if (capabilities.isSet(Capabilities::Basic)) + capabilities.set(Capabilities::Migratable); + return capabilities; +} + +shared_ptr BasicToClientGroupChatRoom::createChatMessage () { + shared_ptr msg = ProxyChatRoom::createChatMessage(); + msg->getPrivate()->setChatRoom(getSharedFromThis()); + return msg; +} + +shared_ptr BasicToClientGroupChatRoom::createChatMessage (const string &text) { + shared_ptr msg = ProxyChatRoom::createChatMessage(text); + msg->getPrivate()->setChatRoom(getSharedFromThis()); + return msg; +} + +void BasicToClientGroupChatRoom::migrate(const std::shared_ptr &clientGroupChatRoom, const std::shared_ptr &chatRoom) { + clientGroupChatRoom->getCore()->getPrivate()->mainDb->migrateBasicToClientGroupChatRoom(chatRoom, clientGroupChatRoom); + + if (chatRoom->getCapabilities() & ChatRoom::Capabilities::Proxy) { + shared_ptr btcgcr = static_pointer_cast(chatRoom); + btcgcr->getCore()->getPrivate()->replaceChatRoom(chatRoom, clientGroupChatRoom); + btcgcr->getPrivate()->chatRoom = clientGroupChatRoom; + } else { + LinphoneChatRoom *lcr = L_GET_C_BACK_PTR(chatRoom); + L_SET_CPP_PTR_FROM_C_OBJECT(lcr, clientGroupChatRoom); + clientGroupChatRoom->getCore()->getPrivate()->replaceChatRoom(chatRoom, clientGroupChatRoom); + } +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/basic-to-client-group-chat-room.h b/src/chat/chat-room/basic-to-client-group-chat-room.h new file mode 100644 index 000000000..151f80c58 --- /dev/null +++ b/src/chat/chat-room/basic-to-client-group-chat-room.h @@ -0,0 +1,53 @@ +/* + * basic-to-client-group-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_BASIC_TO_CLIENT_GROUP_CHAT_ROOM_H_ +#define _L_BASIC_TO_CLIENT_GROUP_CHAT_ROOM_H_ + +#include "proxy-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class BasicToClientGroupChatRoomPrivate; +class ClientGroupChatRoom; + +class LINPHONE_PUBLIC BasicToClientGroupChatRoom : public ProxyChatRoom { +public: + BasicToClientGroupChatRoom (const std::shared_ptr &chatRoom); + + CapabilitiesMask getCapabilities () const override; + + std::shared_ptr createChatMessage () override; + std::shared_ptr createChatMessage (const std::string &text) override; + + static void migrate ( + const std::shared_ptr &clientGroupChatRoom, + const std::shared_ptr &chatRoom + ); + +private: + L_DECLARE_PRIVATE(BasicToClientGroupChatRoom); + L_DISABLE_COPY(BasicToClientGroupChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_BASIC_TO_CLIENT_GROUP_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/chat-room-id.cpp b/src/chat/chat-room/chat-room-id.cpp new file mode 100644 index 000000000..7b11fd77d --- /dev/null +++ b/src/chat/chat-room/chat-room-id.cpp @@ -0,0 +1,83 @@ +/* + * chat-room-id.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "object/clonable-object-p.h" + +#include "chat-room-id.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoomIdPrivate : public ClonableObjectPrivate { +public: + IdentityAddress peerAddress; + IdentityAddress localAddress; +}; + +// ----------------------------------------------------------------------------- + +ChatRoomId::ChatRoomId () : ClonableObject(*new ChatRoomIdPrivate) {} + +ChatRoomId::ChatRoomId ( + const IdentityAddress &peerAddress, + const IdentityAddress &localAddress +) : ClonableObject(*new ChatRoomIdPrivate) { + L_D(); + d->peerAddress = peerAddress; + d->localAddress = localAddress; +} + +L_USE_DEFAULT_CLONABLE_OBJECT_SHARED_IMPL(ChatRoomId); + +bool ChatRoomId::operator== (const ChatRoomId &other) const { + L_D(); + const ChatRoomIdPrivate *dChatRoomId = other.getPrivate(); + return d->peerAddress == dChatRoomId->peerAddress && d->localAddress == dChatRoomId->localAddress; +} + +bool ChatRoomId::operator!= (const ChatRoomId &other) const { + return !(*this == other); +} + +bool ChatRoomId::operator< (const ChatRoomId &other) const { + L_D(); + const ChatRoomIdPrivate *dChatRoomId = other.getPrivate(); + return d->peerAddress < dChatRoomId->peerAddress + || (d->peerAddress == dChatRoomId->peerAddress && d->localAddress < dChatRoomId->localAddress); +} + +const IdentityAddress &ChatRoomId::getPeerAddress () const { + L_D(); + return d->peerAddress; +} + +const IdentityAddress &ChatRoomId::getLocalAddress () const { + L_D(); + return d->localAddress; +} + +bool ChatRoomId::isValid () const { + L_D(); + return d->peerAddress.isValid() && d->localAddress.isValid(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/chat-room-id.h b/src/chat/chat-room/chat-room-id.h new file mode 100644 index 000000000..1751a6820 --- /dev/null +++ b/src/chat/chat-room/chat-room-id.h @@ -0,0 +1,71 @@ +/* + * chat-room-id.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_ROOM_ID_H_ +#define _L_CHAT_ROOM_ID_H_ + +#include "address/identity-address.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoomIdPrivate; + +class LINPHONE_PUBLIC ChatRoomId : public ClonableObject { +public: + ChatRoomId (); + ChatRoomId (const IdentityAddress &peerAddress, const IdentityAddress &localAddress); + ChatRoomId (const ChatRoomId &other); + + ChatRoomId &operator= (const ChatRoomId &other); + + bool operator== (const ChatRoomId &other) const; + bool operator!= (const ChatRoomId &other) const; + + bool operator< (const ChatRoomId &other) const; + + const IdentityAddress &getPeerAddress () const; + const IdentityAddress &getLocalAddress () const; + + bool isValid () const; + +private: + L_DECLARE_PRIVATE(ChatRoomId); +}; + +inline std::ostream &operator<< (std::ostream &os, const ChatRoomId &chatRoomId) { + os << "ChatRoomId(" << chatRoomId.getPeerAddress() << ", local=" << chatRoomId.getLocalAddress() << ")"; + return os; +} + +LINPHONE_END_NAMESPACE + +// Add map key support. +namespace std { + template<> + struct hash { + std::size_t operator() (const LinphonePrivate::ChatRoomId &chatRoomId) const { + return hash()(chatRoomId.getPeerAddress().asString()) ^ + (hash()(chatRoomId.getLocalAddress().asString()) << 1); + } + }; +} + +#endif // ifndef _L_CHAT_ROOM_ID_H_ diff --git a/src/chat/chat-room/chat-room-listener.h b/src/chat/chat-room/chat-room-listener.h new file mode 100644 index 000000000..cdd5166b7 --- /dev/null +++ b/src/chat/chat-room/chat-room-listener.h @@ -0,0 +1,40 @@ +/* + * chat-room-listener.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_ROOM_LISTENER_H_ +#define _L_CHAT_ROOM_LISTENER_H_ + +#include "chat/chat-room/abstract-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoomListener { +public: + virtual ~ChatRoomListener () = default; + + virtual void onChatRoomInsertRequested (const std::shared_ptr &chatRoom) {} + virtual void onChatRoomInsertInDatabaseRequested (const std::shared_ptr &chatRoom) {} + virtual void onChatRoomDeleteRequested (const std::shared_ptr &chatRoom) {} +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CHAT_ROOM_LISTENER_H_ diff --git a/src/chat/chat-room/chat-room-p.h b/src/chat/chat-room/chat-room-p.h new file mode 100644 index 000000000..e882891c9 --- /dev/null +++ b/src/chat/chat-room/chat-room-p.h @@ -0,0 +1,115 @@ +/* + * chat-room-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_ROOM_P_H_ +#define _L_CHAT_ROOM_P_H_ + +#include + +#include "abstract-chat-room-p.h" +#include "chat-room-id.h" +#include "chat-room.h" +#include "chat/notification/imdn.h" +#include "chat/notification/is-composing.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ImdnMessage; +class IsComposingMessage; + +class ChatRoomPrivate : public AbstractChatRoomPrivate, public IsComposingListener { +public: + inline void setProxyChatRoom (AbstractChatRoom *value) { proxyChatRoom = value; } + + inline void setCreationTime (time_t creationTime) override { + this->creationTime = creationTime; + } + + inline void setLastUpdateTime (time_t lastUpdateTime) override { + this->lastUpdateTime = lastUpdateTime; + } + + void setState (ChatRoom::State state) override; + + void sendChatMessage (const std::shared_ptr &chatMessage) override; + void sendIsComposingNotification (); + + void addEvent (const std::shared_ptr &eventLog) override; + + void addTransientEvent (const std::shared_ptr &eventLog) override; + void removeTransientEvent (const std::shared_ptr &eventLog) override; + + std::shared_ptr createChatMessage (ChatMessage::Direction direction); + std::shared_ptr createImdnMessage ( + const std::list> &deliveredMessages, + const std::list> &displayedMessages + ); + std::shared_ptr createImdnMessage (const std::list &nonDeliveredMessages); + std::shared_ptr createImdnMessage (const std::shared_ptr &message); + std::shared_ptr createIsComposingMessage (); + std::list> findChatMessages (const std::string &messageId) const; + + void sendDeliveryErrorNotification (const std::shared_ptr &message, LinphoneReason reason); + void sendDeliveryNotification (const std::shared_ptr &message); + void sendDeliveryNotifications () override; + bool sendDisplayNotification (const std::shared_ptr &message); + + void notifyChatMessageReceived (const std::shared_ptr &chatMessage) override; + void notifyIsComposingReceived (const Address &remoteAddress, bool isComposing); + void notifyStateChanged (); + void notifyUndecryptableChatMessageReceived (const std::shared_ptr &chatMessage) override; + + LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) override; + void onChatMessageReceived (const std::shared_ptr &chatMessage) override; + void onImdnReceived (const std::shared_ptr &chatMessage); + void onIsComposingReceived (const Address &remoteAddress, const std::string &text); + void onIsComposingRefreshNeeded () override; + void onIsComposingStateChanged (bool isComposing) override; + void onIsRemoteComposingStateChanged (const Address &remoteAddress, bool isComposing) override; + + Imdn *getImdnHandler () const { return imdnHandler.get(); } + + LinphoneChatRoom *getCChatRoom () const; + + std::list remoteIsComposing; + std::list> transientEvents; + + ChatRoomId chatRoomId; + +private: + AbstractChatRoom *proxyChatRoom = nullptr; + + ChatRoom::State state = ChatRoom::State::None; + + time_t creationTime = std::time(nullptr); + time_t lastUpdateTime = std::time(nullptr); + + std::unique_ptr imdnHandler; + std::unique_ptr isComposingHandler; + + bool isComposing = false; + + L_DECLARE_PUBLIC(ChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/chat-room.cpp b/src/chat/chat-room/chat-room.cpp new file mode 100644 index 000000000..75f91c676 --- /dev/null +++ b/src/chat/chat-room/chat-room.cpp @@ -0,0 +1,519 @@ +/* + * chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/utils.h" + +#include "c-wrapper/c-wrapper.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-message/imdn-message.h" +#include "chat/chat-message/is-composing-message.h" +#include "chat/chat-message/notification-message-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "core/core-p.h" +#include "logger/logger.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +void ChatRoomPrivate::setState (ChatRoom::State state) { + if (this->state != state) { + this->state = state; + notifyStateChanged(); + } +} + +// ----------------------------------------------------------------------------- + +void ChatRoomPrivate::sendChatMessage (const shared_ptr &chatMessage) { + L_Q(); + + ChatMessagePrivate *dChatMessage = chatMessage->getPrivate(); + dChatMessage->setTime(ms_time(0)); + dChatMessage->send(); + + LinphoneChatRoom *cr = getCChatRoom(); + // TODO: server currently don't stock message, remove condition in the future. + if (!linphone_core_conference_server_enabled(q->getCore()->getCCore())) { + shared_ptr event = static_pointer_cast( + q->getCore()->getPrivate()->mainDb->getEventFromKey(dChatMessage->dbKey) + ); + if (!event) + event = make_shared(time(nullptr), chatMessage); + + _linphone_chat_room_notify_chat_message_sent(cr, L_GET_C_BACK_PTR(event)); + } + + if (isComposing) + isComposing = false; + isComposingHandler->stopIdleTimer(); + isComposingHandler->stopRefreshTimer(); +} + +void ChatRoomPrivate::sendIsComposingNotification () { + L_Q(); + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(q->getCore()->getCCore()); + if (!linphone_im_notif_policy_get_send_is_composing(policy)) + return; + + auto isComposingMsg = createIsComposingMessage(); + isComposingMsg->getPrivate()->send(); +} + +// ----------------------------------------------------------------------------- + +void ChatRoomPrivate::addEvent (const shared_ptr &eventLog) { + L_Q(); + + q->getCore()->getPrivate()->mainDb->addEvent(eventLog); + setLastUpdateTime(eventLog->getCreationTime()); +} + +void ChatRoomPrivate::addTransientEvent (const shared_ptr &eventLog) { + auto it = find(transientEvents.begin(), transientEvents.end(), eventLog); + if (it == transientEvents.end()) + transientEvents.push_back(eventLog); +} + +void ChatRoomPrivate::removeTransientEvent (const shared_ptr &eventLog) { + auto it = find(transientEvents.begin(), transientEvents.end(), eventLog); + if (it != transientEvents.end()) + transientEvents.erase(it); +} + +// ----------------------------------------------------------------------------- + +shared_ptr ChatRoomPrivate::createChatMessage (ChatMessage::Direction direction) { + L_Q(); + return shared_ptr(new ChatMessage(q->getSharedFromThis(), direction)); +} + +shared_ptr ChatRoomPrivate::createImdnMessage ( + const list> &deliveredMessages, + const list> &displayedMessages +) { + L_Q(); + return shared_ptr(new ImdnMessage(q->getSharedFromThis(), deliveredMessages, displayedMessages)); +} + +shared_ptr ChatRoomPrivate::createImdnMessage (const list &nonDeliveredMessages) { + L_Q(); + return shared_ptr(new ImdnMessage(q->getSharedFromThis(), nonDeliveredMessages)); +} + +shared_ptr ChatRoomPrivate::createImdnMessage (const shared_ptr &message) { + return shared_ptr(new ImdnMessage(message)); +} + +shared_ptr ChatRoomPrivate::createIsComposingMessage () { + L_Q(); + return shared_ptr(new IsComposingMessage(q->getSharedFromThis(), *isComposingHandler.get(), isComposing)); +} + +list> ChatRoomPrivate::findChatMessages (const string &messageId) const { + L_Q(); + return q->getCore()->getPrivate()->mainDb->findChatMessages(q->getChatRoomId(), messageId); +} + +// ----------------------------------------------------------------------------- + +void ChatRoomPrivate::sendDeliveryErrorNotification (const shared_ptr &message, LinphoneReason reason) { + L_Q(); + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(q->getCore()->getCCore()); + if (linphone_im_notif_policy_get_send_imdn_delivered(policy)) + imdnHandler->notifyDeliveryError(message, reason); +} + +void ChatRoomPrivate::sendDeliveryNotification (const shared_ptr &message) { + L_Q(); + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(q->getCore()->getCCore()); + if (linphone_im_notif_policy_get_send_imdn_delivered(policy)) + imdnHandler->notifyDelivery(message); +} + +void ChatRoomPrivate::sendDeliveryNotifications () { + L_Q(); + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(q->getCore()->getCCore()); + if (linphone_im_notif_policy_get_send_imdn_delivered(policy)) { + auto messages = q->getCore()->getPrivate()->mainDb->findChatMessagesToBeNotifiedAsDelivered(q->getChatRoomId()); + for (const auto message : messages) + imdnHandler->notifyDelivery(message); + } +} + +bool ChatRoomPrivate::sendDisplayNotification (const shared_ptr &message) { + L_Q(); + LinphoneImNotifPolicy *policy = linphone_core_get_im_notif_policy(q->getCore()->getCCore()); + if (linphone_im_notif_policy_get_send_imdn_displayed(policy)) { + imdnHandler->notifyDisplay(message); + return imdnHandler->aggregationEnabled(); + } + return false; +} + +// ----------------------------------------------------------------------------- + +void ChatRoomPrivate::notifyChatMessageReceived (const shared_ptr &chatMessage) { + L_Q(); + LinphoneChatRoom *cr = getCChatRoom(); + if (!chatMessage->getPrivate()->getText().empty()) { + /* Legacy API */ + LinphoneAddress *fromAddress = linphone_address_new(chatMessage->getFromAddress().asString().c_str()); + linphone_core_notify_text_message_received( + q->getCore()->getCCore(), + cr, + fromAddress, + chatMessage->getPrivate()->getText().c_str() + ); + linphone_address_unref(fromAddress); + } + _linphone_chat_room_notify_message_received(cr, L_GET_C_BACK_PTR(chatMessage)); + linphone_core_notify_message_received(q->getCore()->getCCore(), cr, L_GET_C_BACK_PTR(chatMessage)); +} + +void ChatRoomPrivate::notifyIsComposingReceived (const Address &remoteAddress, bool isComposing) { + L_Q(); + + if (isComposing) { + auto it = find(remoteIsComposing.cbegin(), remoteIsComposing.cend(), remoteAddress); + if (it == remoteIsComposing.cend()) + remoteIsComposing.push_back(remoteAddress); + } else { + remoteIsComposing.remove(remoteAddress); + } + + LinphoneChatRoom *cr = getCChatRoom(); + LinphoneAddress *lAddr = linphone_address_new(remoteAddress.asString().c_str()); + _linphone_chat_room_notify_is_composing_received(cr, lAddr, !!isComposing); + linphone_address_unref(lAddr); + // Legacy notification + linphone_core_notify_is_composing_received(q->getCore()->getCCore(), cr); +} + +void ChatRoomPrivate::notifyStateChanged () { + L_Q(); + LinphoneChatRoom *cr = getCChatRoom(); + linphone_core_notify_chat_room_state_changed(q->getCore()->getCCore(), cr, (LinphoneChatRoomState)state); + _linphone_chat_room_notify_state_changed(cr, (LinphoneChatRoomState)state); +} + +void ChatRoomPrivate::notifyUndecryptableChatMessageReceived (const shared_ptr &chatMessage) { + L_Q(); + LinphoneChatRoom *cr = getCChatRoom(); + _linphone_chat_room_notify_undecryptable_message_received(cr, L_GET_C_BACK_PTR(chatMessage)); + linphone_core_notify_message_received_unable_decrypt(q->getCore()->getCCore(), cr, L_GET_C_BACK_PTR(chatMessage)); +} + +// ----------------------------------------------------------------------------- + +LinphoneReason ChatRoomPrivate::onSipMessageReceived (SalOp *op, const SalMessage *message) { + L_Q(); + + LinphoneReason reason = LinphoneReasonNone; + shared_ptr msg; + + shared_ptr core = q->getCore(); + LinphoneCore *cCore = core->getCCore(); + + msg = createChatMessage( + IdentityAddress(op->getFrom()) == q->getLocalAddress() + ? ChatMessage::Direction::Outgoing + : ChatMessage::Direction::Incoming + ); + + Content content; + if (message->url && (ContentType(message->content_type).weakEqual(ContentType::ExternalBody))) { + lInfo() << "Received a message with an external body URL " << message->url; + content.setContentType(ContentType::FileTransfer); + content.setBody(msg->getPrivate()->createFakeFileTransferFromUrl(message->url)); + } else { + content.setContentType(ContentType(message->content_type)); + content.setBodyFromUtf8(message->text ? message->text : ""); + } + msg->setInternalContent(content); + + msg->getPrivate()->setTime(message->time); + msg->getPrivate()->setImdnMessageId(op->getCallId()); + + const SalCustomHeader *ch = op->getRecvCustomHeaders(); + if (ch) + msg->getPrivate()->setSalCustomHeaders(sal_custom_header_clone(ch)); + + reason = msg->getPrivate()->receive(); + + if (reason == LinphoneReasonNotAcceptable || reason == LinphoneReasonUnknown) { + // Return LinphoneReasonNone to avoid flexisip resending us a message we can't decrypt + return LinphoneReasonNone; + } + + if (msg->getPrivate()->getContentType() == ContentType::ImIsComposing) { + onIsComposingReceived(msg->getFromAddress(), msg->getPrivate()->getText()); + if (lp_config_get_int(linphone_core_get_config(cCore), "sip", "deliver_imdn", 0) != 1) + return reason; + } else if (msg->getPrivate()->getContentType() == ContentType::Imdn) { + onImdnReceived(msg); + if (lp_config_get_int(linphone_core_get_config(cCore), "sip", "deliver_imdn", 0) != 1) + return reason; + } + + onChatMessageReceived(msg); + return reason; +} + +void ChatRoomPrivate::onChatMessageReceived (const shared_ptr &chatMessage) { + const IdentityAddress &fromAddress = chatMessage->getFromAddress(); + if ((chatMessage->getPrivate()->getContentType() != ContentType::ImIsComposing) + && (chatMessage->getPrivate()->getContentType() != ContentType::Imdn) + ) { + isComposingHandler->stopRemoteRefreshTimer(fromAddress.asString()); + notifyIsComposingReceived(fromAddress, false); + } + chatMessage->getPrivate()->notifyReceiving(); +} + +void ChatRoomPrivate::onImdnReceived (const shared_ptr &chatMessage) { + Imdn::parse(chatMessage); +} + +void ChatRoomPrivate::onIsComposingReceived (const Address &remoteAddress, const string &text) { + isComposingHandler->parse(remoteAddress, text); +} + +void ChatRoomPrivate::onIsComposingRefreshNeeded () { + sendIsComposingNotification(); +} + +void ChatRoomPrivate::onIsComposingStateChanged (bool isComposing) { + this->isComposing = isComposing; + sendIsComposingNotification(); +} + +void ChatRoomPrivate::onIsRemoteComposingStateChanged (const Address &remoteAddress, bool isComposing) { + notifyIsComposingReceived(remoteAddress, isComposing); +} + +// ----------------------------------------------------------------------------- + +LinphoneChatRoom *ChatRoomPrivate::getCChatRoom () const { + L_Q(); + if (proxyChatRoom) + return L_GET_C_BACK_PTR(proxyChatRoom); + else + return L_GET_C_BACK_PTR(q); +} + +// ============================================================================= + +ChatRoom::ChatRoom (ChatRoomPrivate &p, const shared_ptr &core, const ChatRoomId &chatRoomId) : + AbstractChatRoom(p, core) { + L_D(); + + d->chatRoomId = chatRoomId; + d->imdnHandler.reset(new Imdn(this)); + d->isComposingHandler.reset(new IsComposing(core->getCCore(), d)); +} + +ChatRoom::~ChatRoom () { + L_D(); + + d->imdnHandler.reset(); +} + +// ----------------------------------------------------------------------------- + +const ChatRoomId &ChatRoom::getChatRoomId () const { + L_D(); + return d->chatRoomId; +} + +const IdentityAddress &ChatRoom::getPeerAddress () const { + L_D(); + return d->chatRoomId.getPeerAddress(); +} + +const IdentityAddress &ChatRoom::getLocalAddress () const { + L_D(); + return d->chatRoomId.getLocalAddress(); +} + +// ----------------------------------------------------------------------------- + +time_t ChatRoom::getCreationTime () const { + L_D(); + return d->creationTime; +} + +time_t ChatRoom::getLastUpdateTime () const { + L_D(); + return d->lastUpdateTime; +} + +// ----------------------------------------------------------------------------- + +ChatRoom::State ChatRoom::getState () const { + L_D(); + return d->state; +} + +// ----------------------------------------------------------------------------- + +list> ChatRoom::getMessageHistory (int nLast) const { + return getCore()->getPrivate()->mainDb->getHistory(getChatRoomId(), nLast, MainDb::Filter::ConferenceChatMessageFilter); +} + +list> ChatRoom::getMessageHistoryRange (int begin, int end) const { + return getCore()->getPrivate()->mainDb->getHistoryRange(getChatRoomId(), begin, end, MainDb::Filter::ConferenceChatMessageFilter); +} + +list> ChatRoom::getHistory (int nLast) const { + return getCore()->getPrivate()->mainDb->getHistory( + getChatRoomId(), + nLast, + MainDb::FilterMask({ MainDb::Filter::ConferenceChatMessageFilter, MainDb::Filter::ConferenceInfoNoDeviceFilter }) + ); +} + +list> ChatRoom::getHistoryRange (int begin, int end) const { + return getCore()->getPrivate()->mainDb->getHistoryRange( + getChatRoomId(), + begin, + end, + MainDb::FilterMask({ MainDb::Filter::ConferenceChatMessageFilter, MainDb::Filter::ConferenceInfoNoDeviceFilter }) + ); +} + +int ChatRoom::getHistorySize () const { + return getCore()->getPrivate()->mainDb->getHistorySize(getChatRoomId()); +} + +void ChatRoom::deleteFromDb () { + L_D(); + // Keep a ref, otherwise the object might be destroyed before we can set the Deleted state + shared_ptr ref = this->getSharedFromThis(); + Core::deleteChatRoom(ref); + d->setState(ChatRoom::State::Deleted); +} + +void ChatRoom::deleteHistory () { + getCore()->getPrivate()->mainDb->cleanHistory(getChatRoomId()); +} + +shared_ptr ChatRoom::getLastChatMessageInHistory () const { + return getCore()->getPrivate()->mainDb->getLastChatMessage(getChatRoomId()); +} + +int ChatRoom::getChatMessageCount () const { + return getCore()->getPrivate()->mainDb->getChatMessageCount(getChatRoomId()); +} + +int ChatRoom::getUnreadChatMessageCount () const { + L_D(); + int dbUnreadCount = getCore()->getPrivate()->mainDb->getUnreadChatMessageCount(getChatRoomId()); + int notifiedCount = d->imdnHandler->getDisplayNotificationCount(); + L_ASSERT(dbUnreadCount >= notifiedCount); + return dbUnreadCount - notifiedCount; +} + +// ----------------------------------------------------------------------------- + +void ChatRoom::compose () { + L_D(); + if (!d->isComposing) { + d->isComposing = true; + d->sendIsComposingNotification(); + d->isComposingHandler->startRefreshTimer(); + } + d->isComposingHandler->startIdleTimer(); +} + +bool ChatRoom::isRemoteComposing () const { + L_D(); + return !d->remoteIsComposing.empty(); +} + +list ChatRoom::getComposingAddresses () const { + L_D(); + return d->remoteIsComposing; +} + +// ----------------------------------------------------------------------------- + +shared_ptr ChatRoom::createChatMessage () { + L_D(); + return d->createChatMessage(ChatMessage::Direction::Outgoing); +} + +shared_ptr ChatRoom::createChatMessage (const string &text) { + shared_ptr chatMessage = createChatMessage(); + Content *content = new Content(); + content->setContentType(ContentType::PlainText); + content->setBody(text); + chatMessage->addContent(content); + return chatMessage; +} + +shared_ptr ChatRoom::createFileTransferMessage (Content *initialContent) { + shared_ptr chatMessage = createChatMessage(); + chatMessage->getPrivate()->setFileTransferInformation(initialContent); + return chatMessage; +} + +// ----------------------------------------------------------------------------- + +shared_ptr ChatRoom::findChatMessage (const string &messageId) const { + L_D(); + list> chatMessages = d->findChatMessages(messageId); + return chatMessages.empty() ? nullptr : chatMessages.front(); +} + +shared_ptr ChatRoom::findChatMessage (const string &messageId, ChatMessage::Direction direction) const { + L_D(); + for (auto &chatMessage : d->findChatMessages(messageId)) + if (chatMessage->getDirection() == direction) + return chatMessage; + return nullptr; +} + +void ChatRoom::markAsRead () { + L_D(); + + bool globallyMarkAsReadInDb = true; + CorePrivate *dCore = getCore()->getPrivate(); + for (auto &chatMessage : dCore->mainDb->getUnreadChatMessages(d->chatRoomId)) { + // Do not send display notification for file transfer until it has been downloaded (it won't have a file transfer content anymore) + if (!chatMessage->getPrivate()->hasFileTransferContent()) { + bool doNotStoreInDb = d->sendDisplayNotification(chatMessage); + // Force the state so it is stored directly in DB, but when the IMDN has successfully been delivered + chatMessage->getPrivate()->setState(ChatMessage::State::Displayed, doNotStoreInDb); + if (doNotStoreInDb) + globallyMarkAsReadInDb = false; + } + } + + if (globallyMarkAsReadInDb) + dCore->mainDb->markChatMessagesAsRead(d->chatRoomId); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/chat-room.h b/src/chat/chat-room/chat-room.h new file mode 100644 index 000000000..9c361df82 --- /dev/null +++ b/src/chat/chat-room/chat-room.h @@ -0,0 +1,93 @@ +/* + * chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_ROOM_H_ +#define _L_CHAT_ROOM_H_ + +#include "abstract-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoomPrivate; + +class LINPHONE_PUBLIC ChatRoom : public AbstractChatRoom { +public: + friend class ChatMessagePrivate; + friend class Imdn; + friend class ImdnMessagePrivate; + friend class ProxyChatRoomPrivate; + + L_OVERRIDE_SHARED_FROM_THIS(ChatRoom); + + ~ChatRoom (); + + const ChatRoomId &getChatRoomId () const override; + + const IdentityAddress &getPeerAddress () const override; + const IdentityAddress &getLocalAddress () const override; + + time_t getCreationTime () const override; + time_t getLastUpdateTime () const override; + + State getState () const override; + + std::list> getMessageHistory (int nLast) const override; + std::list> getMessageHistoryRange (int begin, int end) const override; + std::list> getHistory (int nLast) const override; + std::list> getHistoryRange (int begin, int end) const override; + int getHistorySize () const override; + + void deleteFromDb () override; + void deleteHistory () override; + + std::shared_ptr getLastChatMessageInHistory () const override; + + int getChatMessageCount () const override; + int getUnreadChatMessageCount () const override; + + void compose () override; + bool isRemoteComposing () const override; + std::list getComposingAddresses () const override; + + std::shared_ptr createChatMessage () override; + std::shared_ptr createChatMessage (const std::string &text) override; + + std::shared_ptr createFileTransferMessage (Content *initialContent) override; + + std::shared_ptr findChatMessage (const std::string &messageId) const override; + std::shared_ptr findChatMessage ( + const std::string &messageId, + ChatMessage::Direction direction + ) const override; + + void markAsRead () override; + +protected: + explicit ChatRoom (ChatRoomPrivate &p, const std::shared_ptr &core, const ChatRoomId &chatRoomId); + +private: + L_DECLARE_PRIVATE(ChatRoom); + L_DISABLE_COPY(ChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/client-group-chat-room-p.h b/src/chat/chat-room/client-group-chat-room-p.h new file mode 100644 index 000000000..a23f4c15e --- /dev/null +++ b/src/chat/chat-room/client-group-chat-room-p.h @@ -0,0 +1,68 @@ +/* + * client-group-chat-room-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CLIENT_GROUP_CHAT_ROOM_P_H_ +#define _L_CLIENT_GROUP_CHAT_ROOM_P_H_ + +#include "chat/chat-room/chat-room-p.h" +#include "client-group-chat-room.h" +#include "utils/background-task.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ClientGroupChatRoomPrivate : public ChatRoomPrivate { +public: + std::list cleanAddressesList (const std::list &addresses) const; + std::shared_ptr createSession (); + void notifyReceived (const std::string &body); + void multipartNotifyReceived (const std::string &body); + + void confirmJoining (SalCallOp *op); + void setCallSessionListener (CallSessionListener *listener); + void setChatRoomListener (ChatRoomListener *listener) { chatRoomListener = listener; } + + unsigned int getLastNotifyId () const; + + // ChatRoomListener + void onChatRoomInsertRequested (const std::shared_ptr &chatRoom) override; + void onChatRoomInsertInDatabaseRequested (const std::shared_ptr &chatRoom) override; + void onChatRoomDeleteRequested (const std::shared_ptr &chatRoom) override; + + // CallSessionListener + void onCallSessionSetReleased (const std::shared_ptr &session) override; + void onCallSessionStateChanged (const std::shared_ptr &session, CallSession::State state, const std::string &message) override; + + void onChatRoomCreated (const Address &remoteContact); + +private: + void acceptSession (const std::shared_ptr &session); + + CallSessionListener *callSessionListener = this; + ChatRoomListener *chatRoomListener = this; + ClientGroupChatRoom::CapabilitiesMask capabilities = ClientGroupChatRoom::Capabilities::Conference; + bool deletionOnTerminationEnabled = false; + BackgroundTask bgTask { "Subscribe/notify of full state conference" }; + L_DECLARE_PUBLIC(ClientGroupChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CLIENT_GROUP_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/client-group-chat-room.cpp b/src/chat/chat-room/client-group-chat-room.cpp new file mode 100644 index 000000000..6d4f8817b --- /dev/null +++ b/src/chat/chat-room/client-group-chat-room.cpp @@ -0,0 +1,753 @@ +/* + * client-group-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/utils.h" + +#include "address/address-p.h" +#include "basic-to-client-group-chat-room.h" +#include "c-wrapper/c-wrapper.h" +#include "client-group-chat-room-p.h" +#include "conference/handlers/remote-conference-event-handler-p.h" +#include "conference/handlers/remote-conference-list-event-handler.h" +#include "conference/participant-p.h" +#include "conference/participant-device.h" +#include "conference/remote-conference-p.h" +#include "conference/session/call-session-p.h" +#include "content/content-disposition.h" +#include "content/content-type.h" +#include "core/core-p.h" +#include "logger/logger.h" +#include "sal/refer-op.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +list ClientGroupChatRoomPrivate::cleanAddressesList (const list &addresses) const { + L_Q(); + list cleanedList(addresses); + cleanedList.sort(); + cleanedList.unique(); + for (auto it = cleanedList.begin(); it != cleanedList.end();) { + if (q->findParticipant(*it) || (q->getMe()->getAddress() == *it)) + it = cleanedList.erase(it); + else + it++; + } + return cleanedList; +} + +shared_ptr ClientGroupChatRoomPrivate::createSession () { + L_Q(); + L_Q_T(RemoteConference, qConference); + + CallSessionParams csp; + csp.addCustomHeader("Require", "recipient-list-invite"); + csp.addCustomContactParameter("text"); + if (capabilities & ClientGroupChatRoom::Capabilities::OneToOne) + csp.addCustomHeader("One-To-One-Chat-Room", "true"); + + ParticipantPrivate *dFocus = qConference->getPrivate()->focus->getPrivate(); + shared_ptr session = dFocus->createSession(*q, &csp, false, callSessionListener); + Address myCleanedAddress(q->getMe()->getAddress()); + myCleanedAddress.removeUriParam("gr"); // Remove gr parameter for INVITE. + session->configure(LinphoneCallOutgoing, nullptr, nullptr, myCleanedAddress, dFocus->getDevices().front()->getAddress()); + session->initiateOutgoing(); + session->getPrivate()->createOp(); + return session; +} + +void ClientGroupChatRoomPrivate::notifyReceived (const string &body) { + L_Q_T(RemoteConference, qConference); + qConference->getPrivate()->eventHandler->notifyReceived(body); +} + +void ClientGroupChatRoomPrivate::multipartNotifyReceived (const string &body) { + L_Q_T(RemoteConference, qConference); + qConference->getPrivate()->eventHandler->multipartNotifyReceived(body); +} + +// ----------------------------------------------------------------------------- + +void ClientGroupChatRoomPrivate::setCallSessionListener (CallSessionListener *listener) { + L_Q(); + L_Q_T(RemoteConference, qConference); + + callSessionListener = listener; + shared_ptr session = qConference->getPrivate()->focus->getPrivate()->getSession(); + if (session) + session->getPrivate()->setCallSessionListener(listener); + for (const auto &participant : q->getParticipants()) { + session = participant->getPrivate()->getSession(); + if (session) + session->getPrivate()->setCallSessionListener(listener); + } +} + +unsigned int ClientGroupChatRoomPrivate::getLastNotifyId () const { + L_Q_T(RemoteConference, qConference); + return qConference->getPrivate()->eventHandler->getLastNotify(); +} + +// ----------------------------------------------------------------------------- + +void ClientGroupChatRoomPrivate::confirmJoining (SalCallOp *op) { + L_Q(); + L_Q_T(RemoteConference, qConference); + + auto focus = qConference->getPrivate()->focus; + bool previousSession = (focus->getPrivate()->getSession() != nullptr); + auto session = focus->getPrivate()->createSession(*q, nullptr, false, this); + session->configure(LinphoneCallIncoming, nullptr, op, Address(op->getFrom()), Address(op->getTo())); + session->startIncomingNotification(false); + + if (!previousSession) { + setState(ClientGroupChatRoom::State::CreationPending); + // Handle participants addition + list identAddresses = ClientGroupChatRoom::parseResourceLists(op->getRemoteBody()); + for (const auto &addr : identAddresses) { + auto participant = q->findParticipant(addr); + if (!participant) { + participant = make_shared(q, addr); + qConference->getPrivate()->participants.push_back(participant); + } + } + } + acceptSession(session); +} + +// ----------------------------------------------------------------------------- + +void ClientGroupChatRoomPrivate::onChatRoomInsertRequested (const shared_ptr &chatRoom) { + L_Q(); + q->getCore()->getPrivate()->insertChatRoom(chatRoom); +} + +void ClientGroupChatRoomPrivate::onChatRoomInsertInDatabaseRequested (const shared_ptr &chatRoom) { + L_Q(); + L_Q_T(RemoteConference, qConference); + + unsigned int notifyId = qConference->getPrivate()->eventHandler->getLastNotify();; + q->getCore()->getPrivate()->insertChatRoomWithDb(chatRoom, notifyId); +} + +void ClientGroupChatRoomPrivate::onChatRoomDeleteRequested (const shared_ptr &chatRoom) { + L_Q(); + q->getCore()->deleteChatRoom(q->getSharedFromThis()); + setState(ClientGroupChatRoom::State::Deleted); +} + +// ----------------------------------------------------------------------------- + +void ClientGroupChatRoomPrivate::onCallSessionSetReleased (const shared_ptr &session) { + L_Q_T(RemoteConference, qConference); + + ParticipantPrivate *participantPrivate = qConference->getPrivate()->focus->getPrivate(); + if (session == participantPrivate->getSession()) + participantPrivate->removeSession(); +} + +void ClientGroupChatRoomPrivate::onCallSessionStateChanged ( + const shared_ptr &session, + CallSession::State newState, + const string &message +) { + L_Q(); + L_Q_T(RemoteConference, qConference); + + if (newState == CallSession::State::Connected) { + if (q->getState() == ChatRoom::State::CreationPending) { + onChatRoomCreated(*session->getRemoteContactAddress()); + } else if (q->getState() == ChatRoom::State::TerminationPending) + qConference->getPrivate()->focus->getPrivate()->getSession()->terminate(); + } else if (newState == CallSession::State::End) { + setState(ChatRoom::State::TerminationPending); + } else if (newState == CallSession::State::Released) { + if (q->getState() == ChatRoom::State::TerminationPending) { + if (session->getReason() == LinphoneReasonNone) { + // Everything is fine, the chat room has been left on the server side + q->onConferenceTerminated(q->getConferenceAddress()); + } else { + // Go to state TerminationFailed and then back to Created since it has not been terminated + setState(ChatRoom::State::TerminationFailed); + setState(ChatRoom::State::Created); + } + } + } else if (newState == CallSession::State::Error) { + if (q->getState() == ChatRoom::State::CreationPending) + setState(ChatRoom::State::CreationFailed); + else if (q->getState() == ChatRoom::State::TerminationPending) { + if (session->getReason() == LinphoneReasonNotFound) { + // Somehow the chat room is no longer know on the server, so terminate it + q->onConferenceTerminated(q->getConferenceAddress()); + } else { + // Go to state TerminationFailed and then back to Created since it has not been terminated + setState(ChatRoom::State::TerminationFailed); + setState(ChatRoom::State::Created); + } + } + } +} + +void ClientGroupChatRoomPrivate::onChatRoomCreated (const Address &remoteContact) { + L_Q(); + L_Q_T(RemoteConference, qConference); + + IdentityAddress addr(remoteContact); + q->onConferenceCreated(addr); + if (remoteContact.hasParam("isfocus")) { + if (q->getCore()->getPrivate()->remoteListEventHandler->findHandler(q->getChatRoomId())) { + q->getCore()->getPrivate()->remoteListEventHandler->subscribe(); + } else { + bgTask.start(q->getCore(), 32); // It will be stopped when receiving the first notify + qConference->getPrivate()->eventHandler->subscribe(q->getChatRoomId()); + } + } +} + +// ----------------------------------------------------------------------------- + +void ClientGroupChatRoomPrivate::acceptSession (const shared_ptr &session) { + if (session->getState() == CallSession::State::UpdatedByRemote) + session->acceptUpdate(); + else + session->accept(); +} + +// ============================================================================= + +ClientGroupChatRoom::ClientGroupChatRoom ( + const shared_ptr &core, + const string &uri, + const IdentityAddress &me, + const string &subject, + const Content &content +) : ChatRoom(*new ClientGroupChatRoomPrivate, core, ChatRoomId(IdentityAddress(), me)), +RemoteConference(core, me, nullptr) { + L_D_T(RemoteConference, dConference); + + IdentityAddress focusAddr(uri); + dConference->focus = make_shared(this, focusAddr); + dConference->focus->getPrivate()->addDevice(focusAddr); + RemoteConference::setSubject(subject); + list identAddresses = Conference::parseResourceLists(content); + for (const auto &addr : identAddresses) + dConference->participants.push_back(make_shared(this, addr)); +} + +ClientGroupChatRoom::ClientGroupChatRoom ( + const shared_ptr &core, + const ChatRoomId &chatRoomId, + shared_ptr &me, + AbstractChatRoom::CapabilitiesMask capabilities, + const string &subject, + list> &&participants, + unsigned int lastNotifyId, + bool hasBeenLeft +) : ChatRoom(*new ClientGroupChatRoomPrivate, core, chatRoomId), +RemoteConference(core, me->getAddress(), nullptr) { + L_D(); + L_D_T(RemoteConference, dConference); + + d->capabilities |= capabilities & ClientGroupChatRoom::Capabilities::OneToOne; + const IdentityAddress &peerAddress = chatRoomId.getPeerAddress(); + dConference->focus = make_shared(this, peerAddress); + dConference->focus->getPrivate()->addDevice(peerAddress); + dConference->conferenceAddress = peerAddress; + dConference->subject = subject; + dConference->participants = move(participants); + + getMe()->getPrivate()->setAdmin(me->isAdmin()); + + dConference->eventHandler->setChatRoomId(chatRoomId); + dConference->eventHandler->setLastNotify(lastNotifyId); + if (!hasBeenLeft) + getCore()->getPrivate()->remoteListEventHandler->addHandler(dConference->eventHandler.get()); +} + +ClientGroupChatRoom::~ClientGroupChatRoom () { + L_D(); + L_D_T(RemoteConference, dConference); + + try { + if (getCore()->getPrivate()->remoteListEventHandler) + getCore()->getPrivate()->remoteListEventHandler->removeHandler(dConference->eventHandler.get()); + } catch (const bad_weak_ptr &) { + // Unable to unregister listener here. Core is destroyed and the listener doesn't exist. + } + d->setCallSessionListener(nullptr); +} + +shared_ptr ClientGroupChatRoom::getCore () const { + return ChatRoom::getCore(); +} + +void ClientGroupChatRoom::allowCpim (bool value) { + +} + +void ClientGroupChatRoom::allowMultipart (bool value) { + +} + +bool ClientGroupChatRoom::canHandleCpim () const { + return true; +} + +bool ClientGroupChatRoom::canHandleMultipart () const { + return true; +} + +ClientGroupChatRoom::CapabilitiesMask ClientGroupChatRoom::getCapabilities () const { + L_D(); + return d->capabilities; +} + +bool ClientGroupChatRoom::hasBeenLeft () const { + return (getState() != State::Created); +} + +bool ClientGroupChatRoom::canHandleParticipants () const { + return RemoteConference::canHandleParticipants(); +} + +const IdentityAddress &ClientGroupChatRoom::getConferenceAddress () const { + return RemoteConference::getConferenceAddress(); +} + +void ClientGroupChatRoom::deleteFromDb () { + L_D(); + if (!hasBeenLeft()) { + d->deletionOnTerminationEnabled = true; + leave(); + return; + } + d->chatRoomListener->onChatRoomDeleteRequested(getSharedFromThis()); +} + +void ClientGroupChatRoom::addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) { + L_D(); + + if ((getState() != ChatRoom::State::Instantiated) && (getState() != ChatRoom::State::Created)) { + lError() << "Cannot add participants to the ClientGroupChatRoom in a state other than Instantiated or Created"; + return; + } + + if ((getState() == ChatRoom::State::Created) && (d->capabilities & ClientGroupChatRoom::Capabilities::OneToOne)) { + lError() << "Cannot add more participants to a OneToOne ClientGroupChatRoom"; + return; + } + + LinphoneCore *cCore = getCore()->getCCore(); + if (getState() == ChatRoom::State::Instantiated) { + list addressesList; + addressesList.push_back(addr); + Content content; + content.setBody(getResourceLists(addressesList)); + content.setContentType(ContentType::ResourceLists); + content.setContentDisposition(ContentDisposition::RecipientList); + + auto session = d->createSession(); + session->startInvite(nullptr, getSubject(), &content); + d->setState(ChatRoom::State::CreationPending); + } else { + SalReferOp *referOp = new SalReferOp(cCore->sal); + LinphoneAddress *lAddr = linphone_address_new(getConferenceAddress().asString().c_str()); + linphone_configure_op(cCore, referOp, lAddr, nullptr, true); + linphone_address_unref(lAddr); + Address referToAddr = addr; + referToAddr.setParam("text"); + referOp->sendRefer(referToAddr.getPrivate()->getInternalAddress()); + referOp->unref(); + } +} + +void ClientGroupChatRoom::addParticipants ( + const list &addresses, + const CallSessionParams *params, + bool hasMedia +) { + L_D(); + + list addressesList = d->cleanAddressesList(addresses); + if (addressesList.empty()) + return; + + if ((getState() == ChatRoom::State::Instantiated) + && (addressesList.size() == 1) + && (linphone_config_get_bool(linphone_core_get_config(L_GET_C_BACK_PTR(getCore())), + "misc", "one_to_one_chat_room_enabled", TRUE)) + ) { + d->capabilities |= ClientGroupChatRoom::Capabilities::OneToOne; + } + + if (getState() == ChatRoom::State::Instantiated) { + Content content; + content.setBody(getResourceLists(addressesList)); + content.setContentType(ContentType::ResourceLists); + content.setContentDisposition(ContentDisposition::RecipientList); + if (linphone_core_content_encoding_supported(getCore()->getCCore(), "deflate")) + content.setContentEncoding("deflate"); + + auto session = d->createSession(); + session->startInvite(nullptr, getSubject(), &content); + d->setState(ChatRoom::State::CreationPending); + } else { + for (const auto &addr : addresses) + addParticipant(addr, params, hasMedia); + } +} + +void ClientGroupChatRoom::removeParticipant (const shared_ptr &participant) { + LinphoneCore *cCore = getCore()->getCCore(); + + SalReferOp *referOp = new SalReferOp(cCore->sal); + LinphoneAddress *lAddr = linphone_address_new(getConferenceAddress().asString().c_str()); + linphone_configure_op(cCore, referOp, lAddr, nullptr, false); + linphone_address_unref(lAddr); + Address referToAddr = participant->getAddress(); + referToAddr.setParam("text"); + referToAddr.setUriParam("method", "BYE"); + referOp->sendRefer(referToAddr.getPrivate()->getInternalAddress()); + referOp->unref(); +} + +void ClientGroupChatRoom::removeParticipants (const list> &participants) { + RemoteConference::removeParticipants(participants); +} + +shared_ptr ClientGroupChatRoom::findParticipant (const IdentityAddress &addr) const { + return RemoteConference::findParticipant(addr); +} + +shared_ptr ClientGroupChatRoom::getMe () const { + return RemoteConference::getMe(); +} + +int ClientGroupChatRoom::getParticipantCount () const { + return RemoteConference::getParticipantCount(); +} + +const list> &ClientGroupChatRoom::getParticipants () const { + return RemoteConference::getParticipants(); +} + +void ClientGroupChatRoom::setParticipantAdminStatus (const shared_ptr &participant, bool isAdmin) { + if (isAdmin == participant->isAdmin()) + return; + + if (!getMe()->isAdmin()) { + lError() << "Cannot change the participant admin status because I am not admin"; + return; + } + + LinphoneCore *cCore = getCore()->getCCore(); + + SalReferOp *referOp = new SalReferOp(cCore->sal); + LinphoneAddress *lAddr = linphone_address_new(getConferenceAddress().asString().c_str()); + linphone_configure_op(cCore, referOp, lAddr, nullptr, false); + linphone_address_unref(lAddr); + Address referToAddr = participant->getAddress(); + referToAddr.setParam("text"); + referToAddr.setParam("admin", Utils::toString(isAdmin)); + referOp->sendRefer(referToAddr.getPrivate()->getInternalAddress()); + referOp->unref(); +} + +const string &ClientGroupChatRoom::getSubject () const { + return RemoteConference::getSubject(); +} + +void ClientGroupChatRoom::setSubject (const string &subject) { + L_D(); + L_D_T(RemoteConference, dConference); + + if (getState() != ChatRoom::State::Created) { + lError() << "Cannot change the ClientGroupChatRoom subject in a state other than Created"; + return; + } + + if (!getMe()->isAdmin()) { + lError() << "Cannot change the ClientGroupChatRoom subject because I am not admin"; + return; + } + + shared_ptr session = dConference->focus->getPrivate()->getSession(); + if (session) + session->update(nullptr, subject); + else { + session = d->createSession(); + session->startInvite(nullptr, subject, nullptr); + } +} + +void ClientGroupChatRoom::join () { + L_D(); + L_D_T(RemoteConference, dConference); + + shared_ptr session = dConference->focus->getPrivate()->getSession(); + if (!session && ((getState() == ChatRoom::State::Instantiated) || (getState() == ChatRoom::State::Terminated))) { + session = d->createSession(); + } + if (session) { + if (getState() != ChatRoom::State::TerminationPending) + session->startInvite(nullptr, "", nullptr); + if (getState() != ChatRoom::State::Created) + d->setState(ChatRoom::State::CreationPending); + } +} + +void ClientGroupChatRoom::leave () { + L_D(); + L_D_T(RemoteConference, dConference); + + dConference->eventHandler->unsubscribe(); + shared_ptr session = dConference->focus->getPrivate()->getSession(); + if (session) + session->terminate(); + else { + session = d->createSession(); + session->startInvite(nullptr, "", nullptr); + } + + d->setState(ChatRoom::State::TerminationPending); +} + +// ----------------------------------------------------------------------------- + +void ClientGroupChatRoom::onConferenceCreated (const IdentityAddress &addr) { + L_D(); + L_D_T(RemoteConference, dConference); + dConference->conferenceAddress = addr; + dConference->focus->getPrivate()->setAddress(addr); + dConference->focus->getPrivate()->clearDevices(); + dConference->focus->getPrivate()->addDevice(addr); + d->chatRoomId = ChatRoomId(addr, d->chatRoomId.getLocalAddress()); + d->chatRoomListener->onChatRoomInsertRequested(getSharedFromThis()); + d->setState(ChatRoom::State::Created); +} + +void ClientGroupChatRoom::onConferenceKeywordsChanged (const vector &keywords) { + L_D(); + if (find(keywords.cbegin(), keywords.cend(), "one-to-one") != keywords.cend()) + d->capabilities |= ClientGroupChatRoom::Capabilities::OneToOne; +} + +void ClientGroupChatRoom::onConferenceTerminated (const IdentityAddress &addr) { + L_D(); + L_D_T(RemoteConference, dConference); + + dConference->eventHandler->unsubscribe(); + dConference->eventHandler->resetLastNotify(); + d->setState(ChatRoom::State::Terminated); + + auto event = make_shared( + EventLog::Type::ConferenceTerminated, + time(nullptr), + d->chatRoomId + ); + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_conference_left(cr, L_GET_C_BACK_PTR(event)); + + if (d->deletionOnTerminationEnabled) { + d->deletionOnTerminationEnabled = false; + d->chatRoomListener->onChatRoomDeleteRequested(getSharedFromThis()); + } +} + +void ClientGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) { + L_D(); + + if (getState() != ChatRoom::State::Created) { + lWarning() << "First notify received in ClientGroupChatRoom that is not in the Created state, ignoring it!"; + return; + } + + bool performMigration = false; + shared_ptr chatRoom; + if (getParticipantCount() == 1) { + ChatRoomId id(getParticipants().front()->getAddress(), getMe()->getAddress()); + chatRoom = getCore()->findChatRoom(id); + if (chatRoom && (chatRoom->getCapabilities() & ChatRoom::Capabilities::Basic)) + performMigration = true; + } + + if (performMigration) + BasicToClientGroupChatRoom::migrate(getSharedFromThis(), chatRoom); + else + d->chatRoomListener->onChatRoomInsertInDatabaseRequested(getSharedFromThis()); + + auto event = make_shared( + EventLog::Type::ConferenceCreated, + time(nullptr), + d->chatRoomId + ); + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_conference_joined(cr, L_GET_C_BACK_PTR(event)); + + d->bgTask.stop(); +} + +void ClientGroupChatRoom::onParticipantAdded (const shared_ptr &event, bool isFullState) { + L_D(); + L_D_T(RemoteConference, dConference); + + const IdentityAddress &addr = event->getParticipantAddress(); + if (isMe(addr)) + return; + + shared_ptr participant = findParticipant(addr); + if (participant) { + lWarning() << "Participant " << participant << " added but already in the list of participants!"; + return; + } + + participant = make_shared(this, addr); + dConference->participants.push_back(participant); + + if (isFullState) + return; + + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_participant_added(cr, L_GET_C_BACK_PTR(event)); +} + +void ClientGroupChatRoom::onParticipantRemoved (const shared_ptr &event, bool isFullState) { + (void)isFullState; + + L_D(); + L_D_T(RemoteConference, dConference); + + const IdentityAddress &addr = event->getParticipantAddress(); + shared_ptr participant = findParticipant(addr); + if (!participant) { + lWarning() << "Participant " << addr.asString() << " removed but not in the list of participants!"; + return; + } + + dConference->participants.remove(participant); + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_participant_removed(cr, L_GET_C_BACK_PTR(event)); +} + +void ClientGroupChatRoom::onParticipantSetAdmin (const shared_ptr &event, bool isFullState) { + L_D(); + + const IdentityAddress &addr = event->getParticipantAddress(); + shared_ptr participant; + if (isMe(addr)) + participant = getMe(); + else + participant = findParticipant(addr); + if (!participant) { + lWarning() << "Participant " << addr.asString() << " admin status has been changed but is not in the list of participants!"; + return; + } + + bool isAdmin = event->getType() == EventLog::Type::ConferenceParticipantSetAdmin; + if (participant->isAdmin() == isAdmin) + return; // No change in the local admin status, do not notify + participant->getPrivate()->setAdmin(isAdmin); + + if (isFullState) + return; + + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_participant_admin_status_changed(cr, L_GET_C_BACK_PTR(event)); +} + +void ClientGroupChatRoom::onSubjectChanged (const shared_ptr &event, bool isFullState) { + L_D(); + + if (getSubject() == event->getSubject()) + return; // No change in the local subject, do not notify + RemoteConference::setSubject(event->getSubject()); + + if (isFullState) + return; + + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_subject_changed(cr, L_GET_C_BACK_PTR(event)); +} + +void ClientGroupChatRoom::onParticipantDeviceAdded (const shared_ptr &event, bool isFullState) { + L_D(); + + const IdentityAddress &addr = event->getParticipantAddress(); + shared_ptr participant; + if (isMe(addr)) + participant = getMe(); + else + participant = findParticipant(addr); + if (!participant) { + lWarning() << "Participant " << addr.asString() << " added a device but is not in the list of participants!"; + return; + } + participant->getPrivate()->addDevice(event->getDeviceAddress()); + + if (isFullState) + return; + + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_participant_device_added(cr, L_GET_C_BACK_PTR(event)); +} + +void ClientGroupChatRoom::onParticipantDeviceRemoved (const shared_ptr &event, bool isFullState) { + L_D(); + + (void)isFullState; + + const IdentityAddress &addr = event->getParticipantAddress(); + shared_ptr participant; + if (isMe(addr)) + participant = getMe(); + else + participant = findParticipant(addr); + if (!participant) { + lWarning() << "Participant " << addr.asString() << " removed a device but is not in the list of participants!"; + return; + } + participant->getPrivate()->removeDevice(event->getDeviceAddress()); + d->addEvent(event); + + LinphoneChatRoom *cr = d->getCChatRoom(); + _linphone_chat_room_notify_participant_device_removed(cr, L_GET_C_BACK_PTR(event)); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/client-group-chat-room.h b/src/chat/chat-room/client-group-chat-room.h new file mode 100644 index 000000000..cc3205a67 --- /dev/null +++ b/src/chat/chat-room/client-group-chat-room.h @@ -0,0 +1,120 @@ +/* + * client-group-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CLIENT_GROUP_CHAT_ROOM_H_ +#define _L_CLIENT_GROUP_CHAT_ROOM_H_ + +#include "chat/chat-room/chat-room.h" +#include "conference/remote-conference.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ClientGroupChatRoomPrivate; + +class LINPHONE_PUBLIC ClientGroupChatRoom : public ChatRoom, public RemoteConference { + friend class BasicToClientGroupChatRoomPrivate; + friend class ClientGroupToBasicChatRoomPrivate; + friend class Core; + friend class CorePrivate; + +public: + L_OVERRIDE_SHARED_FROM_THIS(ClientGroupChatRoom); + + // TODO: Make me private. + ClientGroupChatRoom ( + const std::shared_ptr &core, + const std::string &factoryUri, + const IdentityAddress &me, + const std::string &subject, + const Content &content + ); + + ClientGroupChatRoom ( + const std::shared_ptr &core, + const ChatRoomId &chatRoomId, + std::shared_ptr &me, + AbstractChatRoom::CapabilitiesMask capabilities, + const std::string &subject, + std::list> &&participants, + unsigned int lastNotifyId, + bool hasBeenLeft = false + ); + + ~ClientGroupChatRoom (); + + std::shared_ptr getCore () const; + + void allowCpim (bool value) override; + void allowMultipart (bool value) override; + bool canHandleCpim () const override; + bool canHandleMultipart () const override; + + CapabilitiesMask getCapabilities () const override; + bool hasBeenLeft () const override; + + const IdentityAddress &getConferenceAddress () const override; + + bool canHandleParticipants () const override; + + void deleteFromDb () override; + + void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override; + void addParticipants (const std::list &addresses, const CallSessionParams *params, bool hasMedia) override; + + void removeParticipant (const std::shared_ptr &participant) override; + void removeParticipants (const std::list> &participants) override; + + std::shared_ptr findParticipant (const IdentityAddress &addr) const override; + + std::shared_ptr getMe () const override; + int getParticipantCount () const override; + const std::list> &getParticipants () const override; + + void setParticipantAdminStatus (const std::shared_ptr &participant, bool isAdmin) override; + + const std::string &getSubject () const override; + void setSubject (const std::string &subject) override; + + void join () override; + void leave () override; + +private: + // TODO: Move me in ClientGroupChatRoomPrivate. + // ALL METHODS AFTER THIS POINT. + + void onConferenceCreated (const IdentityAddress &addr) override; + void onConferenceKeywordsChanged (const std::vector &keywords) override; + void onConferenceTerminated (const IdentityAddress &addr) override; + void onFirstNotifyReceived (const IdentityAddress &addr) override; + void onParticipantAdded (const std::shared_ptr &event, bool isFullState) override; + void onParticipantDeviceAdded (const std::shared_ptr &event, bool isFullState) override; + void onParticipantDeviceRemoved (const std::shared_ptr &event, bool isFullState) override; + void onParticipantRemoved (const std::shared_ptr &event, bool isFullState) override; + void onParticipantSetAdmin (const std::shared_ptr &event, bool isFullState) override; + void onSubjectChanged (const std::shared_ptr &event, bool isFullState) override; + + L_DECLARE_PRIVATE(ClientGroupChatRoom); + L_DISABLE_COPY(ClientGroupChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CLIENT_GROUP_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/client-group-to-basic-chat-room.cpp b/src/chat/chat-room/client-group-to-basic-chat-room.cpp new file mode 100644 index 000000000..e2f6746f3 --- /dev/null +++ b/src/chat/chat-room/client-group-to-basic-chat-room.cpp @@ -0,0 +1,131 @@ +/* + * client-group-to-basic-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "client-group-chat-room-p.h" +#include "client-group-to-basic-chat-room.h" +#include "proxy-chat-room-p.h" +#include "c-wrapper/c-wrapper.h" +#include "conference/session/call-session.h" +#include "core/core-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class ClientGroupToBasicChatRoomPrivate : public ProxyChatRoomPrivate { +public: + void onChatRoomInsertRequested (const shared_ptr &chatRoom) override { + L_Q(); + // Insert the proxy chat room instead of the real one + q->getCore()->getPrivate()->insertChatRoom(q->getSharedFromThis()); + } + + void onChatRoomInsertInDatabaseRequested (const shared_ptr &chatRoom) override { + L_Q(); + // Insert the proxy chat room instead of the real one + unsigned int notifyId = static_cast(chatRoom->getPrivate())->getLastNotifyId(); + q->getCore()->getPrivate()->insertChatRoomWithDb(q->getSharedFromThis(), notifyId); + } + + void onChatRoomDeleteRequested (const shared_ptr &chatRoom) override { + L_Q(); + // Keep a ref, otherwise the object might be destroyed before we can set the Deleted state + shared_ptr ref = q->getSharedFromThis(); + q->getCore()->deleteChatRoom(ref); + setState(AbstractChatRoom::State::Deleted); + } + + void onCallSessionSetReleased (const shared_ptr &session) override { + if (!(chatRoom->getCapabilities() & ChatRoom::Capabilities::Conference)) + return; + static_pointer_cast(chatRoom)->getPrivate()->onCallSessionSetReleased(session); + } + + void onCallSessionStateChanged ( + const shared_ptr &session, + CallSession::State newState, + const string &message + ) override { + L_Q(); + // Keep a ref, otherwise the object might be destroyed when calling Core::deleteChatRoom() + shared_ptr ref = q->getSharedFromThis(); + // TODO: Avoid cast, use capabilities. + shared_ptr cgcr = dynamic_pointer_cast(chatRoom); + if (!cgcr) + return; + if ((newState == CallSession::State::Error) && (cgcr->getState() == ChatRoom::State::CreationPending) + && (session->getReason() == LinphoneReasonNotAcceptable) && (invitedAddresses.size() == 1)) { + teardownProxy(); + cgcr->getPrivate()->onCallSessionStateChanged(session, newState, message); + cgcr->getPrivate()->setCallSessionListener(nullptr); + cgcr->getPrivate()->setChatRoomListener(nullptr); + Core::deleteChatRoom(q->getSharedFromThis()); + + LinphoneChatRoom *lcr = L_GET_C_BACK_PTR(q); + shared_ptr bcr = cgcr->getCore()->getOrCreateBasicChatRoom(invitedAddresses.front()); + L_SET_CPP_PTR_FROM_C_OBJECT(lcr, bcr); + /* getOrCreateBasicChatRoom will automatically set the state to Instantiated and Created + * but because CPP ptr hasn't been set yet in this case the application's ChatRoom won't be notified + * that's why we set both states again here... */ + bcr->getPrivate()->setState(ChatRoom::State::Instantiated); + bcr->getPrivate()->setState(ChatRoom::State::Created); + return; + } + cgcr->getPrivate()->onCallSessionStateChanged(session, newState, message); + } + +private: + list invitedAddresses; + + L_DECLARE_PUBLIC(ClientGroupToBasicChatRoom); +}; + +// ============================================================================= + +ClientGroupToBasicChatRoom::ClientGroupToBasicChatRoom (const shared_ptr &chatRoom) : + ProxyChatRoom(*new ClientGroupToBasicChatRoomPrivate, chatRoom) {} + +void ClientGroupToBasicChatRoom::addParticipant ( + const IdentityAddress &participantAddress, + const CallSessionParams *params, + bool hasMedia +) { + L_D(); + if (getState() == ChatRoom::State::Instantiated) { + d->invitedAddresses.clear(); + d->invitedAddresses.push_back(participantAddress); + } + ProxyChatRoom::addParticipant(participantAddress, params, hasMedia); +} +void ClientGroupToBasicChatRoom::addParticipants ( + const list &addresses, + const CallSessionParams *params, + bool hasMedia +) { + L_D(); + if ((getState() == ChatRoom::State::Instantiated) && (addresses.size() == 1)) + d->invitedAddresses = addresses; + ProxyChatRoom::addParticipants(addresses, params, hasMedia); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/client-group-to-basic-chat-room.h b/src/chat/chat-room/client-group-to-basic-chat-room.h new file mode 100644 index 000000000..24b4c5646 --- /dev/null +++ b/src/chat/chat-room/client-group-to-basic-chat-room.h @@ -0,0 +1,53 @@ +/* + * basic-to-client-group-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CLIENT_GROUP_TO_BASIC_CHAT_ROOM_H_ +#define _L_CLIENT_GROUP_TO_BASIC_CHAT_ROOM_H_ + +#include "proxy-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ClientGroupToBasicChatRoomPrivate; + +class LINPHONE_PUBLIC ClientGroupToBasicChatRoom : public ProxyChatRoom { +public: + ClientGroupToBasicChatRoom (const std::shared_ptr &chatRoom); + + void addParticipant ( + const IdentityAddress &participantAddress, + const CallSessionParams *params, + bool hasMedia + ) override; + void addParticipants ( + const std::list &addresses, + const CallSessionParams *params, + bool hasMedia + ) override; + +private: + L_DECLARE_PRIVATE(ClientGroupToBasicChatRoom); + L_DISABLE_COPY(ClientGroupToBasicChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CLIENT_GROUP_TO_BASIC_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/proxy-chat-room-p.h b/src/chat/chat-room/proxy-chat-room-p.h new file mode 100644 index 000000000..fc6840b34 --- /dev/null +++ b/src/chat/chat-room/proxy-chat-room-p.h @@ -0,0 +1,90 @@ +/* + * proxy-chat-room-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PROXY_CHAT_ROOM_P_H_ +#define _L_PROXY_CHAT_ROOM_P_H_ + +#include "abstract-chat-room-p.h" +#include "proxy-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ProxyChatRoomPrivate : public AbstractChatRoomPrivate { +public: + inline void setCreationTime (time_t creationTime) override { + chatRoom->getPrivate()->setCreationTime(creationTime); + } + + inline void setLastUpdateTime (time_t lastUpdateTime) override { + chatRoom->getPrivate()->setLastUpdateTime(lastUpdateTime); + } + + inline void setState (AbstractChatRoom::State state) override { + chatRoom->getPrivate()->setState(state); + } + + inline void sendChatMessage (const std::shared_ptr &chatMessage) override { + chatRoom->getPrivate()->sendChatMessage(chatMessage); + } + + inline void addEvent (const std::shared_ptr &eventLog) override { + chatRoom->getPrivate()->addEvent(eventLog); + } + + inline void addTransientEvent (const std::shared_ptr &eventLog) override { + chatRoom->getPrivate()->addTransientEvent(eventLog); + } + + inline void removeTransientEvent (const std::shared_ptr &eventLog) override { + chatRoom->getPrivate()->removeTransientEvent(eventLog); + } + + inline void sendDeliveryNotifications () override { + chatRoom->getPrivate()->sendDeliveryNotifications(); + } + + inline void notifyChatMessageReceived (const std::shared_ptr &chatMessage) override { + chatRoom->getPrivate()->notifyChatMessageReceived(chatMessage); + } + + inline void notifyUndecryptableChatMessageReceived (const std::shared_ptr &chatMessage) override { + chatRoom->getPrivate()->notifyUndecryptableChatMessageReceived(chatMessage); + } + + inline LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) override { + return chatRoom->getPrivate()->onSipMessageReceived(op, message); + } + + inline void onChatMessageReceived (const std::shared_ptr &chatMessage) override { + chatRoom->getPrivate()->onChatMessageReceived(chatMessage); + } + + void setupProxy (); + void teardownProxy (); + + std::shared_ptr chatRoom; + + L_DECLARE_PUBLIC(ProxyChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PROXY_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/proxy-chat-room.cpp b/src/chat/chat-room/proxy-chat-room.cpp new file mode 100644 index 000000000..2316d3f70 --- /dev/null +++ b/src/chat/chat-room/proxy-chat-room.cpp @@ -0,0 +1,317 @@ +/* + * proxy-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "basic-to-client-group-chat-room.h" +#include "chat-room-p.h" +#include "proxy-chat-room-p.h" +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void ProxyChatRoomPrivate::setupProxy () { + L_Q(); + static_pointer_cast(chatRoom)->getPrivate()->setProxyChatRoom(q); +} + +void ProxyChatRoomPrivate::teardownProxy () { + static_pointer_cast(chatRoom)->getPrivate()->setProxyChatRoom(nullptr); +} + +// ----------------------------------------------------------------------------- + + ProxyChatRoom::ProxyChatRoom (ProxyChatRoomPrivate &p, const shared_ptr &chatRoom) : + AbstractChatRoom(p, chatRoom->getCore()) { + L_D(); + d->chatRoom = chatRoom; + d->setupProxy(); +} + +// ----------------------------------------------------------------------------- + +const ChatRoomId &ProxyChatRoom::getChatRoomId () const { + L_D(); + return d->chatRoom->getChatRoomId(); +} + +const IdentityAddress &ProxyChatRoom::getPeerAddress () const { + L_D(); + return d->chatRoom->getPeerAddress(); +} + +const IdentityAddress &ProxyChatRoom::getLocalAddress () const { + L_D(); + return d->chatRoom->getLocalAddress(); +} + +// ----------------------------------------------------------------------------- + +time_t ProxyChatRoom::getCreationTime () const { + L_D(); + return d->chatRoom->getCreationTime(); +} + +time_t ProxyChatRoom::getLastUpdateTime () const { + L_D(); + return d->chatRoom->getLastUpdateTime(); +} + +// ----------------------------------------------------------------------------- + +ProxyChatRoom::CapabilitiesMask ProxyChatRoom::getCapabilities () const { + L_D(); + return d->chatRoom->getCapabilities() | ProxyChatRoom::Capabilities::Proxy; +} + +ProxyChatRoom::State ProxyChatRoom::getState () const { + L_D(); + return d->chatRoom->getState(); +} + +bool ProxyChatRoom::hasBeenLeft () const { + L_D(); + return d->chatRoom->hasBeenLeft(); +} + +// ----------------------------------------------------------------------------- + +list> ProxyChatRoom::getMessageHistory (int nLast) const { + L_D(); + return d->chatRoom->getMessageHistory(nLast); +} + +list> ProxyChatRoom::getMessageHistoryRange (int begin, int end) const { + L_D(); + return d->chatRoom->getMessageHistoryRange(begin, end); +} + +list> ProxyChatRoom::getHistory (int nLast) const { + L_D(); + return d->chatRoom->getHistory(nLast); +} + +list> ProxyChatRoom::getHistoryRange (int begin, int end) const { + L_D(); + return d->chatRoom->getHistoryRange(begin, end); +} + +int ProxyChatRoom::getHistorySize () const { + L_D(); + return d->chatRoom->getHistorySize(); +} + +void ProxyChatRoom::deleteFromDb () { + L_D(); + d->chatRoom->deleteFromDb(); +} + +void ProxyChatRoom::deleteHistory () { + L_D(); + d->chatRoom->deleteHistory(); +} + +shared_ptr ProxyChatRoom::getLastChatMessageInHistory () const { + L_D(); + return d->chatRoom->getLastChatMessageInHistory(); +} + +int ProxyChatRoom::getChatMessageCount () const { + L_D(); + return d->chatRoom->getChatMessageCount(); +} + +int ProxyChatRoom::getUnreadChatMessageCount () const { + L_D(); + return d->chatRoom->getUnreadChatMessageCount(); +} + +// ----------------------------------------------------------------------------- + +void ProxyChatRoom::compose () { + L_D(); + return d->chatRoom->compose(); +} + +bool ProxyChatRoom::isRemoteComposing () const { + L_D(); + return d->chatRoom->isRemoteComposing(); +} + +list ProxyChatRoom::getComposingAddresses () const { + L_D(); + return d->chatRoom->getComposingAddresses(); +} + +// ----------------------------------------------------------------------------- + +shared_ptr ProxyChatRoom::createChatMessage () { + L_D(); + return d->chatRoom->createChatMessage(); +} + +shared_ptr ProxyChatRoom::createChatMessage (const string &text) { + L_D(); + return d->chatRoom->createChatMessage(text); +} + +shared_ptr ProxyChatRoom::createFileTransferMessage (Content *initialContent) { + L_D(); + return d->chatRoom->createFileTransferMessage(initialContent); +} + +// ----------------------------------------------------------------------------- + +shared_ptr ProxyChatRoom::findChatMessage (const string &messageId) const { + L_D(); + return d->chatRoom->findChatMessage(messageId); +} + +shared_ptr ProxyChatRoom::findChatMessage ( + const string &messageId, + ChatMessage::Direction direction +) const { + L_D(); + return d->chatRoom->findChatMessage(messageId, direction); +} + +void ProxyChatRoom::markAsRead () { + L_D(); + d->chatRoom->markAsRead(); +} + +// ----------------------------------------------------------------------------- + +const IdentityAddress &ProxyChatRoom::getConferenceAddress () const { + L_D(); + return d->chatRoom->getConferenceAddress(); +} + +// ----------------------------------------------------------------------------- + +void ProxyChatRoom::allowCpim (bool value) { + +} + +void ProxyChatRoom::allowMultipart (bool value) { + +} + +bool ProxyChatRoom::canHandleCpim () const { + L_D(); + return d->chatRoom->canHandleCpim(); +} + +bool ProxyChatRoom::canHandleMultipart () const { + L_D(); + return d->chatRoom->canHandleMultipart(); +} + +bool ProxyChatRoom::canHandleParticipants () const { + L_D(); + return d->chatRoom->canHandleParticipants(); +} + +void ProxyChatRoom::addParticipant ( + const IdentityAddress &participantAddress, + const CallSessionParams *params, + bool hasMedia +) { + L_D(); + return d->chatRoom->addParticipant(participantAddress, params, hasMedia); +} + +void ProxyChatRoom::addParticipants ( + const list &addresses, + const CallSessionParams *params, + bool hasMedia +) { + L_D(); + return d->chatRoom->addParticipants(addresses, params, hasMedia); +} + +void ProxyChatRoom::removeParticipant (const shared_ptr &participant) { + L_D(); + d->chatRoom->removeParticipant(participant); +} + +void ProxyChatRoom::removeParticipants (const list> &participants) { + L_D(); + d->chatRoom->removeParticipants(participants); +} + +shared_ptr ProxyChatRoom::findParticipant (const IdentityAddress &participantAddress) const { + L_D(); + return d->chatRoom->findParticipant(participantAddress); +} + +shared_ptr ProxyChatRoom::getMe () const { + L_D(); + return d->chatRoom->getMe(); +} + +int ProxyChatRoom::getParticipantCount () const { + L_D(); + return d->chatRoom->getParticipantCount(); +} + +const list> &ProxyChatRoom::getParticipants () const { + L_D(); + return d->chatRoom->getParticipants(); +} + +void ProxyChatRoom::setParticipantAdminStatus (const shared_ptr &participant, bool isAdmin) { + L_D(); + d->chatRoom->setParticipantAdminStatus(participant, isAdmin); +} + +// ----------------------------------------------------------------------------- + +const string &ProxyChatRoom::getSubject () const { + L_D(); + return d->chatRoom->getSubject(); +} + +void ProxyChatRoom::setSubject (const string &subject) { + L_D(); + d->chatRoom->setSubject(subject); +} + +// ----------------------------------------------------------------------------- + +void ProxyChatRoom::join () { + L_D(); + d->chatRoom->join(); +} + +void ProxyChatRoom::leave () { + L_D(); + d->chatRoom->leave(); +} + +// ----------------------------------------------------------------------------- + +const shared_ptr &ProxyChatRoom::getProxiedChatRoom () const { + L_D(); + return d->chatRoom; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/proxy-chat-room.h b/src/chat/chat-room/proxy-chat-room.h new file mode 100644 index 000000000..a464bb791 --- /dev/null +++ b/src/chat/chat-room/proxy-chat-room.h @@ -0,0 +1,128 @@ +/* + * proxy-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PROXY_CHAT_ROOM_H_ +#define _L_PROXY_CHAT_ROOM_H_ + +#include "abstract-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoom; +class ProxyChatRoomPrivate; + +class LINPHONE_PUBLIC ProxyChatRoom : public AbstractChatRoom { + friend class CorePrivate; + +public: + const ChatRoomId &getChatRoomId () const override; + + const IdentityAddress &getPeerAddress () const override; + const IdentityAddress &getLocalAddress () const override; + + time_t getCreationTime () const override; + time_t getLastUpdateTime () const override; + + CapabilitiesMask getCapabilities () const override; + State getState () const override; + bool hasBeenLeft () const override; + + std::list> getMessageHistory (int nLast) const override; + std::list> getMessageHistoryRange (int begin, int end) const override; + std::list> getHistory (int nLast) const override; + std::list> getHistoryRange (int begin, int end) const override; + int getHistorySize () const override; + + void deleteFromDb () override; + void deleteHistory () override; + + std::shared_ptr getLastChatMessageInHistory () const override; + + int getChatMessageCount () const override; + int getUnreadChatMessageCount () const override; + + void compose () override; + bool isRemoteComposing () const override; + std::list getComposingAddresses () const override; + + std::shared_ptr createChatMessage () override; + std::shared_ptr createChatMessage (const std::string &text) override; + + std::shared_ptr createFileTransferMessage (Content *initialContent) override; + + std::shared_ptr findChatMessage (const std::string &messageId) const override; + std::shared_ptr findChatMessage ( + const std::string &messageId, + ChatMessage::Direction direction + ) const override; + + void markAsRead () override; + + const IdentityAddress &getConferenceAddress () const override; + + void allowCpim (bool value) override; + void allowMultipart (bool value) override; + bool canHandleCpim () const override; + bool canHandleMultipart () const override; + + bool canHandleParticipants () const override; + + void addParticipant ( + const IdentityAddress &participantAddress, + const CallSessionParams *params, + bool hasMedia + ) override; + void addParticipants ( + const std::list &addresses, + const CallSessionParams *params, + bool hasMedia + ) override; + + void removeParticipant (const std::shared_ptr &participant) override; + void removeParticipants (const std::list> &participants) override; + + std::shared_ptr findParticipant (const IdentityAddress &participantAddress) const override; + + std::shared_ptr getMe () const override; + int getParticipantCount () const override; + const std::list> &getParticipants () const override; + + void setParticipantAdminStatus (const std::shared_ptr &participant, bool isAdmin) override; + + const std::string &getSubject () const override; + void setSubject (const std::string &subject) override; + + void join () override; + void leave () override; + + const std::shared_ptr &getProxiedChatRoom () const; + +protected: + ProxyChatRoom (ProxyChatRoomPrivate &p, const std::shared_ptr &chatRoom); + +private: + L_DECLARE_PRIVATE(ProxyChatRoom); + L_DISABLE_COPY(ProxyChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PROXY_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/real-time-text-chat-room-p.h b/src/chat/chat-room/real-time-text-chat-room-p.h new file mode 100644 index 000000000..26b89d53b --- /dev/null +++ b/src/chat/chat-room/real-time-text-chat-room-p.h @@ -0,0 +1,51 @@ +/* + * real-time-text-chat-room-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REAL_TIME_TEXT_CHAT_ROOM_P_H_ +#define _L_REAL_TIME_TEXT_CHAT_ROOM_P_H_ + +#include "chat/chat-room/basic-chat-room-p.h" +#include "chat/chat-room/real-time-text-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class RealTimeTextChatRoomPrivate : public BasicChatRoomPrivate { +public: + struct Character { + uint32_t value; + bool hasBeenRead; + }; + + void realtimeTextReceived (uint32_t character, const std::shared_ptr &call); + void sendChatMessage (const std::shared_ptr &chatMessage) override; + void setCall (const std::shared_ptr &value) { call = value; } + + std::weak_ptr call; + std::list receivedRttCharacters; + std::shared_ptr pendingMessage = nullptr; + +private: + L_DECLARE_PUBLIC(RealTimeTextChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REAL_TIME_TEXT_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/real-time-text-chat-room.cpp b/src/chat/chat-room/real-time-text-chat-room.cpp new file mode 100644 index 000000000..bacf87a81 --- /dev/null +++ b/src/chat/chat-room/real-time-text-chat-room.cpp @@ -0,0 +1,133 @@ +/* + * real-time-text-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "c-wrapper/c-wrapper.h" +#include "call/call.h" +#include "chat/chat-message/chat-message-p.h" +#include "conference/participant.h" +#include "core/core-p.h" +#include "logger/logger.h" +#include "real-time-text-chat-room-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +void RealTimeTextChatRoomPrivate::realtimeTextReceived (uint32_t character, const shared_ptr &call) { + L_Q(); + const uint32_t new_line = 0x2028; + const uint32_t crlf = 0x0D0A; + const uint32_t lf = 0x0A; + + shared_ptr core = q->getCore(); + LinphoneCore *cCore = core->getCCore(); + + if (call && call->getCurrentParams()->realtimeTextEnabled()) { + if (!pendingMessage) { + pendingMessage = q->createChatMessage(); + pendingMessage->getPrivate()->setDirection(ChatMessage::Direction::Incoming); + Content *content = new Content(); + content->setContentType(ContentType::PlainText); + pendingMessage->addContent(content); + } + + Character cmc; + cmc.value = character; + cmc.hasBeenRead = false; + receivedRttCharacters.push_back(cmc); + + remoteIsComposing.push_back(q->getPeerAddress()); + linphone_core_notify_is_composing_received(cCore, getCChatRoom()); + + if ((character == new_line) || (character == crlf) || (character == lf)) { + // End of message + auto content = pendingMessage->getContents().front(); + lDebug() << "New line received, forge a message with content " << content->getBodyAsString(); + pendingMessage->getPrivate()->setState(ChatMessage::State::Delivered); + pendingMessage->getPrivate()->setTime(::ms_time(0)); + + if (lp_config_get_int(linphone_core_get_config(cCore), "misc", "store_rtt_messages", 1) == 1) + pendingMessage->setToBeStored(true); + else + pendingMessage->setToBeStored(false); + + onChatMessageReceived(pendingMessage); + pendingMessage = nullptr; + receivedRttCharacters.clear(); + } else { + char *value = Utils::utf8ToChar(character); + auto content = pendingMessage->getContents().front(); + content->setBody(content->getBodyAsString() + string(value)); + lDebug() << "Received RTT character: " << value << " (" << character << "), pending text is " << content->getBodyAsString(); + delete[] value; + } + } +} + +void RealTimeTextChatRoomPrivate::sendChatMessage (const shared_ptr &chatMessage) { + L_Q(); + shared_ptr call = q->getCall(); + if (call && call->getCurrentParams()->realtimeTextEnabled()) { + uint32_t newLine = 0x2028; + chatMessage->putCharacter(newLine); + + ChatMessagePrivate *dChatMessage = chatMessage->getPrivate(); + shared_ptr event = static_pointer_cast( + q->getCore()->getPrivate()->mainDb->getEventFromKey(dChatMessage->dbKey) + ); + if (!event) + event = make_shared(time(nullptr), chatMessage); + + LinphoneChatRoom *cr = getCChatRoom(); + _linphone_chat_room_notify_chat_message_sent(cr, L_GET_C_BACK_PTR(event)); + } +} + +// ============================================================================= + +RealTimeTextChatRoom::RealTimeTextChatRoom (const shared_ptr &core, const ChatRoomId &chatRoomId) : + BasicChatRoom(*new RealTimeTextChatRoomPrivate, core, chatRoomId) {} + +RealTimeTextChatRoom::CapabilitiesMask RealTimeTextChatRoom::getCapabilities () const { + return BasicChatRoom::getCapabilities() | Capabilities::RealTimeText; +} + +uint32_t RealTimeTextChatRoom::getChar () const { + L_D(); + for (const auto &cmc : d->receivedRttCharacters) { + if (!cmc.hasBeenRead) { + const_cast(&cmc)->hasBeenRead = true; + return cmc.value; + } + } + return 0; +} + +// ----------------------------------------------------------------------------- + +shared_ptr RealTimeTextChatRoom::getCall () const { + L_D(); + return d->call.lock(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/real-time-text-chat-room.h b/src/chat/chat-room/real-time-text-chat-room.h new file mode 100644 index 000000000..4f0d8cb7f --- /dev/null +++ b/src/chat/chat-room/real-time-text-chat-room.h @@ -0,0 +1,53 @@ +/* + * real-time-text-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REAL_TIME_TEXT_CHAT_ROOM_H_ +#define _L_REAL_TIME_TEXT_CHAT_ROOM_H_ + +#include "chat/chat-room/basic-chat-room.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Call; +class RealTimeTextChatRoomPrivate; + +class LINPHONE_PUBLIC RealTimeTextChatRoom : public BasicChatRoom { + friend class CallPrivate; + friend class CorePrivate; + +public: + ~RealTimeTextChatRoom () = default; + + CapabilitiesMask getCapabilities () const override; + + uint32_t getChar () const; + std::shared_ptr getCall () const; + +private: + RealTimeTextChatRoom (const std::shared_ptr &core, const ChatRoomId &chatRoomId); + + L_DECLARE_PRIVATE(RealTimeTextChatRoom); + L_DISABLE_COPY(RealTimeTextChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REAL_TIME_TEXT_CHAT_ROOM_H_ diff --git a/src/chat/chat-room/server-group-chat-room-p.h b/src/chat/chat-room/server-group-chat-room-p.h new file mode 100644 index 000000000..daa8ae629 --- /dev/null +++ b/src/chat/chat-room/server-group-chat-room-p.h @@ -0,0 +1,130 @@ +/* + * server-group-chat-room-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SERVER_GROUP_CHAT_ROOM_P_H_ +#define _L_SERVER_GROUP_CHAT_ROOM_P_H_ + +#include +#include +#include + +#include "chat-room-p.h" +#include "server-group-chat-room.h" +#include "conference/participant-device.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ParticipantDevice; + +class ServerGroupChatRoomPrivate : public ChatRoomPrivate { +public: + void setState (ChatRoom::State state) override; + + std::shared_ptr addParticipant (const IdentityAddress &participantAddress); + void removeParticipant (const std::shared_ptr &participant); + + std::shared_ptr findFilteredParticipant (const std::shared_ptr &session) const; + std::shared_ptr findFilteredParticipant (const IdentityAddress &participantAddress) const; + + ParticipantDevice::State getParticipantDeviceState (const std::shared_ptr &device) const; + void setParticipantDeviceState (const std::shared_ptr &device, ParticipantDevice::State state); + + void acceptSession (const std::shared_ptr &session); + void confirmCreation (); + void confirmJoining (SalCallOp *op); + void confirmRecreation (SalCallOp *op); + void declineSession (const std::shared_ptr &session, LinphoneReason reason); + void dispatchQueuedMessages (); + + void subscribeReceived (LinphoneEvent *event); + + bool update (SalCallOp *op); + + void setConferenceAddress (const IdentityAddress &conferenceAddress); + void setParticipantDevices (const IdentityAddress &addr, const std::list &devices); + void addParticipantDevice (const IdentityAddress &participantAddress, const IdentityAddress &deviceAddress); + void addCompatibleParticipants (const IdentityAddress &deviceAddr, const std::list &compatibleParticipants); + void checkCompatibleParticipants (const IdentityAddress &deviceAddr, const std::list &addressesToCheck); + + LinphoneReason onSipMessageReceived (SalOp *op, const SalMessage *message) override; + +private: + struct Message { + Message (const std::string &from, const ContentType &contentType, const std::string &text, const SalCustomHeader *salCustomHeaders) + : fromAddr(from) + { + content.setContentType(contentType); + if (!text.empty()) + content.setBodyFromUtf8(text); + if (salCustomHeaders) + customHeaders = sal_custom_header_clone(salCustomHeaders); + } + + ~Message () { + if (customHeaders) + sal_custom_header_free(customHeaders); + } + + IdentityAddress fromAddr; + Content content; + std::chrono::system_clock::time_point timestamp = std::chrono::system_clock::now(); + SalCustomHeader *customHeaders = nullptr; + }; + + static void copyMessageHeaders (const std::shared_ptr &fromMessage, const std::shared_ptr &toMessage); + + void byeDevice (const std::shared_ptr &device); + void designateAdmin (); + void dispatchMessage (const std::shared_ptr &message, const std::string &uri); + void finalizeCreation (); + void inviteDevice (const std::shared_ptr &device); + bool isAdminLeft () const; + void queueMessage (const std::shared_ptr &message); + void queueMessage (const std::shared_ptr &msg, const IdentityAddress &deviceAddress); + void removeNonPresentParticipants (const std::list &compatibleParticipants); + + void onParticipantDeviceLeft (const std::shared_ptr &device); + + // ChatRoomListener + void onChatRoomInsertRequested (const std::shared_ptr &chatRoom) override; + void onChatRoomInsertInDatabaseRequested (const std::shared_ptr &chatRoom) override; + void onChatRoomDeleteRequested (const std::shared_ptr &chatRoom) override; + + // CallSessionListener + void onCallSessionStateChanged ( + const std::shared_ptr &session, + CallSession::State newState, + const std::string &message + ) override; + void onCallSessionSetReleased (const std::shared_ptr &session) override; + + std::list> filteredParticipants; + ChatRoomListener *chatRoomListener = this; + ServerGroupChatRoom::CapabilitiesMask capabilities = ServerGroupChatRoom::Capabilities::Conference; + bool joiningPendingAfterCreation = false; + std::unordered_map>> queuedMessages; + + L_DECLARE_PUBLIC(ServerGroupChatRoom); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SERVER_GROUP_CHAT_ROOM_P_H_ diff --git a/src/chat/chat-room/server-group-chat-room-stub.cpp b/src/chat/chat-room/server-group-chat-room-stub.cpp new file mode 100644 index 000000000..7e5a3b7a8 --- /dev/null +++ b/src/chat/chat-room/server-group-chat-room-stub.cpp @@ -0,0 +1,236 @@ +/* + * server-group-chat-room-stub.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "core/core.h" +#include "server-group-chat-room-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::setState (ChatRoom::State state) { + ChatRoomPrivate::setState(state); +} + +shared_ptr ServerGroupChatRoomPrivate::addParticipant (const IdentityAddress &) { + return nullptr; +} + +void ServerGroupChatRoomPrivate::removeParticipant (const shared_ptr &) {} + +shared_ptr ServerGroupChatRoomPrivate::findFilteredParticipant (const shared_ptr &session) const { + return nullptr; +} + +shared_ptr ServerGroupChatRoomPrivate::findFilteredParticipant (const IdentityAddress &participantAddress) const { + return nullptr; +} + +ParticipantDevice::State ServerGroupChatRoomPrivate::getParticipantDeviceState (const shared_ptr &device) const { + return device->getState(); +} + +void ServerGroupChatRoomPrivate::setParticipantDeviceState (const shared_ptr &device, ParticipantDevice::State state) { + device->setState(state); +} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::acceptSession (const shared_ptr &session) {} + +void ServerGroupChatRoomPrivate::confirmCreation () {} + +void ServerGroupChatRoomPrivate::confirmJoining (SalCallOp *) {} + +void ServerGroupChatRoomPrivate::confirmRecreation (SalCallOp *) {} + +void ServerGroupChatRoomPrivate::declineSession (const shared_ptr &session, LinphoneReason reason) {} + +void ServerGroupChatRoomPrivate::dispatchQueuedMessages () {} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::subscribeReceived (LinphoneEvent *) {} + +bool ServerGroupChatRoomPrivate::update (SalCallOp *) { return true; } + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::setConferenceAddress (const IdentityAddress &) {} + +void ServerGroupChatRoomPrivate::setParticipantDevices (const IdentityAddress &addr, const list &devices) {} + +void ServerGroupChatRoomPrivate::addParticipantDevice (const IdentityAddress &participantAddress, const IdentityAddress &deviceAddress) {} + +void ServerGroupChatRoomPrivate::addCompatibleParticipants (const IdentityAddress &deviceAddr, const list &participantCompatible) {} + +void ServerGroupChatRoomPrivate::checkCompatibleParticipants (const IdentityAddress &deviceAddr, const list &addressesToCheck) {} + +// ----------------------------------------------------------------------------- + +LinphoneReason ServerGroupChatRoomPrivate::onSipMessageReceived (SalOp *, const SalMessage *) { + return LinphoneReasonNone; +} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::byeDevice (const shared_ptr &device) {} + +void ServerGroupChatRoomPrivate::designateAdmin () {} + +void ServerGroupChatRoomPrivate::dispatchMessage (const shared_ptr &message, const string &uri) {} + +void ServerGroupChatRoomPrivate::finalizeCreation () {} + +void ServerGroupChatRoomPrivate::inviteDevice (const shared_ptr &device) {} + +bool ServerGroupChatRoomPrivate::isAdminLeft () const { + return false; +} + +void ServerGroupChatRoomPrivate::queueMessage (const shared_ptr &message) {} + +void ServerGroupChatRoomPrivate::queueMessage (const shared_ptr &msg, const IdentityAddress &deviceAddress) {} + +void ServerGroupChatRoomPrivate::removeNonPresentParticipants (const list &compatibleParticipants) {} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::onParticipantDeviceLeft (const shared_ptr &device) {} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::onChatRoomInsertRequested (const shared_ptr &chatRoom) {} + +void ServerGroupChatRoomPrivate::onChatRoomInsertInDatabaseRequested (const shared_ptr &chatRoom) {} + +void ServerGroupChatRoomPrivate::onChatRoomDeleteRequested (const shared_ptr &chatRoom) {} + +// ----------------------------------------------------------------------------- + +void ServerGroupChatRoomPrivate::onCallSessionStateChanged ( + const shared_ptr &, + CallSession::State, + const string & +) {} + +void ServerGroupChatRoomPrivate::onCallSessionSetReleased (const shared_ptr &session) {} + +// ============================================================================= + +ServerGroupChatRoom::ServerGroupChatRoom (const shared_ptr &core, SalCallOp *op) +: ChatRoom(*new ServerGroupChatRoomPrivate, core, ChatRoomId(IdentityAddress(op->getTo()), IdentityAddress(op->getTo()))), +LocalConference(core, IdentityAddress(op->getTo()), nullptr) { + L_D(); + d->chatRoomListener = d; +} + +ServerGroupChatRoom::ServerGroupChatRoom ( + const shared_ptr &core, + const IdentityAddress &peerAddress, + AbstractChatRoom::CapabilitiesMask capabilities, + const string &subject, + list> &&participants, + unsigned int lastNotifyId +) : ChatRoom(*new ServerGroupChatRoomPrivate, core, ChatRoomId(peerAddress, peerAddress)), + LocalConference(core, peerAddress, nullptr) {} + +ServerGroupChatRoom::~ServerGroupChatRoom () {}; + +ServerGroupChatRoom::CapabilitiesMask ServerGroupChatRoom::getCapabilities () const { + return 0; +} + +void ServerGroupChatRoom::allowCpim (bool value) { + +} + +void ServerGroupChatRoom::allowMultipart (bool value) { + +} + +bool ServerGroupChatRoom::canHandleCpim () const { + return true; +} + +bool ServerGroupChatRoom::canHandleMultipart () const { + return true; +} + +bool ServerGroupChatRoom::hasBeenLeft () const { + return true; +} + +const IdentityAddress &ServerGroupChatRoom::getConferenceAddress () const { + return LocalConference::getConferenceAddress(); +} + +bool ServerGroupChatRoom::canHandleParticipants () const { + return false; +} + +void ServerGroupChatRoom::addParticipant (const IdentityAddress &, const CallSessionParams *, bool) {} + +void ServerGroupChatRoom::addParticipants (const list &, const CallSessionParams *, bool) {} + +void ServerGroupChatRoom::removeParticipant (const shared_ptr &participant) {} + +void ServerGroupChatRoom::removeParticipants (const list> &) {} + +shared_ptr ServerGroupChatRoom::findParticipant (const IdentityAddress &) const { + return nullptr; +} + +shared_ptr ServerGroupChatRoom::getMe () const { + return nullptr; +} + +int ServerGroupChatRoom::getParticipantCount () const { + return 0; +} + +const list> &ServerGroupChatRoom::getParticipants () const { + return LocalConference::getParticipants(); +} + +void ServerGroupChatRoom::setParticipantAdminStatus (const shared_ptr &, bool) {} + +const string &ServerGroupChatRoom::getSubject () const { + return LocalConference::getSubject(); +} + +void ServerGroupChatRoom::setSubject (const string &) {} + +void ServerGroupChatRoom::join () {} + +void ServerGroupChatRoom::leave () {} + +void ServerGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) {} + +// ----------------------------------------------------------------------------- + +ostream &operator<< (ostream &stream, const ServerGroupChatRoom *chatRoom) { + return stream << "ServerGroupChatRoom [" << reinterpret_cast(chatRoom) << "]"; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/chat-room/server-group-chat-room.h b/src/chat/chat-room/server-group-chat-room.h new file mode 100644 index 000000000..7f83f9253 --- /dev/null +++ b/src/chat/chat-room/server-group-chat-room.h @@ -0,0 +1,102 @@ +/* + * server-group-chat-room.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SERVER_GROUP_CHAT_ROOM_H_ +#define _L_SERVER_GROUP_CHAT_ROOM_H_ + +#include "chat/chat-room/chat-room.h" +#include "conference/local-conference.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class SalCallOp; +class ServerGroupChatRoomPrivate; + +class ServerGroupChatRoom : public ChatRoom, public LocalConference { +public: + // TODO: Make me private! + ServerGroupChatRoom (const std::shared_ptr &core, SalCallOp *op); + + // TODO: Same idea. + ServerGroupChatRoom ( + const std::shared_ptr &core, + const IdentityAddress &peerAddress, + AbstractChatRoom::CapabilitiesMask capabilities, + const std::string &subject, + std::list> &&participants, + unsigned int lastNotifyId + ); + + ~ServerGroupChatRoom (); + + std::shared_ptr getCore () const; + + void allowCpim (bool value) override; + void allowMultipart (bool value) override; + bool canHandleCpim () const override; + bool canHandleMultipart () const override; + + std::shared_ptr findParticipant (const std::shared_ptr &session) const; + + CapabilitiesMask getCapabilities () const override; + bool hasBeenLeft () const override; + + const IdentityAddress &getConferenceAddress () const override; + + bool canHandleParticipants () const override; + + void addParticipant (const IdentityAddress &address, const CallSessionParams *params, bool hasMedia) override; + void addParticipants ( + const std::list &addresses, + const CallSessionParams *params, + bool hasMedia + ) override; + + void removeParticipant (const std::shared_ptr &participant) override; + void removeParticipants (const std::list> &participants) override; + + std::shared_ptr findParticipant (const IdentityAddress &participantAddress) const override; + + std::shared_ptr getMe () const override; + int getParticipantCount () const override; + const std::list> &getParticipants () const override; + + void setParticipantAdminStatus (const std::shared_ptr &participant, bool isAdmin) override; + + const std::string &getSubject () const override; + void setSubject (const std::string &subject) override; + + void join () override; + void leave () override; + + /* ConferenceListener */ + void onFirstNotifyReceived (const IdentityAddress &addr) override; + +private: + L_DECLARE_PRIVATE(ServerGroupChatRoom); + L_DISABLE_COPY(ServerGroupChatRoom); +}; + +std::ostream &operator<< (std::ostream &stream, const ServerGroupChatRoom *chatRoom); + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SERVER_GROUP_CHAT_ROOM_H_ diff --git a/src/chat/cpim/cpim.h b/src/chat/cpim/cpim.h new file mode 100644 index 000000000..58b807731 --- /dev/null +++ b/src/chat/cpim/cpim.h @@ -0,0 +1,27 @@ +/* + * cpim.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CPIM_H_ +#define _L_CPIM_H_ + +#include "message/cpim-message.h" + +// ============================================================================= + +#endif // ifndef _L_CPIM_H_ diff --git a/src/chat/cpim/header/cpim-core-headers.cpp b/src/chat/cpim/header/cpim-core-headers.cpp new file mode 100644 index 000000000..4f35651fe --- /dev/null +++ b/src/chat/cpim/header/cpim-core-headers.cpp @@ -0,0 +1,336 @@ +/* + * cpim-core-headers.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "linphone/utils/utils.h" + +#include "logger/logger.h" + +#include "chat/cpim/parser/cpim-parser.h" +#include "cpim-header-p.h" + +#include "cpim-core-headers.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class Cpim::ContactHeaderPrivate : public HeaderPrivate { +public: + string uri; + string formalName; +}; + +Cpim::ContactHeader::ContactHeader () : Header(*new ContactHeaderPrivate) {} + +Cpim::ContactHeader::ContactHeader (const string &uri, const string &formalName) : ContactHeader() { + setUri(uri); + setFormalName(formalName); +} + +string Cpim::ContactHeader::getUri () const { + L_D(); + return d->uri; +} + +void Cpim::ContactHeader::setUri (const string &uri) { + L_D(); + d->uri = uri; +} + +string Cpim::ContactHeader::getFormalName () const { + L_D(); + return d->formalName; +} + +void Cpim::ContactHeader::setFormalName (const string &formalName) { + L_D(); + if (formalName.front() == '\"' && formalName.back() == '\"') + d->formalName = formalName.substr(1, formalName.size() - 2); + else if (formalName.back() == ' ') + d->formalName = formalName.substr(0, formalName.size() - 1); + else + d->formalName = formalName; +} + +string Cpim::ContactHeader::getValue () const { + L_D(); + string result; + if (!d->formalName.empty()) + result += "\"" + d->formalName + "\""; + result += "<" + d->uri + ">"; + return result; +} + +string Cpim::ContactHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; +} + +// ----------------------------------------------------------------------------- + +class Cpim::DateTimeHeaderPrivate : public HeaderPrivate { +public: + tm dateTime; + tm dateTimeOffset; + string signOffset; +}; + +Cpim::DateTimeHeader::DateTimeHeader () : Header(*new DateTimeHeaderPrivate) {} + +Cpim::DateTimeHeader::DateTimeHeader (time_t time) : DateTimeHeader() { + setTime(time); +} + +Cpim::DateTimeHeader::DateTimeHeader (const tm &time, const tm &timeOffset, const string &signOffset) : DateTimeHeader() { + setTime(time, timeOffset, signOffset); +} + +time_t Cpim::DateTimeHeader::getTime () const { + L_D(); + + tm result = d->dateTime; + result.tm_year -= 1900; + result.tm_isdst = 0; + + if (d->signOffset == "+") { + result.tm_hour += d->dateTimeOffset.tm_hour; + result.tm_min += d->dateTimeOffset.tm_min; + + while (result.tm_min > 59) { + result.tm_hour++; + result.tm_min -= 60; + } + } + else if (d->signOffset == "-") { + result.tm_hour -= d->dateTimeOffset.tm_hour; + result.tm_hour -= d->dateTimeOffset.tm_min; + + while (result.tm_min < 0) { + result.tm_hour--; + result.tm_min += 60; + } + } + + return Utils::getTmAsTimeT(result); +} + +void Cpim::DateTimeHeader::setTime (const time_t time) { + L_D(); + + d->signOffset = "Z"; + d->dateTime = Utils::getTimeTAsTm(time); + d->dateTime.tm_year += 1900; +} + +void Cpim::DateTimeHeader::setTime (const tm &time, const tm &timeOffset, const string &signOffset) { + L_D(); + + d->dateTime = time; + d->dateTimeOffset = timeOffset; + d->signOffset = signOffset; +} + +string Cpim::DateTimeHeader::getValue () const { + L_D(); + + stringstream ss; + ss << setfill('0') << setw(4) << d->dateTime.tm_year << "-" + << setfill('0') << setw(2) << d->dateTime.tm_mon + 1 << "-" + << setfill('0') << setw(2) << d->dateTime.tm_mday << "T" + << setfill('0') << setw(2) << d->dateTime.tm_hour << ":" + << setfill('0') << setw(2) << d->dateTime.tm_min << ":" + << setfill('0') << setw(2) << d->dateTime.tm_sec; + + ss << d->signOffset; + if (d->signOffset != "Z") + ss << setfill('0') << setw(2) << d->dateTimeOffset.tm_hour << ":" + << setfill('0') << setw(2) << d->dateTimeOffset.tm_min; + + return ss.str(); +} + +string Cpim::DateTimeHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; +} + +struct tm Cpim::DateTimeHeader::getTimeStruct () const { + L_D(); + return d->dateTime; +} + +struct tm Cpim::DateTimeHeader::getTimeOffset () const { + L_D(); + return d->dateTimeOffset; +} + +string Cpim::DateTimeHeader::getSignOffset () const { + L_D(); + return d->signOffset; +} + +// ----------------------------------------------------------------------------- + +class Cpim::NsHeaderPrivate : public HeaderPrivate { +public: + string uri; + string prefixName; +}; + +Cpim::NsHeader::NsHeader () : Header(*new NsHeaderPrivate) {} + +Cpim::NsHeader::NsHeader (const string &uri, const string &prefixName) : NsHeader() { + setUri(uri); + setPrefixName(prefixName); +} + +string Cpim::NsHeader::getUri () const { + L_D(); + return d->uri; +} + +void Cpim::NsHeader::setUri (const string &uri) { + L_D(); + d->uri = uri; +} + +string Cpim::NsHeader::getPrefixName () const { + L_D(); + return d->prefixName; +} + +void Cpim::NsHeader::setPrefixName (const string &prefixName) { + L_D(); + d->prefixName = prefixName; +} + +string Cpim::NsHeader::getValue () const { + L_D(); + + string ns; + if (!d->prefixName.empty()) + ns = d->prefixName + " "; + + return ns + "<" + d->uri + ">"; +} + +string Cpim::NsHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; +} + +// ----------------------------------------------------------------------------- + +class Cpim::RequireHeaderPrivate : public HeaderPrivate { +public: + list headerNames; +}; + +Cpim::RequireHeader::RequireHeader () : Header(*new RequireHeaderPrivate) {} + +Cpim::RequireHeader::RequireHeader (const string &headerNames) : RequireHeader() { + for (const string &header : Utils::split(headerNames, ",")) { + addHeaderName(header); + } +} + +Cpim::RequireHeader::RequireHeader (const list &headerNames) : RequireHeader() { + L_D(); + d->headerNames = headerNames; +} + +list Cpim::RequireHeader::getHeaderNames () const { + L_D(); + return d->headerNames; +} + +void Cpim::RequireHeader::addHeaderName (const string &headerName) { + L_D(); + d->headerNames.push_back(headerName); +} + +string Cpim::RequireHeader::getValue () const { + L_D(); + + string requires; + for (const string &header : d->headerNames) { + if (header != d->headerNames.front()) + requires += ","; + requires += header; + } + + return requires; +} + +string Cpim::RequireHeader::asString () const { + return getName() + ": " + getValue() + "\r\n"; +} + +// ----------------------------------------------------------------------------- + +class Cpim::SubjectHeaderPrivate : public HeaderPrivate { +public: + string subject; + string language; +}; + +Cpim::SubjectHeader::SubjectHeader () : Header(*new SubjectHeaderPrivate) {} + +Cpim::SubjectHeader::SubjectHeader (const string &subject, const string &language) : SubjectHeader() { + setSubject(subject); + setLanguage(language); +} + +string Cpim::SubjectHeader::getSubject () const { + L_D(); + return d->subject; +} + +void Cpim::SubjectHeader::setSubject (const string &subject) { + L_D(); + d->subject = subject; +} + +string Cpim::SubjectHeader::getLanguage () const { + L_D(); + return d->language; +} + +void Cpim::SubjectHeader::setLanguage (const string &language) { + L_D(); + d->language = language; +} + +string Cpim::SubjectHeader::getValue () const { + L_D(); + + string languageParam; + if (!d->language.empty()) + languageParam = ";lang=" + d->language; + + return languageParam + " " + d->subject; +} + +string Cpim::SubjectHeader::asString () const { + return getName() + ":" + getValue() + "\r\n"; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/header/cpim-core-headers.h b/src/chat/cpim/header/cpim-core-headers.h new file mode 100644 index 000000000..2ddd7ea29 --- /dev/null +++ b/src/chat/cpim/header/cpim-core-headers.h @@ -0,0 +1,214 @@ +/* + * cpim-core-headers.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CPIM_CORE_HEADERS_H_ +#define _L_CPIM_CORE_HEADERS_H_ + +#include +#include + +#include "cpim-header.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +#define MAKE_CONTACT_HEADER(CLASS_PREFIX, NAME) \ + class LINPHONE_PUBLIC CLASS_PREFIX ## Header : public ContactHeader { \ + public: \ + CLASS_PREFIX ## Header () = default; \ + CLASS_PREFIX ## Header (const std::string &uri, const std::string &formalName = "") : ContactHeader (uri, formalName) {} \ + inline std::string getName () const override { \ + return NAME; \ + } \ + private: \ + L_DISABLE_COPY(CLASS_PREFIX ## Header); \ + }; + +namespace Cpim { + class DateTimeHeaderNode; + + // ------------------------------------------------------------------------- + // Specific Contact headers declaration. + // ------------------------------------------------------------------------- + + class ContactHeaderPrivate; + + class LINPHONE_PUBLIC ContactHeader : public Header { + public: + ContactHeader (); + + ContactHeader (const std::string &uri, const std::string &formalName = ""); + + std::string getUri () const; + void setUri (const std::string &uri); + + std::string getFormalName () const; + void setFormalName (const std::string &formalName); + + std::string getValue () const override; + + std::string asString () const override; + + private: + L_DECLARE_PRIVATE(ContactHeader); + L_DISABLE_COPY(ContactHeader); + }; + + // ------------------------------------------------------------------------- + + MAKE_CONTACT_HEADER(From, "From"); + MAKE_CONTACT_HEADER(To, "To"); + MAKE_CONTACT_HEADER(Cc, "cc"); + + // ------------------------------------------------------------------------- + // Specific DateTime declaration. + // ------------------------------------------------------------------------- + + class DateTimeHeaderPrivate; + + class LINPHONE_PUBLIC DateTimeHeader : public Header { + friend class DateTimeHeaderNode; + + public: + DateTimeHeader (); + + DateTimeHeader (time_t time); + + DateTimeHeader (const tm &time, const tm &timeOffset, const std::string &signOffset); + + inline std::string getName () const override { + return "DateTime"; + } + + time_t getTime () const; + void setTime (const time_t time); + + void setTime (const tm &time, const tm &timeOffset, const std::string &signOffset); + + std::string getValue () const override; + + std::string asString () const override; + + private: + tm getTimeStruct () const; + tm getTimeOffset () const; + std::string getSignOffset () const; + + L_DECLARE_PRIVATE(DateTimeHeader); + L_DISABLE_COPY(DateTimeHeader); + }; + + // ------------------------------------------------------------------------- + // Specific Ns declaration. + // ------------------------------------------------------------------------- + + class NsHeaderPrivate; + + class LINPHONE_PUBLIC NsHeader : public Header { + public: + NsHeader (); + + NsHeader (const std::string &uri, const std::string &prefixName = ""); + + inline std::string getName () const override { + return "NS"; + } + + std::string getPrefixName () const; + void setPrefixName (const std::string &prefixName); + + std::string getUri () const; + void setUri (const std::string &uri); + + std::string getValue () const override; + + std::string asString () const override; + + private: + L_DECLARE_PRIVATE(NsHeader); + L_DISABLE_COPY(NsHeader); + }; + + // ------------------------------------------------------------------------- + // Specific Require declaration. + // ------------------------------------------------------------------------- + + class RequireHeaderPrivate; + + class LINPHONE_PUBLIC RequireHeader : public Header { + public: + RequireHeader (); + + RequireHeader (const std::string &headerNames); + RequireHeader (const std::list &headerNames); + + inline std::string getName () const override { + return "Require"; + } + + std::list getHeaderNames () const; + void addHeaderName (const std::string &headerName); + + std::string getValue () const override; + + std::string asString () const override; + + private: + L_DECLARE_PRIVATE(RequireHeader); + L_DISABLE_COPY(RequireHeader); + }; + + // ------------------------------------------------------------------------- + // Specific Subject declaration. + // ------------------------------------------------------------------------- + + class SubjectHeaderPrivate; + + class LINPHONE_PUBLIC SubjectHeader : public Header { + public: + SubjectHeader (); + + SubjectHeader (const std::string &subject, const std::string &language = ""); + + inline std::string getName () const override { + return "Subject"; + } + + std::string getSubject () const; + void setSubject (const std::string &subject); + + std::string getLanguage () const; + void setLanguage (const std::string &language); + + std::string getValue () const override; + + std::string asString () const override; + + private: + L_DECLARE_PRIVATE(SubjectHeader); + L_DISABLE_COPY(SubjectHeader); + }; +} + +#undef MAKE_CONTACT_HEADER + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CPIM_CORE_HEADERS_H_ diff --git a/src/chat/cpim/header/cpim-generic-header.cpp b/src/chat/cpim/header/cpim-generic-header.cpp new file mode 100644 index 000000000..6c5947777 --- /dev/null +++ b/src/chat/cpim/header/cpim-generic-header.cpp @@ -0,0 +1,108 @@ +/* + * cpim-generic-header.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/utils.h" + +#include "chat/cpim/parser/cpim-parser.h" +#include "cpim-header-p.h" + +#include "cpim-generic-header.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class Cpim::GenericHeaderPrivate : public HeaderPrivate { +public: + GenericHeaderPrivate () : parameters(make_shared>>()) {} + + string name; + string value; + shared_ptr>> parameters; +}; + +Cpim::GenericHeader::GenericHeader () : Header(*new GenericHeaderPrivate) {} + +Cpim::GenericHeader::GenericHeader (string name, string value, string parameters) : GenericHeader() { + setName(name); + setValue(value); + + for (const auto ¶meter : Utils::split(parameters, ';')) { + size_t equalIndex = parameter.find('='); + if (equalIndex != string::npos) + addParameter(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1)); + } +} + +string Cpim::GenericHeader::getName () const { + L_D(); + return d->name; +} + +void Cpim::GenericHeader::setName (const string &name) { + L_D(); + + static const set reserved = { + "From", "To", "cc", "DateTime", "Subject", "NS", "Require" + }; + + if (reserved.find(name) == reserved.end()) + d->name = name; +} + +string Cpim::GenericHeader::getValue () const { + L_D(); + return d->value; +} + +void Cpim::GenericHeader::setValue (const string &value) { + L_D(); + d->value = value; +} + +Cpim::GenericHeader::ParameterList Cpim::GenericHeader::getParameters () const { + L_D(); + return d->parameters; +} + +void Cpim::GenericHeader::addParameter (const string &key, const string &value) { + L_D(); + d->parameters->push_back(make_pair(key, value)); +} + +void Cpim::GenericHeader::removeParameter (const string &key, const string &value) { + L_D(); + d->parameters->remove(make_pair(key, value)); +} + +string Cpim::GenericHeader::asString () const { + L_D(); + + string parameters; + for (const auto ¶meter : *d->parameters) + parameters += ";" + parameter.first + "=" + parameter.second; + + return d->name + ":" + parameters + " " + getValue() + "\r\n"; +} + +LINPHONE_END_NAMESPACE diff --git a/src/cpim/header/cpim-generic-header.h b/src/chat/cpim/header/cpim-generic-header.h similarity index 55% rename from src/cpim/header/cpim-generic-header.h rename to src/chat/cpim/header/cpim-generic-header.h index 259e60046..6ee8a3695 100644 --- a/src/cpim/header/cpim-generic-header.h +++ b/src/chat/cpim/header/cpim-generic-header.h @@ -1,11 +1,11 @@ /* * cpim-generic-header.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,14 +13,14 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CPIM_GENERIC_HEADER_H_ -#define _CPIM_GENERIC_HEADER_H_ +#ifndef _L_CPIM_GENERIC_HEADER_H_ +#define _L_CPIM_GENERIC_HEADER_H_ #include -#include #include "cpim-header.h" @@ -38,24 +38,22 @@ namespace Cpim { public: GenericHeader (); + GenericHeader (std::string name, std::string value, std::string parameters = ""); + std::string getName () const override; - bool setName (const std::string &name); + void setName (const std::string &name); - bool setValue (const std::string &value) override; + std::string getValue () const override; + void setValue (const std::string &value); - typedef std::shared_ptr > > ParameterList; + typedef std::shared_ptr>> ParameterList; ParameterList getParameters () const; - bool addParameter (const std::string &key, const std::string &value); + void addParameter (const std::string &key, const std::string &value); void removeParameter (const std::string &key, const std::string &value); - bool isValid () const override; - std::string asString () const override; - protected: - void force (const std::string &name, const std::string &value, const std::string ¶meters); - private: L_DECLARE_PRIVATE(GenericHeader); L_DISABLE_COPY(GenericHeader); @@ -64,4 +62,4 @@ namespace Cpim { LINPHONE_END_NAMESPACE -#endif // ifndef _CPIM_GENERIC_HEADER_H_ +#endif // ifndef _L_CPIM_GENERIC_HEADER_H_ diff --git a/src/cpim/header/cpim-header-p.h b/src/chat/cpim/header/cpim-header-p.h similarity index 54% rename from src/cpim/header/cpim-header-p.h rename to src/chat/cpim/header/cpim-header-p.h index af1606b12..2aaea0acb 100644 --- a/src/cpim/header/cpim-header-p.h +++ b/src/chat/cpim/header/cpim-header-p.h @@ -1,11 +1,11 @@ /* * cpim-header-p.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CPIM_HEADER_P_H_ -#define _CPIM_HEADER_P_H_ +#ifndef _L_CPIM_HEADER_P_H_ +#define _L_CPIM_HEADER_P_H_ #include "cpim-header.h" #include "object/object-p.h" @@ -28,16 +29,11 @@ LINPHONE_BEGIN_NAMESPACE namespace Cpim { class HeaderPrivate : public ObjectPrivate { - public: - virtual ~HeaderPrivate () = default; - private: - std::string value; - L_DECLARE_PUBLIC(Header); }; } LINPHONE_END_NAMESPACE -#endif // ifndef _CPIM_HEADER_P_H_ +#endif // ifndef _L_CPIM_HEADER_P_H_ diff --git a/src/chat/cpim/header/cpim-header.cpp b/src/chat/cpim/header/cpim-header.cpp new file mode 100644 index 000000000..6a3b83470 --- /dev/null +++ b/src/chat/cpim/header/cpim-header.cpp @@ -0,0 +1,32 @@ +/* + * cpim-header.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cpim-header-p.h" + +#include "cpim-header.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +Cpim::Header::Header (HeaderPrivate &p) : Object(p) {} + +LINPHONE_END_NAMESPACE diff --git a/src/cpim/header/cpim-header.h b/src/chat/cpim/header/cpim-header.h similarity index 55% rename from src/cpim/header/cpim-header.h rename to src/chat/cpim/header/cpim-header.h index 8fadea125..f71d115b0 100644 --- a/src/cpim/header/cpim-header.h +++ b/src/chat/cpim/header/cpim-header.h @@ -1,11 +1,11 @@ /* * cpim-header.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,13 +13,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CPIM_HEADER_H_ -#define _CPIM_HEADER_H_ - -#include +#ifndef _L_CPIM_HEADER_H_ +#define _L_CPIM_HEADER_H_ #include "object/object.h" @@ -36,12 +35,9 @@ namespace Cpim { virtual std::string getName () const = 0; - std::string getValue () const; - virtual bool setValue (const std::string &value); + virtual std::string getValue () const = 0; - virtual bool isValid () const = 0; - - virtual std::string asString () const; + virtual std::string asString () const = 0; protected: explicit Header (HeaderPrivate &p); @@ -54,4 +50,4 @@ namespace Cpim { LINPHONE_END_NAMESPACE -#endif // ifndef _CPIM_HEADER_H_ +#endif // ifndef _L_CPIM_HEADER_H_ diff --git a/src/chat/cpim/message/cpim-message.cpp b/src/chat/cpim/message/cpim-message.cpp new file mode 100644 index 000000000..8fc7fe259 --- /dev/null +++ b/src/chat/cpim/message/cpim-message.cpp @@ -0,0 +1,186 @@ +/* + * cpim-message.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "linphone/utils/utils.h" + +#include "logger/logger.h" +#include "chat/cpim/parser/cpim-parser.h" +#include "content/content-type.h" +#include "object/object-p.h" + +#include "cpim-message.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class Cpim::MessagePrivate : public ObjectPrivate { +public: + using PrivHeaderList = list>; + using PrivHeaderMap = map>; + + PrivHeaderMap messageHeaders; + shared_ptr contentHeaders = make_shared(); + string content; +}; + +Cpim::Message::Message () : Object(*new MessagePrivate) {} + +// ----------------------------------------------------------------------------- + +Cpim::Message::HeaderList Cpim::Message::getMessageHeaders (const string &ns) const { + L_D(); + + if (d->messageHeaders.find(ns) == d->messageHeaders.end()) + return nullptr; + + return d->messageHeaders.at(ns); +} + +bool Cpim::Message::addMessageHeader (const Header &messageHeader, const string &ns) { + L_D(); + + auto header = Parser::getInstance()->cloneHeader(messageHeader); + if (header == nullptr) + return false; + + if (d->messageHeaders.find(ns) == d->messageHeaders.end()) + d->messageHeaders[ns] = make_shared(); + + auto list = d->messageHeaders.at(ns); + list->push_back(header); + + return true; +} + +void Cpim::Message::removeMessageHeader (const Header &messageHeader, const string &ns) { + L_D(); + + if (d->messageHeaders.find(ns) != d->messageHeaders.end()) + d->messageHeaders.at(ns)->remove_if([&messageHeader](const shared_ptr &header) { + return messageHeader.getName() == header->getName() && messageHeader.getValue() == header->getValue(); + }); +} + +shared_ptr Cpim::Message::getMessageHeader (const string &name, const string &ns) const { + L_D(); + + if (d->messageHeaders.find(ns) == d->messageHeaders.end()) + return nullptr; + + auto list = d->messageHeaders.at(ns); + for (const auto &messageHeader : *list) { + if (messageHeader->getName() == name) + return messageHeader; + } + + return nullptr; +} + +// ----------------------------------------------------------------------------- + +Cpim::Message::HeaderList Cpim::Message::getContentHeaders () const { + L_D(); + return d->contentHeaders; +} + +bool Cpim::Message::addContentHeader (const Header &contentHeader) { + L_D(); + + auto header = Parser::getInstance()->cloneHeader(contentHeader); + if (header == nullptr) + return false; + + d->contentHeaders->push_back(header); + + return true; +} + +void Cpim::Message::removeContentHeader (const Header &contentHeader) { + L_D(); + d->contentHeaders->remove_if([&contentHeader](const shared_ptr &header) { + return contentHeader.getName() == header->getName() && contentHeader.getValue() == header->getValue(); + }); +} + +shared_ptr Cpim::Message::getContentHeader(const string &name) const { + L_D(); + + for (const auto &contentHeader : *d->contentHeaders) { + if (contentHeader->getName() == name) + return contentHeader; + } + + return nullptr; +} + +// ----------------------------------------------------------------------------- + +string Cpim::Message::getContent () const { + L_D(); + return d->content; +} + +bool Cpim::Message::setContent (const string &content) { + L_D(); + d->content = content; + return true; +} + +// ----------------------------------------------------------------------------- + +string Cpim::Message::asString () const { + L_D(); + + string output; + if (d->messageHeaders.size() > 0) { + for (const auto &entry : d->messageHeaders) { + auto list = entry.second; + for (const auto &messageHeader : *list) { + if (entry.first != "") + output += entry.first + "."; + output += messageHeader->asString(); + } + } + + output += "\r\n"; + } + + for (const auto &contentHeaders : *d->contentHeaders) + output += contentHeaders->asString(); + + output += "\r\n"; + + output += getContent(); + + return output; +} + +// ----------------------------------------------------------------------------- + +shared_ptr Cpim::Message::createFromString (const string &str) { + return Parser::getInstance()->parseMessage(str); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/message/cpim-message.h b/src/chat/cpim/message/cpim-message.h new file mode 100644 index 000000000..ff2a26e30 --- /dev/null +++ b/src/chat/cpim/message/cpim-message.h @@ -0,0 +1,64 @@ +/* + * cpim-message.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CPIM_MESSAGE_H_ +#define _L_CPIM_MESSAGE_H_ + +#include "chat/cpim/header/cpim-core-headers.h" +#include "chat/cpim/header/cpim-generic-header.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +namespace Cpim { + class MessagePrivate; + + class LINPHONE_PUBLIC Message : public Object { + public: + Message (); + + typedef std::shared_ptr>> HeaderList; + + HeaderList getMessageHeaders (const std::string &ns = "") const; + bool addMessageHeader (const Header &messageHeader, const std::string &ns = ""); + void removeMessageHeader (const Header &messageHeader, const std::string &ns = ""); + std::shared_ptr getMessageHeader (const std::string &name, const std::string &ns = "") const; + + HeaderList getContentHeaders () const; + bool addContentHeader (const Header &contentHeader); + void removeContentHeader (const Header &contentHeader); + std::shared_ptr getContentHeader (const std::string &name) const; + + std::string getContent () const; + bool setContent (const std::string &content); + + std::string asString () const; + + static std::shared_ptr createFromString (const std::string &str); + + private: + L_DECLARE_PRIVATE(Message); + L_DISABLE_COPY(Message); + }; +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CPIM_MESSAGE_H_ diff --git a/src/chat/cpim/parser/cpim-parser.cpp b/src/chat/cpim/parser/cpim-parser.cpp new file mode 100644 index 000000000..83dd037ce --- /dev/null +++ b/src/chat/cpim/parser/cpim-parser.cpp @@ -0,0 +1,701 @@ +/* + * cpim-parser.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include + +#include "linphone/utils/utils.h" + +#include "content/content-type.h" +#include "logger/logger.h" +#include "object/object-p.h" + +#include "cpim-parser.h" + +#define CPIM_GRAMMAR "cpim_grammar" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +namespace Cpim { + class Node { + public: + virtual ~Node () = default; + }; + + class HeaderNode : public Node { + public: + HeaderNode () = default; + + explicit HeaderNode (const Header &header) : mName(header.getName()), mValue(header.getValue()) { + const GenericHeader *genericHeader = dynamic_cast(&header); + if (genericHeader) { + for (const auto ¶meter : *genericHeader->getParameters()) + mParameters += ";" + parameter.first + "=" + parameter.second; + } + } + + string getName () const { + return mName; + } + + void setName (const string &name) { + static const set reserved = { + "From", "To", "cc", "DateTime", "Subject", "NS", "Require" + }; + + if (reserved.find(name) == reserved.end()) + mName = name; + } + + string getParameters () const { + return mParameters; + } + + void setParameters (const string ¶meters) { + mParameters = parameters; + } + + string getValue () const { + return mValue; + } + + void setValue (const string &value) { + mValue = value; + } + + virtual shared_ptr
createHeader () const; + + virtual bool isValid () const; + + private: + string mName; + string mValue; + string mParameters; + }; + + bool HeaderNode::isValid () const { + return !mName.empty() && !mValue.empty(); + } + + shared_ptr
HeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + shared_ptr genericHeader = make_shared(); + genericHeader->setName(mName); + + for (const auto ¶meter : Utils::split(mParameters, ';')) { + size_t equalIndex = parameter.find('='); + if (equalIndex != string::npos) + genericHeader->addParameter(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1)); + } + + genericHeader->setValue(mValue); + return genericHeader; + } + + // ------------------------------------------------------------------------- + + class ContactHeaderNode : public HeaderNode { + public: + ContactHeaderNode () = default; + + string getFormalName () const { + return mFormalName; + } + + void setFormalName (const string &formalName) { + mFormalName = formalName; + } + + string getUri () const { + return mUri; + } + + void setUri (const string &uri) { + mUri = uri; + } + + bool isValid () const override; + + private: + string mFormalName; + string mUri; + }; + + bool ContactHeaderNode::isValid () const { + return !mUri.empty(); + } + + // ------------------------------------------------------------------------- + + class FromHeaderNode : public ContactHeaderNode { + public: + FromHeaderNode () = default; + + explicit FromHeaderNode (const Header &header) { + const FromHeader *fromHeader = dynamic_cast(&header); + if (fromHeader) { + setFormalName(fromHeader->getFormalName()); + setUri(fromHeader->getUri()); + } + } + + shared_ptr
createHeader () const override; + }; + + shared_ptr
FromHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getUri(), getFormalName()); + } + + // ------------------------------------------------------------------------- + + class ToHeaderNode : public ContactHeaderNode { + public: + ToHeaderNode () = default; + + explicit ToHeaderNode (const Header &header) { + const ToHeader *toHeader = dynamic_cast(&header); + if (toHeader) { + setFormalName(toHeader->getFormalName()); + setUri(toHeader->getUri()); + } + } + + shared_ptr
createHeader () const override; + }; + + shared_ptr
ToHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getUri(), getFormalName()); + } + + // ------------------------------------------------------------------------- + + class CcHeaderNode : public ContactHeaderNode { + public: + CcHeaderNode () = default; + + explicit CcHeaderNode (const Header &header) { + const CcHeader *ccHeader = dynamic_cast(&header); + if (ccHeader) { + setFormalName(ccHeader->getFormalName()); + setUri(ccHeader->getUri()); + } + } + + shared_ptr
createHeader () const override; + }; + + shared_ptr
CcHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getUri(), getFormalName()); + } + + // ------------------------------------------------------------------------- + + class DateTimeOffsetNode : public Node { + friend class DateTimeHeaderNode; + + public: + DateTimeOffsetNode () { + mSign = "Z"; + } + + void setHour (const string &value) { + mHour = Utils::stoi(value); + } + + void setMinute (const string &value) { + mMinute = Utils::stoi(value); + } + + void setSign (const string &value) { + mSign = value; + } + + private: + string mSign; + int mHour; + int mMinute; + }; + + class DateTimeHeaderNode : public HeaderNode { + public: + DateTimeHeaderNode () = default; + + explicit DateTimeHeaderNode (const Header &header) { + const DateTimeHeader *dateTimeHeader = dynamic_cast(&header); + if (dateTimeHeader) { + setTime(dateTimeHeader->getTimeStruct()); + setTimeOffset(dateTimeHeader->getTimeOffset()); + setSignOffset(dateTimeHeader->getSignOffset()); + } + } + + struct tm getTime () const { + return mTime; + } + + void setTime (const struct tm &time) { + mTime = time; + } + + struct tm getTimeOffset () const { + return mTimeOffset; + } + + void setTimeOffset (const struct tm &timeOffset) { + mTimeOffset = timeOffset; + } + + string getSignOffset () const { + return mSignOffset; + } + + void setSignOffset (const string &signOffset) { + mSignOffset = signOffset; + } + + void setYear (const string &value) { + mTime.tm_year = Utils::stoi(value); + } + + void setMonth (const string &value) { + mTime.tm_mon = Utils::stoi(value) - 1; + } + + void setMonthDay (const string &value) { + mTime.tm_mday = Utils::stoi(value); + } + + void setHour (const string &value) { + mTime.tm_hour = Utils::stoi(value); + } + + void setMinute (const string &value) { + mTime.tm_min = Utils::stoi(value); + } + + void setSecond (const string &value) { + mTime.tm_sec = Utils::stoi(value); + } + + void setOffset (const shared_ptr &offset) { + mTimeOffset.tm_hour = offset->mHour; + mTimeOffset.tm_min = offset->mMinute; + mSignOffset = offset->mSign; + } + + bool isValid () const override; + + shared_ptr
createHeader() const override; + + private: + tm mTime; + tm mTimeOffset; + string mSignOffset; + }; + + bool DateTimeHeaderNode::isValid () const { + static const int daysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + // Check date. + const bool isLeapYear = (mTime.tm_year % 4 == 0 && mTime.tm_year % 100 != 0) || mTime.tm_year % 400 == 0; + + if (mTime.tm_mon < 1 || mTime.tm_mon > 12) + return false; + + if (mTime.tm_mday < 1 || (mTime.tm_mon == 2 && isLeapYear ? mTime.tm_mday > 29 : mTime.tm_mday > daysInMonth[mTime.tm_mon])) + return false; + + // Check time. + if (mTime.tm_hour > 24 || mTime.tm_min > 59 || mTime.tm_sec > 60) + return false; + + // Check num offset. + if (mSignOffset != "Z") { + if (mTimeOffset.tm_hour > 24 || mTime.tm_min > 59) + return false; + } + + return true; + } + + shared_ptr
DateTimeHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getTime(), getTimeOffset(), getSignOffset()); + } + + // ------------------------------------------------------------------------- + + class SubjectHeaderNode : public HeaderNode { + public: + SubjectHeaderNode () = default; + + explicit SubjectHeaderNode (const Header &header) { + const SubjectHeader *subjectHeader = dynamic_cast(&header); + if (subjectHeader) { + setLanguage(subjectHeader->getLanguage()); + setSubject(subjectHeader->getSubject()); + } + } + + string getLanguage () const { + return mLanguage; + } + + void setLanguage (const string &language) { + mLanguage = language; + } + + string getSubject () const { + return mSubject; + } + + void setSubject (const string &subject) { + mSubject = subject; + } + + bool isValid () const override; + + shared_ptr
createHeader () const override; + + private: + string mLanguage; + string mSubject; + }; + + bool SubjectHeaderNode::isValid () const { + return !mSubject.empty(); + } + + shared_ptr
SubjectHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getSubject(), getLanguage()); + } + + // ------------------------------------------------------------------------- + + class NsHeaderNode : public HeaderNode { + public: + NsHeaderNode () = default; + + explicit NsHeaderNode (const Header &header) { + const NsHeader *nsHeader = dynamic_cast(&header); + if (nsHeader) { + setPrefixName(nsHeader->getPrefixName()); + setUri(nsHeader->getUri()); + } + } + + string getPrefixName () const { + return mPrefixName; + } + + void setPrefixName (const string &prefixName) { + mPrefixName = prefixName; + } + + string getUri () const { + return mUri; + } + + void setUri (const string &uri) { + mUri = uri; + } + + bool isValid () const override; + + shared_ptr
createHeader () const override; + + private: + string mPrefixName; + string mUri; + }; + + bool NsHeaderNode::isValid () const { + return !mUri.empty(); + } + + shared_ptr
NsHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(getUri(), getPrefixName()); + } + + // ------------------------------------------------------------------------- + + class RequireHeaderNode : public HeaderNode { + public: + RequireHeaderNode () = default; + + explicit RequireHeaderNode (const Header &header) { + const RequireHeader *requireHeader = dynamic_cast(&header); + if (requireHeader) { + for (const auto &header : requireHeader->getHeaderNames()) { + if (header != requireHeader->getHeaderNames().front()) + mHeaderNames += ","; + mHeaderNames += header; + } + } + } + + string getHeaderNames () const { + return mHeaderNames; + } + + void setHeaderNames (const string &headerNames) { + mHeaderNames = headerNames; + } + + bool isValid () const override; + + shared_ptr
createHeader () const override; + + private: + string mHeaderNames; + }; + + bool RequireHeaderNode::isValid () const { + return !mHeaderNames.empty(); + } + + shared_ptr
RequireHeaderNode::createHeader () const { + if (!isValid()) + return nullptr; + + return make_shared(mHeaderNames); + } + + // ------------------------------------------------------------------------- + + class ListHeaderNode : + public Node, + public list > {}; + + // ------------------------------------------------------------------------- + + class MessageNode : public Node { + public: + void addMessageHeaders (const shared_ptr &headers) { + for (const auto &headerNode : *headers) { + mMessageHeaders.push_back(headerNode); + } + } + + void addContentHeaders (const shared_ptr &headers) { + for (const auto &headerNode : *headers) { + mContentHeaders.push_back(headerNode); + } + } + + // Warning: Call this function one time! + shared_ptr createMessage () const { + if (mContentHeaders.empty() || mMessageHeaders.empty()) { + lWarning() << "Bad headers lists size."; + return nullptr; + } + + //TODO: Verify all headers from other namespaces + + const shared_ptr message = make_shared(); + + // Add message headers. + for (const auto &headerNode : mMessageHeaders) { + string ns = ""; + + string::size_type n = headerNode->getName().find("."); + if (n != string::npos) { + ns = headerNode->getName().substr(0, n); + headerNode->setName(headerNode->getName().substr(n + 1)); + } + + const shared_ptr header = headerNode->createHeader(); + if (!header) + return nullptr; + + message->addMessageHeader(*header, ns); + } + + // Add content headers. + for (const auto &headerNode : mContentHeaders) { + const shared_ptr header = headerNode->createHeader(); + if (!header) + return nullptr; + + message->addContentHeader(*header); + } + + return message; + } + + private: + list> mContentHeaders; + list> mMessageHeaders; + }; +} + +// ----------------------------------------------------------------------------- + +class Cpim::ParserPrivate : public ObjectPrivate { +public: + shared_ptr grammar; +}; + +Cpim::Parser::Parser () : Singleton(*new ParserPrivate) { + L_D(); + d->grammar = belr::GrammarLoader::get().load(CPIM_GRAMMAR); + if (!d->grammar) + lFatal() << "Unable to load CPIM grammar."; +} + +// ----------------------------------------------------------------------------- + +shared_ptr Cpim::Parser::parseMessage (const string &input) { + L_D(); + + typedef void (list >::*pushPtr)(const shared_ptr &value); + + belr::Parser > parser(d->grammar); + parser.setHandler("Message", belr::make_fn(make_shared)) + ->setCollector("Message-headers", belr::make_sfn(&MessageNode::addMessageHeaders)) + ->setCollector("Content-headers", belr::make_sfn(&MessageNode::addContentHeaders)); + + parser.setHandler("Message-headers", belr::make_fn(make_shared)) + ->setCollector("Header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("From-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("To-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("DateTime-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("cc-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("Subject-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("NS-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))) + ->setCollector("Require-header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))); + + parser.setHandler("Content-headers", belr::make_fn(make_shared)) + ->setCollector("Header", belr::make_sfn(static_cast(&ListHeaderNode::push_back))); + + parser.setHandler("Header", belr::make_fn(make_shared)) + ->setCollector("Header-name", belr::make_sfn(&HeaderNode::setName)) + ->setCollector("Header-value", belr::make_sfn(&HeaderNode::setValue)) + ->setCollector("Header-parameters", belr::make_sfn(&HeaderNode::setParameters)); + + parser.setHandler("From-header", belr::make_fn(make_shared)) + ->setCollector("Formal-name", belr::make_sfn(&FromHeaderNode::setFormalName)) + ->setCollector("URI", belr::make_sfn(&FromHeaderNode::setUri)); + + parser.setHandler("To-header", belr::make_fn(make_shared)) + ->setCollector("Formal-name", belr::make_sfn(&ToHeaderNode::setFormalName)) + ->setCollector("URI", belr::make_sfn(&ToHeaderNode::setUri)); + + parser.setHandler("cc-header", belr::make_fn(make_shared)) + ->setCollector("Formal-name", belr::make_sfn(&CcHeaderNode::setFormalName)) + ->setCollector("URI", belr::make_sfn(&CcHeaderNode::setUri)); + + parser.setHandler("DateTime-header", belr::make_fn(make_shared)) + ->setCollector("date-fullyear", belr::make_sfn(&DateTimeHeaderNode::setYear)) + ->setCollector("date-month", belr::make_sfn(&DateTimeHeaderNode::setMonth)) + ->setCollector("date-mday", belr::make_sfn(&DateTimeHeaderNode::setMonthDay)) + ->setCollector("time-hour", belr::make_sfn(&DateTimeHeaderNode::setHour)) + ->setCollector("time-minute", belr::make_sfn(&DateTimeHeaderNode::setMinute)) + ->setCollector("time-second", belr::make_sfn(&DateTimeHeaderNode::setSecond)) + ->setCollector("time-offset", belr::make_sfn(&DateTimeHeaderNode::setOffset)); + + parser.setHandler("time-offset", belr::make_fn(make_shared)) + ->setCollector("time-sign", belr::make_sfn(&DateTimeOffsetNode::setSign)) + ->setCollector("time-hour", belr::make_sfn(&DateTimeOffsetNode::setHour)) + ->setCollector("time-minute", belr::make_sfn(&DateTimeOffsetNode::setMinute)); + + parser.setHandler("Subject-header", belr::make_fn(make_shared)) + ->setCollector("Language-tag", belr::make_sfn(&SubjectHeaderNode::setLanguage)) + ->setCollector("Header-value", belr::make_sfn(&SubjectHeaderNode::setSubject)); + + parser.setHandler("Ns-header", belr::make_fn(make_shared)) + ->setCollector("Name-prefix", belr::make_sfn(&NsHeaderNode::setPrefixName)) + ->setCollector("URI", belr::make_sfn(&NsHeaderNode::setUri)); + + parser.setHandler("Require-header", belr::make_fn(make_shared)) + ->setCollector("Require-header-value", belr::make_sfn(&RequireHeaderNode::setHeaderNames)); + + size_t parsedSize; + shared_ptr node = parser.parseInput("Message", input, &parsedSize); + if (!node) { + lWarning() << "Unable to parse message."; + return nullptr; + } + + shared_ptr messageNode = dynamic_pointer_cast(node); + if (!messageNode) { + lWarning() << "Unable to cast belr result to message node."; + return nullptr; + } + + shared_ptr message = messageNode->createMessage(); + if (message) { + message->setContent(input.substr(parsedSize)); + } + return message; +} + +// ----------------------------------------------------------------------------- + +shared_ptr Cpim::Parser::cloneHeader (const Header &header) { + if (header.getName() == "From") + return FromHeaderNode(header).createHeader(); + + if (header.getName() == "To") + return ToHeaderNode(header).createHeader(); + + if (header.getName() == "cc") + return CcHeaderNode(header).createHeader(); + + if (header.getName() == "DateTime") + return DateTimeHeaderNode(header).createHeader(); + + if (header.getName() == "Subject") + return SubjectHeaderNode(header).createHeader(); + + if (header.getName() == "NS") + return NsHeaderNode(header).createHeader(); + + if (header.getName() == "Require") + return RequireHeaderNode(header).createHeader(); + + return HeaderNode(header).createHeader(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/cpim/parser/cpim-parser.h b/src/chat/cpim/parser/cpim-parser.h new file mode 100644 index 000000000..076400841 --- /dev/null +++ b/src/chat/cpim/parser/cpim-parser.h @@ -0,0 +1,51 @@ +/* + * cpim-parser.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CPIM_PARSER_H_ +#define _L_CPIM_PARSER_H_ + +#include "chat/cpim/message/cpim-message.h" +#include "object/singleton.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +namespace Cpim { + class ParserPrivate; + + class Parser : public Singleton { + friend class Singleton; + + public: + std::shared_ptr parseMessage (const std::string &input); + + std::shared_ptr
cloneHeader (const Header &header); + + private: + Parser (); + + L_DECLARE_PRIVATE(Parser); + L_DISABLE_COPY(Parser); + }; +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CPIM_PARSER_H_ diff --git a/src/chat/cpim/parser/cpim-rules b/src/chat/cpim/parser/cpim-rules new file mode 100644 index 000000000..18c438efc --- /dev/null +++ b/src/chat/cpim/parser/cpim-rules @@ -0,0 +1,152 @@ +Message = [Crappy-header CRLF] Message-headers CRLF Content-headers CRLF + +Crappy-header = "Content-Type: Message/CPIM" CRLF + +Message-headers = 1*( Message-header CRLF ) +Message-header = From-header / To-header / DateTime-header / cc-header / Subject-header / NS-header / Require-header / Header + +Content-headers = 1*( Header CRLF ) + +Header = Header-name ":" Header-parameters SP Header-value + +Header-name = [ Name-prefix "." ] Name +Name-prefix = Name + +Header-parameters = *( ";" Parameter ) + +Parameter = Lang-param / Ext-param +Lang-param = "lang=" Language-tag +Ext-param = Param-name "=" Param-value +Param-name = Name +Param-value = Token / Number / String + +Header-value = *HEADERCHAR + +From-header = %d70.114.111.109 ": " From-header-value +From-header-value = [ Formal-name ] "<" URI ">" + +To-header = %d84.111 ": " To-header-value +To-header-value = [ Formal-name ] "<" URI ">" + +DateTime-header = %d68.97.116.101.84.105.109.101 ": " DateTime-header-value +DateTime-header-value = date-time + +cc-header = %d99.99 ": " cc-header-value +cc-header-value = [ Formal-name ] "<" URI ">" + +Subject-header = %d83.117.98.106.101.99.116 ":" Subject-header-value +Subject-header-value = [ ";" Lang-param ] SP Header-value + +NS-header = %d78.83 ": " NS-header-value +NS-header-value = [ Name-prefix SP ] "<" URI ">" + +Require-header = %d82.101.113.117.105.114.101 ": " Require-header-value +Require-header-value = Header-name *( "," Header-name ) + +Name = 1*NAMECHAR +Token = 1*TOKENCHAR +Number = 1*DIGIT +String = DQUOTE *( Str-char / Escape ) DQUOTE +Str-char = %x20-21 / %x23-5B / %x5D-7E / UCS-high +Escape = "\" ( "u" 4(HEXDIG) / "b" / "t" / "n" / "r" / DQUOTE / "'" / "\" ) + +Formal-name = 1*( Token SP ) / String + +HEADERCHAR = UCS-no-CTL / Escape + +NAMECHAR = %x21 / %x23-27 / %x2a-2b / %x2d / %x5e-60 + / %x7c / %x7e / ALPHA / DIGIT + +TOKENCHAR = NAMECHAR / "." / UCS-high + +UCS-no-CTL = UTF8-no-CTL +UCS-high = UTF8-multi +UTF8-no-CTL = %x20-7e / UTF8-multi +UTF8-multi = %xC0-DF %x80-BF + / %xE0-EF %x80-BF %x80-BF + / %xF0-F7 %x80-BF %x80-BF %x80-BF + / %xF8-FB %x80-BF %x80-BF %x80-BF %x80-BF + / %xFC-FD %x80-BF %x80-BF %x80-BF %x80-BF %x80-BF + +URI = absoluteURI + +absoluteURI = scheme ":" ( hier-part / opaque-part ) +relativeURI = ( net-path / abs-path / rel-path ) [ "?" query ] + +hier-part = ( net-path / abs-path ) [ "?" query ] +opaque-part = uric-no-slash *uric + +uric-no-slash = unreserved / escaped / ";" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," + +net-path = "//" authority [ abs-path ] +abs-path = "/" path-segments +rel-path = rel-segment [ abs-path ] + +rel-segment = 1*( unreserved / escaped / ";" / "@" / "&" / "=" / "+" / "$" / "," ) + +scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) + +authority = server / reg-name + +reg-name = 1*( unreserved / escaped / "$" / "," / ";" / ":" / "@" / "&" / "=" / "+" ) + +server = [ [ userinfo "@" ] hostport ] +userinfo = *( unreserved / escaped / ";" / ":" / "&" / "=" / "+" / "$" / "," ) + +hostport = host [ ":" port ] +host = hostname / IPv4address / IPv6address +ipv6reference = "[" IPv6address "]" +hostname = *( domainlabel "." ) toplabel [ "." ] +domainlabel = alphanum / alphanum *( alphanum / "-" ) alphanum +toplabel = ALPHA / ALPHA *( alphanum / "-" ) alphanum +IPv6address = hexpart [ ":" IPv4address ] +IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT +port = *DIGIT + +IPv6prefix = hexpart "/" 1*2DIGIT +hexpart = hexseq / hexseq "::" [ hexseq ] / "::" [ hexseq ] +hexseq = hex4 *( ":" hex4) +hex4 = 1*4HEXDIG + +path = [ abs-path / opaque-part ] +path-segments = segment *( "/" segment ) +segment = *pchar *( ";" param ) +param = *pchar +pchar = unreserved / escaped / ":" / "@" / "&" / "=" / "+" / "$" / "," + +query = *uric + +fragment = *uric + +uric = reserved / unreserved / escaped +reserved = ";" / "/" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / "," / "[" / "]" +unreserved = alphanum / mark +mark = "-" / "_" / "." / "!" / "~" / "*" / "'" / "(" / ")" + +escaped = "%" HEXDIG HEXDIG + +alphanum = ALPHA / DIGIT + +Language-Tag = Primary-subtag *( "-" Subtag ) +Primary-subtag = 1*8ALPHA +Subtag = 1*8(ALPHA / DIGIT) + +date-fullyear = 4DIGIT +date-month = 2DIGIT +date-mday = 2DIGIT + +time-hour = 2DIGIT +time-minute = 2DIGIT +time-second = 2DIGIT + +time-secfrac = "." 1*DIGIT +time-sign = "+" / "-" +time-numoffset = time-sign time-hour ":" time-minute +time-offset = "Z" / time-numoffset + +partial-time = time-hour ":" time-minute ":" time-second [ time-secfrac ] + +full-date = date-fullyear "-" date-month "-" date-mday +full-time = partial-time time-offset + +date-time = full-date "T" full-time diff --git a/src/chat/modifier/chat-message-modifier.h b/src/chat/modifier/chat-message-modifier.h new file mode 100644 index 000000000..a930f966d --- /dev/null +++ b/src/chat/modifier/chat-message-modifier.h @@ -0,0 +1,58 @@ +/* + * chat-message-modifier.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_MESSAGE_MODIFIER_H_ +#define _L_CHAT_MESSAGE_MODIFIER_H_ + +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatMessage; + +class ChatMessageModifier { +public: + enum class Result { + Skipped = -1, + Done = 0, + Suspended = 1, + Error = 2 + }; + + virtual ~ChatMessageModifier () = default; + + /** + * This method will be called when the message is about to be sent. + * It should check first if the internalContent is filled. + * If so, it should apply it's changes to it, otherwise it should use the contentsList. + */ + virtual Result encode (const std::shared_ptr &message, int &errorCode) = 0; + + /** + * This method will be called when the message is about to be received. + * It should apply it's changes to the internal content, the last modifier will take care of filling the contentsList. + */ + virtual Result decode (const std::shared_ptr &message, int &errorCode) = 0; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CPIM_CHAT_MESSAGE_MODIFIER_H_ diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp new file mode 100644 index 000000000..0e40e6dc1 --- /dev/null +++ b/src/chat/modifier/cpim-chat-message-modifier.cpp @@ -0,0 +1,207 @@ +/* + * cpim-chat-message-modifier.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "address/address.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/cpim/cpim.h" +#include "content/content.h" +#include "content/content-disposition.h" +#include "content/content-type.h" +#include "logger/logger.h" + +#include "cpim-chat-message-modifier.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +ChatMessageModifier::Result CpimChatMessageModifier::encode (const shared_ptr &message, int &errorCode) { + Cpim::Message cpimMessage; + + cpimMessage.addMessageHeader( + Cpim::FromHeader(cpimAddressUri(message->getFromAddress()), cpimAddressDisplayName(message->getFromAddress())) + ); + cpimMessage.addMessageHeader( + Cpim::ToHeader(cpimAddressUri(message->getToAddress()), cpimAddressDisplayName(message->getToAddress())) + ); + cpimMessage.addMessageHeader( + Cpim::DateTimeHeader(message->getTime()) + ); + + if (message->getPrivate()->getPositiveDeliveryNotificationRequired() + || message->getPrivate()->getNegativeDeliveryNotificationRequired() + || message->getPrivate()->getDisplayNotificationRequired() + ) { + const string imdnNamespace = "imdn"; + cpimMessage.addMessageHeader(Cpim::NsHeader("urn:ietf:params:imdn", imdnNamespace)); + + char token[13]; + belle_sip_random_token(token, sizeof(token)); + cpimMessage.addMessageHeader( + Cpim::GenericHeader("Message-ID", token) // TODO: Replace by imdnNamespace + ".Message-ID"); + ); + message->getPrivate()->setImdnMessageId(token); + + vector dispositionNotificationValues; + if (message->getPrivate()->getPositiveDeliveryNotificationRequired()) + dispositionNotificationValues.emplace_back("positive-delivery"); + if (message->getPrivate()->getNegativeDeliveryNotificationRequired()) + dispositionNotificationValues.emplace_back("negative-delivery"); + if (message->getPrivate()->getDisplayNotificationRequired()) + dispositionNotificationValues.emplace_back("display"); + cpimMessage.addMessageHeader( + Cpim::GenericHeader( + imdnNamespace + ".Disposition-Notification", + Utils::join(dispositionNotificationValues, ", ") + ) + ); + } + + const Content *content; + if (!message->getInternalContent().isEmpty()) { + // Another ChatMessageModifier was called before this one, we apply our changes on the private content + content = &(message->getInternalContent()); + } else { + // We're the first ChatMessageModifier to be called, we'll create the private content from the public one + // We take the first one because if there is more of them, the multipart modifier should have been called first + // So we should not be in this block + content = message->getContents().front(); + } + + const string contentBody = content->getBodyAsString(); + if (content->getContentDisposition().isValid()) { + cpimMessage.addContentHeader( + Cpim::GenericHeader("Content-Disposition", content->getContentDisposition().asString()) + ); + } + cpimMessage.addContentHeader( + Cpim::GenericHeader("Content-Type", content->getContentType().asString()) + ); + cpimMessage.addContentHeader( + Cpim::GenericHeader("Content-Length", Utils::toString(contentBody.size())) + ); + cpimMessage.setContent(contentBody); + + Content newContent; + newContent.setContentType(ContentType::Cpim); + newContent.setBody(cpimMessage.asString()); + message->setInternalContent(newContent); + + return ChatMessageModifier::Result::Done; +} + +ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptr &message, int &errorCode) { + const Content *content; + if (!message->getInternalContent().isEmpty()) + content = &(message->getInternalContent()); + else + content = message->getContents().front(); + + if (content->getContentType() != ContentType::Cpim) { + lError() << "[CPIM] Message is not CPIM but " << content->getContentType(); + return ChatMessageModifier::Result::Skipped; + } + + const string contentBody = content->getBodyAsString(); + const shared_ptr cpimMessage = Cpim::Message::createFromString(contentBody); + if (!cpimMessage || !cpimMessage->getMessageHeader("From") || !cpimMessage->getMessageHeader("To")) { + lError() << "[CPIM] Message is invalid: " << contentBody; + errorCode = 488; // Not Acceptable + return ChatMessageModifier::Result::Error; + } + + Content newContent; + auto contentTypeHeader = cpimMessage->getContentHeader("Content-Type"); + if (!contentTypeHeader) { + lError() << "[CPIM] No Content-type for the content of the message"; + errorCode = 488; // Not Acceptable + return ChatMessageModifier::Result::Error; + } + newContent.setContentType(ContentType(contentTypeHeader->getValue())); + auto contentDispositionHeader = cpimMessage->getContentHeader("Content-Disposition"); + if (contentDispositionHeader) + newContent.setContentDisposition(ContentDisposition(contentDispositionHeader->getValue())); + newContent.setBody(cpimMessage->getContent()); + + message->getPrivate()->setPositiveDeliveryNotificationRequired(false); + message->getPrivate()->setNegativeDeliveryNotificationRequired(false); + message->getPrivate()->setDisplayNotificationRequired(false); + + string imdnNamespace = ""; + auto messageHeaders = cpimMessage->getMessageHeaders(); + if (messageHeaders) { + for (const auto &header : *messageHeaders.get()) { + if (header->getName() != "NS") + continue; + auto nsHeader = static_pointer_cast(header); + if (nsHeader->getUri() == "urn:ietf:params:imdn") { + imdnNamespace = nsHeader->getPrefixName(); + break; + } + } + } + + auto fromHeader = static_pointer_cast(cpimMessage->getMessageHeader("From")); + Address cpimFromAddress(fromHeader->getValue()); + auto toHeader = static_pointer_cast(cpimMessage->getMessageHeader("To")); + Address cpimToAddress(toHeader->getValue()); + auto dateTimeHeader = static_pointer_cast(cpimMessage->getMessageHeader("DateTime")); + if (dateTimeHeader) + message->getPrivate()->setTime(dateTimeHeader->getTime()); + + auto messageIdHeader = cpimMessage->getMessageHeader("Message-ID"); // TODO: For compatibility, to remove + if (!imdnNamespace.empty()) { + if (!messageIdHeader) + messageIdHeader = cpimMessage->getMessageHeader("Message-ID", imdnNamespace); + auto dispositionNotificationHeader = cpimMessage->getMessageHeader("Disposition-Notification", imdnNamespace); + if (dispositionNotificationHeader) { + vector values = Utils::split(dispositionNotificationHeader->getValue(), ", "); + for (const auto &value : values) + if (value == "positive-delivery") + message->getPrivate()->setPositiveDeliveryNotificationRequired(true); + else if (value == "negative-delivery") + message->getPrivate()->setNegativeDeliveryNotificationRequired(true); + else if (value == "display") + message->getPrivate()->setDisplayNotificationRequired(true); + } + } + if (messageIdHeader) + message->getPrivate()->setImdnMessageId(messageIdHeader->getValue()); + + // Modify the initial message since there was no error + message->setInternalContent(newContent); + if (cpimFromAddress.isValid()) + message->getPrivate()->forceFromAddress(cpimFromAddress); + + return ChatMessageModifier::Result::Done; +} + +string CpimChatMessageModifier::cpimAddressDisplayName (const Address &addr) const { + return addr.getDisplayName(); +} + +string CpimChatMessageModifier::cpimAddressUri (const Address &addr) const { + return addr.asStringUriOnly(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/cpim-chat-message-modifier.h b/src/chat/modifier/cpim-chat-message-modifier.h new file mode 100644 index 000000000..04dab858a --- /dev/null +++ b/src/chat/modifier/cpim-chat-message-modifier.h @@ -0,0 +1,43 @@ +/* + * cpim-chat-message-modifier.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CPIM_CHAT_MESSAGE_MODIFIER_H_ +#define _L_CPIM_CHAT_MESSAGE_MODIFIER_H_ + +#include "chat-message-modifier.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CpimChatMessageModifier : public ChatMessageModifier { +public: + CpimChatMessageModifier () = default; + + Result encode (const std::shared_ptr &message, int &errorCode) override; + Result decode (const std::shared_ptr &message, int &errorCode) override; + +private: + std::string cpimAddressDisplayName (const Address &addr) const; + std::string cpimAddressUri (const Address &addr) const; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CPIM_CHAT_MESSAGE_MODIFIER_H_ diff --git a/src/chat/modifier/encryption-chat-message-modifier.cpp b/src/chat/modifier/encryption-chat-message-modifier.cpp new file mode 100644 index 000000000..245a0c6b3 --- /dev/null +++ b/src/chat/modifier/encryption-chat-message-modifier.cpp @@ -0,0 +1,102 @@ +/* + * encryption-chat-message-modifier.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" +#include "chat/chat-message/chat-message.h" +#include "chat/chat-room/chat-room.h" +#include "content/content-type.h" +#include "content/content.h" +#include "core/core.h" + +#include "encryption-chat-message-modifier.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +ChatMessageModifier::Result EncryptionChatMessageModifier::encode ( + const shared_ptr &message, + int &errorCode +) { + shared_ptr chatRoom = message->getChatRoom(); + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore()); + if (!imee) + return ChatMessageModifier::Result::Skipped; + + LinphoneImEncryptionEngineCbsOutgoingMessageCb cbProcessOutgoingMessage = + linphone_im_encryption_engine_cbs_get_process_outgoing_message( + linphone_im_encryption_engine_get_callbacks(imee) + ); + + if (!cbProcessOutgoingMessage) + return ChatMessageModifier::Result::Skipped; + + int retval = cbProcessOutgoingMessage(imee, L_GET_C_BACK_PTR(chatRoom), L_GET_C_BACK_PTR(message)); + if (retval == -1) + return ChatMessageModifier::Result::Skipped; + + if (retval != 0 && retval != 1) { + errorCode = retval; + return ChatMessageModifier::Result::Error; + } + + message->setIsSecured(true); + if (retval == 1) + return ChatMessageModifier::Result::Suspended; + + return ChatMessageModifier::Result::Done; +} + +ChatMessageModifier::Result EncryptionChatMessageModifier::decode ( + const shared_ptr &message, + int &errorCode +) { + shared_ptr chatRoom = message->getChatRoom(); + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(chatRoom->getCore()->getCCore()); + if (!imee) + return ChatMessageModifier::Result::Skipped; + + LinphoneImEncryptionEngineCbsIncomingMessageCb cbProcessIncomingMessage = + linphone_im_encryption_engine_cbs_get_process_incoming_message( + linphone_im_encryption_engine_get_callbacks(imee) + ); + + if (!cbProcessIncomingMessage) + return ChatMessageModifier::Result::Skipped; + + int retval = cbProcessIncomingMessage(imee, L_GET_C_BACK_PTR(chatRoom), L_GET_C_BACK_PTR(message)); + if (retval == -1) + return ChatMessageModifier::Result::Skipped; + + if (retval != 0 && retval != 1) { + errorCode = retval; + return ChatMessageModifier::Result::Error; + } + + message->setIsSecured(true); + if (retval == 1) + return ChatMessageModifier::Result::Suspended; + + return ChatMessageModifier::Result::Done; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/encryption-chat-message-modifier.h b/src/chat/modifier/encryption-chat-message-modifier.h new file mode 100644 index 000000000..9d839b919 --- /dev/null +++ b/src/chat/modifier/encryption-chat-message-modifier.h @@ -0,0 +1,39 @@ +/* + * encryption-chat-message-modifier.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ENCRYPTION_CHAT_MESSAGE_MODIFIER_H_ +#define _L_ENCRYPTION_CHAT_MESSAGE_MODIFIER_H_ + +#include "chat-message-modifier.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class EncryptionChatMessageModifier : public ChatMessageModifier { +public: + EncryptionChatMessageModifier () = default; + + Result encode (const std::shared_ptr &message, int &errorCode) override; + Result decode (const std::shared_ptr &message, int &errorCode) override; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ENCRYPTION_CHAT_MESSAGE_MODIFIER_H_ diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp new file mode 100644 index 000000000..c3001231a --- /dev/null +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -0,0 +1,1044 @@ +/* + * file-transfer-chat-message-modifier.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-content.h" + +#include "address/address.h" +#include "bctoolbox/crypto.h" +#include "c-wrapper/c-wrapper.h" +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "content/content-type.h" +#include "content/content.h" +#include "core/core.h" +#include "logger/logger.h" + +#include "file-transfer-chat-message-modifier.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +FileTransferChatMessageModifier::FileTransferChatMessageModifier (belle_http_provider_t *prov) : provider(prov) { + bgTask.setName("File transfer upload"); +} + +belle_http_request_t *FileTransferChatMessageModifier::getHttpRequest () const { + return httpRequest; +} + +void FileTransferChatMessageModifier::setHttpRequest (belle_http_request_t *request) { + httpRequest = request; +} + +FileTransferChatMessageModifier::~FileTransferChatMessageModifier () { + if (isFileTransferInProgressAndValid()) + cancelFileTransfer(); //to avoid body handler to still refference zombie FileTransferChatMessageModifier + else + releaseHttpRequest(); +} + +ChatMessageModifier::Result FileTransferChatMessageModifier::encode (const shared_ptr &message, int &errorCode) { + chatMessage = message; + + currentFileContentToTransfer = nullptr; + // For each FileContent, upload it and create a FileTransferContent + for (Content *content : message->getContents()) { + if (content->isFile()) { + lInfo() << "Found file content, set it for file upload"; + FileContent *fileContent = (FileContent *)content; + currentFileContentToTransfer = fileContent; + break; + } + } + if (!currentFileContentToTransfer) + return ChatMessageModifier::Result::Skipped; + + /* Open a transaction with the server and send an empty request(RCS5.1 section 3.5.4.8.3.1) */ + if (uploadFile() == 0) + return ChatMessageModifier::Result::Suspended; + + return ChatMessageModifier::Result::Error; +} + +// ---------------------------------------------------------- + +static void _chat_message_file_transfer_on_progress ( + belle_sip_body_handler_t *bh, + belle_sip_message_t *m, + void *data, + size_t offset, + size_t total +) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->fileTransferOnProgress(bh, m, offset, total); +} + +void FileTransferChatMessageModifier::fileTransferOnProgress ( + belle_sip_body_handler_t *bh, + belle_sip_message_t *m, + size_t offset, + size_t total +) { + if (!isFileTransferInProgressAndValid()) { + releaseHttpRequest(); + return; + } + + shared_ptr message = chatMessage.lock(); + if (!message) + return; + + LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + if (linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)) { + linphone_chat_message_cbs_get_file_transfer_progress_indication(cbs)(msg, content, offset, total); + } else { + // Legacy: call back given by application level. + linphone_core_notify_file_transfer_progress_indication(message->getCore()->getCCore(), msg, content, offset, total); + } +} + +static int _chat_message_on_send_body ( + belle_sip_user_body_handler_t *bh, + belle_sip_message_t *m, + void *data, + size_t offset, + uint8_t *buffer, + size_t *size +) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + return d->onSendBody(bh, m, offset, buffer, size); +} + +int FileTransferChatMessageModifier::onSendBody ( + belle_sip_user_body_handler_t *bh, + belle_sip_message_t *m, + size_t offset, + uint8_t *buffer, + size_t *size +) { + int retval = -1; + shared_ptr message = chatMessage.lock(); + if (!message) + return BELLE_SIP_STOP; + + LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); + + if (!isFileTransferInProgressAndValid()) { + if (httpRequest) { + releaseHttpRequest(); + } + return BELLE_SIP_STOP; + } + + // if we've not reach the end of file yet, ask for more data + // in case of file body handler, won't be called + if (currentFileContentToTransfer->getFilePath().empty() && offset < currentFileContentToTransfer->getFileSize()) { + // get data from call back + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + LinphoneChatMessageCbsFileTransferSendCb file_transfer_send_cb = + linphone_chat_message_cbs_get_file_transfer_send(cbs); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + if (file_transfer_send_cb) { + LinphoneBuffer *lb = file_transfer_send_cb(msg, content, offset, *size); + if (lb) { + *size = linphone_buffer_get_size(lb); + memcpy(buffer, linphone_buffer_get_content(lb), *size); + linphone_buffer_unref(lb); + } else { + *size = 0; + } + } else { + // Legacy + linphone_core_notify_file_transfer_send(message->getCore()->getCCore(), msg, content, (char *)buffer, size); + } + } + + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsUploadingFileCb cb_process_uploading_file = + linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs); + if (cb_process_uploading_file) { + size_t max_size = *size; + uint8_t *encrypted_buffer = (uint8_t *)ms_malloc0(max_size); + retval = cb_process_uploading_file(imee, msg, offset, (const uint8_t *)buffer, size, encrypted_buffer); + if (retval == 0) { + if (*size > max_size) { + lError() << "IM encryption engine process upload file callback returned a size bigger than the size of the buffer, so it will be truncated !"; + *size = max_size; + } + memcpy(buffer, encrypted_buffer, *size); + } + ms_free(encrypted_buffer); + } + } + + return retval <= 0 ? BELLE_SIP_CONTINUE : BELLE_SIP_STOP; +} + +static void _chat_message_on_send_end (belle_sip_user_body_handler_t *bh, void *data) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->onSendEnd(bh); +} + +void FileTransferChatMessageModifier::onSendEnd (belle_sip_user_body_handler_t *bh) { + shared_ptr message = chatMessage.lock(); + if (!message) + return; + + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsUploadingFileCb cb_process_uploading_file = linphone_im_encryption_engine_cbs_get_process_uploading_file(imee_cbs); + if (cb_process_uploading_file) { + cb_process_uploading_file(imee, L_GET_C_BACK_PTR(message), 0, nullptr, nullptr, nullptr); + } + } +} + +static void _chat_message_process_response_from_post_file (void *data, const belle_http_response_event_t *event) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->processResponseFromPostFile(event); +} + +void FileTransferChatMessageModifier::processResponseFromPostFile (const belle_http_response_event_t *event) { + if (httpRequest && !isFileTransferInProgressAndValid()) { + releaseHttpRequest(); + return; + } + + shared_ptr message = chatMessage.lock(); + if (!message) + return; + + // check the answer code + if (event->response) { + int code = belle_http_response_get_status_code(event->response); + if (code == 204) { // this is the reply to the first post to the server - an empty msg + // start uploading the file + belle_sip_multipart_body_handler_t *bh; + string first_part_header; + belle_sip_body_handler_t *first_part_bh; + + bool is_file_encryption_enabled = false; + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); + if (imee && message->getChatRoom()) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsIsEncryptionEnabledForFileTransferCb is_encryption_enabled_for_file_transfer_cb = + linphone_im_encryption_engine_cbs_get_is_encryption_enabled_for_file_transfer(imee_cbs); + if (is_encryption_enabled_for_file_transfer_cb) { + is_file_encryption_enabled = !!is_encryption_enabled_for_file_transfer_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom())); + } + } + + FileTransferContent *fileTransferContent = new FileTransferContent(); + fileTransferContent->setContentType(ContentType::FileTransfer); + fileTransferContent->setFileSize(currentFileContentToTransfer->getFileSize()); // Copy file size information + message->getPrivate()->addContent(fileTransferContent); + + // shall we encrypt the file + if (is_file_encryption_enabled && message->getChatRoom()) { + // temporary storage for the Content-disposition header value : use a generic filename to not leak it + // Actual filename stored in msg->file_transfer_information->name will be set in encrypted msg + // sended to the + first_part_header = "form-data; name=\"File\"; filename=\"filename.txt\""; + + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsGenerateFileTransferKeyCb generate_file_transfer_key_cb = + linphone_im_encryption_engine_cbs_get_generate_file_transfer_key(imee_cbs); + if (generate_file_transfer_key_cb) { + generate_file_transfer_key_cb(imee, L_GET_C_BACK_PTR(message->getChatRoom()), L_GET_C_BACK_PTR(message)); + } + } else { + // temporary storage for the Content-disposition header value + first_part_header = "form-data; name=\"File\"; filename=\"" + currentFileContentToTransfer->getFileName() + "\""; + } + + // 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_body_handler_t *)belle_sip_user_body_handler_new(currentFileContentToTransfer->getFileSize(), + _chat_message_file_transfer_on_progress, nullptr, nullptr, + _chat_message_on_send_body, _chat_message_on_send_end, this); + if (!currentFileContentToTransfer->getFilePath().empty()) { + belle_sip_user_body_handler_t *body_handler = (belle_sip_user_body_handler_t *)first_part_bh; + // No need to add again the callback for progression, otherwise it will be called twice + first_part_bh = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(currentFileContentToTransfer->getFilePath().c_str(), nullptr, this); + belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)first_part_bh, body_handler); + // Ensure the file size has been set to the correct value + fileTransferContent->setFileSize(belle_sip_file_body_handler_get_file_size((belle_sip_file_body_handler_t *)first_part_bh)); + } else if (!currentFileContentToTransfer->isEmpty()) { + first_part_bh = (belle_sip_body_handler_t *)belle_sip_memory_body_handler_new_from_buffer( + ms_strdup(currentFileContentToTransfer->getBodyAsString().c_str()), + currentFileContentToTransfer->getSize(), _chat_message_file_transfer_on_progress, this); + } + + belle_sip_body_handler_add_header(first_part_bh, + belle_sip_header_create("Content-disposition", first_part_header.c_str())); + belle_sip_body_handler_add_header(first_part_bh, + (belle_sip_header_t *)belle_sip_header_content_type_create( + currentFileContentToTransfer->getContentType().getType().c_str(), + currentFileContentToTransfer->getContentType().getSubType().c_str())); + + // insert it in a multipart body handler which will manage the boundaries of multipart msg + bh = belle_sip_multipart_body_handler_new(_chat_message_file_transfer_on_progress, this, first_part_bh, nullptr); + + releaseHttpRequest(); + fileUploadBeginBackgroundTask(); + uploadFile(); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(httpRequest), BELLE_SIP_BODY_HANDLER(bh)); + } else if (code == 200) { // file has been uploaded correctly, get server reply and send it + FileTransferContent *fileTransferContent = nullptr; + for (Content *c : message->getPrivate()->getContents()) { + if (c->isFileTransfer()) { + FileTransferContent *tmpContent = static_cast(c); + if (!tmpContent->getFileContent() && tmpContent->getSize() == 0) { + // If FileTransferContent doesn't have a FileContent yet and is empty + // It's the one we seek, otherwise it may be a previous uploaded FileTransferContent + fileTransferContent = tmpContent; + break; + } + } + } + + const char *body = belle_sip_message_get_body((belle_sip_message_t *)event->response); + if (body && strlen(body) > 0) { + // if we have an encryption key for the file, we must insert it into the msg and restore the correct filename + const unsigned char *contentKey = reinterpret_cast(fileTransferContent->getFileKey().data()); + size_t contentKeySize = fileTransferContent->getFileKeySize(); + if (contentKeySize > 0) { + // parse the msg body + xmlDocPtr xmlMessageBody = xmlParseDoc((const xmlChar *)body); + + xmlNodePtr cur = xmlDocGetRootElement(xmlMessageBody); + if (cur != nullptr) { + cur = cur->xmlChildrenNode; + while (cur != nullptr) { + // we found a file info node, check it has a type="file" attribute + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { + xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); + // this is the node we are looking for : add a file-key children node + if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { + // need to parse the children node to update the file-name one + xmlNodePtr fileInfoNodeChildren = cur->xmlChildrenNode; + // convert key to base64 + size_t b64Size; + bctbx_base64_encode(nullptr, &b64Size, contentKey, contentKeySize); + unsigned char *keyb64 = (unsigned char *)ms_malloc0(b64Size + 1); + int xmlStringLength; + + bctbx_base64_encode(keyb64, &b64Size, contentKey, contentKeySize); + keyb64[b64Size] = '\0'; // libxml need a null terminated string + + // add the node containing the key to the file-info node + xmlNewTextChild(cur, nullptr, (const xmlChar *)"file-key", (const xmlChar *)keyb64); + xmlFree(typeAttribute); + ms_free(keyb64); + + // look for the file-name node and update its content + while (fileInfoNodeChildren != nullptr) { + // we found a the file-name node, update its content with the real filename + if (!xmlStrcmp(fileInfoNodeChildren->name, (const xmlChar *)"file-name")) { + // update node content + xmlNodeSetContent(fileInfoNodeChildren, (const xmlChar *)(currentFileContentToTransfer->getFileName().c_str())); + break; + } + fileInfoNodeChildren = fileInfoNodeChildren->next; + } + + // dump the xml into msg->message + char *buffer; + xmlDocDumpFormatMemoryEnc(xmlMessageBody, (xmlChar **)&buffer, &xmlStringLength, "UTF-8", 0); + fileTransferContent->setBody(buffer); + break; + } + xmlFree(typeAttribute); + } + cur = cur->next; + } + } + xmlFreeDoc(xmlMessageBody); + } else { // no encryption key, transfer in plain, just copy the msg sent by server + fileTransferContent->setBody(body); + } + + FileContent *fileContent = currentFileContentToTransfer; + fileTransferContent->setFileContent(fileContent); + + message->getPrivate()->removeContent(fileContent); + + message->getPrivate()->setState(ChatMessage::State::FileTransferDone); + releaseHttpRequest(); + message->getPrivate()->send(); + fileUploadEndBackgroundTask(); + } else { + lWarning() << "Received empty response from server, file transfer failed"; + FileTransferContent *fileTransferContent = nullptr; + for (Content *c : message->getPrivate()->getContents()) { + if (c->isFileTransfer()) { + fileTransferContent = static_cast(c); + message->getPrivate()->removeContent(fileTransferContent); + delete fileTransferContent; + break; + } + } + message->getPrivate()->setState(ChatMessage::State::NotDelivered); + releaseHttpRequest(); + fileUploadEndBackgroundTask(); + } + } else if (code == 400) { + lWarning() << "Received HTTP code response " << code << " for file transfer, probably meaning file is too large"; + FileTransferContent *fileTransferContent = nullptr; + for (Content *c : message->getPrivate()->getContents()) { + if (c->isFileTransfer()) { + fileTransferContent = static_cast(c); + message->getPrivate()->removeContent(fileTransferContent); + delete fileTransferContent; + break; + } + } + message->getPrivate()->setState(ChatMessage::State::FileTransferError); + releaseHttpRequest(); + fileUploadEndBackgroundTask(); + } else { + lWarning() << "Unhandled HTTP code response " << code << " for file transfer"; + FileTransferContent *fileTransferContent = nullptr; + for (Content *c : message->getPrivate()->getContents()) { + if (c->isFileTransfer()) { + fileTransferContent = static_cast(c); + message->getPrivate()->removeContent(fileTransferContent); + delete fileTransferContent; + break; + } + } + message->getPrivate()->setState(ChatMessage::State::NotDelivered); + releaseHttpRequest(); + fileUploadEndBackgroundTask(); + } + } +} + +static void _chat_message_process_io_error_upload (void *data, const belle_sip_io_error_event_t *event) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->processIoErrorUpload(event); +} + +void FileTransferChatMessageModifier::processIoErrorUpload (const belle_sip_io_error_event_t *event) { + lError() << "I/O Error during file upload of msg [" << this << "]"; + shared_ptr message = chatMessage.lock(); + if (!message) + return; + message->getPrivate()->setState(ChatMessage::State::NotDelivered); + releaseHttpRequest(); +} + +static void _chat_message_process_auth_requested_upload (void *data, belle_sip_auth_event *event) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->processAuthRequestedUpload(event); +} + +void FileTransferChatMessageModifier::processAuthRequestedUpload (const belle_sip_auth_event *event) { + lError() << "Error during file upload: auth requested for msg [" << this << "]"; + shared_ptr message = chatMessage.lock(); + if (!message) + return; + message->getPrivate()->setState(ChatMessage::State::NotDelivered); + releaseHttpRequest(); +} + +int FileTransferChatMessageModifier::uploadFile () { + if (httpRequest) { + lError() << "Unable to upload file: there is already an upload in progress."; + return -1; + } + + shared_ptr message = chatMessage.lock(); + if (!message) + return -1; + + // THIS IS ONLY FOR BACKWARD C API COMPAT + if (currentFileContentToTransfer->getFilePath().empty() && !message->getPrivate()->getFileTransferFilepath().empty()) { + currentFileContentToTransfer->setFilePath(message->getPrivate()->getFileTransferFilepath()); + } + + belle_http_request_listener_callbacks_t cbs = { 0 }; + cbs.process_response = _chat_message_process_response_from_post_file; + cbs.process_io_error = _chat_message_process_io_error_upload; + cbs.process_auth_requested = _chat_message_process_auth_requested_upload; + + const char *url = linphone_core_get_file_transfer_server(message->getCore()->getCCore()); + return startHttpTransfer(url ? url : "", "POST", &cbs); +} + +int FileTransferChatMessageModifier::startHttpTransfer (const string &url, const string &action, belle_http_request_listener_callbacks_t *cbs) { + belle_generic_uri_t *uri = nullptr; + + shared_ptr message = chatMessage.lock(); + if (!message) + return -1; + + if (url.empty()) { + lWarning() << "Cannot process file transfer msg [" << this << "]: no file remote URI configured."; + goto error; + } + uri = belle_generic_uri_parse(url.c_str()); + if (!uri || !belle_generic_uri_get_host(uri)) { + lWarning() << "Cannot process file transfer msg [" << this << "]: incorrect file remote URI configured '" << + url << "'."; + goto error; + } + + httpRequest = belle_http_request_create( + action.c_str(), + uri, + belle_sip_header_create("User-Agent", linphone_core_get_user_agent(message->getCore()->getCCore())), + nullptr + ); + + if (!httpRequest) { + lWarning() << "Could not create http request for uri " << url; + goto error; + } + // keep a reference to the http request to be able to cancel it during upload + belle_sip_object_ref(httpRequest); + + // give msg to listener to be able to start the actual file upload when server answer a 204 No content + httpListener = belle_http_request_listener_create_from_callbacks(cbs, this); + belle_http_provider_send_request(provider, httpRequest, httpListener); + return 0; + +error: + if (uri) { + belle_sip_object_unref(uri); + } + return -1; +} + +void FileTransferChatMessageModifier::fileUploadBeginBackgroundTask () { + shared_ptr message = chatMessage.lock(); + if (!message) + return; + bgTask.start(message->getCore()); +} + +void FileTransferChatMessageModifier::fileUploadEndBackgroundTask () { + bgTask.stop(); +} + +// ---------------------------------------------------------- + +static void fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml (FileTransferContent *fileTransferContent) { + xmlChar *fileUrl = nullptr; + xmlDocPtr xmlMessageBody; + xmlNodePtr cur; + /* parse the msg body to get all informations from it */ + xmlMessageBody = xmlParseDoc((const xmlChar *)fileTransferContent->getBodyAsString().c_str()); + + cur = xmlDocGetRootElement(xmlMessageBody); + if (cur) { + cur = cur->xmlChildrenNode; + while (cur) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { + /* we found a file info node, check if it has a type="file" attribute */ + xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); + if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */ + cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */ + while (cur) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) { + xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + size_t size = (size_t)strtol((const char *)fileSizeString, nullptr, 10); + fileTransferContent->setFileSize(size); + xmlFree(fileSizeString); + } + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-name")) { + xmlChar *filename = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + fileTransferContent->setFileName((char *)filename); + xmlFree(filename); + } + if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) { + fileUrl = xmlGetProp(cur, (const xmlChar *)"url"); + } + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { + // there is a key in the msg: file has been encrypted + // convert the key from base 64 + xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + size_t keyLength; + bctbx_base64_decode(NULL, &keyLength, (unsigned char *)keyb64, strlen((const char *)keyb64)); + uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); + // decode the key into local key buffer + bctbx_base64_decode(keyBuffer, &keyLength, (unsigned char *)keyb64, strlen((const char *)keyb64)); + fileTransferContent->setFileKey((const char *)keyBuffer, keyLength); + // duplicate key value into the linphone content private structure + xmlFree(keyb64); + free(keyBuffer); + } + + cur = cur->next; + } + xmlFree(typeAttribute); + break; + } + xmlFree(typeAttribute); + } + cur = cur->next; + } + } + xmlFreeDoc(xmlMessageBody); + + fileTransferContent->setFileUrl(fileUrl ? (const char *)fileUrl : ""); + + xmlFree(fileUrl); +} + +ChatMessageModifier::Result FileTransferChatMessageModifier::decode (const shared_ptr &message, int &errorCode) { + chatMessage = message; + + Content internalContent = message->getInternalContent(); + if (internalContent.getContentType() == ContentType::FileTransfer) { + FileTransferContent *fileTransferContent = new FileTransferContent(); + fileTransferContent->setContentType(internalContent.getContentType()); + fileTransferContent->setBody(internalContent.getBody()); + fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); + message->addContent(fileTransferContent); + return ChatMessageModifier::Result::Done; + } + + for (Content *content : message->getContents()) { + if (content->isFileTransfer()) { + FileTransferContent *fileTransferContent = static_cast(content); + fillFileTransferContentInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); + } + } + return ChatMessageModifier::Result::Done; +} + +// ---------------------------------------------------------- + +static void createFileTransferInformationsFromVndGsmaRcsFtHttpXml (FileTransferContent *fileTransferContent) { + xmlChar *fileUrl = nullptr; + xmlDocPtr xmlMessageBody; + xmlNodePtr cur; + /* parse the msg body to get all informations from it */ + xmlMessageBody = xmlParseDoc((const xmlChar *)fileTransferContent->getBodyAsString().c_str()); + FileContent *fileContent = new FileContent(); + + cur = xmlDocGetRootElement(xmlMessageBody); + if (cur) { + cur = cur->xmlChildrenNode; + while (cur) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-info")) { + /* we found a file info node, check if it has a type="file" attribute */ + xmlChar *typeAttribute = xmlGetProp(cur, (const xmlChar *)"type"); + if (!xmlStrcmp(typeAttribute, (const xmlChar *)"file")) { /* this is the node we are looking for */ + cur = cur->xmlChildrenNode; /* now loop on the content of the file-info node */ + while (cur) { + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-size")) { + xmlChar *fileSizeString = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + size_t size = (size_t)strtol((const char *)fileSizeString, nullptr, 10); + fileContent->setFileSize(size); + xmlFree(fileSizeString); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-name")) { + xmlChar *filename = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + fileContent->setFileName((char *)filename); + + xmlFree(filename); + } + if (!xmlStrcmp(cur->name, (const xmlChar *)"content-type")) { + xmlChar *content_type = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + int contentTypeIndex = 0; + char *type; + char *subtype; + while (content_type[contentTypeIndex] != '/' && content_type[contentTypeIndex] != '\0') { + contentTypeIndex++; + } + type = ms_strndup((char *)content_type, contentTypeIndex); + subtype = ms_strdup(((char *)content_type + contentTypeIndex + 1)); + ContentType contentType(type, subtype); + fileContent->setContentType(contentType); + ms_free(subtype); + ms_free(type); + ms_free(content_type); + } + if (!xmlStrcmp(cur->name, (const xmlChar *)"data")) { + fileUrl = xmlGetProp(cur, (const xmlChar *)"url"); + } + + if (!xmlStrcmp(cur->name, (const xmlChar *)"file-key")) { + // there is a key in the msg: file has been encrypted + // convert the key from base 64 + xmlChar *keyb64 = xmlNodeListGetString(xmlMessageBody, cur->xmlChildrenNode, 1); + size_t keyLength; + bctbx_base64_decode(NULL, &keyLength, (unsigned char *)keyb64, strlen((const char *)keyb64)); + uint8_t *keyBuffer = (uint8_t *)malloc(keyLength); + // decode the key into local key buffer + bctbx_base64_decode(keyBuffer, &keyLength, (unsigned char *)keyb64, strlen((const char *)keyb64)); + fileTransferContent->setFileKey((const char *)keyBuffer, keyLength); + // duplicate key value into the linphone content private structure + xmlFree(keyb64); + free(keyBuffer); + } + + cur = cur->next; + } + xmlFree(typeAttribute); + break; + } + xmlFree(typeAttribute); + } + cur = cur->next; + } + } + xmlFreeDoc(xmlMessageBody); + + fileContent->setFilePath(fileTransferContent->getFilePath()); // Copy file path from file transfer content to file content for file body handler + // Link the FileContent to the FileTransferContent + fileTransferContent->setFileContent(fileContent); + + xmlFree(fileUrl); +} + +static void _chat_message_on_recv_body (belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, void *data, size_t offset, uint8_t *buffer, size_t size) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->onRecvBody(bh, m, offset, buffer, size); +} + +void FileTransferChatMessageModifier::onRecvBody (belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, size_t offset, uint8_t *buffer, size_t size) { + if (!httpRequest || belle_http_request_is_cancelled(httpRequest)) { + lWarning() << "Cancelled request for msg [" << this << "], ignoring " << __FUNCTION__; + return; + } + + // first call may be with a zero size, ignore it + if (size == 0) { + return; + } + + shared_ptr message = chatMessage.lock(); + if (!message) + return; + + int retval = -1; + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs); + if (cb_process_downloading_file) { + uint8_t *decrypted_buffer = (uint8_t *)ms_malloc0(size); + retval = cb_process_downloading_file(imee, L_GET_C_BACK_PTR(message), offset, (const uint8_t *)buffer, size, decrypted_buffer); + if (retval == 0) { + memcpy(buffer, decrypted_buffer, size); + } + ms_free(decrypted_buffer); + } + } + + if (retval <= 0) { + if (currentFileContentToTransfer->getFilePath().empty()) { + LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { + LinphoneBuffer *lb = linphone_buffer_new_from_data(buffer, size); + linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); + linphone_buffer_unref(lb); + } else { + // Legacy: call back given by application level + linphone_core_notify_file_transfer_recv(message->getCore()->getCCore(), msg, content, (const char *)buffer, size); + } + } + } else { + lWarning() << "File transfer decrypt failed with code " << (int)retval; + message->getPrivate()->setState(ChatMessage::State::FileTransferError); + } +} + +static void _chat_message_on_recv_end (belle_sip_user_body_handler_t *bh, void *data) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->onRecvEnd(bh); +} + +void FileTransferChatMessageModifier::onRecvEnd (belle_sip_user_body_handler_t *bh) { + shared_ptr message = chatMessage.lock(); + if (!message) + return; + + int retval = -1; + LinphoneImEncryptionEngine *imee = linphone_core_get_im_encryption_engine(message->getCore()->getCCore()); + if (imee) { + LinphoneImEncryptionEngineCbs *imee_cbs = linphone_im_encryption_engine_get_callbacks(imee); + LinphoneImEncryptionEngineCbsDownloadingFileCb cb_process_downloading_file = linphone_im_encryption_engine_cbs_get_process_downloading_file(imee_cbs); + if (cb_process_downloading_file) { + retval = cb_process_downloading_file(imee, L_GET_C_BACK_PTR(message), 0, nullptr, 0, nullptr); + } + } + + if (retval <= 0) { + if (currentFileContentToTransfer->getFilePath().empty()) { + LinphoneChatMessage *msg = L_GET_C_BACK_PTR(message); + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + LinphoneContent *content = L_GET_C_BACK_PTR((Content *)currentFileContentToTransfer); + if (linphone_chat_message_cbs_get_file_transfer_recv(cbs)) { + LinphoneBuffer *lb = linphone_buffer_new(); + linphone_chat_message_cbs_get_file_transfer_recv(cbs)(msg, content, lb); + linphone_buffer_unref(lb); + } else { + // Legacy: call back given by application level + linphone_core_notify_file_transfer_recv(message->getCore()->getCCore(), msg, content, nullptr, 0); + } + } + } + + if (retval <= 0 && message->getState() != ChatMessage::State::FileTransferError) { + // Remove the FileTransferContent from the message and store the FileContent + FileContent *fileContent = currentFileContentToTransfer; + message->getPrivate()->addContent(fileContent); + for (Content *content : message->getContents()) { + if (content->isFileTransfer()) { + FileTransferContent *fileTransferContent = static_cast(content); + if (fileTransferContent->getFileContent() == fileContent) { + message->getPrivate()->removeContent(content); + delete fileTransferContent; + break; + } + } + } + message->getPrivate()->setState(ChatMessage::State::FileTransferDone); + } +} + +static void _chat_process_response_headers_from_get_file (void *data, const belle_http_response_event_t *event) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->processResponseHeadersFromGetFile(event); +} + +static FileContent* createFileTransferInformationFromHeaders (const belle_sip_message_t *m) { + FileContent *fileContent = new FileContent(); + + belle_sip_header_content_length_t *content_length_hdr = BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(m, "Content-Length")); + belle_sip_header_content_type_t *content_type_hdr = BELLE_SIP_HEADER_CONTENT_TYPE(belle_sip_message_get_header(m, "Content-Type")); + + if (content_type_hdr) { + const char *type = belle_sip_header_content_type_get_type(content_type_hdr); + const char *subtype = belle_sip_header_content_type_get_subtype(content_type_hdr); + lInfo() << "Extracted content type " << type << " / " << subtype << " from header"; + ContentType contentType(type, subtype); + fileContent->setContentType(contentType); + } + if (content_length_hdr) { + fileContent->setFileSize(belle_sip_header_content_length_get_content_length(content_length_hdr)); + lInfo() << "Extracted content length " << fileContent->getFileSize() << " from header"; + } + + return fileContent; +} + +void FileTransferChatMessageModifier::processResponseHeadersFromGetFile (const belle_http_response_event_t *event) { + if (event->response) { + // we are receiving a response, set a specific body handler to acquire the response. + // if not done, belle-sip will create a memory body handler, the default + belle_sip_message_t *response = BELLE_SIP_MESSAGE(event->response); + + shared_ptr message = chatMessage.lock(); + if (!message) + return; + + if (currentFileContentToTransfer) { + belle_sip_header_content_length_t *content_length_hdr = BELLE_SIP_HEADER_CONTENT_LENGTH(belle_sip_message_get_header(response, "Content-Length")); + currentFileContentToTransfer->setFileSize(belle_sip_header_content_length_get_content_length(content_length_hdr)); + lInfo() << "Extracted content length " << currentFileContentToTransfer->getFileSize() << " from header"; + } else { + lWarning() << "No file transfer information for msg [" << this << "]: creating..."; + FileContent *content = createFileTransferInformationFromHeaders(response); + message->addContent(content); + } + + size_t body_size = 0; + if (currentFileContentToTransfer) + body_size = currentFileContentToTransfer->getFileSize(); + + belle_sip_body_handler_t *body_handler = (belle_sip_body_handler_t *)belle_sip_user_body_handler_new( + body_size, _chat_message_file_transfer_on_progress, + nullptr, _chat_message_on_recv_body, + nullptr, _chat_message_on_recv_end, this + ); + if (!currentFileContentToTransfer->getFilePath().empty()) { + belle_sip_user_body_handler_t *bh = (belle_sip_user_body_handler_t *)body_handler; + body_handler = (belle_sip_body_handler_t *)belle_sip_file_body_handler_new(currentFileContentToTransfer->getFilePath().c_str(), _chat_message_file_transfer_on_progress, this); + if (belle_sip_body_handler_get_size((belle_sip_body_handler_t *)body_handler) == 0) { + // If the size of the body has not been initialized from the file stat, use the one from the + // file_transfer_information. + belle_sip_body_handler_set_size((belle_sip_body_handler_t *)body_handler, body_size); + } + belle_sip_file_body_handler_set_user_body_handler((belle_sip_file_body_handler_t *)body_handler, bh); + } + belle_sip_message_set_body_handler((belle_sip_message_t *)event->response, body_handler); + } +} + +static void _chat_message_process_auth_requested_download (void *data, belle_sip_auth_event *event) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->processAuthRequestedDownload(event); +} + +void FileTransferChatMessageModifier::processAuthRequestedDownload (const belle_sip_auth_event *event) { + lError() << "Error during file download : auth requested for msg [" << this << "]"; + shared_ptr message = chatMessage.lock(); + if (!message) + return; + message->getPrivate()->setState(ChatMessage::State::FileTransferError); + releaseHttpRequest(); +} + +static void _chat_message_process_io_error_download (void *data, const belle_sip_io_error_event_t *event) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->processIoErrorDownload(event); +} + +void FileTransferChatMessageModifier::processIoErrorDownload (const belle_sip_io_error_event_t *event) { + lError() << "I/O Error during file download msg [" << this << "]"; + shared_ptr message = chatMessage.lock(); + if (!message) + return; + message->getPrivate()->setState(ChatMessage::State::FileTransferError); + releaseHttpRequest(); +} + +static void _chat_message_process_response_from_get_file (void *data, const belle_http_response_event_t *event) { + FileTransferChatMessageModifier *d = (FileTransferChatMessageModifier *)data; + d->processResponseFromGetFile(event); +} + +void FileTransferChatMessageModifier::processResponseFromGetFile (const belle_http_response_event_t *event) { + // check the answer code + if (event->response) { + shared_ptr message = chatMessage.lock(); + if (!message) + return; + + int code = belle_http_response_get_status_code(event->response); + if (code >= 400 && code < 500) { + lWarning() << "File transfer failed with code " << code; + message->getPrivate()->setState(ChatMessage::State::FileTransferError); + } else if (code != 200) { + lWarning() << "Unhandled HTTP code response " << code << " for file transfer"; + } + releaseHttpRequest(); + } +} + +bool FileTransferChatMessageModifier::downloadFile ( + const shared_ptr &message, + FileTransferContent *fileTransferContent +) { + chatMessage = message; + + if (httpRequest) { + lError() << "There is already a download in progress."; + return false; + } + + if (fileTransferContent->getContentType() != ContentType::FileTransfer) { + lError() << "Content type is not a FileTransfer."; + return false; + } + + createFileTransferInformationsFromVndGsmaRcsFtHttpXml(fileTransferContent); + FileContent *fileContent = fileTransferContent->getFileContent(); + currentFileContentToTransfer = fileContent; + if (!currentFileContentToTransfer) + return false; + + // THIS IS ONLY FOR BACKWARD C API COMPAT + if (currentFileContentToTransfer->getFilePath().empty() && !message->getPrivate()->getFileTransferFilepath().empty()) { + currentFileContentToTransfer->setFilePath(message->getPrivate()->getFileTransferFilepath()); + } + + belle_http_request_listener_callbacks_t cbs = { 0 }; + cbs.process_response_headers = _chat_process_response_headers_from_get_file; + cbs.process_response = _chat_message_process_response_from_get_file; + cbs.process_io_error = _chat_message_process_io_error_download; + cbs.process_auth_requested = _chat_message_process_auth_requested_download; + int err = startHttpTransfer(fileTransferContent->getFileUrl(), "GET", &cbs); // File URL has been set by createFileTransferInformationsFromVndGsmaRcsFtHttpXml + if (err == -1) + return false; + // start the download, status is In Progress + message->getPrivate()->setState(ChatMessage::State::InProgress); + return true; +} + +// ---------------------------------------------------------- + +void FileTransferChatMessageModifier::cancelFileTransfer () { + if (!httpRequest) { + lInfo() << "No existing file transfer - nothing to cancel"; + return; + } + + if (!belle_http_request_is_cancelled(httpRequest)) { + shared_ptr message = chatMessage.lock(); + if (message) { + lInfo() << "Canceling file transfer " << ( + currentFileContentToTransfer->getFilePath().empty() + ? L_C_TO_STRING(linphone_core_get_file_transfer_server(message->getCore()->getCCore())) + : currentFileContentToTransfer->getFilePath().c_str() + ); + + } else { + lInfo() << "Warning: http request still running for ORPHAN msg: this is a memory leak"; + } + belle_http_provider_cancel_request(provider, httpRequest); + } + releaseHttpRequest(); +} + +bool FileTransferChatMessageModifier::isFileTransferInProgressAndValid () { + return httpRequest && !belle_http_request_is_cancelled(httpRequest); +} + +void FileTransferChatMessageModifier::releaseHttpRequest () { + if (httpRequest) { + belle_sip_object_unref(httpRequest); + httpRequest = nullptr; + if (httpListener) { + belle_sip_object_unref(httpListener); + httpListener = nullptr; + } + } +} + +string FileTransferChatMessageModifier::createFakeFileTransferFromUrl (const string &url) { + string fileName = url.substr(url.find_last_of("/") + 1); + stringstream fakeXml; + fakeXml << "\r\n"; + fakeXml << "\r\n"; + fakeXml << "\r\n"; + fakeXml << "" << fileName << "\r\n"; + fakeXml << "application/binary\r\n"; + fakeXml << "\r\n"; + fakeXml << "\r\n"; + fakeXml << ""; + return fakeXml.str(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.h b/src/chat/modifier/file-transfer-chat-message-modifier.h new file mode 100644 index 000000000..d2dde9b7d --- /dev/null +++ b/src/chat/modifier/file-transfer-chat-message-modifier.h @@ -0,0 +1,88 @@ +/* + * file-transfer-chat-message-modifier.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_FILE_TRANSFER_CHAT_MESSAGE_MODIFIER_H_ +#define _L_FILE_TRANSFER_CHAT_MESSAGE_MODIFIER_H_ + +#include + +#include "chat-message-modifier.h" +#include "utils/background-task.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoom; +class Core; +class FileContent; +class FileTransferContent; + +class FileTransferChatMessageModifier : public ChatMessageModifier { +public: + FileTransferChatMessageModifier (belle_http_provider_t *prov); + ~FileTransferChatMessageModifier (); + + Result encode (const std::shared_ptr &message, int &errorCode) override; + Result decode (const std::shared_ptr &message, int &errorCode) override; + + belle_http_request_t *getHttpRequest() const; + void setHttpRequest(belle_http_request_t *request); + + int onSendBody (belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, size_t offset, uint8_t *buffer, size_t *size); + void onSendEnd (belle_sip_user_body_handler_t *bh); + void fileUploadBackgroundTaskEnded(); + void fileTransferOnProgress (belle_sip_body_handler_t *bh, belle_sip_message_t *m, size_t offset, size_t total); + void processResponseFromPostFile (const belle_http_response_event_t *event); + void processIoErrorUpload (const belle_sip_io_error_event_t *event); + void processAuthRequestedUpload (const belle_sip_auth_event *event); + + void onRecvBody (belle_sip_user_body_handler_t *bh, belle_sip_message_t *m, size_t offset, uint8_t *buffer, size_t size); + void onRecvEnd (belle_sip_user_body_handler_t *bh); + void processResponseHeadersFromGetFile (const belle_http_response_event_t *event); + void processAuthRequestedDownload (const belle_sip_auth_event *event); + void processIoErrorDownload (const belle_sip_io_error_event_t *event); + void processResponseFromGetFile (const belle_http_response_event_t *event); + + bool downloadFile (const std::shared_ptr &message, FileTransferContent *fileTransferContent); + void cancelFileTransfer (); + bool isFileTransferInProgressAndValid (); + std::string createFakeFileTransferFromUrl (const std::string &url); + +private: + int uploadFile (); + int startHttpTransfer (const std::string &url, const std::string &action, belle_http_request_listener_callbacks_t *cbs); + void fileUploadBeginBackgroundTask (); + void fileUploadEndBackgroundTask (); + + void releaseHttpRequest (); + + std::weak_ptr chatMessage; + FileContent* currentFileContentToTransfer = nullptr; + + belle_http_request_t *httpRequest = nullptr; + belle_http_request_listener_t *httpListener = nullptr; + belle_http_provider_t *provider = nullptr; + + BackgroundTask bgTask; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_FILE_TRANSFER_CHAT_MESSAGE_MODIFIER_H_ diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp new file mode 100644 index 000000000..8ed8312d9 --- /dev/null +++ b/src/chat/modifier/multipart-chat-message-modifier.cpp @@ -0,0 +1,73 @@ +/* + * multipart-chat-message-modifier.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// TODO: Remove me later. +#include "private.h" + +#include "chat/chat-message/chat-message.h" +#include "content/content-type.h" +#include "content/header/header.h" +#include "content/content-manager.h" +#include "content/file-transfer-content.h" + +#include "multipart-chat-message-modifier.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +ChatMessageModifier::Result MultipartChatMessageModifier::encode ( + const shared_ptr &message, + int &errorCode +) { + if (message->getContents().size() <= 1) + return ChatMessageModifier::Result::Skipped; + + Content content = ContentManager::contentListToMultipart(message->getContents()); + message->setInternalContent(content); + + return ChatMessageModifier::Result::Done; +} + +ChatMessageModifier::Result MultipartChatMessageModifier::decode (const shared_ptr &message, int &errorCode) { + if (message->getInternalContent().getContentType().isMultipart()) { + for (Content &c : ContentManager::multipartToContentList(message->getInternalContent())) { + Content *content; + if (c.getContentType() == ContentType::FileTransfer) { + content = new FileTransferContent(); + content->setContentType(c.getContentType()); + content->setContentDisposition(c.getContentDisposition()); + content->setContentEncoding(c.getContentEncoding()); + for (const Header &header : c.getHeaders()) { + content->addHeader(header); + } + content->setBodyFromUtf8(c.getBodyAsUtf8String()); + } else { + content = new Content(c); + } + message->addContent(content); + } + return ChatMessageModifier::Result::Done; + } + return ChatMessageModifier::Result::Skipped; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/modifier/multipart-chat-message-modifier.h b/src/chat/modifier/multipart-chat-message-modifier.h new file mode 100644 index 000000000..e892c31a8 --- /dev/null +++ b/src/chat/modifier/multipart-chat-message-modifier.h @@ -0,0 +1,39 @@ +/* + * multipart-chat-message-modifier.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MULTIPART_CHAT_MESSAGE_MODIFIER_H_ +#define _L_MULTIPART_CHAT_MESSAGE_MODIFIER_H_ + +#include "chat-message-modifier.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class MultipartChatMessageModifier : public ChatMessageModifier { +public: + MultipartChatMessageModifier () = default; + + Result encode (const std::shared_ptr &message, int &errorCode) override; + Result decode (const std::shared_ptr &message, int &errorCode) override; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MULTIPART_CHAT_MESSAGE_MODIFIER_H_ diff --git a/src/chat/notification/imdn.cpp b/src/chat/notification/imdn.cpp new file mode 100644 index 000000000..41f189857 --- /dev/null +++ b/src/chat/notification/imdn.cpp @@ -0,0 +1,258 @@ +/* + * imdn.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "chat/chat-message/imdn-message-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "core/core-p.h" +#include "logger/logger.h" +#include "xml/imdn.h" +#include "xml/linphone-imdn.h" + +#include "imdn.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +Imdn::Imdn (ChatRoom *chatRoom) : chatRoom(chatRoom) { + chatRoom->getCore()->getPrivate()->registerListener(this); +} + +Imdn::~Imdn () { + stopTimer(); + chatRoom->getCore()->getPrivate()->unregisterListener(this); +} + +// ----------------------------------------------------------------------------- + +int Imdn::getDisplayNotificationCount () const { + return static_cast(displayedMessages.size()); +} + +// ----------------------------------------------------------------------------- + +void Imdn::notifyDelivery (const shared_ptr &message) { + if (find(deliveredMessages.begin(), deliveredMessages.end(), message) == deliveredMessages.end()) { + deliveredMessages.push_back(message); + startTimer(); + } +} + +void Imdn::notifyDeliveryError (const shared_ptr &message, LinphoneReason reason) { + auto it = find_if(nonDeliveredMessages.begin(), nonDeliveredMessages.end(), [message](const MessageReason mr) { + return message == mr.message; + }); + if (it == nonDeliveredMessages.end()) { + nonDeliveredMessages.emplace_back(message, reason); + startTimer(); + } +} + +void Imdn::notifyDisplay (const shared_ptr &message) { + auto it = find(deliveredMessages.begin(), deliveredMessages.end(), message); + if (it != deliveredMessages.end()) + deliveredMessages.erase(it); + + if (find(displayedMessages.begin(), displayedMessages.end(), message) == displayedMessages.end()) { + displayedMessages.push_back(message); + startTimer(); + } +} + +// ----------------------------------------------------------------------------- + +void Imdn::onImdnMessageDelivered (const std::shared_ptr &message) { + // If an IMDN has been successfully delivered, remove it from the list so that + // it does not get sent again + auto context = message->getPrivate()->getContext(); + for (const auto &deliveredMsg : context.deliveredMessages) + deliveredMessages.remove(deliveredMsg); + + for (const auto &displayedMsg : context.displayedMessages) + displayedMessages.remove(displayedMsg); + + for (const auto &nonDeliveredMsg : context.nonDeliveredMessages) + nonDeliveredMessages.remove(nonDeliveredMsg); + + sentImdnMessages.remove(message); +} + +// ----------------------------------------------------------------------------- + +void Imdn::onGlobalStateChanged (LinphoneGlobalState state) { + if (state == LinphoneGlobalShutdown) { + auto ref = chatRoom->getSharedFromThis(); + deliveredMessages.clear(); + displayedMessages.clear(); + nonDeliveredMessages.clear(); + sentImdnMessages.clear(); + } +} + +void Imdn::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + if (sipNetworkReachable) { + // When the SIP network gets up, retry notification + sentImdnMessages.clear(); + send(); + } +} + +// ----------------------------------------------------------------------------- + +string Imdn::createXml (const string &id, time_t timestamp, Imdn::Type imdnType, LinphoneReason reason) { + char *datetime = linphone_timestamp_to_rfc3339_string(timestamp); + Xsd::Imdn::Imdn imdn(id, datetime); + ms_free(datetime); + bool needLinphoneImdnNamespace = false; + if (imdnType == Imdn::Type::Delivery) { + Xsd::Imdn::Status status; + if (reason == LinphoneReasonNone) { + auto delivered = Xsd::Imdn::Delivered(); + status.setDelivered(delivered); + } else { + auto failed = Xsd::Imdn::Failed(); + status.setFailed(failed); + Xsd::LinphoneImdn::ImdnReason imdnReason(linphone_reason_to_string(reason)); + imdnReason.setCode(linphone_reason_to_error_code(reason)); + status.setReason(imdnReason); + needLinphoneImdnNamespace = true; + } + Xsd::Imdn::DeliveryNotification deliveryNotification(status); + imdn.setDeliveryNotification(deliveryNotification); + } else if (imdnType == Imdn::Type::Display) { + Xsd::Imdn::Status1 status; + auto displayed = Xsd::Imdn::Displayed(); + status.setDisplayed(displayed); + Xsd::Imdn::DisplayNotification displayNotification(status); + imdn.setDisplayNotification(displayNotification); + } + + stringstream ss; + Xsd::XmlSchema::NamespaceInfomap map; + map[""].name = "urn:ietf:params:xml:ns:imdn"; + if (needLinphoneImdnNamespace) + map["imdn"].name = "http://www.linphone.org/xsds/imdn.xsd"; + Xsd::Imdn::serializeImdn(ss, imdn, map, "UTF-8", Xsd::XmlSchema::Flags::dont_pretty_print); + return ss.str(); +} + +void Imdn::parse (const shared_ptr &chatMessage) { + shared_ptr cr = chatMessage->getChatRoom(); + for (const auto &content : chatMessage->getPrivate()->getContents()) { + istringstream data(content->getBodyAsString()); + unique_ptr imdn(Xsd::Imdn::parseImdn(data, Xsd::XmlSchema::Flags::dont_validate)); + if (!imdn) + continue; + shared_ptr cm = cr->findChatMessage(imdn->getMessageId()); + if (!cm) { + lWarning() << "Received IMDN for unknown message " << imdn->getMessageId(); + } else { + auto policy = linphone_core_get_im_notif_policy(cr->getCore()->getCCore()); + time_t imdnTime = chatMessage->getTime(); + const IdentityAddress &participantAddress = chatMessage->getFromAddress().getAddressWithoutGruu(); + auto &deliveryNotification = imdn->getDeliveryNotification(); + auto &displayNotification = imdn->getDisplayNotification(); + if (deliveryNotification.present()) { + auto &status = deliveryNotification.get().getStatus(); + if (status.getDelivered().present() && linphone_im_notif_policy_get_recv_imdn_delivered(policy)) + cm->getPrivate()->setParticipantState(participantAddress, ChatMessage::State::DeliveredToUser, imdnTime); + else if ((status.getFailed().present() || status.getError().present()) + && linphone_im_notif_policy_get_recv_imdn_delivered(policy) + ) + cm->getPrivate()->setParticipantState(participantAddress, ChatMessage::State::NotDelivered, imdnTime); + } else if (displayNotification.present()) { + auto &status = displayNotification.get().getStatus(); + if (status.getDisplayed().present() && linphone_im_notif_policy_get_recv_imdn_displayed(policy)) + cm->getPrivate()->setParticipantState(participantAddress, ChatMessage::State::Displayed, imdnTime); + } + } + } +} + +// ----------------------------------------------------------------------------- + +int Imdn::timerExpired (void *data, unsigned int revents) { + Imdn *d = reinterpret_cast(data); + d->stopTimer(); + d->send(); + return BELLE_SIP_STOP; +} + +// ----------------------------------------------------------------------------- + +bool Imdn::aggregationEnabled () const { + auto config = linphone_core_get_config(chatRoom->getCore()->getCCore()); + return (chatRoom->canHandleCpim() && linphone_config_get_bool(config, "misc", "aggregate_imdn", TRUE)); +} + +void Imdn::send () { + if (!linphone_core_is_network_reachable(chatRoom->getCore()->getCCore())) + return; + + if (!deliveredMessages.empty() || !displayedMessages.empty()) { + auto imdnMessage = chatRoom->getPrivate()->createImdnMessage(deliveredMessages, displayedMessages); + sentImdnMessages.push_back(imdnMessage); + imdnMessage->getPrivate()->send(); + if (!aggregationEnabled()) { + deliveredMessages.clear(); + displayedMessages.clear(); + } + } + if (!nonDeliveredMessages.empty()) { + auto imdnMessage = chatRoom->getPrivate()->createImdnMessage(nonDeliveredMessages); + sentImdnMessages.push_back(imdnMessage); + imdnMessage->getPrivate()->send(); + if (!aggregationEnabled()) + nonDeliveredMessages.clear(); + } +} + +void Imdn::startTimer () { + if (!aggregationEnabled()) { + // Compatibility mode for basic chat rooms, do not aggregate notifications + send(); + return; + } + + unsigned int duration = 500; + if (!timer) + timer = chatRoom->getCore()->getCCore()->sal->createTimer(timerExpired, this, duration, "imdn timeout"); + else + belle_sip_source_set_timeout(timer, duration); + bgTask.start(chatRoom->getCore(), 1); +} + +void Imdn::stopTimer () { + if (timer) { + auto core = chatRoom->getCore()->getCCore(); + if (core && core->sal) + core->sal->cancelTimer(timer); + belle_sip_object_unref(timer); + timer = nullptr; + } + bgTask.stop(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/notification/imdn.h b/src/chat/notification/imdn.h new file mode 100644 index 000000000..fd765b040 --- /dev/null +++ b/src/chat/notification/imdn.h @@ -0,0 +1,96 @@ +/* + * imdn.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_IMDN_H_ +#define _L_IMDN_H_ + +#include "linphone/utils/general.h" + +#include "core/core-listener.h" +#include "utils/background-task.h" + +#include "private.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatMessage; +class ChatRoom; +class ImdnMessage; + +class Imdn : public CoreListener { +public: + enum class Type { + Delivery, + Display + }; + + struct MessageReason { + MessageReason (const std::shared_ptr &message, LinphoneReason reason) + : message(message), reason(reason) {} + + bool operator== (const MessageReason &other) const { + return (message == other.message) && (reason == other.reason); + } + + const std::shared_ptr message; + LinphoneReason reason; + }; + + Imdn (ChatRoom *chatRoom); + ~Imdn (); + + int getDisplayNotificationCount () const; + + void notifyDelivery (const std::shared_ptr &message); + void notifyDeliveryError (const std::shared_ptr &message, LinphoneReason reason); + void notifyDisplay (const std::shared_ptr &message); + + void onImdnMessageDelivered (const std::shared_ptr &message); + + // CoreListener + void onGlobalStateChanged (LinphoneGlobalState state) override; + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; + + bool aggregationEnabled () const; + + static std::string createXml (const std::string &id, time_t time, Imdn::Type imdnType, LinphoneReason reason); + static void parse (const std::shared_ptr &chatMessage); + +private: + static int timerExpired (void *data, unsigned int revents); + + void send (); + void startTimer (); + void stopTimer (); + +private: + ChatRoom *chatRoom = nullptr; + std::list> deliveredMessages; + std::list> displayedMessages; + std::list nonDeliveredMessages; + std::list> sentImdnMessages; + belle_sip_source_t *timer = nullptr; + BackgroundTask bgTask { "IMDN sending" }; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_IMDN_H_ diff --git a/src/chat/notification/is-composing-listener.h b/src/chat/notification/is-composing-listener.h new file mode 100644 index 000000000..9cf52d453 --- /dev/null +++ b/src/chat/notification/is-composing-listener.h @@ -0,0 +1,42 @@ +/* + * is-composing-listener.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_IS_COMPOSING_LISTENER_H_ +#define _L_IS_COMPOSING_LISTENER_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Address; + +class IsComposingListener { +public: + virtual ~IsComposingListener() = default; + + virtual void onIsComposingStateChanged (bool isComposing) = 0; + virtual void onIsRemoteComposingStateChanged (const Address &remoteAddr, bool isComposing) = 0; + virtual void onIsComposingRefreshNeeded () = 0; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_IS_COMPOSING_LISTENER_H_ diff --git a/src/chat/notification/is-composing.cpp b/src/chat/notification/is-composing.cpp new file mode 100644 index 000000000..343bf53d9 --- /dev/null +++ b/src/chat/notification/is-composing.cpp @@ -0,0 +1,218 @@ +/* + * is-composing.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/utils.h" + +#include "chat/chat-room/chat-room-p.h" +#include "chat/notification/is-composing.h" +#include "logger/logger.h" +#include "xml/is-composing.h" + + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +struct IsRemoteComposingData { + IsRemoteComposingData (IsComposing *isComposingHandler, string uri) + : isComposingHandler(isComposingHandler), uri(uri) {} + + IsComposing *isComposingHandler; + string uri; +}; + +// ----------------------------------------------------------------------------- + +IsComposing::IsComposing (LinphoneCore *core, IsComposingListener *listener) + : core(core), listener(listener) {} + +IsComposing::~IsComposing () { + stopTimers(); +} + +// ----------------------------------------------------------------------------- + +string IsComposing::createXml (bool isComposing) { + Xsd::IsComposing::IsComposing node(isComposing ? "active" : "idle"); + if (isComposing) + node.setRefresh(static_cast(lp_config_get_int(core->config, "sip", "composing_refresh_timeout", defaultRefreshTimeout))); + + stringstream ss; + Xsd::XmlSchema::NamespaceInfomap map; + map[""].name = "urn:ietf:params:xml:ns:im-iscomposing"; + Xsd::IsComposing::serializeIsComposing(ss, node, map, "UTF-8", Xsd::XmlSchema::Flags::dont_pretty_print); + return ss.str(); +} + +void IsComposing::parse (const Address &remoteAddr, const string &text) { + istringstream data(text); + unique_ptr node(Xsd::IsComposing::parseIsComposing(data, Xsd::XmlSchema::Flags::dont_validate)); + if (!node) + return; + + if (node->getState() == "active") { + unsigned long long refresh = 0; + if (node->getRefresh().present()) + refresh = node->getRefresh().get(); + startRemoteRefreshTimer(remoteAddr.asStringUriOnly(), refresh); + listener->onIsRemoteComposingStateChanged(remoteAddr, true); + } else if (node->getState() == "idle") { + stopRemoteRefreshTimer(remoteAddr.asStringUriOnly()); + listener->onIsRemoteComposingStateChanged(remoteAddr, false); + } +} + +void IsComposing::startIdleTimer () { + unsigned int duration = getIdleTimerDuration(); + if (!idleTimer) { + idleTimer = core->sal->createTimer(idleTimerExpired, this, + duration * 1000, "composing idle timeout"); + } else { + belle_sip_source_set_timeout(idleTimer, duration * 1000); + } +} + +void IsComposing::startRefreshTimer () { + unsigned int duration = getRefreshTimerDuration(); + if (!refreshTimer) { + refreshTimer = core->sal->createTimer(refreshTimerExpired, this, + duration * 1000, "composing refresh timeout"); + } else { + belle_sip_source_set_timeout(refreshTimer, duration * 1000); + } +} + +void IsComposing::stopTimers () { + stopIdleTimer(); + stopRefreshTimer(); + stopAllRemoteRefreshTimers(); +} + +// ----------------------------------------------------------------------------- + +void IsComposing::stopIdleTimer () { + if (idleTimer) { + if (core && core->sal) + core->sal->cancelTimer(idleTimer); + belle_sip_object_unref(idleTimer); + idleTimer = nullptr; + } +} + +void IsComposing::stopRefreshTimer () { + if (refreshTimer) { + if (core && core->sal) + core->sal->cancelTimer(refreshTimer); + belle_sip_object_unref(refreshTimer); + refreshTimer = nullptr; + } +} + +void IsComposing::stopRemoteRefreshTimer (const string &uri) { + auto it = remoteRefreshTimers.find(uri); + if (it != remoteRefreshTimers.end()) + stopRemoteRefreshTimer(it); +} + +// ----------------------------------------------------------------------------- + +unsigned int IsComposing::getIdleTimerDuration () { + int idleTimerDuration = lp_config_get_int(core->config, "sip", "composing_idle_timeout", defaultIdleTimeout); + return idleTimerDuration < 0 ? 0 : static_cast(idleTimerDuration); +} + +unsigned int IsComposing::getRefreshTimerDuration () { + int refreshTimerDuration = lp_config_get_int(core->config, "sip", "composing_refresh_timeout", defaultRefreshTimeout); + return refreshTimerDuration < 0 ? 0 : static_cast(refreshTimerDuration); +} + +unsigned int IsComposing::getRemoteRefreshTimerDuration () { + int remoteRefreshTimerDuration = lp_config_get_int(core->config, "sip", "composing_remote_refresh_timeout", defaultRemoteRefreshTimeout); + return remoteRefreshTimerDuration < 0 ? 0 : static_cast(remoteRefreshTimerDuration); +} + +int IsComposing::idleTimerExpired () { + stopRefreshTimer(); + stopIdleTimer(); + listener->onIsComposingStateChanged(false); + return BELLE_SIP_STOP; +} + +int IsComposing::refreshTimerExpired () { + listener->onIsComposingRefreshNeeded(); + return BELLE_SIP_CONTINUE; +} + +int IsComposing::remoteRefreshTimerExpired (const string &uri) { + stopRemoteRefreshTimer(uri); + listener->onIsRemoteComposingStateChanged(Address(uri), false); + return BELLE_SIP_STOP; +} + +void IsComposing::startRemoteRefreshTimer (const string &uri, unsigned long long refresh) { + unsigned int duration = getRemoteRefreshTimerDuration(); + if (refresh != 0) + duration = static_cast(refresh); + auto it = remoteRefreshTimers.find(uri); + if (it == remoteRefreshTimers.end()) { + IsRemoteComposingData *data = new IsRemoteComposingData(this, uri); + belle_sip_source_t *timer = core->sal->createTimer(remoteRefreshTimerExpired, data, + duration * 1000, "composing remote refresh timeout"); + pair p(uri, timer); + remoteRefreshTimers.insert(p); + } else + belle_sip_source_set_timeout(it->second, duration * 1000); +} + +void IsComposing::stopAllRemoteRefreshTimers () { + for (auto it = remoteRefreshTimers.begin(); it != remoteRefreshTimers.end();) + it = stopRemoteRefreshTimer(it); +} + +unordered_map::iterator IsComposing::stopRemoteRefreshTimer (const unordered_map::const_iterator it) { + belle_sip_source_t *timer = it->second; + if (core && core->sal) { + core->sal->cancelTimer(timer); + delete reinterpret_cast(belle_sip_source_get_user_data(timer)); + } + belle_sip_object_unref(timer); + return remoteRefreshTimers.erase(it); +} + +int IsComposing::idleTimerExpired (void *data, unsigned int revents) { + IsComposing *d = reinterpret_cast(data); + return d->idleTimerExpired(); +} + +int IsComposing::refreshTimerExpired (void *data, unsigned int revents) { + IsComposing *d = reinterpret_cast(data); + return d->refreshTimerExpired(); +} + +int IsComposing::remoteRefreshTimerExpired (void *data, unsigned int revents) { + IsRemoteComposingData *d = reinterpret_cast(data); + int result = d->isComposingHandler->remoteRefreshTimerExpired(d->uri); + return result; +} + +LINPHONE_END_NAMESPACE diff --git a/src/chat/notification/is-composing.h b/src/chat/notification/is-composing.h new file mode 100644 index 000000000..b556dffef --- /dev/null +++ b/src/chat/notification/is-composing.h @@ -0,0 +1,79 @@ +/* + * is-composing.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_IS_COMPOSING_H_ +#define _L_IS_COMPOSING_H_ + +#include + +#include "linphone/utils/general.h" + +#include "chat/notification/is-composing-listener.h" + +// TODO: Remove me later. +#include "private.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class IsComposing { +public: + IsComposing (LinphoneCore *core, IsComposingListener *listener); + ~IsComposing (); + + std::string createXml (bool isComposing); + void parse (const Address &remoteAddr, const std::string &content); + void startIdleTimer (); + void startRefreshTimer (); + void stopIdleTimer (); + void stopRefreshTimer (); + void stopRemoteRefreshTimer (const std::string &uri); + void stopTimers (); + +private: + unsigned int getIdleTimerDuration (); + unsigned int getRefreshTimerDuration (); + unsigned int getRemoteRefreshTimerDuration (); + int idleTimerExpired (); + int refreshTimerExpired (); + int remoteRefreshTimerExpired (const std::string &uri); + void startRemoteRefreshTimer (const std::string &uri, unsigned long long refresh); + void stopAllRemoteRefreshTimers (); + std::unordered_map::iterator stopRemoteRefreshTimer (const std::unordered_map::const_iterator it); + + static int idleTimerExpired (void *data, unsigned int revents); + static int refreshTimerExpired (void *data, unsigned int revents); + static int remoteRefreshTimerExpired (void *data, unsigned int revents); + +private: + static const int defaultIdleTimeout = 15; + static const int defaultRefreshTimeout = 60; + static const int defaultRemoteRefreshTimeout = 120; + + LinphoneCore *core = nullptr; + IsComposingListener *listener = nullptr; + std::unordered_mapremoteRefreshTimers; + belle_sip_source_t *idleTimer = nullptr; + belle_sip_source_t *refreshTimer = nullptr; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_IS_COMPOSING_H_ diff --git a/src/conference/conference-interface.h b/src/conference/conference-interface.h new file mode 100644 index 000000000..cf694327a --- /dev/null +++ b/src/conference/conference-interface.h @@ -0,0 +1,66 @@ +/* + * conference-interface.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_INTERFACE_H_ +#define _L_CONFERENCE_INTERFACE_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class IdentityAddress; +class CallSessionParams; +class Participant; + +class LINPHONE_PUBLIC ConferenceInterface { +public: + virtual ~ConferenceInterface () = default; + + virtual void addParticipant ( + const IdentityAddress &participantAddress, + const CallSessionParams *params, + bool hasMedia + ) = 0; + virtual void addParticipants ( + const std::list &addresses, + const CallSessionParams *params, + bool hasMedia + ) = 0; + virtual bool canHandleParticipants () const = 0; + virtual std::shared_ptr findParticipant (const IdentityAddress &participantAddress) const = 0; + virtual const IdentityAddress &getConferenceAddress () const = 0; + virtual std::shared_ptr getMe () const = 0; + virtual int getParticipantCount () const = 0; + virtual const std::list> &getParticipants () const = 0; + virtual const std::string &getSubject () const = 0; + virtual void join () = 0; + virtual void leave () = 0; + virtual void removeParticipant (const std::shared_ptr &participant) = 0; + virtual void removeParticipants (const std::list> &participants) = 0; + virtual void setParticipantAdminStatus (const std::shared_ptr &participant, bool isAdmin) = 0; + virtual void setSubject (const std::string &subject) = 0; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_INTERFACE_H_ diff --git a/src/conference/conference-listener.h b/src/conference/conference-listener.h new file mode 100644 index 000000000..292928059 --- /dev/null +++ b/src/conference/conference-listener.h @@ -0,0 +1,49 @@ +/* + * cenference-listener.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_LISTENER_H_ +#define _L_CONFERENCE_LISTENER_H_ + +#include + +#include "event-log/events.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class LINPHONE_PUBLIC ConferenceListener { +public: + virtual ~ConferenceListener () = default; + + virtual void onConferenceCreated (const IdentityAddress &addr) {} + virtual void onConferenceKeywordsChanged (const std::vector &keywords) {} + virtual void onConferenceTerminated (const IdentityAddress &addr) {} + virtual void onFirstNotifyReceived (const IdentityAddress &addr) {} + virtual void onParticipantAdded (const std::shared_ptr &event, bool isFullState) {} + virtual void onParticipantRemoved (const std::shared_ptr &event, bool isFullState) {} + virtual void onParticipantSetAdmin (const std::shared_ptr &event, bool isFullState) {} + virtual void onSubjectChanged (const std::shared_ptr &event, bool isFullState) {} + virtual void onParticipantDeviceAdded (const std::shared_ptr &event, bool isFullState) {} + virtual void onParticipantDeviceRemoved (const std::shared_ptr &event, bool isFullState) {} +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_LISTENER_H_ diff --git a/src/conference/conference-p.h b/src/conference/conference-p.h new file mode 100644 index 000000000..c2f21013c --- /dev/null +++ b/src/conference/conference-p.h @@ -0,0 +1,55 @@ +/* + * conference-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_P_H_ +#define _L_CONFERENCE_P_H_ + +#include "address/identity-address.h" +#include "conference.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSessionListener; +class Participant; + +class ConferencePrivate { +public: + virtual ~ConferencePrivate () = default; + + IdentityAddress conferenceAddress; + std::list> participants; + std::string subject; + +protected: + std::shared_ptr activeParticipant; + std::shared_ptr me; + + CallSessionListener *listener = nullptr; + + Conference *mPublic = nullptr; + +private: + L_DECLARE_PUBLIC(Conference); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_P_H_ diff --git a/src/conference/conference.cpp b/src/conference/conference.cpp new file mode 100644 index 000000000..672695eb0 --- /dev/null +++ b/src/conference/conference.cpp @@ -0,0 +1,215 @@ +/* + * conference.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference-p.h" +#include "conference/participant-device.h" +#include "conference/session/call-session-p.h" +#include "content/content.h" +#include "content/content-disposition.h" +#include "content/content-type.h" +#include "logger/logger.h" +#include "participant-p.h" +#include "xml/resource-lists.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +Conference::Conference ( + ConferencePrivate &p, + const shared_ptr &core, + const IdentityAddress &myAddress, + CallSessionListener *listener +) : CoreAccessor(core), mPrivate(&p) { + L_D(); + d->mPublic = this; + d->me = make_shared(this, myAddress); + d->listener = listener; +} + +Conference::~Conference () { + delete mPrivate; +} + +// ----------------------------------------------------------------------------- + +shared_ptr Conference::getActiveParticipant () const { + L_D(); + return d->activeParticipant; +} + +// ----------------------------------------------------------------------------- + +void Conference::addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) { + lError() << "Conference class does not handle addParticipant() generically"; +} + +void Conference::addParticipants (const list &addresses, const CallSessionParams *params, bool hasMedia) { + list sortedAddresses(addresses); + sortedAddresses.sort(); + sortedAddresses.unique(); + for (const auto &addr: sortedAddresses) + addParticipant(addr, params, hasMedia); +} + +bool Conference::canHandleParticipants () const { + return true; +} + +const IdentityAddress &Conference::getConferenceAddress () const { + L_D(); + return d->conferenceAddress; +} + +shared_ptr Conference::getMe () const { + L_D(); + return d->me; +} + +int Conference::getParticipantCount () const { + return static_cast(getParticipants().size()); +} + +const list> &Conference::getParticipants () const { + L_D(); + return d->participants; +} + +const string &Conference::getSubject () const { + L_D(); + return d->subject; +} + +void Conference::join () {} + +void Conference::leave () {} + +void Conference::removeParticipant (const shared_ptr &participant) { + lError() << "Conference class does not handle removeParticipant() generically"; +} + +void Conference::removeParticipants (const list> &participants) { + for (const auto &p : participants) + removeParticipant(p); +} + +void Conference::setParticipantAdminStatus (const shared_ptr &participant, bool isAdmin) { + lError() << "Conference class does not handle setParticipantAdminStatus() generically"; +} + +void Conference::setSubject (const string &subject) { + L_D(); + d->subject = subject; +} + +// ----------------------------------------------------------------------------- + +shared_ptr Conference::findParticipant (const IdentityAddress &addr) const { + L_D(); + + IdentityAddress searchedAddr(addr); + searchedAddr.setGruu(""); + for (const auto &participant : d->participants) { + if (participant->getAddress() == searchedAddr) + return participant; + } + + return nullptr; +} + +shared_ptr Conference::findParticipant (const shared_ptr &session) const { + L_D(); + + for (const auto &participant : d->participants) { + if (participant->getPrivate()->getSession() == session) + return participant; + } + + return nullptr; +} + +shared_ptr Conference::findParticipantDevice (const shared_ptr &session) const { + L_D(); + + for (const auto &participant : d->participants) { + for (const auto &device : participant->getPrivate()->getDevices()) { + if (device->getSession() == session) + return device; + } + } + + return nullptr; +} + +// ----------------------------------------------------------------------------- + +bool Conference::isMe (const IdentityAddress &addr) const { + L_D(); + IdentityAddress cleanedAddr(addr); + cleanedAddr.setGruu(""); + IdentityAddress cleanedMeAddr(d->me->getAddress()); + cleanedMeAddr.setGruu(""); + return cleanedMeAddr == cleanedAddr; +} + +// ----------------------------------------------------------------------------- + +string Conference::getResourceLists (const list &addresses) const { + Xsd::ResourceLists::ResourceLists rl = Xsd::ResourceLists::ResourceLists(); + Xsd::ResourceLists::ListType l = Xsd::ResourceLists::ListType(); + for (const auto &addr : addresses) { + Xsd::ResourceLists::EntryType entry = Xsd::ResourceLists::EntryType(addr.asString()); + l.getEntry().push_back(entry); + } + rl.getList().push_back(l); + + Xsd::XmlSchema::NamespaceInfomap map; + stringstream xmlBody; + serializeResourceLists(xmlBody, rl, map); + return xmlBody.str(); +} + +// ----------------------------------------------------------------------------- + +list Conference::parseResourceLists (const Content &content) { + if ((content.getContentType() == ContentType::ResourceLists) + && ((content.getContentDisposition().weakEqual(ContentDisposition::RecipientList)) + || (content.getContentDisposition().weakEqual(ContentDisposition::RecipientListHistory)) + ) + ) { + istringstream data(content.getBodyAsString()); + unique_ptr rl(Xsd::ResourceLists::parseResourceLists( + data, + Xsd::XmlSchema::Flags::dont_validate + )); + list addresses; + for (const auto &l : rl->getList()) { + for (const auto &entry : l.getEntry()) { + IdentityAddress addr(entry.getUri()); + addresses.push_back(move(addr)); + } + } + return addresses; + } + return list(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/conference.h b/src/conference/conference.h new file mode 100644 index 000000000..a5ee6643b --- /dev/null +++ b/src/conference/conference.h @@ -0,0 +1,93 @@ +/* + * conference.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_H_ +#define _L_CONFERENCE_H_ + +#include "linphone/types.h" + +#include "conference/conference-interface.h" +#include "conference/conference-listener.h" +#include "core/core-accessor.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSession; +class CallSessionListener; +class CallSessionPrivate; +class ConferencePrivate; +class Content; +class ParticipantDevice; + +class LINPHONE_PUBLIC Conference : + public ConferenceInterface, + public ConferenceListener, + public CoreAccessor { + friend class CallSessionPrivate; + +public: + ~Conference(); + + std::shared_ptr getActiveParticipant () const; + + std::shared_ptr findParticipant (const std::shared_ptr &session) const; + std::shared_ptr findParticipantDevice (const std::shared_ptr &session) const; + + /* ConferenceInterface */ + void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override; + void addParticipants (const std::list &addresses, const CallSessionParams *params, bool hasMedia) override; + bool canHandleParticipants () const override; + std::shared_ptr findParticipant (const IdentityAddress &addr) const override; + const IdentityAddress &getConferenceAddress () const override; + std::shared_ptr getMe () const override; + int getParticipantCount () const override; + const std::list> &getParticipants () const override; + const std::string &getSubject () const override; + void join () override; + void leave () override; + void removeParticipant (const std::shared_ptr &participant) override; + void removeParticipants (const std::list> &participants) override; + void setParticipantAdminStatus (const std::shared_ptr &participant, bool isAdmin) override; + void setSubject (const std::string &subject) override; + + std::string getResourceLists (const std::list &addresses) const; + static std::list parseResourceLists (const Content &content); + +protected: + explicit Conference ( + ConferencePrivate &p, + const std::shared_ptr &core, + const IdentityAddress &myAddress, + CallSessionListener *listener + ); + + bool isMe (const IdentityAddress &addr) const; + + ConferencePrivate *mPrivate = nullptr; + +private: + L_DECLARE_PRIVATE(Conference); + L_DISABLE_COPY(Conference); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_H_ diff --git a/src/conference/handlers/local-conference-event-handler-p.h b/src/conference/handlers/local-conference-event-handler-p.h new file mode 100644 index 000000000..2c79157b8 --- /dev/null +++ b/src/conference/handlers/local-conference-event-handler-p.h @@ -0,0 +1,69 @@ +/* + * local-conference-event-handler-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LOCAL_CONFERENCE_EVENT_HANDLER_P_H_ +#define _L_LOCAL_CONFERENCE_EVENT_HANDLER_P_H_ + +#include + +#include "chat/chat-room/chat-room-id.h" +#include "local-conference-event-handler.h" +#include "object/object-p.h" +#include "xml/conference-info.h" + +LINPHONE_BEGIN_NAMESPACE + +class Participant; +class ParticipantDevice; + +class LINPHONE_INTERNAL_PUBLIC LocalConferenceEventHandlerPrivate : public ObjectPrivate { +public: + void notifyFullState (const std::string ¬ify, const std::shared_ptr &device); + void notifyAllExcept (const std::string ¬ify, const std::shared_ptr &exceptParticipant); + void notifyAll (const std::string ¬ify); + std::string createNotifyFullState (int notifyId = -1, bool oneToOne = false); + std::string createNotifyMultipart (int notifyId); + std::string createNotifyParticipantAdded (const Address &addr, int notifyId = -1); + std::string createNotifyParticipantAdminStatusChanged (const Address &addr, bool isAdmin, int notifyId = -1); + std::string createNotifyParticipantRemoved (const Address &addr, int notifyId = -1); + std::string createNotifyParticipantDeviceAdded (const Address &addr, const Address &gruu, int notifyId = -1); + std::string createNotifyParticipantDeviceRemoved (const Address &addr, const Address &gruu, int notifyId = -1); + std::string createNotifySubjectChanged (int notifyId = -1); + + inline unsigned int getLastNotify () const { return lastNotify; }; + +private: + ChatRoomId chatRoomId; + + LocalConference *conf = nullptr; + unsigned int lastNotify = 1; + + static void notifyResponseCb (const LinphoneEvent *ev); + + std::string createNotify (Xsd::ConferenceInfo::ConferenceType confInfo, int notifyId = -1, bool isFullState = false); + std::string createNotifySubjectChanged (const std::string &subject, int notifyId = -1); + void notifyParticipant (const std::string ¬ify, const std::shared_ptr &participant); + void notifyParticipantDevice (const std::string ¬ify, const std::shared_ptr &device, bool multipart = false); + + L_DECLARE_PUBLIC(LocalConferenceEventHandler); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LOCAL_CONFERENCE_EVENT_HANDLER_P_H_ diff --git a/src/conference/handlers/local-conference-event-handler.cpp b/src/conference/handlers/local-conference-event-handler.cpp new file mode 100644 index 000000000..de857918a --- /dev/null +++ b/src/conference/handlers/local-conference-event-handler.cpp @@ -0,0 +1,555 @@ +/* + * local-conference-event-handler.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/api/c-content.h" +#include "linphone/utils/utils.h" + +#include "c-wrapper/c-wrapper.h" +#include "conference/local-conference.h" +#include "conference/participant-device.h" +#include "conference/participant-p.h" +#include "content/content-manager.h" +#include "content/content-type.h" +#include "content/content.h" +#include "core/core-p.h" +#include "db/main-db.h" +#include "event-log/events.h" +#include "local-conference-event-handler-p.h" +#include "logger/logger.h" +#include "object/object-p.h" + +// TODO: remove me. +#include "private.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +using namespace Xsd::ConferenceInfo; + +// ----------------------------------------------------------------------------- + +void LocalConferenceEventHandlerPrivate::notifyFullState (const string ¬ify, const shared_ptr &device) { + notifyParticipantDevice(notify, device); +} + +void LocalConferenceEventHandlerPrivate::notifyAllExcept (const string ¬ify, const shared_ptr &exceptParticipant) { + for (const auto &participant : conf->getParticipants()) { + if (participant != exceptParticipant) + notifyParticipant(notify, participant); + } +} + +void LocalConferenceEventHandlerPrivate::notifyAll (const string ¬ify) { + for (const auto &participant : conf->getParticipants()) + notifyParticipant(notify, participant); +} + +string LocalConferenceEventHandlerPrivate::createNotifyFullState (int notifyId, bool oneToOne) { + string entity = conf->getConferenceAddress().asString(); + string subject = conf->getSubject(); + ConferenceType confInfo = ConferenceType(entity); + UsersType users; + ConferenceDescriptionType confDescr = ConferenceDescriptionType(); + confDescr.setSubject(subject); + if (oneToOne) { + KeywordsType keywords(sizeof(char), "one-to-one"); + confDescr.setKeywords(keywords); + } + confInfo.setUsers(users); + confInfo.setConferenceDescription((const ConferenceDescriptionType) confDescr); + + for (const auto &participant : conf->getParticipants()) { + UserType user = UserType(); + UserRolesType roles; + UserType::EndpointSequence endpoints; + user.setRoles(roles); + user.setEndpoint(endpoints); + user.setEntity(participant->getAddress().asString()); + user.getRoles()->getEntry().push_back(participant->isAdmin() ? "admin" : "participant"); + user.setState(StateType::full); + + for (const auto &device : participant->getPrivate()->getDevices()) { + const string &gruu = device->getAddress().asString(); + EndpointType endpoint = EndpointType(); + endpoint.setEntity(gruu); + endpoint.setState(StateType::full); + user.getEndpoint().push_back(endpoint); + } + + confInfo.getUsers()->getUser().push_back(user); + } + + return createNotify(confInfo, notifyId, true); +} + +string LocalConferenceEventHandlerPrivate::createNotifyMultipart (int notifyId) { + list> events = conf->getCore()->getPrivate()->mainDb->getConferenceNotifiedEvents( + ChatRoomId(conf->getConferenceAddress(), conf->getConferenceAddress()), + static_cast(notifyId) + ); + + list contents; + for (const auto &eventLog : events) { + Content *content = new Content(); + content->setContentType(ContentType::ConferenceInfo); + string body; + shared_ptr notifiedEvent = static_pointer_cast(eventLog); + int eventNotifyId = static_cast(notifiedEvent->getNotifyId()); + switch (eventLog->getType()) { + case EventLog::Type::ConferenceParticipantAdded: { + shared_ptr addedEvent = static_pointer_cast(eventLog); + body = createNotifyParticipantAdded( + addedEvent->getParticipantAddress(), + eventNotifyId + ); + } break; + + case EventLog::Type::ConferenceParticipantRemoved: { + shared_ptr removedEvent = static_pointer_cast(eventLog); + body = createNotifyParticipantRemoved( + removedEvent->getParticipantAddress(), + eventNotifyId + ); + } break; + + case EventLog::Type::ConferenceParticipantSetAdmin: { + shared_ptr setAdminEvent = static_pointer_cast(eventLog); + body = createNotifyParticipantAdminStatusChanged( + setAdminEvent->getParticipantAddress(), + true, + eventNotifyId + ); + } break; + + case EventLog::Type::ConferenceParticipantUnsetAdmin: { + shared_ptr unsetAdminEvent = static_pointer_cast(eventLog); + body = createNotifyParticipantAdminStatusChanged( + unsetAdminEvent->getParticipantAddress(), + false, + eventNotifyId + ); + } break; + + case EventLog::Type::ConferenceParticipantDeviceAdded: { + shared_ptr deviceAddedEvent = static_pointer_cast(eventLog); + body = createNotifyParticipantDeviceAdded( + deviceAddedEvent->getParticipantAddress(), + deviceAddedEvent->getDeviceAddress(), + eventNotifyId + ); + } break; + + case EventLog::Type::ConferenceParticipantDeviceRemoved: { + shared_ptr deviceRemovedEvent = static_pointer_cast(eventLog); + body = createNotifyParticipantDeviceRemoved( + deviceRemovedEvent->getParticipantAddress(), + deviceRemovedEvent->getDeviceAddress(), + eventNotifyId + ); + } break; + + case EventLog::Type::ConferenceSubjectChanged: { + shared_ptr subjectEvent = static_pointer_cast(eventLog); + body = createNotifySubjectChanged( + subjectEvent->getSubject(), + eventNotifyId + ); + } break; + + default: + // We should never pass here! + L_ASSERT(false); + continue; + } + contents.emplace_back(Content()); + contents.back().setContentType(ContentType::ConferenceInfo); + contents.back().setBody(body); + } + + if (contents.empty()) + return Utils::getEmptyConstRefObject(); + + list contentPtrs; + for (auto &content : contents) + contentPtrs.push_back(&content); + string multipart = ContentManager::contentListToMultipart(contentPtrs).getBodyAsString(); + return multipart; +} + +string LocalConferenceEventHandlerPrivate::createNotifyParticipantAdded (const Address &addr, int notifyId) { + string entity = conf->getConferenceAddress().asString(); + ConferenceType confInfo = ConferenceType(entity); + UsersType users; + confInfo.setUsers(users); + UserType user = UserType(); + UserRolesType roles; + UserType::EndpointSequence endpoints; + + shared_ptr p = conf->findParticipant(addr); + if (p) { + for (const auto &device : p->getPrivate()->getDevices()) { + const string &gruu = device->getAddress().asString(); + EndpointType endpoint = EndpointType(); + endpoint.setEntity(gruu); + endpoint.setState(StateType::full); + user.getEndpoint().push_back(endpoint); + } + } + + user.setRoles(roles); + user.setEntity(addr.asStringUriOnly()); + user.getRoles()->getEntry().push_back("participant"); + user.setState(StateType::full); + + confInfo.getUsers()->getUser().push_back(user); + + return createNotify(confInfo, notifyId); +} + +string LocalConferenceEventHandlerPrivate::createNotifyParticipantAdminStatusChanged (const Address &addr, bool isAdmin, int notifyId) { + string entity = conf->getConferenceAddress().asString(); + ConferenceType confInfo = ConferenceType(entity); + UsersType users; + confInfo.setUsers(users); + + UserType user = UserType(); + UserRolesType roles; + user.setRoles(roles); + user.setEntity(addr.asStringUriOnly()); + user.getRoles()->getEntry().push_back(isAdmin ? "admin" : "participant"); + user.setState(StateType::partial); + confInfo.getUsers()->getUser().push_back(user); + + return createNotify(confInfo, notifyId); +} + +string LocalConferenceEventHandlerPrivate::createNotifyParticipantRemoved (const Address &addr, int notifyId) { + string entity = conf->getConferenceAddress().asString(); + ConferenceType confInfo = ConferenceType(entity); + UsersType users; + confInfo.setUsers(users); + + UserType user = UserType(); + user.setEntity(addr.asStringUriOnly()); + user.setState(StateType::deleted); + confInfo.getUsers()->getUser().push_back(user); + + return createNotify(confInfo, notifyId); +} + +string LocalConferenceEventHandlerPrivate::createNotifyParticipantDeviceAdded (const Address &addr, const Address &gruu, int notifyId) { + string entity = conf->getConferenceAddress().asString(); + ConferenceType confInfo = ConferenceType(entity); + UsersType users; + confInfo.setUsers(users); + + UserType user = UserType(); + UserType::EndpointSequence endpoints; + user.setEntity(addr.asStringUriOnly()); + user.setState(StateType::partial); + + EndpointType endpoint = EndpointType(); + endpoint.setEntity(gruu.asStringUriOnly()); + endpoint.setState(StateType::full); + user.getEndpoint().push_back(endpoint); + + confInfo.getUsers()->getUser().push_back(user); + + return createNotify(confInfo, notifyId); +} + +string LocalConferenceEventHandlerPrivate::createNotifyParticipantDeviceRemoved (const Address &addr, const Address &gruu, int notifyId) { + string entity = conf->getConferenceAddress().asString(); + ConferenceType confInfo = ConferenceType(entity); + UsersType users; + confInfo.setUsers(users); + + UserType user = UserType(); + UserType::EndpointSequence endpoints; + user.setEntity(addr.asStringUriOnly()); + user.setState(StateType::partial); + + EndpointType endpoint = EndpointType(); + endpoint.setEntity(gruu.asStringUriOnly()); + endpoint.setState(StateType::deleted); + user.getEndpoint().push_back(endpoint); + + confInfo.getUsers()->getUser().push_back(user); + + return createNotify(confInfo, notifyId); +} + +string LocalConferenceEventHandlerPrivate::createNotifySubjectChanged (int notifyId) { + return createNotifySubjectChanged(conf->getSubject(), notifyId); +} + +// ----------------------------------------------------------------------------- + +void LocalConferenceEventHandlerPrivate::notifyResponseCb (const LinphoneEvent *ev) { + LinphoneEventCbs *cbs = linphone_event_get_callbacks(ev); + LocalConferenceEventHandlerPrivate *handler = reinterpret_cast( + linphone_event_cbs_get_user_data(cbs) + ); + linphone_event_cbs_set_user_data(cbs, nullptr); + linphone_event_cbs_set_notify_response(cbs, nullptr); + + if (linphone_event_get_reason(ev) != LinphoneReasonNone) + return; + + for (const auto &p : handler->conf->getParticipants()) { + for (const auto &d : p->getPrivate()->getDevices()) { + if ((d->getConferenceSubscribeEvent() == ev) && (d->getState() == ParticipantDevice::State::Joining)) { + handler->conf->onFirstNotifyReceived(d->getAddress()); + return; + } + } + } +} + +// ----------------------------------------------------------------------------- + +string LocalConferenceEventHandlerPrivate::createNotify (ConferenceType confInfo, int notifyId, bool isFullState) { + confInfo.setVersion(notifyId == -1 ? ++lastNotify : static_cast(notifyId)); + confInfo.setState(isFullState ? StateType::full : StateType::partial); + + if (!confInfo.getConferenceDescription()) { + ConferenceDescriptionType description = ConferenceDescriptionType(); + confInfo.setConferenceDescription(description); + } + + time_t result = time(nullptr); + confInfo.getConferenceDescription()->setFreeText(Utils::toString(static_cast(result))); + + stringstream notify; + Xsd::XmlSchema::NamespaceInfomap map; + map[""].name = "urn:ietf:params:xml:ns:conference-info"; + serializeConferenceInfo(notify, confInfo, map); + return notify.str(); +} + +string LocalConferenceEventHandlerPrivate::createNotifySubjectChanged (const string &subject, int notifyId) { + string entity = conf->getConferenceAddress().asString(); + ConferenceType confInfo = ConferenceType(entity); + ConferenceDescriptionType confDescr = ConferenceDescriptionType(); + confDescr.setSubject(subject); + confInfo.setConferenceDescription((const ConferenceDescriptionType)confDescr); + + return createNotify(confInfo, notifyId); +} + +void LocalConferenceEventHandlerPrivate::notifyParticipant (const string ¬ify, const shared_ptr &participant) { + for (const auto &device : participant->getPrivate()->getDevices()) + notifyParticipantDevice(notify, device); +} + +void LocalConferenceEventHandlerPrivate::notifyParticipantDevice (const string ¬ify, const shared_ptr &device, bool multipart) { + if (!device->isSubscribedToConferenceEventPackage() || notify.empty()) + return; + + LinphoneEvent *ev = device->getConferenceSubscribeEvent(); + LinphoneEventCbs *cbs = linphone_event_get_callbacks(ev); + linphone_event_cbs_set_user_data(cbs, this); + linphone_event_cbs_set_notify_response(cbs, notifyResponseCb); + + Content content; + content.setBody(notify); + ContentType contentType; + if (multipart) { + contentType = ContentType(ContentType::Multipart); + contentType.addParameter("boundary", MultipartBoundary); + } else + contentType = ContentType(ContentType::ConferenceInfo); + + content.setContentType(contentType); + // TODO: Activate compression + //if (linphone_core_content_encoding_supported(conf->getCore()->getCCore(), "deflate")) + // linphone_content_set_encoding(content, "deflate"); + // TODO: Activate compression + LinphoneContent *cContent = L_GET_C_BACK_PTR(&content); + linphone_event_notify(ev, cContent); +} + +// ============================================================================= + +LocalConferenceEventHandler::LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify) : + Object(*new LocalConferenceEventHandlerPrivate) { + L_D(); + d->conf = localConference; + d->lastNotify = notify; +} + +// ----------------------------------------------------------------------------- + +void LocalConferenceEventHandler::subscribeReceived (LinphoneEvent *lev, bool oneToOne) { + L_D(); + const LinphoneAddress *lAddr = linphone_event_get_from(lev); + char *addrStr = linphone_address_as_string(lAddr); + shared_ptr participant = d->conf->findParticipant(Address(addrStr)); + bctbx_free(addrStr); + if (!participant) { + lError() << "received SUBSCRIBE corresponds to no participant of the conference; " << d->conf->getConferenceAddress().asString() << ", no NOTIFY sent."; + linphone_event_deny_subscription(lev, LinphoneReasonDeclined); + return; + } + + const LinphoneAddress *lContactAddr = linphone_event_get_remote_contact(lev); + char *contactAddrStr = linphone_address_as_string(lContactAddr); + IdentityAddress contactAddr(contactAddrStr); + bctbx_free(contactAddrStr); + shared_ptr device = participant->getPrivate()->findDevice(contactAddr); + if (!device || (device->getState() != ParticipantDevice::State::Present && device->getState() != ParticipantDevice::State::Joining)) { + lError() << "received SUBSCRIBE for conference: " << d->conf->getConferenceAddress().asString() + << "device sending subscribe: " << contactAddr.asString() << " is not known, no NOTIFY sent."; + linphone_event_deny_subscription(lev, LinphoneReasonDeclined); + return; + } + + linphone_event_accept_subscription(lev); + if (linphone_event_get_subscription_state(lev) == LinphoneSubscriptionActive) { + unsigned int lastNotify = static_cast(Utils::stoi(linphone_event_get_custom_header(lev, "Last-Notify-Version"))); + device->setConferenceSubscribeEvent(lev); + if (lastNotify == 0 || (device->getState() == ParticipantDevice::State::Joining)) { + lInfo() << "Sending initial notify of conference:" << d->conf->getConferenceAddress().asString() << " to: " << device->getAddress().asString(); + d->notifyFullState(d->createNotifyFullState(static_cast(d->lastNotify), oneToOne), device); + } else if (lastNotify < d->lastNotify) { + lInfo() << "Sending all missed notify [" << lastNotify << "-" << d->lastNotify << + "] for conference:" << d->conf->getConferenceAddress().asString() << + " to: " << participant->getAddress().asString(); + d->notifyParticipantDevice(d->createNotifyMultipart(static_cast(lastNotify)), device, true); + } else if (lastNotify > d->lastNotify) { + lError() << "last notify received by client: [" << lastNotify <<"] for conference:" << + d->conf->getConferenceAddress().asString() << + " should not be higher than last notify sent by server: [" << d->lastNotify << "]"; + } + } else if (linphone_event_get_subscription_state(lev) == LinphoneSubscriptionTerminated) + device->setConferenceSubscribeEvent(nullptr); +} + +shared_ptr LocalConferenceEventHandler::notifyParticipantAdded (const Address &addr) { + L_D(); + shared_ptr participant = d->conf->findParticipant(addr); + d->notifyAllExcept(d->createNotifyParticipantAdded(addr), participant); + shared_ptr event = make_shared( + EventLog::Type::ConferenceParticipantAdded, + time(nullptr), + d->chatRoomId, + d->lastNotify, + addr + ); + return event; +} + +shared_ptr LocalConferenceEventHandler::notifyParticipantRemoved (const Address &addr) { + L_D(); + shared_ptr participant = d->conf->findParticipant(addr); + d->notifyAllExcept(d->createNotifyParticipantRemoved(addr), participant); + shared_ptr event = make_shared( + EventLog::Type::ConferenceParticipantRemoved, + time(nullptr), + d->chatRoomId, + d->lastNotify, + addr + ); + return event; +} + +shared_ptr LocalConferenceEventHandler::notifyParticipantSetAdmin (const Address &addr, bool isAdmin) { + L_D(); + d->notifyAll(d->createNotifyParticipantAdminStatusChanged(addr, isAdmin)); + shared_ptr event = make_shared( + isAdmin ? EventLog::Type::ConferenceParticipantSetAdmin : EventLog::Type::ConferenceParticipantUnsetAdmin, + time(nullptr), + d->chatRoomId, + d->lastNotify, + addr + ); + return event; +} + +shared_ptr LocalConferenceEventHandler::notifySubjectChanged () { + L_D(); + d->notifyAll(d->createNotifySubjectChanged()); + shared_ptr event = make_shared( + time(nullptr), + d->chatRoomId, + d->lastNotify, + d->conf->getSubject() + ); + return event; +} + +shared_ptr LocalConferenceEventHandler::notifyParticipantDeviceAdded (const Address &addr, const Address &gruu) { + L_D(); + d->notifyAll(d->createNotifyParticipantDeviceAdded(addr, gruu)); + shared_ptr event = make_shared( + EventLog::Type::ConferenceParticipantDeviceAdded, + time(nullptr), + d->chatRoomId, + d->lastNotify, + addr, + gruu + ); + return event; +} + +shared_ptr LocalConferenceEventHandler::notifyParticipantDeviceRemoved (const Address &addr, const Address &gruu) { + L_D(); + d->notifyAll(d->createNotifyParticipantDeviceRemoved(addr, gruu)); + shared_ptr event = make_shared( + EventLog::Type::ConferenceParticipantDeviceRemoved, + time(nullptr), + d->chatRoomId, + d->lastNotify, + addr, + gruu + ); + return event; +} + +void LocalConferenceEventHandler::setLastNotify (unsigned int lastNotify) { + L_D(); + d->lastNotify = lastNotify; +} + +void LocalConferenceEventHandler::setChatRoomId (const ChatRoomId &chatRoomId) { + L_D(); + d->chatRoomId = chatRoomId; +} + +ChatRoomId LocalConferenceEventHandler::getChatRoomId () const { + L_D(); + return d->chatRoomId; +} + +string LocalConferenceEventHandler::getNotifyForId (int notifyId, bool oneToOne) { + L_D(); + if (notifyId == 0) + return d->createNotifyFullState(static_cast(d->lastNotify), oneToOne); + else if (notifyId < static_cast(d->lastNotify)) + return d->createNotifyMultipart(notifyId); + + return Utils::getEmptyConstRefObject(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/handlers/local-conference-event-handler.h b/src/conference/handlers/local-conference-event-handler.h new file mode 100644 index 000000000..6f8a5cc3c --- /dev/null +++ b/src/conference/handlers/local-conference-event-handler.h @@ -0,0 +1,66 @@ +/* + * local-conference-event-handler.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LOCAL_CONFERENCE_EVENT_HANDLER_H_ +#define _L_LOCAL_CONFERENCE_EVENT_HANDLER_H_ + +#include "linphone/types.h" + +#include "address/address.h" +#include "core/core-accessor.h" +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoomId; +class ConferenceParticipantDeviceEvent; +class ConferenceParticipantEvent; +class ConferenceSubjectEvent; +class LocalConference; +class LocalConferenceEventHandlerPrivate; + +class LocalConferenceEventHandler : public Object { +friend class LocalConferenceListEventHandler; +public: + LocalConferenceEventHandler (LocalConference *localConference, unsigned int notify = 0); + + void subscribeReceived (LinphoneEvent *lev, bool oneToOne = false); + std::shared_ptr notifyParticipantAdded (const Address &addr); + std::shared_ptr notifyParticipantRemoved (const Address &addr); + std::shared_ptr notifyParticipantSetAdmin (const Address &addr, bool isAdmin); + std::shared_ptr notifySubjectChanged (); + std::shared_ptr notifyParticipantDeviceAdded (const Address &addr, const Address &gruu); + std::shared_ptr notifyParticipantDeviceRemoved (const Address &addr, const Address &gruu); + + void setLastNotify (unsigned int lastNotify); + void setChatRoomId (const ChatRoomId &chatRoomId); + ChatRoomId getChatRoomId () const; + + std::string getNotifyForId (int notifyId, bool oneToOne = false); + +private: + L_DECLARE_PRIVATE(LocalConferenceEventHandler); + L_DISABLE_COPY(LocalConferenceEventHandler); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LOCAL_CONFERENCE_EVENT_HANDLER_H_ diff --git a/src/conference/handlers/local-conference-list-event-handler.cpp b/src/conference/handlers/local-conference-list-event-handler.cpp new file mode 100644 index 000000000..af0d6d9dd --- /dev/null +++ b/src/conference/handlers/local-conference-list-event-handler.cpp @@ -0,0 +1,202 @@ +/* + * local-conference-list-event-handler.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "belle-sip/utils.h" +#include "linphone/enums/chat-room-enums.h" +#include "linphone/utils/utils.h" +#include "linphone/api/c-address.h" + +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" +#include "chat/chat-room/abstract-chat-room.h" +#include "conference/participant-p.h" +#include "conference/participant-device.h" +#include "content/content.h" +#include "content/content-manager.h" +#include "content/content-type.h" +#include "core/core.h" +#include "local-conference-event-handler.h" +#include "local-conference-list-event-handler.h" +#include "logger/logger.h" +#include "xml/resource-lists.h" +#include "xml/rlmi.h" + +// TODO: Remove me later. +#include "private.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +namespace { + constexpr const char MultipartBoundaryListEventHandler[] = "---------------------------14737809831412343453453"; +} + +// ----------------------------------------------------------------------------- + +LocalConferenceListEventHandler::LocalConferenceListEventHandler (const std::shared_ptr &core) : CoreAccessor(core) {} + +// ----------------------------------------------------------------------------- + +void LocalConferenceListEventHandler::subscribeReceived (LinphoneEvent *lev, const LinphoneContent *body) { + LinphoneSubscriptionState subscriptionState = linphone_event_get_subscription_state(lev); + + const string &xmlBody = string(linphone_content_get_string_buffer(body)); + if (xmlBody.empty()) { + linphone_event_deny_subscription(lev, LinphoneReasonDeclined); + return; + } + + linphone_event_accept_subscription(lev); + + if (subscriptionState != LinphoneSubscriptionIncomingReceived && subscriptionState != LinphoneSubscriptionTerminated) + return; + + const LinphoneAddress *lAddr = linphone_event_get_from(lev); + char *addrStr = linphone_address_as_string(lAddr); + IdentityAddress participantAddr(addrStr); + bctbx_free(addrStr); + + const LinphoneAddress *lDeviceAddr = linphone_event_get_remote_contact(lev); + char *deviceAddrStr = linphone_address_as_string(lDeviceAddr); + IdentityAddress deviceAddr(deviceAddrStr); + bctbx_free(deviceAddrStr); + + list contents; + Content *rlmiContent = new Content(); + rlmiContent->setContentType(ContentType::Rlmi); + + // Create Rlmi body + Xsd::Rlmi::List::ResourceSequence resources; + + // Parse resource list + bool noContent = true; + istringstream data(xmlBody); + unique_ptr rl(Xsd::ResourceLists::parseResourceLists( + data, + Xsd::XmlSchema::Flags::dont_validate + )); + for (const auto &l : rl->getList()) { + for (const auto &entry : l.getEntry()) { + Address addr(entry.getUri()); + string notifyIdStr = addr.getUriParamValue("Last-Notify"); + addr.removeUriParam("Last-Notify"); + ChatRoomId chatRoomId(addr, addr); + LocalConferenceEventHandler *handler = findHandler(chatRoomId); + if (!handler) + continue; + + shared_ptr chatRoom = L_GET_CPP_PTR_FROM_C_OBJECT(linphone_event_get_core(lev))->findChatRoom(chatRoomId); + if (!chatRoom) { + lError() << "Received subscribe for unknown chat room: " << chatRoomId; + continue; + } + + shared_ptr participant = chatRoom->findParticipant(participantAddr); + if (!participant) { + lError() << "Received subscribe for unknown participant: " << participantAddr << " for chat room: " << chatRoomId; + continue; + } + shared_ptr device = participant->getPrivate()->findDevice(deviceAddr); + if (!device || (device->getState() != ParticipantDevice::State::Present && device->getState() != ParticipantDevice::State::Joining)) { + lError() << "Received subscribe for unknown device: " << deviceAddr << " for participant: " + << participantAddr << " for chat room: " << chatRoomId; + continue; + } + device->setConferenceSubscribeEvent((subscriptionState == LinphoneSubscriptionIncomingReceived) ? lev : nullptr); + + int notifyId = (notifyIdStr.empty() || device->getState() == ParticipantDevice::State::Joining) ? 0 : Utils::stoi(notifyIdStr); + string notifyBody = handler->getNotifyForId(notifyId, !!(chatRoom->getCapabilities() & AbstractChatRoom::Capabilities::OneToOne)); + if (notifyBody.empty()) + continue; + + noContent = false; + Content *content = new Content(); + if (notifyId > 0) { + ContentType contentType(ContentType::Multipart); + contentType.addParameter("boundary", string(MultipartBoundary)); + content->setContentType(contentType); + } else + content->setContentType(ContentType::ConferenceInfo); + + content->setBody(notifyBody); + char token[17]; + belle_sip_random_token(token, sizeof(token)); + content->addHeader("Content-Id", token); + content->addHeader("Content-Length", Utils::toString(notifyBody.size())); + contents.push_back(content); + + // Add entry into the Rlmi content of the notify body + Xsd::Rlmi::Resource resource(addr.asStringUriOnly()); + Xsd::Rlmi::Resource::InstanceSequence instances; + Xsd::Rlmi::Instance instance(token, Xsd::Rlmi::State::Value::active); + instances.push_back(instance); + resource.setInstance(instances); + resources.push_back(resource); + } + } + + if (noContent) + return; + + Xsd::Rlmi::List list("", 0, TRUE); + list.setResource(resources); + Xsd::XmlSchema::NamespaceInfomap map; + stringstream rlmiBody; + Xsd::Rlmi::serializeList(rlmiBody, list, map); + rlmiContent->setBody(rlmiBody.str()); + + contents.push_front(rlmiContent); + Content multipart = ContentManager::contentListToMultipart(contents, MultipartBoundaryListEventHandler); + if (linphone_core_content_encoding_supported(getCore()->getCCore(), "deflate")) + multipart.setContentEncoding("deflate"); + LinphoneContent *cContent = L_GET_C_BACK_PTR(&multipart); + linphone_event_notify(lev, cContent); + contents.clear(); +} + +// ----------------------------------------------------------------------------- + +void LocalConferenceListEventHandler::addHandler (LocalConferenceEventHandler *handler) { + if (handler) + handlers.push_back(handler); +} + +void LocalConferenceListEventHandler::removeHandler (LocalConferenceEventHandler *handler) { + if (handler) + handlers.remove(handler); +} + +LocalConferenceEventHandler *LocalConferenceListEventHandler::findHandler (const ChatRoomId &chatRoomId) const { + for (const auto &handler : handlers) { + if (handler->getChatRoomId() == chatRoomId) + return handler; + } + + return nullptr; +} + +const list &LocalConferenceListEventHandler::getHandlers () const { + return handlers; +} + +LINPHONE_END_NAMESPACE + diff --git a/src/conference/handlers/local-conference-list-event-handler.h b/src/conference/handlers/local-conference-list-event-handler.h new file mode 100644 index 000000000..854fa37c1 --- /dev/null +++ b/src/conference/handlers/local-conference-list-event-handler.h @@ -0,0 +1,54 @@ +/* + * local-conference-list-event-handler.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LOCAL_CONFERENCE_LIST_EVENT_HANDLER_H_ +#define _L_LOCAL_CONFERENCE_LIST_EVENT_HANDLER_H_ + +#include +#include + +#include "chat/chat-room/chat-room-id.h" +#include "core/core-accessor.h" +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class LocalConferenceEventHandler; + +class LocalConferenceListEventHandler : public CoreAccessor { +public: + LocalConferenceListEventHandler (const std::shared_ptr &core); + + void subscribeReceived (LinphoneEvent *lev, const LinphoneContent *body); + void addHandler (LocalConferenceEventHandler *handler); + void removeHandler (LocalConferenceEventHandler *handler); + LocalConferenceEventHandler *findHandler (const ChatRoomId &chatRoomId) const; + const std::list &getHandlers () const; + +private: + std::list handlers; + +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LOCAL_CONFERENCE_LIST_EVENT_HANDLER_H_ + diff --git a/src/conference/handlers/remote-conference-event-handler-p.h b/src/conference/handlers/remote-conference-event-handler-p.h new file mode 100644 index 000000000..84903a293 --- /dev/null +++ b/src/conference/handlers/remote-conference-event-handler-p.h @@ -0,0 +1,60 @@ +/* + * remote-conference-event-handler-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REMOTE_CONFERENCE_EVENT_HANDLER_P_H_ +#define _L_REMOTE_CONFERENCE_EVENT_HANDLER_P_H_ + +#include "linphone/types.h" + +#include "chat/chat-room/chat-room-id.h" +#include "core/core-listener.h" +#include "object/object-p.h" +#include "remote-conference-event-handler.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class RemoteConferenceEventHandlerPrivate : public ObjectPrivate, public CoreListener { + friend class ClientGroupChatRoom; +private: + void simpleNotifyReceived (const std::string &xmlBody); + void subscribe (); + void unsubscribe (); + + // CoreListener + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; + void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message) override; + void onEnteringBackground () override; + void onEnteringForeground () override; + + ChatRoomId chatRoomId; + + RemoteConference *conf = nullptr; + LinphoneEvent *lev = nullptr; + + unsigned int lastNotify = 0; + bool subscriptionWanted = false; + + L_DECLARE_PUBLIC(RemoteConferenceEventHandler); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REMOTE_CONFERENCE_EVENT_HANDLER_P_H_ diff --git a/src/conference/handlers/remote-conference-event-handler.cpp b/src/conference/handlers/remote-conference-event-handler.cpp new file mode 100644 index 000000000..bc97ca183 --- /dev/null +++ b/src/conference/handlers/remote-conference-event-handler.cpp @@ -0,0 +1,334 @@ +/* + * remote-conference-event-handler.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/algorithm.h" +#include "linphone/utils/utils.h" + +#include "conference/remote-conference.h" +#include "content/content-manager.h" +#include "content/content-type.h" +#include "content/content.h" +#include "core/core-p.h" +#include "logger/logger.h" +#include "remote-conference-event-handler-p.h" +#include "xml/conference-info.h" + +// TODO: Remove me later. +#include "private.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +using namespace Xsd::ConferenceInfo; + +// ----------------------------------------------------------------------------- + +void RemoteConferenceEventHandlerPrivate::simpleNotifyReceived (const string &xmlBody) { + istringstream data(xmlBody); + unique_ptr confInfo = parseConferenceInfo(data, Xsd::XmlSchema::Flags::dont_validate); + + IdentityAddress entityAddress(confInfo->getEntity().c_str()); + if (entityAddress != chatRoomId.getPeerAddress()) + return; + + auto &confDescription = confInfo->getConferenceDescription(); + + // 1. Compute event time. + time_t creationTime = time(nullptr); + { + auto &freeText = confDescription->getFreeText(); + if (freeText.present()) + creationTime = static_cast(Utils::stoll(freeText.get())); + } + + // 2. Update last notify. + { + auto &version = confInfo->getVersion(); + if (version.present()) + lastNotify = version.get(); + } + + bool isFullState = confInfo->getState() == StateType::full; + ConferenceListener *confListener = static_cast(conf); + + // 3. Notify subject and keywords. + if (confDescription.present()) { + auto &subject = confDescription.get().getSubject(); + if (subject.present() && !subject.get().empty()) + confListener->onSubjectChanged( + make_shared( + creationTime, + chatRoomId, + lastNotify, + subject.get() + ), + isFullState + ); + + auto &keywords = confDescription.get().getKeywords(); + if (keywords.present() && !keywords.get().empty()) { + KeywordsType xmlKeywords = keywords.get(); + confListener->onConferenceKeywordsChanged( + vector(xmlKeywords.begin(), xmlKeywords.end()) + ); + } + } + + auto &users = confInfo->getUsers(); + if (!users.present()) + return; + + // 4. Notify changes on users. + for (auto &user : users->getUser()) { + LinphoneAddress *cAddr = linphone_core_interpret_url(conf->getCore()->getCCore(), user.getEntity()->c_str()); + char *cAddrStr = linphone_address_as_string(cAddr); + linphone_address_unref(cAddr); + + Address addr(cAddrStr); + bctbx_free(cAddrStr); + + StateType state = user.getState(); + + if (state == StateType::deleted) { + confListener->onParticipantRemoved( + make_shared( + EventLog::Type::ConferenceParticipantRemoved, + creationTime, + chatRoomId, + lastNotify, + addr + ), + isFullState + ); + + continue; + } + + if (state == StateType::full) + confListener->onParticipantAdded( + make_shared( + EventLog::Type::ConferenceParticipantAdded, + creationTime, + chatRoomId, + lastNotify, + addr + ), + isFullState + ); + + auto &roles = user.getRoles(); + if (roles) { + auto &entry = roles->getEntry(); + confListener->onParticipantSetAdmin( + make_shared( + find(entry, "admin") != entry.end() + ? EventLog::Type::ConferenceParticipantSetAdmin + : EventLog::Type::ConferenceParticipantUnsetAdmin, + creationTime, + chatRoomId, + lastNotify, + addr + ), + isFullState + ); + } + + for (const auto &endpoint : user.getEndpoint()) { + if (!endpoint.getEntity().present()) + break; + + Address gruu(endpoint.getEntity().get()); + StateType state = endpoint.getState(); + + if (state == StateType::deleted) { + confListener->onParticipantDeviceRemoved( + make_shared( + EventLog::Type::ConferenceParticipantDeviceRemoved, + creationTime, + chatRoomId, + lastNotify, + addr, + gruu + ), + isFullState + ); + } else if (state == StateType::full) { + confListener->onParticipantDeviceAdded( + make_shared( + EventLog::Type::ConferenceParticipantDeviceAdded, + creationTime, + chatRoomId, + lastNotify, + addr, + gruu + ), + isFullState + ); + } + } + } + + if (isFullState) + confListener->onFirstNotifyReceived(chatRoomId.getPeerAddress()); +} + +// ----------------------------------------------------------------------------- + +void RemoteConferenceEventHandlerPrivate::subscribe () { + if (lev || !subscriptionWanted) + return; // Already subscribed or application did not request subscription + + const string &peerAddress = chatRoomId.getPeerAddress().asString(); + LinphoneAddress *lAddr = linphone_address_new(peerAddress.c_str()); + LinphoneCore *lc = conf->getCore()->getCCore(); + LinphoneProxyConfig *cfg = linphone_core_lookup_known_proxy(lc, lAddr); + if (!cfg || (linphone_proxy_config_get_state(cfg) != LinphoneRegistrationOk)) { + linphone_address_unref(lAddr); + return; + } + + lev = linphone_core_create_subscribe(conf->getCore()->getCCore(), lAddr, "conference", 600); + lev->op->setFrom(chatRoomId.getLocalAddress().asString().c_str()); + const string &lastNotifyStr = Utils::toString(lastNotify); + linphone_event_add_custom_header(lev, "Last-Notify-Version", lastNotifyStr.c_str()); + linphone_address_unref(lAddr); + linphone_event_set_internal(lev, TRUE); + linphone_event_set_user_data(lev, this); + lInfo() << "Subscribing to chat room: " << peerAddress << "with last notify: " << lastNotifyStr; + linphone_event_send_subscribe(lev, nullptr); +} + +void RemoteConferenceEventHandlerPrivate::unsubscribe () { + if (lev) { + linphone_event_terminate(lev); + lev = nullptr; + } +} + +// ----------------------------------------------------------------------------- + +void RemoteConferenceEventHandlerPrivate::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + if (!sipNetworkReachable) + unsubscribe(); +} + +void RemoteConferenceEventHandlerPrivate::onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message) { + if (state == LinphoneRegistrationOk) + subscribe(); +} + +void RemoteConferenceEventHandlerPrivate::onEnteringBackground () { + unsubscribe(); +} + +void RemoteConferenceEventHandlerPrivate::onEnteringForeground () { + subscribe(); +} + +// ----------------------------------------------------------------------------- + +RemoteConferenceEventHandler::RemoteConferenceEventHandler (RemoteConference *remoteConference) : +Object(*new RemoteConferenceEventHandlerPrivate) { + L_D(); + d->conf = remoteConference; + d->conf->getCore()->getPrivate()->registerListener(d); +} + +RemoteConferenceEventHandler::~RemoteConferenceEventHandler () { + L_D(); + + try { + d->conf->getCore()->getPrivate()->unregisterListener(d); + } catch (const bad_weak_ptr &) { + // Unable to unregister listener here. Core is destroyed and the listener doesn't exist. + } + + unsubscribe(); +} + +// ----------------------------------------------------------------------------- + +void RemoteConferenceEventHandler::subscribe (const ChatRoomId &chatRoomId) { + L_D(); + d->chatRoomId = chatRoomId; + d->subscriptionWanted = true; + d->subscribe(); +} + +void RemoteConferenceEventHandler::unsubscribe () { + L_D(); + d->unsubscribe(); + d->subscriptionWanted = false; +} + +void RemoteConferenceEventHandler::notifyReceived (const string &xmlBody) { + L_D(); + + lInfo() << "NOTIFY received for conference: " << d->chatRoomId; + + d->simpleNotifyReceived(xmlBody); +} + +void RemoteConferenceEventHandler::multipartNotifyReceived (const string &xmlBody) { + L_D(); + + lInfo() << "multipart NOTIFY received for conference: " << d->chatRoomId; + + Content multipart; + multipart.setBody(xmlBody); + ContentType contentType(ContentType::Multipart); + contentType.addParameter("boundary", MultipartBoundary); + multipart.setContentType(contentType); + + for (const auto &content : ContentManager::multipartToContentList(multipart)) + d->simpleNotifyReceived(content.getBodyAsString()); +} + +// ----------------------------------------------------------------------------- + +void RemoteConferenceEventHandler::setChatRoomId (ChatRoomId chatRoomId) { + L_D(); + d->chatRoomId = chatRoomId; +} + +const ChatRoomId &RemoteConferenceEventHandler::getChatRoomId () const { + L_D(); + return d->chatRoomId; +} + +unsigned int RemoteConferenceEventHandler::getLastNotify () const { + L_D(); + return d->lastNotify; +}; + +void RemoteConferenceEventHandler::setLastNotify (unsigned int lastNotify) { + L_D(); + d->lastNotify = lastNotify; +} + +void RemoteConferenceEventHandler::resetLastNotify () { + setLastNotify(0); +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/handlers/remote-conference-event-handler.h b/src/conference/handlers/remote-conference-event-handler.h new file mode 100644 index 000000000..f1d13db6e --- /dev/null +++ b/src/conference/handlers/remote-conference-event-handler.h @@ -0,0 +1,59 @@ +/* + * remote-conference-event-handler.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REMOTE_CONFERENCE_EVENT_HANDLER_H_ +#define _L_REMOTE_CONFERENCE_EVENT_HANDLER_H_ + +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatRoomId; +class RemoteConference; +class RemoteConferenceEventHandlerPrivate; + +class LINPHONE_PUBLIC RemoteConferenceEventHandler : public Object { + friend class ClientGroupChatRoom; + +public: + RemoteConferenceEventHandler (RemoteConference *remoteConference); + ~RemoteConferenceEventHandler (); + + void subscribe (const ChatRoomId &chatRoomId); + void notifyReceived (const std::string &xmlBody); + void multipartNotifyReceived (const std::string &xmlBody); + void unsubscribe (); + + void setChatRoomId (ChatRoomId chatRoomId); + const ChatRoomId &getChatRoomId () const; + + unsigned int getLastNotify () const; + void setLastNotify (unsigned int lastNotify); + void resetLastNotify (); + +private: + L_DECLARE_PRIVATE(RemoteConferenceEventHandler); + L_DISABLE_COPY(RemoteConferenceEventHandler); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REMOTE_CONFERENCE_EVENT_HANDLER_H_ diff --git a/src/conference/handlers/remote-conference-list-event-handler.cpp b/src/conference/handlers/remote-conference-list-event-handler.cpp new file mode 100644 index 000000000..0ea5f22c3 --- /dev/null +++ b/src/conference/handlers/remote-conference-list-event-handler.cpp @@ -0,0 +1,255 @@ +/* + * remote-conference-list-event-handler.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/core.h" +#include "linphone/event.h" +#include "linphone/proxy_config.h" +#include "linphone/utils/utils.h" + +#include "address/address.h" +#include "c-wrapper/c-wrapper.h" +#include "content/content-manager.h" +#include "content/content-type.h" +#include "core/core-p.h" +#include "logger/logger.h" +#include "remote-conference-event-handler.h" +#include "remote-conference-list-event-handler.h" +#include "xml/conference-info.h" +#include "xml/resource-lists.h" +#include "xml/rlmi.h" + +// TODO: Remove me later. +#include "private.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +RemoteConferenceListEventHandler::RemoteConferenceListEventHandler (const std::shared_ptr &core) : CoreAccessor(core) { + getCore()->getPrivate()->registerListener(this); +} + +RemoteConferenceListEventHandler::~RemoteConferenceListEventHandler () { + try { + getCore()->getPrivate()->unregisterListener(this); + } catch (const bad_weak_ptr &) { + // Unable to unregister listener here. Core is destroyed and the listener doesn't exist. + } + + unsubscribe(); +} + +// ----------------------------------------------------------------------------- + +void RemoteConferenceListEventHandler::subscribe () { + if (lev) { + linphone_event_unref(lev); + lev = nullptr; + } + + if (handlers.size() == 0) + return; + + Content content; + content.setContentType(ContentType::ResourceLists); + + Xsd::ResourceLists::ResourceLists rl = Xsd::ResourceLists::ResourceLists(); + Xsd::ResourceLists::ListType l = Xsd::ResourceLists::ListType(); + for (const auto &handler : handlers) { + const ChatRoomId &chatRoomId = handler->getChatRoomId(); + shared_ptr cr = getCore()->findChatRoom(chatRoomId); + if (!cr) + continue; + + if (cr->hasBeenLeft()) + continue; + + Address addr = chatRoomId.getPeerAddress(); + addr.setUriParam("Last-Notify", Utils::toString(handler->getLastNotify())); + Xsd::ResourceLists::EntryType entry = Xsd::ResourceLists::EntryType(addr.asStringUriOnly()); + l.getEntry().push_back(entry); + } + rl.getList().push_back(l); + + Xsd::XmlSchema::NamespaceInfomap map; + stringstream xmlBody; + serializeResourceLists(xmlBody, rl, map); + content.setBody(xmlBody.str()); + + LinphoneCore *lc = getCore()->getCCore(); + LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(lc); + if (!cfg || (linphone_proxy_config_get_state(cfg) != LinphoneRegistrationOk)) + return; + + LinphoneAddress *rlsAddr = linphone_address_new(linphone_proxy_config_get_conference_factory_uri(cfg)); + + lev = linphone_core_create_subscribe(lc, rlsAddr, "conference", 600); + char *from = linphone_address_as_string(linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(getCore()->getCCore()))); + lev->op->setFrom(from); + bctbx_free(from); + linphone_address_unref(rlsAddr); + linphone_event_set_internal(lev, TRUE); + linphone_event_add_custom_header(lev, "Require", "recipient-list-subscribe"); + linphone_event_add_custom_header(lev, "Accept", "multipart/related, application/conference-info+xml, application/rlmi+xml"); + linphone_event_add_custom_header(lev, "Content-Disposition", "recipient-list"); + if (linphone_core_content_encoding_supported(lc, "deflate")) { + content.setContentEncoding("deflate"); + linphone_event_add_custom_header(lev, "Accept-Encoding", "deflate"); + } + linphone_event_set_user_data(lev, this); + LinphoneContent *cContent = L_GET_C_BACK_PTR(&content); + linphone_event_send_subscribe(lev, cContent); +} + +void RemoteConferenceListEventHandler::unsubscribe () { + if (lev) { + linphone_event_terminate(lev); + lev = nullptr; + } +} + +void RemoteConferenceListEventHandler::notifyReceived (const Content *notifyContent) { + char *from = linphone_address_as_string(linphone_event_get_from(lev)); + const IdentityAddress local(from); + + if (notifyContent->getContentType().weakEqual(ContentType::ConferenceInfo)) { + // Simple notify received directly from a chat-room + const string &xmlBody = notifyContent->getBodyAsString(); + istringstream data(xmlBody); + unique_ptr confInfo = Xsd::ConferenceInfo::parseConferenceInfo(data, Xsd::XmlSchema::Flags::dont_validate); + + IdentityAddress entityAddress(confInfo->getEntity().c_str()); + ChatRoomId id(entityAddress, local); + RemoteConferenceEventHandler *handler = findHandler(id); + if (!handler) + return; + + handler->notifyReceived(xmlBody); + return; + } + + list contents = ContentManager::multipartToContentList(*notifyContent); + bctbx_free(from); + map addresses; + for (const auto &content : contents) { + const string &body = content.getBodyAsString(); + const ContentType &contentType = content.getContentType(); + if (contentType == ContentType::Rlmi) { + addresses = parseRlmi(body); + continue; + } + + const string &cid = content.getHeader("Content-Id").getValue(); + if (cid.empty()) + continue; + + map::const_iterator it = addresses.find(cid); + if (it == addresses.cend()) + continue; + + IdentityAddress peer = it->second; + ChatRoomId id(peer, local); + RemoteConferenceEventHandler *handler = findHandler(id); + if (!handler) + continue; + + if (contentType.weakEqual(ContentType::Multipart)) + handler->multipartNotifyReceived(body); + else if (contentType.weakEqual(ContentType::ConferenceInfo)) + handler->notifyReceived(body); + } +} + +// ----------------------------------------------------------------------------- + +RemoteConferenceEventHandler *RemoteConferenceListEventHandler::findHandler (const ChatRoomId &chatRoomId) const { + for (const auto &handler : handlers) { + if (handler->getChatRoomId() == chatRoomId) + return handler; + } + + return nullptr; +} + +const list &RemoteConferenceListEventHandler::getHandlers () const { + return handlers; +} + +void RemoteConferenceListEventHandler::addHandler (RemoteConferenceEventHandler *handler) { + if (handler) + handlers.push_back(handler); +} + +void RemoteConferenceListEventHandler::removeHandler (RemoteConferenceEventHandler *handler) { + if (handler) + handlers.remove(handler); +} + +map RemoteConferenceListEventHandler::parseRlmi (const string &xmlBody) const { + istringstream data(xmlBody); + unique_ptr rlmi(Xsd::Rlmi::parseList( + data, + Xsd::XmlSchema::Flags::dont_validate + )); + map addresses; + for (const auto &resource : rlmi->getResource()) { + if (resource.getInstance().empty()) + continue; + + const string &uri = string(resource.getUri()); + if (uri.empty()) + continue; + + IdentityAddress peer(uri); + for (const auto &instance : resource.getInstance()) { + const string &cid = string(instance.getId()); + if (cid.empty()) + continue; + + addresses.emplace(cid, peer); + } + } + return addresses; +} + +// ----------------------------------------------------------------------------- + +void RemoteConferenceListEventHandler::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + if (!sipNetworkReachable) + unsubscribe(); +} + +void RemoteConferenceListEventHandler::onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message) { + if (state == LinphoneRegistrationOk) + subscribe(); +} + +void RemoteConferenceListEventHandler::onEnteringBackground () { + unsubscribe(); +} + +void RemoteConferenceListEventHandler::onEnteringForeground () { + subscribe(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/handlers/remote-conference-list-event-handler.h b/src/conference/handlers/remote-conference-list-event-handler.h new file mode 100644 index 000000000..c93dc4ca5 --- /dev/null +++ b/src/conference/handlers/remote-conference-list-event-handler.h @@ -0,0 +1,70 @@ +/* + * remote-conference-list-event-handler.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REMOTE_CONFERENCE_LIST_EVENT_HANDLER_H_ +#define _L_REMOTE_CONFERENCE_LIST_EVENT_HANDLER_H_ + +#include +#include +#include + +#include "linphone/types.h" +#include "linphone/utils/general.h" + +#include "chat/chat-room/chat-room-id.h" +#include "core/core-accessor.h" +#include "core/core-listener.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Address; +class Content; +class RemoteConferenceEventHandler; + +class RemoteConferenceListEventHandler : public CoreAccessor , public CoreListener { +public: + RemoteConferenceListEventHandler (const std::shared_ptr &core); + ~RemoteConferenceListEventHandler (); + + void subscribe (); + void unsubscribe (); + void notifyReceived (const Content *notifyContent); + void addHandler (RemoteConferenceEventHandler *handler); + void removeHandler (RemoteConferenceEventHandler *handler); + RemoteConferenceEventHandler *findHandler (const ChatRoomId &chatRoomId) const; + const std::list &getHandlers () const; + +private: + std::list handlers; + LinphoneEvent *lev = nullptr; + + std::map parseRlmi (const std::string &xmlBody) const; + + // CoreListener + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; + void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message) override; + void onEnteringBackground () override; + void onEnteringForeground () override; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REMOTE_CONFERENCE_LIST_EVENT_HANDLER_H_ diff --git a/src/conference/local-conference-p.h b/src/conference/local-conference-p.h new file mode 100644 index 000000000..eef8f9f87 --- /dev/null +++ b/src/conference/local-conference-p.h @@ -0,0 +1,42 @@ +/* + * local-conference-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LOCAL_CONFERENCE_P_H_ +#define _L_LOCAL_CONFERENCE_P_H_ + +#include "conference-p.h" +#include "local-conference.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class LocalConferenceEventHandler; + +class LocalConferencePrivate : public ConferencePrivate { +public: + std::unique_ptr eventHandler; + +private: + L_DECLARE_PUBLIC(LocalConference); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LOCAL_CONFERENCE_P_H_ diff --git a/src/conference/local-conference.cpp b/src/conference/local-conference.cpp new file mode 100644 index 000000000..ea6e9caa4 --- /dev/null +++ b/src/conference/local-conference.cpp @@ -0,0 +1,68 @@ +/* + * local-conference.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "handlers/local-conference-event-handler.h" +#include "local-conference-p.h" +#include "logger/logger.h" +#include "participant-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +LocalConference::LocalConference (const shared_ptr &core, const IdentityAddress &myAddress, CallSessionListener *listener) + : Conference(*new LocalConferencePrivate, core, myAddress, listener) { + L_D(); + d->eventHandler.reset(new LocalConferenceEventHandler(this)); +} + +LocalConference::~LocalConference () { + L_D(); + d->eventHandler.reset(); +} + +// ----------------------------------------------------------------------------- + +void LocalConference::addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) { + L_D(); + shared_ptr participant = findParticipant(addr); + if (participant) { + lInfo() << "Not adding participant '" << addr.asString() << "' because it is already a participant of the LocalConference"; + return; + } + participant = make_shared(this, addr); + participant->getPrivate()->createSession(*this, params, hasMedia, d->listener); + d->participants.push_back(participant); + if (!d->activeParticipant) + d->activeParticipant = participant; +} + +void LocalConference::removeParticipant (const shared_ptr &participant) { + L_D(); + for (const auto &p : d->participants) { + if (participant->getAddress() == p->getAddress()) { + d->participants.remove(p); + return; + } + } +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/local-conference.h b/src/conference/local-conference.h new file mode 100644 index 000000000..31942e241 --- /dev/null +++ b/src/conference/local-conference.h @@ -0,0 +1,49 @@ +/* + * local-conference.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LOCAL_CONFERENCE_H_ +#define _L_LOCAL_CONFERENCE_H_ + +#include "conference.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class LocalConferencePrivate; + +class LINPHONE_PUBLIC LocalConference : public Conference { + friend class ServerGroupChatRoomPrivate; + +public: + LocalConference (const std::shared_ptr &core, const IdentityAddress &myAddress, CallSessionListener *listener); + virtual ~LocalConference (); + + /* ConferenceInterface */ + void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override; + void removeParticipant (const std::shared_ptr &participant) override; + +private: + L_DECLARE_PRIVATE(LocalConference); + L_DISABLE_COPY(LocalConference); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LOCAL_CONFERENCE_H_ diff --git a/src/conference/params/call-session-params-p.h b/src/conference/params/call-session-params-p.h new file mode 100644 index 000000000..74a7c0072 --- /dev/null +++ b/src/conference/params/call-session-params-p.h @@ -0,0 +1,72 @@ +/* + * call-sessio-params-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_SESSION_PARAMS_P_H_ +#define _L_CALL_SESSION_PARAMS_P_H_ + +#include + +#include "object/clonable-object-p.h" + +#include "call-session-params.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSession; + +class CallSessionParamsPrivate : public ClonableObjectPrivate { +public: + void clone (const CallSessionParamsPrivate *src); + + bool getInConference () const { return inConference; } + void setInConference (bool value) { inConference = value; } + bool getInternalCallUpdate () const { return internalCallUpdate; } + void setInternalCallUpdate (bool value) { internalCallUpdate = value; } + bool getNoUserConsent () const { return noUserConsent; } + void setNoUserConsent (bool value) { noUserConsent = value; } + + SalCustomHeader * getCustomHeaders () const; + void setCustomHeaders (const SalCustomHeader *ch); + + const std::unordered_map &getCustomContactParameters () const { return customContactParameters; } + + std::shared_ptr getReferer () const { return referer; } + void setReferer (std::shared_ptr session) { referer = session; } + +public: + std::string sessionName; + + LinphonePrivacyMask privacy = LinphonePrivacyNone; + +private: + bool inConference = false; + bool internalCallUpdate = false; + bool noUserConsent = false; /* When set to true an UPDATE request will be used instead of reINVITE */ + SalCustomHeader *customHeaders = nullptr; + std::unordered_map customContactParameters; + std::shared_ptr referer; /* In case call creation is consecutive to an incoming transfer, this points to the original call */ + + L_DECLARE_PUBLIC(CallSessionParams); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CALL_SESSION_PARAMS_P_H_ diff --git a/src/conference/params/call-session-params.cpp b/src/conference/params/call-session-params.cpp new file mode 100644 index 000000000..4b8a11912 --- /dev/null +++ b/src/conference/params/call-session-params.cpp @@ -0,0 +1,160 @@ +/* + * call-session-params.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "call-session-params-p.h" + +#include "call-session-params.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ============================================================================= + +void CallSessionParamsPrivate::clone (const CallSessionParamsPrivate *src) { + sessionName = src->sessionName; + privacy = src->privacy; + inConference = src->inConference; + internalCallUpdate = src->internalCallUpdate; + noUserConsent = src->noUserConsent; + /* The management of the custom headers is not optimal. We copy everything while ref counting would be more efficient. */ + if (customHeaders) { + sal_custom_header_free(customHeaders); + customHeaders = nullptr; + } + if (src->customHeaders) + customHeaders = sal_custom_header_clone(src->customHeaders); + customContactParameters = src->customContactParameters; + referer = src->referer; +} + +// ----------------------------------------------------------------------------- + +SalCustomHeader * CallSessionParamsPrivate::getCustomHeaders () const { + return customHeaders; +} + +void CallSessionParamsPrivate::setCustomHeaders (const SalCustomHeader *ch) { + if (customHeaders) { + sal_custom_header_free(customHeaders); + customHeaders = nullptr; + } + if (ch) + customHeaders = sal_custom_header_clone(ch); +} + +// ============================================================================= + +CallSessionParams::CallSessionParams () : ClonableObject(*new CallSessionParamsPrivate) {} + +CallSessionParams::CallSessionParams (CallSessionParamsPrivate &p) : ClonableObject(p) {} + +CallSessionParams::CallSessionParams (const CallSessionParams &other) + : ClonableObject(*new CallSessionParamsPrivate) { + L_D(); + d->clone(other.getPrivate()); +} + +CallSessionParams::~CallSessionParams () { + L_D(); + if (d->customHeaders) + sal_custom_header_free(d->customHeaders); +} + +CallSessionParams &CallSessionParams::operator= (const CallSessionParams &other) { + L_D(); + if (this != &other) + d->clone(other.getPrivate()); + return *this; +} + +// ----------------------------------------------------------------------------- + +void CallSessionParams::initDefault (const std::shared_ptr &core) { + L_D(); + d->inConference = false; + d->privacy = LinphonePrivacyDefault; +} + +// ----------------------------------------------------------------------------- + +const string& CallSessionParams::getSessionName () const { + L_D(); + return d->sessionName; +} + +void CallSessionParams::setSessionName (const string &sessionName) { + L_D(); + d->sessionName = sessionName; +} + +// ----------------------------------------------------------------------------- + +LinphonePrivacyMask CallSessionParams::getPrivacy () const { + L_D(); + return d->privacy; +} + +void CallSessionParams::setPrivacy (LinphonePrivacyMask privacy) { + L_D(); + d->privacy = privacy; +} + +// ----------------------------------------------------------------------------- + +void CallSessionParams::addCustomHeader (const string &headerName, const string &headerValue) { + L_D(); + d->customHeaders = sal_custom_header_append(d->customHeaders, headerName.c_str(), headerValue.c_str()); +} + +void CallSessionParams::clearCustomHeaders () { + L_D(); + d->setCustomHeaders(nullptr); +} + +const char * CallSessionParams::getCustomHeader (const string &headerName) const { + L_D(); + return sal_custom_header_find(d->customHeaders, headerName.c_str()); +} + +// ----------------------------------------------------------------------------- + +void CallSessionParams::addCustomContactParameter (const std::string ¶mName, const std::string ¶mValue) { + L_D(); + auto it = d->customContactParameters.find(paramName); + if (it != d->customContactParameters.end()) + d->customContactParameters.erase(it); + pair param(paramName, paramValue); + d->customContactParameters.insert(param); +} + +void CallSessionParams::clearCustomContactParameters () { + L_D(); + d->customContactParameters.clear(); +} + +std::string CallSessionParams::getCustomContactParameter (const std::string ¶mName) const { + L_D(); + auto it = d->customContactParameters.find(paramName); + if (it == d->customContactParameters.end()) + return ""; + return it->second; +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/params/call-session-params.h b/src/conference/params/call-session-params.h new file mode 100644 index 000000000..986c53216 --- /dev/null +++ b/src/conference/params/call-session-params.h @@ -0,0 +1,73 @@ +/* + * call-session-params.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_SESSION_PARAMS_H_ +#define _L_CALL_SESSION_PARAMS_H_ + +#include "object/clonable-object.h" + +#include "linphone/types.h" +#include "c-wrapper/internal/c-sal.h" +#include "sal/sal.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSessionParamsPrivate; +class Core; + +class LINPHONE_PUBLIC CallSessionParams : public ClonableObject { + friend class CallSession; + friend class CallSessionPrivate; + friend class ClientGroupChatRoom; + +public: + CallSessionParams (); + CallSessionParams (const CallSessionParams &other); + virtual ~CallSessionParams (); + + CallSessionParams &operator= (const CallSessionParams &other); + + virtual void initDefault (const std::shared_ptr &core); + + const std::string& getSessionName () const; + void setSessionName (const std::string &sessionName); + + LinphonePrivacyMask getPrivacy () const; + void setPrivacy (LinphonePrivacyMask privacy); + + void addCustomHeader (const std::string &headerName, const std::string &headerValue); + void clearCustomHeaders (); + const char * getCustomHeader (const std::string &headerName) const; + + void addCustomContactParameter (const std::string ¶mName, const std::string ¶mValue = ""); + void clearCustomContactParameters (); + std::string getCustomContactParameter (const std::string ¶mName) const; + +protected: + explicit CallSessionParams (CallSessionParamsPrivate &p); + +private: + L_DECLARE_PRIVATE(CallSessionParams); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CALL_SESSION_PARAMS_H_ diff --git a/src/conference/params/media-session-params-p.h b/src/conference/params/media-session-params-p.h new file mode 100644 index 000000000..2961aa525 --- /dev/null +++ b/src/conference/params/media-session-params-p.h @@ -0,0 +1,120 @@ +/* + * media-session-params-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MEDIA_SESSION_PARAMS_P_H_ +#define _L_MEDIA_SESSION_PARAMS_P_H_ + +#include "call-session-params-p.h" + +#include "media-session-params.h" + +// ============================================================================= + +extern LinphoneCallParams * linphone_call_params_new_for_wrapper(void); + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class MediaSessionParamsPrivate : public CallSessionParamsPrivate { +public: + void clone (const MediaSessionParamsPrivate *src); + void clean (); + + static SalStreamDir mediaDirectionToSalStreamDir (LinphoneMediaDirection direction); + static LinphoneMediaDirection salStreamDirToMediaDirection (SalStreamDir dir); + + void adaptToNetwork (LinphoneCore *core, int pingTimeMs); + + SalStreamDir getSalAudioDirection () const; + SalStreamDir getSalVideoDirection () const; + + void enableImplicitRtcpFb (bool value) { _implicitRtcpFbEnabled = value; } + bool implicitRtcpFbEnabled () const { return _implicitRtcpFbEnabled; } + int getDownBandwidth () const { return downBandwidth; } + void setDownBandwidth (int value) { downBandwidth = value; } + int getUpBandwidth () const { return upBandwidth; } + void setUpBandwidth (int value) { upBandwidth = value; } + int getDownPtime () const { return downPtime; } + void setDownPtime (int value) { downPtime = value; } + int getUpPtime () const { return upPtime; } + void setUpPtime (int value) { upPtime = value; } + bool getUpdateCallWhenIceCompleted () const { return updateCallWhenIceCompleted; } + void setUpdateCallWhenIceCompleted (bool value) { updateCallWhenIceCompleted = value; } + + void setReceivedFps (float value) { receivedFps = value; } + void setReceivedVideoDefinition (LinphoneVideoDefinition *value); + void setSentFps (float value) { sentFps = value; } + void setSentVideoDefinition (LinphoneVideoDefinition *value); + void setUsedAudioCodec (OrtpPayloadType *pt) { usedAudioCodec = pt; } + void setUsedVideoCodec (OrtpPayloadType *pt) { usedVideoCodec = pt; } + void setUsedRealtimeTextCodec (OrtpPayloadType *pt) { usedRealtimeTextCodec = pt; } + + SalCustomSdpAttribute * getCustomSdpAttributes () const; + void setCustomSdpAttributes (const SalCustomSdpAttribute *csa); + SalCustomSdpAttribute * getCustomSdpMediaAttributes (LinphoneStreamType lst) const; + void setCustomSdpMediaAttributes (LinphoneStreamType lst, const SalCustomSdpAttribute *csa); + +public: + bool audioEnabled = true; + int audioBandwidthLimit = 0; + LinphoneMediaDirection audioDirection = LinphoneMediaDirectionSendRecv; + bool audioMulticastEnabled = false; + PayloadType *usedAudioCodec = nullptr; + + bool videoEnabled = false; + LinphoneMediaDirection videoDirection = LinphoneMediaDirectionSendRecv; + bool videoMulticastEnabled = false; + PayloadType *usedVideoCodec = nullptr; + float receivedFps = 0.f; + LinphoneVideoDefinition *receivedVideoDefinition = nullptr; + float sentFps = 0.f; + LinphoneVideoDefinition *sentVideoDefinition = nullptr; + + bool realtimeTextEnabled = false; + PayloadType *usedRealtimeTextCodec = nullptr; + + bool avpfEnabled = false; + uint16_t avpfRrInterval = 0; /* In milliseconds */ + + bool lowBandwidthEnabled = false; + + std::string recordFilePath; + + bool earlyMediaSendingEnabled = false; /* Send real media even during early media (for outgoing calls) */ + + LinphoneMediaEncryption encryption = LinphoneMediaEncryptionNone; + bool mandatoryMediaEncryptionEnabled = false; + +private: + bool _implicitRtcpFbEnabled = false; + int downBandwidth = 0; + int upBandwidth = 0; + int downPtime = 0; + int upPtime = 0; + bool updateCallWhenIceCompleted = true; + SalCustomSdpAttribute *customSdpAttributes = nullptr; + SalCustomSdpAttribute *customSdpMediaAttributes[LinphoneStreamTypeUnknown]; + + L_DECLARE_PUBLIC(MediaSessionParams); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MEDIA_SESSION_PARAMS_P_H_ diff --git a/src/conference/params/media-session-params.cpp b/src/conference/params/media-session-params.cpp new file mode 100644 index 000000000..680e8385b --- /dev/null +++ b/src/conference/params/media-session-params.cpp @@ -0,0 +1,520 @@ +/* + * media-session-params.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "call-session-params-p.h" +#include "media-session-params-p.h" + +#include "media-session-params.h" + +#include "core/core.h" +#include "logger/logger.h" + +#include "private.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ============================================================================= + +void MediaSessionParamsPrivate::clone (const MediaSessionParamsPrivate *src) { + clean(); + CallSessionParamsPrivate::clone(src); + audioEnabled = src->audioEnabled; + audioBandwidthLimit = src->audioBandwidthLimit; + audioDirection = src->audioDirection; + audioMulticastEnabled = src->audioMulticastEnabled; + usedAudioCodec = src->usedAudioCodec; + videoEnabled = src->videoEnabled; + videoDirection = src->videoDirection; + videoMulticastEnabled = src->videoMulticastEnabled; + usedVideoCodec = src->usedVideoCodec; + receivedFps = src->receivedFps; + receivedVideoDefinition = src->receivedVideoDefinition ? linphone_video_definition_ref(src->receivedVideoDefinition) : nullptr; + sentFps = src->sentFps; + sentVideoDefinition = src->sentVideoDefinition ? linphone_video_definition_ref(src->sentVideoDefinition) : nullptr; + realtimeTextEnabled = src->realtimeTextEnabled; + usedRealtimeTextCodec = src->usedRealtimeTextCodec; + avpfEnabled = src->avpfEnabled; + avpfRrInterval = src->avpfRrInterval; + lowBandwidthEnabled = src->lowBandwidthEnabled; + recordFilePath = src->recordFilePath; + earlyMediaSendingEnabled = src->earlyMediaSendingEnabled; + encryption = src->encryption; + mandatoryMediaEncryptionEnabled = src->mandatoryMediaEncryptionEnabled; + _implicitRtcpFbEnabled = src->_implicitRtcpFbEnabled; + downBandwidth = src->downBandwidth; + upBandwidth = src->upBandwidth; + downPtime = src->downPtime; + upPtime = src->upPtime; + updateCallWhenIceCompleted = src->updateCallWhenIceCompleted; + if (src->customSdpAttributes) + customSdpAttributes = sal_custom_sdp_attribute_clone(src->customSdpAttributes); + for (unsigned int i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) { + if (src->customSdpMediaAttributes[i]) + customSdpMediaAttributes[i] = sal_custom_sdp_attribute_clone(src->customSdpMediaAttributes[i]); + } +} + +void MediaSessionParamsPrivate::clean () { + if (receivedVideoDefinition) + linphone_video_definition_unref(receivedVideoDefinition); + if (sentVideoDefinition) + linphone_video_definition_unref(sentVideoDefinition); + if (customSdpAttributes) + sal_custom_sdp_attribute_free(customSdpAttributes); + for (unsigned int i = 0; i < (unsigned int)LinphoneStreamTypeUnknown; i++) { + if (customSdpMediaAttributes[i]) + sal_custom_sdp_attribute_free(customSdpMediaAttributes[i]); + } + memset(customSdpMediaAttributes, 0, sizeof(customSdpMediaAttributes)); +} + +// ----------------------------------------------------------------------------- + +SalStreamDir MediaSessionParamsPrivate::mediaDirectionToSalStreamDir (LinphoneMediaDirection direction) { + switch (direction) { + case LinphoneMediaDirectionInactive: + return SalStreamInactive; + case LinphoneMediaDirectionSendOnly: + return SalStreamSendOnly; + case LinphoneMediaDirectionRecvOnly: + return SalStreamRecvOnly; + case LinphoneMediaDirectionSendRecv: + return SalStreamSendRecv; + case LinphoneMediaDirectionInvalid: + lError() << "LinphoneMediaDirectionInvalid shall not be used"; + return SalStreamInactive; + } + return SalStreamSendRecv; +} + +LinphoneMediaDirection MediaSessionParamsPrivate::salStreamDirToMediaDirection (SalStreamDir dir) { + switch (dir) { + case SalStreamInactive: + return LinphoneMediaDirectionInactive; + case SalStreamSendOnly: + return LinphoneMediaDirectionSendOnly; + case SalStreamRecvOnly: + return LinphoneMediaDirectionRecvOnly; + case SalStreamSendRecv: + return LinphoneMediaDirectionSendRecv; + } + return LinphoneMediaDirectionSendRecv; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParamsPrivate::adaptToNetwork (LinphoneCore *core, int pingTimeMs) { + L_Q(); + if ((pingTimeMs > 0) && lp_config_get_int(linphone_core_get_config(core), "net", "activate_edge_workarounds", 0)) { + lInfo() << "STUN server ping time is " << pingTimeMs << " ms"; + int threshold = lp_config_get_int(linphone_core_get_config(core), "net", "edge_ping_time", 500); + if (pingTimeMs > threshold) { + /* We might be in a 2G network */ + q->enableLowBandwidth(true); + } /* else use default settings */ + } + if (q->lowBandwidthEnabled()) { + setUpBandwidth(linphone_core_get_edge_bw(core)); + setDownBandwidth(linphone_core_get_edge_bw(core)); + setUpPtime(linphone_core_get_edge_ptime(core)); + setDownPtime(linphone_core_get_edge_ptime(core)); + q->enableVideo(false); + } +} + +// ----------------------------------------------------------------------------- + +SalStreamDir MediaSessionParamsPrivate::getSalAudioDirection () const { + L_Q(); + return mediaDirectionToSalStreamDir(q->getAudioDirection()); +} + +SalStreamDir MediaSessionParamsPrivate::getSalVideoDirection () const { + L_Q(); + return mediaDirectionToSalStreamDir(q->getVideoDirection()); +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParamsPrivate::setReceivedVideoDefinition (LinphoneVideoDefinition *value) { + if (receivedVideoDefinition) + linphone_video_definition_unref(receivedVideoDefinition); + receivedVideoDefinition = linphone_video_definition_ref(value); +} + +void MediaSessionParamsPrivate::setSentVideoDefinition (LinphoneVideoDefinition *value) { + if (sentVideoDefinition) + linphone_video_definition_unref(sentVideoDefinition); + sentVideoDefinition = linphone_video_definition_ref(value); +} + +// ----------------------------------------------------------------------------- + +SalCustomSdpAttribute * MediaSessionParamsPrivate::getCustomSdpAttributes () const { + return customSdpAttributes; +} + +void MediaSessionParamsPrivate::setCustomSdpAttributes (const SalCustomSdpAttribute *csa) { + if (customSdpAttributes) { + sal_custom_sdp_attribute_free(customSdpAttributes); + customSdpAttributes = nullptr; + } + if (csa) + customSdpAttributes = sal_custom_sdp_attribute_clone(csa); +} + +// ----------------------------------------------------------------------------- + +SalCustomSdpAttribute * MediaSessionParamsPrivate::getCustomSdpMediaAttributes (LinphoneStreamType lst) const { + return customSdpMediaAttributes[lst]; +} + +void MediaSessionParamsPrivate::setCustomSdpMediaAttributes (LinphoneStreamType lst, const SalCustomSdpAttribute *csa) { + if (customSdpMediaAttributes[lst]) { + sal_custom_sdp_attribute_free(customSdpMediaAttributes[lst]); + customSdpMediaAttributes[lst] = nullptr; + } + if (csa) + customSdpMediaAttributes[lst] = sal_custom_sdp_attribute_clone(csa); +} + +// ============================================================================= + +MediaSessionParams::MediaSessionParams () : CallSessionParams(*new MediaSessionParamsPrivate) { + L_D(); + memset(d->customSdpMediaAttributes, 0, sizeof(d->customSdpMediaAttributes)); +} + +MediaSessionParams::MediaSessionParams (const MediaSessionParams &other) + : CallSessionParams(*new MediaSessionParamsPrivate) { + L_D(); + memset(d->customSdpMediaAttributes, 0, sizeof(d->customSdpMediaAttributes)); + d->clone(other.getPrivate()); +} + +MediaSessionParams::~MediaSessionParams () { + L_D(); + d->clean(); +} + +MediaSessionParams &MediaSessionParams::operator= (const MediaSessionParams &other) { + L_D(); + if (this != &other) + d->clone(other.getPrivate()); + return *this; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParams::initDefault (const std::shared_ptr &core) { + L_D(); + CallSessionParams::initDefault(core); + LinphoneCore *cCore = core->getCCore(); + d->audioEnabled = true; + d->videoEnabled = linphone_core_video_enabled(cCore) && cCore->video_policy.automatically_initiate; + if (!linphone_core_video_enabled(cCore) && cCore->video_policy.automatically_initiate) { + lError() << "LinphoneCore has video disabled for both capture and display, but video policy is to start the call with video. " + "This is a possible mis-use of the API. In this case, video is disabled in default LinphoneCallParams"; + } + d->realtimeTextEnabled = !!linphone_core_realtime_text_enabled(cCore); + d->encryption = linphone_core_get_media_encryption(cCore); + d->avpfEnabled = (linphone_core_get_avpf_mode(cCore) == LinphoneAVPFEnabled); + d->_implicitRtcpFbEnabled = !!lp_config_get_int(linphone_core_get_config(cCore), "rtp", "rtcp_fb_implicit_rtcp_fb", true); + d->avpfRrInterval = static_cast(linphone_core_get_avpf_rr_interval(cCore)); + d->audioDirection = LinphoneMediaDirectionSendRecv; + d->videoDirection = LinphoneMediaDirectionSendRecv; + d->earlyMediaSendingEnabled = !!lp_config_get_int(linphone_core_get_config(cCore), "misc", "real_early_media", false); + d->audioMulticastEnabled = !!linphone_core_audio_multicast_enabled(cCore); + d->videoMulticastEnabled = !!linphone_core_video_multicast_enabled(cCore); + d->updateCallWhenIceCompleted = !!lp_config_get_int(linphone_core_get_config(cCore), "sip", "update_call_when_ice_completed", true); + d->mandatoryMediaEncryptionEnabled = !!linphone_core_is_media_encryption_mandatory(cCore); +} + +// ----------------------------------------------------------------------------- + +bool MediaSessionParams::audioEnabled () const { + L_D(); + return d->audioEnabled; +} + +bool MediaSessionParams::audioMulticastEnabled () const { + L_D(); + return d->audioMulticastEnabled; +} + +void MediaSessionParams::enableAudio (bool value) { + L_D(); + d->audioEnabled = value; + if (d->audioEnabled && (getAudioDirection() == LinphoneMediaDirectionInactive)) + setAudioDirection(LinphoneMediaDirectionSendRecv); +} + +void MediaSessionParams::enableAudioMulticast (bool value) { + L_D(); + d->audioMulticastEnabled = value; +} + +int MediaSessionParams::getAudioBandwidthLimit () const { + L_D(); + return d->audioBandwidthLimit; +} + +LinphoneMediaDirection MediaSessionParams::getAudioDirection () const { + L_D(); + return d->audioDirection; +} + +const OrtpPayloadType * MediaSessionParams::getUsedAudioCodec () const { + L_D(); + return d->usedAudioCodec; +} + +LinphonePayloadType * MediaSessionParams::getUsedAudioPayloadType () const { + L_D(); + return d->usedAudioCodec ? linphone_payload_type_new(nullptr, d->usedAudioCodec) : nullptr; +} + +void MediaSessionParams::setAudioBandwidthLimit (int value) { + L_D(); + d->audioBandwidthLimit = value; +} + +void MediaSessionParams::setAudioDirection (LinphoneMediaDirection direction) { + L_D(); + d->audioDirection = direction; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParams::enableVideo (bool value) { + L_D(); + d->videoEnabled = value; + if (d->videoEnabled && (getVideoDirection() == LinphoneMediaDirectionInactive)) + setVideoDirection(LinphoneMediaDirectionSendRecv); +} + +void MediaSessionParams::enableVideoMulticast (bool value) { + L_D(); + d->videoMulticastEnabled = value; +} + +float MediaSessionParams::getReceivedFps () const { + L_D(); + return d->receivedFps; +} + +LinphoneVideoDefinition * MediaSessionParams::getReceivedVideoDefinition () const { + L_D(); + return d->receivedVideoDefinition; +} + +float MediaSessionParams::getSentFps () const { + L_D(); + return d->sentFps; +} + +LinphoneVideoDefinition * MediaSessionParams::getSentVideoDefinition () const { + L_D(); + return d->sentVideoDefinition; +} + +const OrtpPayloadType * MediaSessionParams::getUsedVideoCodec () const { + L_D(); + return d->usedVideoCodec; +} + +LinphonePayloadType * MediaSessionParams::getUsedVideoPayloadType () const { + L_D(); + return d->usedVideoCodec ? linphone_payload_type_new(nullptr, d->usedVideoCodec) : nullptr; +} + +LinphoneMediaDirection MediaSessionParams::getVideoDirection () const { + L_D(); + return d->videoDirection; +} + +void MediaSessionParams::setVideoDirection (LinphoneMediaDirection direction) { + L_D(); + d->videoDirection = direction; +} + +bool MediaSessionParams::videoEnabled () const { + L_D(); + return d->videoEnabled; +} + +bool MediaSessionParams::videoMulticastEnabled () const { + L_D(); + return d->videoMulticastEnabled; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParams::enableRealtimeText (bool value) { + L_D(); + d->realtimeTextEnabled = value; +} + +const OrtpPayloadType * MediaSessionParams::getUsedRealtimeTextCodec () const { + L_D(); + return d->usedRealtimeTextCodec; +} + +LinphonePayloadType * MediaSessionParams::getUsedRealtimeTextPayloadType () const { + L_D(); + return d->usedRealtimeTextCodec ? linphone_payload_type_new(nullptr, d->usedRealtimeTextCodec) : nullptr; +} + +bool MediaSessionParams::realtimeTextEnabled () const { + L_D(); + return d->realtimeTextEnabled; +} + +// ----------------------------------------------------------------------------- + +bool MediaSessionParams::avpfEnabled () const { + L_D(); + return d->avpfEnabled; +} + +void MediaSessionParams::enableAvpf (bool value) { + L_D(); + d->avpfEnabled = value; +} + +uint16_t MediaSessionParams::getAvpfRrInterval () const { + L_D(); + return d->avpfRrInterval; +} + +void MediaSessionParams::setAvpfRrInterval (uint16_t value) { + L_D(); + d->avpfRrInterval = value; +} + +// ----------------------------------------------------------------------------- + +bool MediaSessionParams::lowBandwidthEnabled () const { + L_D(); + return d->lowBandwidthEnabled; +} + +void MediaSessionParams::enableLowBandwidth (bool value) { + L_D(); + d->lowBandwidthEnabled = value; +} + +// ----------------------------------------------------------------------------- + +const string& MediaSessionParams::getRecordFilePath () const { + L_D(); + return d->recordFilePath; +} + +void MediaSessionParams::setRecordFilePath (const string &path) { + L_D(); + d->recordFilePath = path; +} + +// ----------------------------------------------------------------------------- + +bool MediaSessionParams::earlyMediaSendingEnabled () const { + L_D(); + return d->earlyMediaSendingEnabled; +} + +void MediaSessionParams::enableEarlyMediaSending (bool value) { + L_D(); + d->earlyMediaSendingEnabled = value; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParams::enableMandatoryMediaEncryption (bool value) { + L_D(); + d->mandatoryMediaEncryptionEnabled = value; +} + +LinphoneMediaEncryption MediaSessionParams::getMediaEncryption () const { + L_D(); + return d->encryption; +} + +bool MediaSessionParams::mandatoryMediaEncryptionEnabled () const { + L_D(); + return d->mandatoryMediaEncryptionEnabled; +} + +void MediaSessionParams::setMediaEncryption (LinphoneMediaEncryption encryption) { + L_D(); + d->encryption = encryption; +} + +// ----------------------------------------------------------------------------- + +SalMediaProto MediaSessionParams::getMediaProto () const { + if ((getMediaEncryption() == LinphoneMediaEncryptionSRTP) && avpfEnabled()) return SalProtoRtpSavpf; + if (getMediaEncryption() == LinphoneMediaEncryptionSRTP) return SalProtoRtpSavp; + if ((getMediaEncryption() == LinphoneMediaEncryptionDTLS) && avpfEnabled()) return SalProtoUdpTlsRtpSavpf; + if (getMediaEncryption() == LinphoneMediaEncryptionDTLS) return SalProtoUdpTlsRtpSavp; + if (avpfEnabled()) return SalProtoRtpAvpf; + return SalProtoRtpAvp; +} + +const char * MediaSessionParams::getRtpProfile () const { + return sal_media_proto_to_string(getMediaProto()); +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParams::addCustomSdpAttribute (const string &attributeName, const string &attributeValue) { + L_D(); + d->customSdpAttributes = sal_custom_sdp_attribute_append(d->customSdpAttributes, attributeName.c_str(), attributeValue.c_str()); +} + +void MediaSessionParams::clearCustomSdpAttributes () { + L_D(); + d->setCustomSdpAttributes(nullptr); +} + +const char * MediaSessionParams::getCustomSdpAttribute (const string &attributeName) const { + L_D(); + return sal_custom_sdp_attribute_find(d->customSdpAttributes, attributeName.c_str()); +} + +// ----------------------------------------------------------------------------- + +void MediaSessionParams::addCustomSdpMediaAttribute (LinphoneStreamType lst, const string &attributeName, const string &attributeValue) { + L_D(); + d->customSdpMediaAttributes[lst] = sal_custom_sdp_attribute_append(d->customSdpMediaAttributes[lst], attributeName.c_str(), attributeValue.c_str()); +} + +void MediaSessionParams::clearCustomSdpMediaAttributes (LinphoneStreamType lst) { + L_D(); + d->setCustomSdpMediaAttributes(lst, nullptr); +} + +const char * MediaSessionParams::getCustomSdpMediaAttribute (LinphoneStreamType lst, const string &attributeName) const { + L_D(); + return sal_custom_sdp_attribute_find(d->customSdpMediaAttributes[lst], attributeName.c_str()); +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/params/media-session-params.h b/src/conference/params/media-session-params.h new file mode 100644 index 000000000..80ceff38f --- /dev/null +++ b/src/conference/params/media-session-params.h @@ -0,0 +1,113 @@ +/* + * media-session-params.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MEDIA_SESSION_PARAMS_H_ +#define _L_MEDIA_SESSION_PARAMS_H_ + +#include + +#include "call-session-params.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class MediaSession; +class MediaSessionPrivate; +class MediaSessionParamsPrivate; + +class MediaSessionParams : public CallSessionParams { + friend class MediaSession; + friend class MediaSessionPrivate; + +public: + MediaSessionParams (); + MediaSessionParams (const MediaSessionParams &other); + virtual ~MediaSessionParams (); + + MediaSessionParams &operator= (const MediaSessionParams &other); + + void initDefault (const std::shared_ptr &core) override; + + bool audioEnabled () const; + bool audioMulticastEnabled () const; + void enableAudio (bool value); + void enableAudioMulticast (bool value); + int getAudioBandwidthLimit () const; + LinphoneMediaDirection getAudioDirection () const; + const OrtpPayloadType * getUsedAudioCodec () const; + LinphonePayloadType * getUsedAudioPayloadType () const; + void setAudioBandwidthLimit (int value); + void setAudioDirection (LinphoneMediaDirection direction); + + void enableVideo (bool value); + void enableVideoMulticast (bool value); + float getReceivedFps () const; + LinphoneVideoDefinition * getReceivedVideoDefinition () const; + float getSentFps () const; + LinphoneVideoDefinition * getSentVideoDefinition () const; + const OrtpPayloadType * getUsedVideoCodec () const; + LinphonePayloadType * getUsedVideoPayloadType () const; + LinphoneMediaDirection getVideoDirection () const; + void setVideoDirection (LinphoneMediaDirection direction); + bool videoEnabled () const; + bool videoMulticastEnabled () const; + + void enableRealtimeText (bool value); + const OrtpPayloadType * getUsedRealtimeTextCodec () const; + LinphonePayloadType * getUsedRealtimeTextPayloadType () const; + bool realtimeTextEnabled () const; + + bool avpfEnabled () const; + void enableAvpf (bool value); + uint16_t getAvpfRrInterval () const; + void setAvpfRrInterval (uint16_t value); + + bool lowBandwidthEnabled () const; + void enableLowBandwidth (bool value); + + const std::string& getRecordFilePath () const; + void setRecordFilePath (const std::string &path); + + bool earlyMediaSendingEnabled () const; + void enableEarlyMediaSending (bool value); + + void enableMandatoryMediaEncryption (bool value); + LinphoneMediaEncryption getMediaEncryption () const; + bool mandatoryMediaEncryptionEnabled () const; + void setMediaEncryption (LinphoneMediaEncryption encryption); + + SalMediaProto getMediaProto () const; + const char * getRtpProfile () const; + + void addCustomSdpAttribute (const std::string &attributeName, const std::string &attributeValue); + void clearCustomSdpAttributes (); + const char * getCustomSdpAttribute (const std::string &attributeName) const; + + void addCustomSdpMediaAttribute (LinphoneStreamType lst, const std::string &attributeName, const std::string &attributeValue); + void clearCustomSdpMediaAttributes (LinphoneStreamType lst); + const char * getCustomSdpMediaAttribute (LinphoneStreamType lst, const std::string &attributeName) const; + +private: + L_DECLARE_PRIVATE(MediaSessionParams); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MEDIA_SESSION_PARAMS_H_ diff --git a/src/conference/participant-device.cpp b/src/conference/participant-device.cpp new file mode 100644 index 000000000..18bb24dd2 --- /dev/null +++ b/src/conference/participant-device.cpp @@ -0,0 +1,69 @@ +/* + * participant-device.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "participant-device.h" +#include "participant-p.h" + +#include "linphone/event.h" + +using namespace std; + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +ParticipantDevice::ParticipantDevice () {} + +ParticipantDevice::ParticipantDevice (Participant *participant, const IdentityAddress &gruu) + : mParticipant(participant), mGruu(gruu) {} + +ParticipantDevice::~ParticipantDevice () { + if (mConferenceSubscribeEvent) + linphone_event_unref(mConferenceSubscribeEvent); +} + +bool ParticipantDevice::operator== (const ParticipantDevice &device) const { + return (mGruu == device.getAddress()); +} + +shared_ptr ParticipantDevice::getCore () const { + return mParticipant ? mParticipant->getPrivate()->getCore() : nullptr; +} + +void ParticipantDevice::setConferenceSubscribeEvent (LinphoneEvent *ev) { + if (mConferenceSubscribeEvent) + linphone_event_unref(mConferenceSubscribeEvent); + mConferenceSubscribeEvent = linphone_event_ref(ev); +} + +ostream &operator<< (ostream &stream, ParticipantDevice::State state) { + switch (state) { + case ParticipantDevice::State::Joining: + return stream << "Joining"; + case ParticipantDevice::State::Present: + return stream << "Present"; + case ParticipantDevice::State::Leaving: + return stream << "Leaving"; + case ParticipantDevice::State::Left: + return stream << "Left"; + } + return stream; +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/participant-device.h b/src/conference/participant-device.h new file mode 100644 index 000000000..a2a46109c --- /dev/null +++ b/src/conference/participant-device.h @@ -0,0 +1,82 @@ +/* + * participant-device.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PARTICIPANT_DEVICE_H_ +#define _L_PARTICIPANT_DEVICE_H_ + +#include + +#include "address/identity-address.h" + +#include "linphone/types.h" +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSession; +class Core; +class Participant; + +class ParticipantDevice { +public: + enum class State { + Joining, + Present, + Leaving, + Left + }; + + ParticipantDevice (); + explicit ParticipantDevice (Participant *participant, const IdentityAddress &gruu); + virtual ~ParticipantDevice (); + + bool operator== (const ParticipantDevice &device) const; + + std::shared_ptr getCore () const; + + inline const IdentityAddress &getAddress () const { return mGruu; } + Participant *getParticipant () const { return mParticipant; } + inline std::shared_ptr getSession () const { return mSession; } + inline void setSession (std::shared_ptr session) { mSession = session; } + inline State getState () const { return mState; } + inline void setState (State newState) { mState = newState; } + + inline bool isSubscribedToConferenceEventPackage () const { return mConferenceSubscribeEvent != nullptr; } + LinphoneEvent *getConferenceSubscribeEvent () const { return mConferenceSubscribeEvent; } + void setConferenceSubscribeEvent (LinphoneEvent *ev); + + bool isValid () const { return mGruu.isValid(); } + +private: + Participant *mParticipant = nullptr; + IdentityAddress mGruu; + std::shared_ptr mSession; + LinphoneEvent *mConferenceSubscribeEvent = nullptr; + State mState = State::Joining; + + L_DISABLE_COPY(ParticipantDevice); +}; + +std::ostream &operator<< (std::ostream &stream, ParticipantDevice::State state); + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PARTICIPANT_DEVICE_H_ diff --git a/src/conference/participant-imdn-state-p.h b/src/conference/participant-imdn-state-p.h new file mode 100644 index 000000000..981bfefb1 --- /dev/null +++ b/src/conference/participant-imdn-state-p.h @@ -0,0 +1,42 @@ +/* + * participant-imdn-state-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PARTICIPANT_IMDN_STATE_P_H_ +#define _L_PARTICIPANT_IMDN_STATE_P_H_ + +#include "object/clonable-object-p.h" + +#include "conference/participant-imdn-state.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ParticipantImdnStatePrivate : public ClonableObjectPrivate { +public: + std::shared_ptr participant; + ChatMessage::State state = ChatMessage::State::Idle; + time_t stateChangeTime = 0; + + L_DECLARE_PUBLIC(ParticipantImdnState); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PARTICIPANT_IMDN_STATE_P_H_ diff --git a/src/conference/participant-imdn-state.cpp b/src/conference/participant-imdn-state.cpp new file mode 100644 index 000000000..cd3772bdb --- /dev/null +++ b/src/conference/participant-imdn-state.cpp @@ -0,0 +1,61 @@ +/* + * participant-imdn-state.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "participant-imdn-state-p.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ============================================================================= + +ParticipantImdnState::ParticipantImdnState (const shared_ptr &participant, ChatMessage::State state, time_t stateChangeTime) + : ClonableObject(*new ParticipantImdnStatePrivate) +{ + L_D(); + d->participant = participant; + d->state = state; + d->stateChangeTime = stateChangeTime; +} + +ParticipantImdnState::ParticipantImdnState(const ParticipantImdnState &other) : ClonableObject(*new ParticipantImdnStatePrivate) { + L_D(); + d->participant = other.getParticipant(); + d->state = other.getState(); + d->stateChangeTime = other.getStateChangeTime(); +} + +// ----------------------------------------------------------------------------- + +shared_ptr ParticipantImdnState::getParticipant () const { + L_D(); + return d->participant; +} + +ChatMessage::State ParticipantImdnState::getState () const { + L_D(); + return d->state; +} + +time_t ParticipantImdnState::getStateChangeTime () const { + L_D(); + return d->stateChangeTime; +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/participant-imdn-state.h b/src/conference/participant-imdn-state.h new file mode 100644 index 000000000..0a9c7ded4 --- /dev/null +++ b/src/conference/participant-imdn-state.h @@ -0,0 +1,48 @@ +/* + * participant-imdn-state.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PARTICIPANT_IMDN_STATE_H_ +#define _L_PARTICIPANT_IMDN_STATE_H_ + +#include "chat/chat-message/chat-message.h" +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Participant; +class ParticipantImdnStatePrivate; + +class ParticipantImdnState : public ClonableObject { +public: + ParticipantImdnState (const std::shared_ptr &participant, ChatMessage::State state, time_t stateChangeTime); + ParticipantImdnState (const ParticipantImdnState &other); + + std::shared_ptr getParticipant () const; + ChatMessage::State getState () const; + time_t getStateChangeTime () const; + +private: + L_DECLARE_PRIVATE(ParticipantImdnState); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PARTICIPANT_IMDN_STATE_H_ diff --git a/src/conference/participant-p.h b/src/conference/participant-p.h new file mode 100644 index 000000000..cdff47ac5 --- /dev/null +++ b/src/conference/participant-p.h @@ -0,0 +1,65 @@ +/* + * participant-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PARTICIPANT_P_H_ +#define _L_PARTICIPANT_P_H_ + +#include "object/object-p.h" + +#include "conference/participant.h" +#include "conference/session/call-session.h" +#include "conference/session/call-session-listener.h" +#include "conference/params/call-session-params.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ParticipantPrivate : public ObjectPrivate { +public: + std::shared_ptr getCore () const { return mConference ? mConference->getCore() : nullptr; } + Conference *getConference () const { return mConference; } + void setConference (Conference *conference) { mConference = conference; } + + std::shared_ptr createSession (const Conference &conference, const CallSessionParams *params, bool hasMedia, CallSessionListener *listener); + inline std::shared_ptr getSession () const { return session; } + inline void removeSession () { session.reset(); } + inline void setAddress (const IdentityAddress &newAddr) { addr = newAddr; } + inline void setAdmin (bool isAdmin) { this->isAdmin = isAdmin; } + + std::shared_ptr addDevice (const IdentityAddress &gruu); + void clearDevices (); + std::shared_ptr findDevice (const IdentityAddress &gruu) const; + std::shared_ptr findDevice (const std::shared_ptr &session); + const std::list> &getDevices () const; + void removeDevice (const IdentityAddress &gruu); + +private: + Conference *mConference = nullptr; + IdentityAddress addr; + bool isAdmin = false; + std::shared_ptr session; + std::list> devices; + + L_DECLARE_PUBLIC(Participant); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PARTICIPANT_P_H_ diff --git a/src/conference/participant.cpp b/src/conference/participant.cpp new file mode 100644 index 000000000..564118f40 --- /dev/null +++ b/src/conference/participant.cpp @@ -0,0 +1,115 @@ +/* + * participant.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "object/object-p.h" +#include "participant-device.h" +#include "participant-p.h" + +#include "participant.h" +#include "params/media-session-params.h" +#include "session/media-session.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ============================================================================= + +shared_ptr ParticipantPrivate::createSession ( + const Conference &conference, const CallSessionParams *params, bool hasMedia, CallSessionListener *listener +) { + L_Q(); + if (hasMedia && (!params || dynamic_cast(params))) { + session = make_shared(conference.getCore(), q->getSharedFromThis(), params, listener); + } else { + session = make_shared(conference.getCore(), params, listener); + } + return session; +} + +// ----------------------------------------------------------------------------- + +shared_ptr ParticipantPrivate::addDevice (const IdentityAddress &gruu) { + L_Q(); + shared_ptr device = findDevice(gruu); + if (device) + return device; + device = make_shared(q, gruu); + devices.push_back(device); + return device; +} + +void ParticipantPrivate::clearDevices () { + devices.clear(); +} + +shared_ptr ParticipantPrivate::findDevice (const IdentityAddress &gruu) const { + for (const auto &device : devices) { + if (device->getAddress() == gruu) + return device; + } + return nullptr; +} + +shared_ptr ParticipantPrivate::findDevice (const shared_ptr &session) { + for (const auto &device : devices) { + if (device->getSession() == session) + return device; + } + return nullptr; +} + +const list> &ParticipantPrivate::getDevices () const { + return devices; +} + +void ParticipantPrivate::removeDevice (const IdentityAddress &gruu) { + for (auto it = devices.begin(); it != devices.end(); it++) { + if ((*it)->getAddress() == gruu) { + devices.erase(it); + return; + } + } +} + +// ============================================================================= + +Participant::Participant (Conference *conference, const IdentityAddress &address) : Object(*new ParticipantPrivate) { + L_D(); + d->mConference = conference; + d->addr = address.getAddressWithoutGruu(); +} + +// ----------------------------------------------------------------------------- + +const IdentityAddress& Participant::getAddress () const { + L_D(); + return d->addr; +} + +// ----------------------------------------------------------------------------- + +bool Participant::isAdmin () const { + L_D(); + return d->isAdmin; +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/participant.h b/src/conference/participant.h new file mode 100644 index 000000000..1a248a022 --- /dev/null +++ b/src/conference/participant.h @@ -0,0 +1,80 @@ +/* + * participant.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PARTICIPANT_H_ +#define _L_PARTICIPANT_H_ + +#include + +#include "address/identity-address.h" +#include "conference/params/call-session-params.h" +#include "object/object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ClientGroupChatRoom; +class Conference; +class ParticipantPrivate; + +class Participant : public Object { + // TODO: Remove... It's ugly. + friend class Call; + friend class CallPrivate; + friend class ClientGroupChatRoom; + friend class ClientGroupChatRoomPrivate; + friend class Conference; + friend class LocalConference; + friend class LocalConferenceCall; + friend class LocalConferenceCallPrivate; + friend class LocalConferenceEventHandler; + friend class LocalConferenceEventHandlerPrivate; + friend class LocalConferenceListEventHandler; + friend class MainDb; + friend class MainDbPrivate; + friend class MediaSessionPrivate; + friend class ParticipantDevice; + friend class RemoteConference; + friend class RemoteConferenceCall; + friend class RemoteConferenceCallPrivate; + friend class ServerGroupChatRoom; + friend class ServerGroupChatRoomPrivate; + +public: + L_OVERRIDE_SHARED_FROM_THIS(Participant); + + explicit Participant (Conference *conference, const IdentityAddress &address); + + const IdentityAddress &getAddress () const; + bool isAdmin () const; + +private: + L_DECLARE_PRIVATE(Participant); + L_DISABLE_COPY(Participant); +}; + +inline std::ostream &operator<< (std::ostream &os, const Participant &participant) { + return os << participant.getAddress().asString(); + return os; +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PARTICIPANT_H_ diff --git a/src/conference/remote-conference-p.h b/src/conference/remote-conference-p.h new file mode 100644 index 000000000..9d256af10 --- /dev/null +++ b/src/conference/remote-conference-p.h @@ -0,0 +1,43 @@ +/* + * remote-conference-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REMOTE_CONFERENCE_P_H_ +#define _L_REMOTE_CONFERENCE_P_H_ + +#include "conference-p.h" +#include "remote-conference.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class RemoteConferenceEventHandler; + +class RemoteConferencePrivate : public ConferencePrivate { +public: + std::shared_ptr focus; + std::shared_ptr eventHandler; + +private: + L_DECLARE_PUBLIC(RemoteConference); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REMOTE_CONFERENCE_P_H_ diff --git a/src/conference/remote-conference.cpp b/src/conference/remote-conference.cpp new file mode 100644 index 000000000..ea50c58b5 --- /dev/null +++ b/src/conference/remote-conference.cpp @@ -0,0 +1,94 @@ +/* + * remote-conference.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "handlers/remote-conference-event-handler.h" +#include "logger/logger.h" +#include "participant-p.h" +#include "remote-conference-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +RemoteConference::RemoteConference ( + const shared_ptr &core, + const IdentityAddress &myAddress, + CallSessionListener *listener +) : Conference(*new RemoteConferencePrivate, core, myAddress, listener) { + L_D(); + d->eventHandler.reset(new RemoteConferenceEventHandler(this)); +} + +RemoteConference::~RemoteConference () { + L_D(); + d->eventHandler.reset(); +} + +// ----------------------------------------------------------------------------- + +void RemoteConference::addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) { + L_D(); + shared_ptr participant = findParticipant(addr); + if (participant) { + lInfo() << "Not adding participant '" << addr.asString() << "' because it is already a participant of the RemoteConference"; + return; + } + participant = make_shared(this, addr); + participant->getPrivate()->createSession(*this, params, hasMedia, d->listener); + d->participants.push_back(participant); + if (!d->activeParticipant) + d->activeParticipant = participant; +} + +void RemoteConference::removeParticipant (const shared_ptr &participant) { + L_D(); + for (const auto &p : d->participants) { + if (participant->getAddress() == p->getAddress()) { + d->participants.remove(p); + return; + } + } +} + +// ----------------------------------------------------------------------------- + +void RemoteConference::onConferenceCreated (const IdentityAddress &) {} + +void RemoteConference::onConferenceTerminated (const IdentityAddress &) { + L_D(); + d->eventHandler->unsubscribe(); +} + +void RemoteConference::onFirstNotifyReceived (const IdentityAddress &) {} + +void RemoteConference::onParticipantAdded (const std::shared_ptr &, bool) {} + +void RemoteConference::onParticipantRemoved (const std::shared_ptr &, bool) {} + +void RemoteConference::onParticipantSetAdmin (const std::shared_ptr &, bool) {} + +void RemoteConference::onSubjectChanged (const std::shared_ptr &, bool) {} + +void RemoteConference::onParticipantDeviceAdded (const std::shared_ptr &, bool) {} + +void RemoteConference::onParticipantDeviceRemoved (const std::shared_ptr &, bool) {} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/remote-conference.h b/src/conference/remote-conference.h new file mode 100644 index 000000000..3490113e5 --- /dev/null +++ b/src/conference/remote-conference.h @@ -0,0 +1,62 @@ +/* + * remote-conference.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_REMOTE_CONFERENCE_H_ +#define _L_REMOTE_CONFERENCE_H_ + +#include "conference.h" +#include "core/core-accessor.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class RemoteConferencePrivate; + +class LINPHONE_PUBLIC RemoteConference : public Conference { + friend class ClientGroupChatRoomPrivate; + +public: + RemoteConference (const std::shared_ptr &core, const IdentityAddress &myAddress, CallSessionListener *listener); + virtual ~RemoteConference (); + + /* ConferenceInterface */ + void addParticipant (const IdentityAddress &addr, const CallSessionParams *params, bool hasMedia) override; + void removeParticipant (const std::shared_ptr &participant) override; + +protected: + /* ConferenceListener */ + void onConferenceCreated (const IdentityAddress &addr) override; + void onConferenceTerminated (const IdentityAddress &addr) override; + void onFirstNotifyReceived (const IdentityAddress &addr) override; + void onParticipantAdded (const std::shared_ptr &event, bool isFullState) override; + void onParticipantRemoved (const std::shared_ptr &event, bool isFullState) override; + void onParticipantSetAdmin (const std::shared_ptr &event, bool isFullState) override; + void onSubjectChanged (const std::shared_ptr &event, bool isFullState) override; + void onParticipantDeviceAdded (const std::shared_ptr &event, bool isFullState) override; + void onParticipantDeviceRemoved (const std::shared_ptr &event, bool isFullState) override; + +private: + L_DECLARE_PRIVATE(RemoteConference); + L_DISABLE_COPY(RemoteConference); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_REMOTE_CONFERENCE_H_ diff --git a/src/conference/session/call-session-listener.h b/src/conference/session/call-session-listener.h new file mode 100644 index 000000000..3b9c20668 --- /dev/null +++ b/src/conference/session/call-session-listener.h @@ -0,0 +1,89 @@ +/* + * call-session-listener.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_SESSION_LISTENER_H_ +#define _L_CALL_SESSION_LISTENER_H_ + +#include "conference/session/call-session.h" + +#include + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSession; + +class LINPHONE_PUBLIC CallSessionListener { +public: + virtual ~CallSessionListener() = default; + + virtual void onAckBeingSent (const std::shared_ptr &session, LinphoneHeaders *headers) {} + virtual void onAckReceived (const std::shared_ptr &session, LinphoneHeaders *headers) {} + virtual void onBackgroundTaskToBeStarted (const std::shared_ptr &session) {} + virtual void onBackgroundTaskToBeStopped (const std::shared_ptr &session) {} + virtual bool onCallSessionAccepted (const std::shared_ptr &session) { return false; } + virtual void onCallSessionConferenceStreamStarting (const std::shared_ptr &session, bool mute) {} + virtual void onCallSessionConferenceStreamStopping (const std::shared_ptr &session) {} + virtual void onCallSessionEarlyFailed (const std::shared_ptr &session, LinphoneErrorInfo *ei) {} + virtual void onCallSessionSetReleased (const std::shared_ptr &session) {} + virtual void onCallSessionSetTerminated (const std::shared_ptr &session) {} + virtual void onCallSessionStartReferred (const std::shared_ptr &session) {} + virtual void onCallSessionStateChanged (const std::shared_ptr &session, CallSession::State state, const std::string &message) {} + virtual void onCallSessionTransferStateChanged (const std::shared_ptr &session, CallSession::State state) {} + virtual void onCheckForAcceptation (const std::shared_ptr &session) {} + virtual void onDtmfReceived (const std::shared_ptr &session, char dtmf) {} + virtual void onIncomingCallSessionNotified (const std::shared_ptr &session) {} + virtual void onIncomingCallSessionStarted (const std::shared_ptr &session) {} + virtual void onIncomingCallSessionTimeoutCheck (const std::shared_ptr &session, int elapsed, bool oneSecondElapsed) {} + virtual void onInfoReceived (const std::shared_ptr &session, const LinphoneInfoMessage *im) {} + virtual void onNoMediaTimeoutCheck (const std::shared_ptr &session, bool oneSecondElapsed) {} + virtual void onTmmbrReceived (const std::shared_ptr &session, int streamIndex, int tmmbr) {} + virtual void onSnapshotTaken(const std::shared_ptr &session, const char *file_path) {} + + virtual void onEncryptionChanged (const std::shared_ptr &session, bool activated, const std::string &authToken) {} + + virtual void onCallSessionStateChangedForReporting (const std::shared_ptr &session) {} + virtual void onRtcpUpdateForReporting (const std::shared_ptr &session, SalStreamType type) {} + virtual void onStatsUpdated (const std::shared_ptr &session, const LinphoneCallStats *stats) {} + virtual void onUpdateMediaInfoForReporting (const std::shared_ptr &session, int statsType) {} + + virtual void onResetCurrentSession (const std::shared_ptr &session) {} + virtual void onSetCurrentSession (const std::shared_ptr &session) {} + + virtual void onFirstVideoFrameDecoded (const std::shared_ptr &session) {} + virtual void onResetFirstVideoFrameDecoded (const std::shared_ptr &session) {} + + virtual void onPlayErrorTone (const std::shared_ptr &session, LinphoneReason reason) {} + virtual void onRingbackToneRequested (const std::shared_ptr &session, bool requested) {} + virtual void onStartRinging (const std::shared_ptr &session) {} + virtual void onStopRinging (const std::shared_ptr &session) {} + virtual void onStopRingingIfInCall (const std::shared_ptr &session) {} + virtual void onStopRingingIfNeeded (const std::shared_ptr &session) {} + + virtual bool areSoundResourcesAvailable (const std::shared_ptr &session) { return true; } + virtual bool isPlayingRingbackTone (const std::shared_ptr &session) { return false; } + + virtual void onRealTimeTextCharacterReceived (const std::shared_ptr &session, RealtimeTextReceivedCharacter *data) {} + +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CALL_SESSION_LISTENER_H_ diff --git a/src/conference/session/call-session-p.h b/src/conference/session/call-session-p.h new file mode 100644 index 000000000..b2ddba767 --- /dev/null +++ b/src/conference/session/call-session-p.h @@ -0,0 +1,151 @@ +/* + * call-session-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_SESSION_P_H_ +#define _L_CALL_SESSION_P_H_ + +#include "object/object-p.h" + +#include "call-session.h" +#include "sal/call-op.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallSessionPrivate : public ObjectPrivate, public CoreListener { +public: + int computeDuration () const; + virtual void initializeParamsAccordingToIncomingCallParams (); + void notifyReferState (); + virtual void setState (CallSession::State newState, const std::string &message); + void setTransferState (CallSession::State newState); + void startIncomingNotification (); + bool startPing (); + void setPingTime (int value) { pingTime = value; } + + void createOp (); + CallSessionParams *getCurrentParams () const { return currentParams; } + LinphoneProxyConfig * getDestProxy () const { return destProxy; } + SalCallOp * getOp () const { return op; } + bool isBroken () const { return broken; } + bool isInConference () const; + void setParams (CallSessionParams *csp); + void setReferPending (bool value) { referPending = value; } + void setTransferTarget (std::shared_ptr session) { transferTarget = session; } + + virtual void abort (const std::string &errorMsg); + virtual void accepted (); + void ackBeingSent (LinphoneHeaders *headers); + virtual void ackReceived (LinphoneHeaders *headers); + void cancelDone (); + virtual bool failure (); + void infoReceived (SalBodyHandler *bodyHandler); + void pingReply (); + void referred (const Address &referToAddr); + virtual void remoteRinging (); + virtual void replaceOp (SalCallOp *newOp); + virtual void terminated (); + void updated (bool isUpdate); + void updatedByRemote (); + virtual void updating (bool isUpdate); + + void setCallSessionListener (CallSessionListener *listener) { this->listener = listener; } + +protected: + void init (); + + void accept (const CallSessionParams *params); + virtual LinphoneStatus acceptUpdate (const CallSessionParams *csp, CallSession::State nextState, const std::string &stateInfo); + LinphoneStatus checkForAcceptation (); + virtual void handleIncomingReceivedStateInIncomingNotification (); + virtual bool isReadyForInvite () const; + bool isUpdateAllowed (CallSession::State &nextState) const; + virtual int restartInvite (); + virtual void setReleased (); + virtual void setTerminated (); + virtual LinphoneStatus startAcceptUpdate (CallSession::State nextState, const std::string &stateInfo); + virtual LinphoneStatus startUpdate (const std::string &subject); + virtual void terminate (); + virtual void updateCurrentParams () const; + + void setBroken (); + void setContactOp (); + + virtual void reinviteToRecoverFromConnectionLoss (); + virtual void repairByInviteWithReplaces (); + + // CoreListener + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; + void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const std::string &message) override; + +private: + void completeLog (); + void createOpTo (const LinphoneAddress *to); + + LinphoneAddress * getFixedContact () const; + + void repairIfBroken (); + +protected: + CallSessionListener *listener = nullptr; + + CallSessionParams *params = nullptr; + mutable CallSessionParams *currentParams = nullptr; + CallSessionParams *remoteParams = nullptr; + mutable Address diversionAddress; + mutable Address remoteContactAddress; + mutable Address toAddress; + + std::string subject; + LinphoneCallDir direction = LinphoneCallOutgoing; + CallSession::State state = CallSession::State::Idle; + CallSession::State prevState = CallSession::State::Idle; + CallSession::State transferState = CallSession::State::Idle; + LinphoneProxyConfig *destProxy = nullptr; + LinphoneErrorInfo *ei = nullptr; + LinphoneCallLog *log = nullptr; + std::string referTo; + + SalCallOp *op = nullptr; + + SalOp *pingOp = nullptr; + bool pingReplied = false; + int pingTime = 0; + + std::shared_ptr referer; + std::shared_ptr transferTarget; + + bool broken = false; + bool deferIncomingNotification = false; + bool deferUpdate = false; + bool deferUpdateInternal = false; + bool needLocalIpRefresh = false; + bool nonOpError = false; /* Set when the LinphoneErrorInfo was set at higher level than sal */ + bool notifyRinging = true; + bool referPending = false; + bool reinviteOnCancelResponseRequested = false; + +private: + L_DECLARE_PUBLIC(CallSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CALL_SESSION_P_H_ diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp new file mode 100644 index 000000000..a7b03fe0f --- /dev/null +++ b/src/conference/session/call-session.cpp @@ -0,0 +1,1375 @@ +/* + * call-session.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/api/c-content.h" +#include "linphone/core.h" + +#include "address/address-p.h" +#include "c-wrapper/c-wrapper.h" +#include "call/call-p.h" +#include "conference/params/call-session-params-p.h" +#include "conference/session/call-session-p.h" +#include "conference/session/call-session.h" +#include "core/core-p.h" +#include "logger/logger.h" + +#include "private.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ============================================================================= + +int CallSessionPrivate::computeDuration () const { + if (log->connected_date_time == 0) + return 0; + return (int)(ms_time(nullptr) - log->connected_date_time); +} + +/* + * 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... + */ +void CallSessionPrivate::initializeParamsAccordingToIncomingCallParams () { + currentParams->setPrivacy((LinphonePrivacyMask)op->getPrivacy()); +} + +void CallSessionPrivate::notifyReferState () { + SalCallOp *refererOp = referer->getPrivate()->getOp(); + if (refererOp) + refererOp->notifyReferState(op); +} + +void CallSessionPrivate::setState (CallSession::State newState, const string &message) { + L_Q(); + // Keep a ref on the CallSession, otherwise it might get destroyed before the end of the method + shared_ptr ref = q->getSharedFromThis(); + if (state != newState){ + prevState = state; + + /* Make sanity checks with call state changes. Any bad transition can result in unpredictable results + or irrecoverable errors in the application. */ + if ((state == CallSession::State::End) || (state == CallSession::State::Error)) { + if (newState != CallSession::State::Released) { + lFatal() << "Abnormal call resurection from " << Utils::toString(state) << + " to " << Utils::toString(newState) << " , aborting"; + return; + } + } else if ((newState == CallSession::State::Released) && (prevState != CallSession::State::Error) && (prevState != CallSession::State::End)) { + lFatal() << "Attempt to move CallSession [" << q << "] to Released state while it was not previously in Error or End state, aborting"; + return; + } + lInfo() << "CallSession [" << q << "] moving from state " << Utils::toString(state) << " to " << Utils::toString(newState); + + if (newState != CallSession::State::Referred) { + /* CallSession::State::Referred is rather an event, not a state. + Indeed it does not change the state of the call (still paused or running). */ + state = newState; + } + + switch (newState) { + case CallSession::State::End: + case CallSession::State::Error: + switch (linphone_error_info_get_reason(q->getErrorInfo())) { + case LinphoneReasonDeclined: + if (log->status != LinphoneCallMissed) // Do not re-change the status of a call if it's already set + log->status = LinphoneCallDeclined; + break; + case LinphoneReasonNotAnswered: + if (log->dir == LinphoneCallIncoming) + log->status = LinphoneCallMissed; + break; + case LinphoneReasonNone: + if (log->dir == LinphoneCallIncoming) { + if (ei) { + int code = linphone_error_info_get_protocol_code(ei); + if ((code >= 200) && (code < 300)) + log->status = LinphoneCallAcceptedElsewhere; + } + } + break; + case LinphoneReasonDoNotDisturb: + if (log->dir == LinphoneCallIncoming) { + if (ei) { + int code = linphone_error_info_get_protocol_code(ei); + if ((code >= 600) && (code < 700)) + log->status = LinphoneCallDeclinedElsewhere; + } + } + break; + default: + break; + } + setTerminated(); + break; + case CallSession::State::Connected: + log->status = LinphoneCallSuccess; + log->connected_date_time = ms_time(nullptr); + break; + default: + break; + } + + if (message.empty()) { + lError() << "You must fill a reason when changing call state (from " << + Utils::toString(prevState) << " to " << Utils::toString(state) << ")"; + } + if (listener) + listener->onCallSessionStateChanged(q->getSharedFromThis(), newState, message); + if (newState == CallSession::State::Released) + setReleased(); /* Shall be performed after app notification */ + } +} + +void CallSessionPrivate::setTransferState (CallSession::State newState) { + L_Q(); + if (newState == transferState) + return; + lInfo() << "Transfer state for CallSession [" << q << "] changed from [" + << Utils::toString(transferState) << "] to [" << Utils::toString(newState) << "]"; + transferState = newState; + if (listener) + listener->onCallSessionTransferStateChanged(q->getSharedFromThis(), newState); +} + +void CallSessionPrivate::startIncomingNotification () { + L_Q(); + if (listener) + listener->onIncomingCallSessionStarted(q->getSharedFromThis()); + + setState(CallSession::State::IncomingReceived, "Incoming CallSession"); + + // From now on, the application is aware of the call and supposed to take background task or already submitted + // notification to the user. We can then drop our background task. + if (listener) + listener->onBackgroundTaskToBeStopped(q->getSharedFromThis()); + + if (state == CallSession::State::IncomingReceived) { + handleIncomingReceivedStateInIncomingNotification(); + } +} + +bool CallSessionPrivate::startPing () { + L_Q(); + if (q->getCore()->getCCore()->sip_conf.ping_with_options) { + /* Defer the start of the call after the OPTIONS ping for outgoing call or + * send an option request back to the caller so that we get a chance to discover our nat'd address + * before answering for incoming call */ + pingReplied = false; + pingOp = new SalOp(q->getCore()->getCCore()->sal); + if (direction == LinphoneCallIncoming) { + string from = pingOp->getFrom(); + string to = pingOp->getTo(); + linphone_configure_op(q->getCore()->getCCore(), pingOp, log->from, nullptr, false); + pingOp->setRoute(op->getNetworkOrigin()); + pingOp->ping(from.c_str(), to.c_str()); + } else if (direction == LinphoneCallOutgoing) { + char *from = linphone_address_as_string(log->from); + char *to = linphone_address_as_string(log->to); + pingOp->ping(from, to); + ms_free(from); + ms_free(to); + } + pingOp->setUserPointer(this); + return true; + } + return false; +} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::setParams (CallSessionParams *csp) { + if (params) + delete params; + params = csp; +} + +void CallSessionPrivate::createOp () { + createOpTo(log->to); +} + +bool CallSessionPrivate::isInConference () const { + return params->getPrivate()->getInConference(); +} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::abort (const string &errorMsg) { + op->terminate(); + setState(CallSession::State::Error, errorMsg); +} + +void CallSessionPrivate::accepted () { + /* Immediately notify the connected state, even if errors occur after */ + switch (state) { + case CallSession::State::OutgoingProgress: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + /* Immediately notify the connected state */ + setState(CallSession::State::Connected, "Connected"); + break; + default: + break; + } + currentParams->setPrivacy((LinphonePrivacyMask)op->getPrivacy()); +} + +void CallSessionPrivate::ackBeingSent (LinphoneHeaders *headers) { + L_Q(); + if (listener) + listener->onAckBeingSent(q->getSharedFromThis(), headers); +} + +void CallSessionPrivate::ackReceived (LinphoneHeaders *headers) { + L_Q(); + if (listener) + listener->onAckReceived(q->getSharedFromThis(), headers); +} + +void CallSessionPrivate::cancelDone () { + if (reinviteOnCancelResponseRequested) { + reinviteOnCancelResponseRequested = false; + reinviteToRecoverFromConnectionLoss(); + } +} + +bool CallSessionPrivate::failure () { + L_Q(); + const SalErrorInfo *ei = op->getErrorInfo(); + switch (ei->reason) { + case SalReasonRedirect: + if ((state == CallSession::State::OutgoingInit) || (state == CallSession::State::OutgoingProgress) + || (state == CallSession::State::OutgoingRinging) /* Push notification case */ || (state == CallSession::State::OutgoingEarlyMedia)) { + const SalAddress *redirectionTo = op->getRemoteContactAddress(); + if (redirectionTo) { + char *url = sal_address_as_string(redirectionTo); + lWarning() << "Redirecting CallSession [" << q << "] to " << url; + if (log->to) + linphone_address_unref(log->to); + log->to = linphone_address_new(url); + ms_free(url); + restartInvite(); + return true; + } + } + break; + default: + break; + } + + /* Some call errors are not fatal */ + switch (state) { + case CallSession::State::Updating: + case CallSession::State::Pausing: + case CallSession::State::Resuming: + if (ei->reason != SalReasonNoMatch) { + lInfo() << "Call error on state [" << Utils::toString(state) << "], restoring previous state [" << Utils::toString(prevState) << "]"; + setState(prevState, ei->full_string); + return true; + } + default: + break; + } + + if ((state != CallSession::State::End) && (state != CallSession::State::Error)) { + if (ei->reason == SalReasonDeclined) + setState(CallSession::State::End, "Call declined"); + else { + if (CallSession::isEarlyState(state)) + setState(CallSession::State::Error, ei->full_string ? ei->full_string : ""); + else + setState(CallSession::State::End, ei->full_string ? ei->full_string : ""); + } + if ((ei->reason != SalReasonNone) && listener) + listener->onPlayErrorTone(q->getSharedFromThis(), linphone_reason_from_sal(ei->reason)); + } + if (referer) { + // Notify referer of the failure + notifyReferState(); + } + return false; +} + +void CallSessionPrivate::infoReceived (SalBodyHandler *bodyHandler) { + L_Q(); + LinphoneInfoMessage *info = linphone_core_create_info_message(q->getCore()->getCCore()); + linphone_info_message_set_headers(info, op->getRecvCustomHeaders()); + if (bodyHandler) { + LinphoneContent *content = linphone_content_from_sal_body_handler(bodyHandler); + linphone_info_message_set_content(info, content); + linphone_content_unref(content); + } + if (listener) + listener->onInfoReceived(q->getSharedFromThis(), info); + linphone_info_message_unref(info); +} + +void CallSessionPrivate::pingReply () { + L_Q(); + if (state == CallSession::State::OutgoingInit) { + pingReplied = true; + if (isReadyForInvite()) + q->startInvite(nullptr, ""); + } +} + +void CallSessionPrivate::referred (const Address &referToAddr) { + L_Q(); + referTo = referToAddr.asString(); + referPending = true; + setState(CallSession::State::Referred, "Referred"); + if (referPending && listener) + listener->onCallSessionStartReferred(q->getSharedFromThis()); +} + +void CallSessionPrivate::remoteRinging () { + L_Q(); + /* Set privacy */ + currentParams->setPrivacy((LinphonePrivacyMask)op->getPrivacy()); + if (listener) + listener->onStartRinging(q->getSharedFromThis()); + lInfo() << "Remote ringing..."; + setState(CallSession::State::OutgoingRinging, "Remote ringing"); +} + +void CallSessionPrivate::replaceOp (SalCallOp *newOp) { + L_Q(); + SalCallOp *oldOp = op; + CallSession::State oldState = state; + op = newOp; + op->setUserPointer(q); + op->setLocalMediaDescription(oldOp->getLocalMediaDescription()); + switch (state) { + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::IncomingReceived: + op->notifyRinging((state == CallSession::State::IncomingEarlyMedia) ? true : false); + break; + case CallSession::State::Connected: + case CallSession::State::StreamsRunning: + op->accept(); + break; + default: + lWarning() << "CallSessionPrivate::replaceOp(): don't know what to do in state [" << Utils::toString(state) << "]"; + break; + } + switch (oldState) { + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::IncomingReceived: + oldOp->setUserPointer(nullptr); // In order for the call session to not get terminated by terminating this op + // Do not terminate a forked INVITE + if (op->getReplaces()) + oldOp->terminate(); + else + oldOp->killDialog(); + break; + case CallSession::State::Connected: + case CallSession::State::StreamsRunning: + oldOp->terminate(); + oldOp->killDialog(); + break; + default: + break; + } + oldOp->release(); +} + +void CallSessionPrivate::terminated () { + L_Q(); + switch (state) { + case CallSession::State::End: + case CallSession::State::Error: + lWarning() << "terminated: already terminated, ignoring"; + return; + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + if (!op->getReasonErrorInfo()->protocol || strcmp(op->getReasonErrorInfo()->protocol, "") == 0) { + linphone_error_info_set(ei, nullptr, LinphoneReasonNotAnswered, 0, "Incoming call cancelled", nullptr); + nonOpError = true; + } + break; + default: + break; + } + if (referPending && listener) + listener->onCallSessionStartReferred(q->getSharedFromThis()); + if (listener) + listener->onStopRingingIfInCall(q->getSharedFromThis()); + setState(CallSession::State::End, "Call ended"); +} + +void CallSessionPrivate::updated (bool isUpdate) { + L_Q(); + deferUpdate = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "defer_update_default", FALSE); + SalErrorInfo sei; + memset(&sei, 0, sizeof(sei)); + switch (state) { + case CallSession::State::PausedByRemote: + updatedByRemote(); + break; + /* SIP UPDATE CASE */ + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::IncomingEarlyMedia: + if (isUpdate) { + setState(CallSession::State::EarlyUpdatedByRemote, "EarlyUpdatedByRemote"); + acceptUpdate(nullptr, prevState, Utils::toString(prevState)); + } + break; + case CallSession::State::StreamsRunning: + case CallSession::State::Connected: + case CallSession::State::UpdatedByRemote: /* Can happen on UAC connectivity loss */ + updatedByRemote(); + break; + case CallSession::State::Paused: + /* We'll remain in pause state but accept the offer anyway according to default parameters */ + acceptUpdate(nullptr, state, Utils::toString(state)); + break; + case CallSession::State::Updating: + case CallSession::State::Pausing: + case CallSession::State::Resuming: + sal_error_info_set(&sei, SalReasonInternalError, "SIP", 0, nullptr, nullptr); + op->declineWithErrorInfo(&sei, nullptr); + BCTBX_NO_BREAK; /* no break */ + case CallSession::State::Idle: + case CallSession::State::OutgoingInit: + case CallSession::State::End: + case CallSession::State::IncomingReceived: + case CallSession::State::OutgoingProgress: + case CallSession::State::Referred: + case CallSession::State::Error: + case CallSession::State::Released: + case CallSession::State::EarlyUpdatedByRemote: + case CallSession::State::EarlyUpdating: + lWarning() << "Receiving reINVITE or UPDATE while in state [" << Utils::toString(state) << "], should not happen"; + break; + } +} + +void CallSessionPrivate::updatedByRemote () { + L_Q(); + setState(CallSession::State::UpdatedByRemote,"Call updated by remote"); + if (deferUpdate || deferUpdateInternal) { + if (state == CallSession::State::UpdatedByRemote && !deferUpdateInternal){ + lInfo() << "CallSession [" << q << "]: UpdatedByRemoted was signaled but defered. LinphoneCore expects the application to call linphone_call_accept_update() later"; + } + } else { + if (state == CallSession::State::UpdatedByRemote) + q->acceptUpdate(nullptr); + else { + // Otherwise it means that the app responded by CallSession::acceptUpdate() within the callback, + // so job is already done + } + } +} + +void CallSessionPrivate::updating (bool isUpdate) { + updated(isUpdate); +} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::init () { + currentParams = new CallSessionParams(); + ei = linphone_error_info_new(); +} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::accept (const CallSessionParams *csp) { + L_Q(); + /* Try to be best-effort in giving real local or routable contact address */ + setContactOp(); + if (csp) + setParams(new CallSessionParams(*csp)); + if (params) + op->setSentCustomHeaders(params->getPrivate()->getCustomHeaders()); + + op->accept(); + if (listener) + listener->onSetCurrentSession(q->getSharedFromThis()); + setState(CallSession::State::Connected, "Connected"); +} + +LinphoneStatus CallSessionPrivate::acceptUpdate (const CallSessionParams *csp, CallSession::State nextState, const string &stateInfo) { + return startAcceptUpdate(nextState, stateInfo); +} + +LinphoneStatus CallSessionPrivate::checkForAcceptation () { + L_Q(); + switch (state) { + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + break; + default: + lError() << "checkForAcceptation() CallSession [" << q << "] is in state [" << Utils::toString(state) << "], operation not permitted"; + return -1; + } + if (listener) + listener->onCheckForAcceptation(q->getSharedFromThis()); + + /* Check if this call is supposed to replace an already running one */ + SalOp *replaced = op->getReplaces(); + if (replaced) { + CallSession *session = reinterpret_cast(replaced->getUserPointer()); + if (session) { + lInfo() << "CallSession " << q << " replaces CallSession " << session << ". This last one is going to be terminated automatically"; + session->terminate(); + } + } + return 0; +} + +void CallSessionPrivate::handleIncomingReceivedStateInIncomingNotification () { + L_Q(); + /* Try to be best-effort in giving real local or routable contact address for 100Rel case */ + setContactOp(); + if (notifyRinging) + op->notifyRinging(false); + if (op->getReplaces() && lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "auto_answer_replacing_calls", 1)) + q->accept(); +} + +bool CallSessionPrivate::isReadyForInvite () const { + bool pingReady = false; + if (pingOp) { + if (pingReplied) + pingReady = true; + } else + pingReady = true; + return pingReady; +} + +bool CallSessionPrivate::isUpdateAllowed (CallSession::State &nextState) const { + switch (state) { + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + nextState = CallSession::State::EarlyUpdating; + break; + case CallSession::State::Connected: + case CallSession::State::StreamsRunning: + case CallSession::State::PausedByRemote: + case CallSession::State::UpdatedByRemote: + nextState = CallSession::State::Updating; + break; + case CallSession::State::Paused: + nextState = CallSession::State::Pausing; + break; + case CallSession::State::OutgoingProgress: + case CallSession::State::Pausing: + case CallSession::State::Resuming: + case CallSession::State::Updating: + nextState = state; + break; + default: + lError() << "Update is not allowed in [" << Utils::toString(state) << "] state"; + return false; + } + return true; +} + +int CallSessionPrivate::restartInvite () { + L_Q(); + createOp(); + return q->startInvite(nullptr, subject); +} + +/* + * Called internally when reaching the Released state, to perform cleanups to break circular references. +**/ +void CallSessionPrivate::setReleased () { + L_Q(); + if (op) { + /* Transfer the last error so that it can be obtained even in Released state */ + if (!nonOpError) + linphone_error_info_from_sal_op(ei, op); + /* So that we cannot have anymore upcalls for SAL concerning this call */ + op->release(); + op = nullptr; + } + referer = nullptr; + transferTarget = nullptr; + + if (listener) + listener->onCallSessionSetReleased(q->getSharedFromThis()); +} + +/* This method is called internally to get rid of a call that was notified to the application, + * because it reached the end or error state. It performs the following tasks: + * - remove the call from the internal list of calls + * - update the call logs accordingly + */ +void CallSessionPrivate::setTerminated() { + L_Q(); + completeLog(); + if (listener) + listener->onCallSessionSetTerminated(q->getSharedFromThis()); +} + +LinphoneStatus CallSessionPrivate::startAcceptUpdate (CallSession::State nextState, const std::string &stateInfo) { + op->accept(); + setState(nextState, stateInfo); + return 0; +} + +LinphoneStatus CallSessionPrivate::startUpdate (const string &subject) { + L_Q(); + string newSubject(subject); + if (newSubject.empty()) { + if (q->getParams()->getPrivate()->getInConference()) + newSubject = "Conference"; + else if (q->getParams()->getPrivate()->getInternalCallUpdate()) + newSubject = "ICE processing concluded"; + else if (q->getParams()->getPrivate()->getNoUserConsent()) + newSubject = "Refreshing"; + else + newSubject = "Media change"; + } + if (destProxy && destProxy->op) { + /* Give a chance to update the contact address if connectivity has changed */ + op->setContactAddress(destProxy->op->getContactAddress()); + } else + op->setContactAddress(nullptr); + return op->update(newSubject.c_str(), q->getParams()->getPrivate()->getNoUserConsent()); +} + +void CallSessionPrivate::terminate () { + if ((state == CallSession::State::IncomingReceived) && (linphone_error_info_get_reason(ei) != LinphoneReasonNotAnswered)) { + linphone_error_info_set_reason(ei, LinphoneReasonDeclined); + nonOpError = true; + } + setState(CallSession::State::End, "Call terminated"); +} + +void CallSessionPrivate::updateCurrentParams () const {} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::setBroken () { + switch (state) { + // For all the early states, we prefer to drop the call + case CallSession::State::OutgoingInit: + case CallSession::State::OutgoingProgress: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + // During the early states, the SAL layer reports the failure from the dialog or transaction layer, + // hence, there is nothing special to do + case CallSession::State::StreamsRunning: + case CallSession::State::Updating: + case CallSession::State::Pausing: + case CallSession::State::Resuming: + case CallSession::State::Paused: + case CallSession::State::PausedByRemote: + case CallSession::State::UpdatedByRemote: + // During these states, the dialog is established. A failure of a transaction is not expected to close it. + // Instead we have to repair the dialog by sending a reINVITE + broken = true; + needLocalIpRefresh = true; + break; + default: + lError() << "CallSessionPrivate::setBroken(): unimplemented case"; + break; + } +} + +void CallSessionPrivate::setContactOp () { + L_Q(); + SalAddress *salAddress = nullptr; + LinphoneAddress *contact = getFixedContact(); + if (contact) { + auto contactParams = q->getParams()->getPrivate()->getCustomContactParameters(); + for (auto it = contactParams.begin(); it != contactParams.end(); it++) + linphone_address_set_param(contact, it->first.c_str(), it->second.empty() ? nullptr : it->second.c_str()); + salAddress = const_cast(L_GET_PRIVATE_FROM_C_OBJECT(contact)->getInternalAddress()); + op->setContactAddress(salAddress); + linphone_address_unref(contact); + } +} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + if (sipNetworkReachable) + repairIfBroken(); + else + setBroken(); +} + +void CallSessionPrivate::onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState cstate, const std::string &message) { + repairIfBroken(); +} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::completeLog () { + L_Q(); + log->duration = computeDuration(); /* Store duration since connected */ + log->error_info = linphone_error_info_ref(ei); + if (log->status == LinphoneCallMissed) + q->getCore()->getCCore()->missed_calls++; + linphone_core_report_call_log(q->getCore()->getCCore(), log); +} + +void CallSessionPrivate::createOpTo (const LinphoneAddress *to) { + L_Q(); + if (op) + op->release(); + op = new SalCallOp(q->getCore()->getCCore()->sal); + op->setUserPointer(q); + if (params->getPrivate()->getReferer()) + op->setReferrer(params->getPrivate()->getReferer()->getPrivate()->getOp()); + linphone_configure_op(q->getCore()->getCCore(), op, to, q->getParams()->getPrivate()->getCustomHeaders(), false); + if (q->getParams()->getPrivacy() != LinphonePrivacyDefault) + op->setPrivacy((SalPrivacyMask)q->getParams()->getPrivacy()); + /* else privacy might be set by proxy */ +} + +// ----------------------------------------------------------------------------- + +LinphoneAddress * CallSessionPrivate::getFixedContact () const { + L_Q(); + LinphoneAddress *result = nullptr; + if (op && op->getContactAddress()) { + /* If already choosed, don't change it */ + return nullptr; + } else if (pingOp && pingOp->getContactAddress()) { + /* If the ping OPTIONS request succeeded use the contact guessed from the received, rport */ + lInfo() << "Contact has been fixed using OPTIONS"; + char *addr = sal_address_as_string(pingOp->getContactAddress()); + result = linphone_address_new(addr); + ms_free(addr); + } else if (destProxy && destProxy->op && linphone_proxy_config_get_contact(destProxy)) { + /* If using a proxy, use the contact address as guessed with the REGISTERs */ + lInfo() << "Contact has been fixed using proxy"; + result = linphone_address_clone(linphone_proxy_config_get_contact(destProxy)); + } else { + result = linphone_core_get_primary_contact_parsed(q->getCore()->getCCore()); + if (result) { + /* Otherwise use supplied localip */ + linphone_address_set_domain(result, nullptr /* localip */); + linphone_address_set_port(result, -1 /* linphone_core_get_sip_port(core) */); + lInfo() << "Contact has not been fixed, stack will do"; + } + } + return result; +} + +// ----------------------------------------------------------------------------- + +void CallSessionPrivate::reinviteToRecoverFromConnectionLoss () { + L_Q(); + lInfo() << "CallSession [" << q << "] is going to be updated (reINVITE) in order to recover from lost connectivity"; + q->update(params); +} + +void CallSessionPrivate::repairByInviteWithReplaces () { + L_Q(); + lInfo() << "CallSession [" << q << "] is going to have a new INVITE replacing the previous one in order to recover from lost connectivity"; + string callId = op->getCallId(); + const char *fromTag = op->getLocalTag(); + const char *toTag = op->getRemoteTag(); + op->killDialog(); + createOp(); + op->setReplaces(callId.c_str(), fromTag, toTag); + q->startInvite(nullptr); +} + +void CallSessionPrivate::repairIfBroken () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + LinphoneConfig *config = linphone_core_get_config(lc); + if (!lp_config_get_int(config, "sip", "repair_broken_calls", 1) || !lc->media_network_reachable || !broken) + return; + + // If we are registered and this session has been broken due to a past network disconnection, + // attempt to repair it + + // Make sure that the proxy from which we received this call, or to which we routed this call is registered first + if (destProxy) { + // In all other cases, ie no proxy config, or a proxy config for which no registration was requested, + // we can start the call session repair immediately. + if (linphone_proxy_config_register_enabled(destProxy) + && (linphone_proxy_config_get_state(destProxy) != LinphoneRegistrationOk)) + return; + } + + SalErrorInfo sei; + memset(&sei, 0, sizeof(sei)); + switch (state) { + case CallSession::State::Updating: + case CallSession::State::Pausing: + if (op->dialogRequestPending()) { + // Need to cancel first re-INVITE as described in section 5.5 of RFC 6141 + if (op->cancelInvite() == 0){ + reinviteOnCancelResponseRequested = true; + } + } + break; + case CallSession::State::StreamsRunning: + case CallSession::State::Paused: + case CallSession::State::PausedByRemote: + if (!op->dialogRequestPending()) + reinviteToRecoverFromConnectionLoss(); + break; + case CallSession::State::UpdatedByRemote: + if (op->dialogRequestPending()) { + sal_error_info_set(&sei, SalReasonServiceUnavailable, "SIP", 0, nullptr, nullptr); + op->declineWithErrorInfo(&sei, nullptr); + } + reinviteToRecoverFromConnectionLoss(); + break; + case CallSession::State::OutgoingInit: + case CallSession::State::OutgoingProgress: + if (op->cancelInvite() == 0){ + reinviteOnCancelResponseRequested = true; + } + break; + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::OutgoingRinging: + repairByInviteWithReplaces(); + break; + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::IncomingReceived: + // Keep the call broken until a forked INVITE is received from the server + break; + default: + lWarning() << "CallSessionPrivate::repairIfBroken: don't know what to do in state [" << Utils::toString(state); + broken = false; + break; + } + sal_error_info_reset(&sei); +} + +// ============================================================================= + +CallSession::CallSession (const shared_ptr &core, const CallSessionParams *params, CallSessionListener *listener) + : Object(*new CallSessionPrivate), CoreAccessor(core) { + L_D(); + getCore()->getPrivate()->registerListener(d); + d->listener = listener; + if (params) + d->setParams(new CallSessionParams(*params)); + d->init(); + lInfo() << "New CallSession [" << this << "] initialized (LinphoneCore version: " << linphone_core_get_version() << ")"; +} + +CallSession::CallSession (CallSessionPrivate &p, const shared_ptr &core) : Object(p), CoreAccessor(core) { + L_D(); + getCore()->getPrivate()->registerListener(d); + d->init(); +} + +CallSession::~CallSession () { + L_D(); + getCore()->getPrivate()->unregisterListener(d); + if (d->currentParams) + delete d->currentParams; + if (d->params) + delete d->params; + if (d->remoteParams) + delete d->remoteParams; + if (d->ei) + linphone_error_info_unref(d->ei); + if (d->log) + linphone_call_log_unref(d->log); + if (d->op) + d->op->release(); +} + +// ----------------------------------------------------------------------------- + +LinphoneStatus CallSession::accept (const CallSessionParams *csp) { + L_D(); + LinphoneStatus result = d->checkForAcceptation(); + if (result < 0) return result; + d->accept(csp); + return 0; +} + +LinphoneStatus CallSession::acceptUpdate (const CallSessionParams *csp) { + L_D(); + if (d->state != CallSession::State::UpdatedByRemote) { + lError() << "CallSession::acceptUpdate(): invalid state " << Utils::toString(d->state) << " to call this method"; + return -1; + } + return d->acceptUpdate(csp, d->prevState, Utils::toString(d->prevState)); +} + +void CallSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) { + L_D(); + d->direction = direction; + d->destProxy = cfg; + LinphoneAddress *fromAddr = linphone_address_new(from.asString().c_str()); + LinphoneAddress *toAddr = linphone_address_new(to.asString().c_str()); + if (!d->destProxy) { + /* Try to define the destination proxy if it has not already been done to have a correct contact field in the SIP messages */ + d->destProxy = linphone_core_lookup_known_proxy(getCore()->getCCore(), toAddr); + } + d->log = linphone_call_log_new(direction, fromAddr, toAddr); + + if (op) { + /* We already have an op for incoming calls */ + d->op = op; + d->op->setUserPointer(this); + op->enableCnxIpTo0000IfSendOnly( + !!lp_config_get_default_int( + linphone_core_get_config(getCore()->getCCore()), "sip", "cnx_ip_to_0000_if_sendonly_enabled", 0 + ) + ); + d->log->call_id = ms_strdup(op->getCallId().c_str()); /* Must be known at that time */ + } + + if (direction == LinphoneCallOutgoing) { + if (d->params->getPrivate()->getReferer()) + d->referer = d->params->getPrivate()->getReferer(); + d->startPing(); + } else if (direction == LinphoneCallIncoming) { + d->setParams(new CallSessionParams()); + d->params->initDefault(getCore()); + } +} + +LinphoneStatus CallSession::decline (LinphoneReason reason) { + LinphoneErrorInfo *ei = linphone_error_info_new(); + linphone_error_info_set(ei, "SIP", reason, linphone_reason_to_error_code(reason), nullptr, nullptr); + LinphoneStatus status = decline(ei); + linphone_error_info_unref(ei); + return status; +} + +LinphoneStatus CallSession::decline (const LinphoneErrorInfo *ei) { + L_D(); + SalErrorInfo sei; + SalErrorInfo sub_sei; + memset(&sei, 0, sizeof(sei)); + memset(&sub_sei, 0, sizeof(sub_sei)); + sei.sub_sei = &sub_sei; + if ((d->state != CallSession::State::IncomingReceived) && (d->state != CallSession::State::IncomingEarlyMedia)) { + lError() << "Cannot decline a CallSession that is in state " << Utils::toString(d->state); + return -1; + } + if (ei) { + linphone_error_info_to_sal(ei, &sei); + d->op->declineWithErrorInfo(&sei , nullptr); + } else + d->op->decline(SalReasonDeclined, nullptr); + sal_error_info_reset(&sei); + sal_error_info_reset(&sub_sei); + d->terminate(); + return 0; +} + +LinphoneStatus CallSession::declineNotAnswered (LinphoneReason reason) { + L_D(); + d->log->status = LinphoneCallMissed; + d->nonOpError = true; + linphone_error_info_set(d->ei, nullptr, reason, linphone_reason_to_error_code(reason), "Not answered", nullptr); + return decline(reason); +} + +LinphoneStatus CallSession::deferUpdate () { + L_D(); + if (d->state != CallSession::State::UpdatedByRemote) { + lError() << "CallSession::deferUpdate() not done in state CallSession::State::UpdatedByRemote"; + return -1; + } + d->deferUpdate = true; + return 0; +} + +bool CallSession::hasTransferPending () { + L_D(); + return d->referPending; +} + +void CallSession::initiateIncoming () {} + +bool CallSession::initiateOutgoing () { + L_D(); + bool defer = false; + d->setState(CallSession::State::OutgoingInit, "Starting outgoing call"); + d->log->start_date_time = ms_time(nullptr); + if (!d->destProxy) + defer = d->startPing(); + return defer; +} + +void CallSession::iterate (time_t currentRealTime, bool oneSecondElapsed) { + L_D(); + int elapsed = (int)(currentRealTime - d->log->start_date_time); + if ((d->state == CallSession::State::OutgoingInit) && (elapsed > getCore()->getCCore()->sip_conf.delayed_timeout)) { + /* Start the call even if the OPTIONS reply did not arrive */ + startInvite(nullptr, ""); + } + if ((d->state == CallSession::State::IncomingReceived) || (d->state == CallSession::State::IncomingEarlyMedia)) { + if (d->listener) + d->listener->onIncomingCallSessionTimeoutCheck(getSharedFromThis(), elapsed, oneSecondElapsed); + } + if ((getCore()->getCCore()->sip_conf.in_call_timeout > 0) && (d->log->connected_date_time != 0) + && ((currentRealTime - d->log->connected_date_time) > getCore()->getCCore()->sip_conf.in_call_timeout)) { + lInfo() << "In call timeout (" << getCore()->getCCore()->sip_conf.in_call_timeout << ")"; + terminate(); + } +} + +LinphoneStatus CallSession::redirect (const string &redirectUri) { + LinphoneAddress *realParsedAddr = linphone_core_interpret_url(getCore()->getCCore(), redirectUri.c_str()); + if (!realParsedAddr) { + /* Bad url */ + lError() << "Bad redirect URI: " << redirectUri; + return -1; + } + char *realParsedUri = linphone_address_as_string(realParsedAddr); + Address redirectAddr(realParsedUri); + bctbx_free(realParsedUri); + linphone_address_unref(realParsedAddr); + return redirect(redirectAddr); +} + +LinphoneStatus CallSession::redirect (const Address &redirectAddr) { + L_D(); + if (d->state != CallSession::State::IncomingReceived) { + lError() << "Bad state for CallSession redirection"; + return -1; + } + SalErrorInfo sei; + memset(&sei, 0, sizeof(sei)); + sal_error_info_set(&sei, SalReasonRedirect, "SIP", 0, nullptr, nullptr); + d->op->declineWithErrorInfo(&sei, redirectAddr.getPrivate()->getInternalAddress()); + linphone_error_info_set(d->ei, nullptr, LinphoneReasonMovedPermanently, 302, "Call redirected", nullptr); + d->nonOpError = true; + d->terminate(); + sal_error_info_reset(&sei); + return 0; +} + +void CallSession::startIncomingNotification (bool notifyRinging) { + L_D(); + d->notifyRinging = notifyRinging; + if (d->listener) { + d->listener->onIncomingCallSessionNotified(getSharedFromThis()); + d->listener->onBackgroundTaskToBeStarted(getSharedFromThis()); + } + /* Prevent the CallSession from being destroyed while we are notifying, if the user declines within the state callback */ + shared_ptr ref = getSharedFromThis(); + if (d->deferIncomingNotification) { + lInfo() << "Defer incoming notification"; + return; + } + + d->startIncomingNotification(); +} + +int CallSession::startInvite (const Address *destination, const string &subject, const Content *content) { + L_D(); + d->subject = subject; + /* Try to be best-effort in giving real local or routable contact address */ + d->setContactOp(); + string destinationStr; + char *realUrl = nullptr; + if (destination) + destinationStr = destination->asString(); + else { + realUrl = linphone_address_as_string(d->log->to); + destinationStr = realUrl; + ms_free(realUrl); + } + char *from = linphone_address_as_string(d->log->from); + /* Take a ref because sal_call() may destroy the CallSession if no SIP transport is available */ + shared_ptr ref = getSharedFromThis(); + if (content) + d->op->setLocalBody(*content); + int result = d->op->call(from, destinationStr.c_str(), subject.empty() ? nullptr : subject.c_str()); + ms_free(from); + if (result < 0) { + if ((d->state != CallSession::State::Error) && (d->state != CallSession::State::Released)) { + /* sal_call() may invoke call_failure() and call_released() SAL callbacks synchronously, + in which case there is no need to perform a state change here. */ + d->setState(CallSession::State::Error, "Call failed"); + } + } else { + d->log->call_id = ms_strdup(d->op->getCallId().c_str()); /* Must be known at that time */ + d->setState(CallSession::State::OutgoingProgress, "Outgoing call in progress"); + } + return result; +} + +LinphoneStatus CallSession::terminate (const LinphoneErrorInfo *ei) { + L_D(); + lInfo() << "Terminate CallSession [" << this << "] which is currently in state [" << Utils::toString(d->state) << "]"; + SalErrorInfo sei; + memset(&sei, 0, sizeof(sei)); + switch (d->state) { + case CallSession::State::Released: + case CallSession::State::End: + case CallSession::State::Error: + lWarning() << "No need to terminate CallSession [" << this << "] in state [" << Utils::toString(d->state) << "]"; + return -1; + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + return decline(ei); + case CallSession::State::OutgoingInit: + /* In state OutgoingInit, op has to be destroyed */ + d->op->release(); + d->op = nullptr; + break; + default: + if (ei) { + linphone_error_info_to_sal(ei, &sei); + d->op->terminate(&sei); + sal_error_info_reset(&sei); + } else + d->op->terminate(); + break; + } + + d->terminate(); + return 0; +} + +LinphoneStatus CallSession::transfer (const shared_ptr &dest) { + L_D(); + int result = d->op->referWithReplaces(dest->getPrivate()->op); + d->setTransferState(CallSession::State::OutgoingInit); + return result; +} + +LinphoneStatus CallSession::transfer (const string &dest) { + L_D(); + LinphoneAddress *destAddr = linphone_core_interpret_url(getCore()->getCCore(), dest.c_str()); + if (!destAddr) + return -1; + char *addrStr = linphone_address_as_string(destAddr); + d->op->refer(addrStr); + bctbx_free(addrStr); + linphone_address_unref(destAddr); + d->setTransferState(CallSession::State::OutgoingInit); + return 0; +} + +LinphoneStatus CallSession::update (const CallSessionParams *csp, const string &subject, const Content *content) { + L_D(); + CallSession::State nextState; + CallSession::State initialState = d->state; + if (!d->isUpdateAllowed(nextState)) + return -1; + if (d->currentParams == csp) + lWarning() << "CallSession::update() is given the current params, this is probably not what you intend to do!"; + if (csp) + d->setParams(new CallSessionParams(*csp)); + d->op->setLocalBody(content ? *content : Content()); + LinphoneStatus result = d->startUpdate(subject); + if (result && (d->state != initialState)) { + /* Restore initial state */ + d->setState(initialState, "Restore initial state"); + } + return result; +} + +// ----------------------------------------------------------------------------- + +LinphoneCallDir CallSession::getDirection () const { + L_D(); + return d->direction; +} + +const Address& CallSession::getDiversionAddress () const { + L_D(); + if (d->op) { + char *addrStr = sal_address_as_string(d->op->getDiversionAddress()); + d->diversionAddress = Address(addrStr); + bctbx_free(addrStr); + } else { + d->diversionAddress = Address(); + } + return d->diversionAddress; +} + +int CallSession::getDuration () const { + L_D(); + switch (d->state) { + case CallSession::State::End: + case CallSession::State::Error: + case CallSession::State::Released: + return d->log->duration; + default: + return d->computeDuration(); + } +} + +const LinphoneErrorInfo * CallSession::getErrorInfo () const { + L_D(); + if (!d->nonOpError) + linphone_error_info_from_sal_op(d->ei, d->op); + return d->ei; +} + +const Address& CallSession::getLocalAddress () const { + L_D(); + return *L_GET_CPP_PTR_FROM_C_OBJECT((d->direction == LinphoneCallIncoming) + ? linphone_call_log_get_to(d->log) : linphone_call_log_get_from(d->log)); +} + +LinphoneCallLog * CallSession::getLog () const { + L_D(); + return d->log; +} + +LinphoneReason CallSession::getReason () const { + return linphone_error_info_get_reason(getErrorInfo()); +} + +shared_ptr CallSession::getReferer () const { + L_D(); + return d->referer; +} + +string CallSession::getReferTo () const { + L_D(); + return d->referTo; +} + +const Address& CallSession::getRemoteAddress () const { + L_D(); + return *L_GET_CPP_PTR_FROM_C_OBJECT((d->direction == LinphoneCallIncoming) + ? linphone_call_log_get_from(d->log) : linphone_call_log_get_to(d->log)); +} + +string CallSession::getRemoteContact () const { + L_D(); + if (d->op) { + /* sal_op_get_remote_contact preserves header params */ + return d->op->getRemoteContact(); + } + return string(); +} + +const Address *CallSession::getRemoteContactAddress () const { + L_D(); + if (!d->op) { + return nullptr; + } + char *addrStr = sal_address_as_string(d->op->getRemoteContactAddress()); + d->remoteContactAddress = Address(addrStr); + bctbx_free(addrStr); + return &d->remoteContactAddress; +} + +const CallSessionParams * CallSession::getRemoteParams () { + L_D(); + if (d->op){ + const SalCustomHeader *ch = d->op->getRecvCustomHeaders(); + if (ch) { + /* Instanciate a remote_params only if a SIP message was received before (custom headers indicates this) */ + if (!d->remoteParams) + d->remoteParams = new CallSessionParams(); + d->remoteParams->getPrivate()->setCustomHeaders(ch); + } + return d->remoteParams; + } + return nullptr; +} + +CallSession::State CallSession::getState () const { + L_D(); + return d->state; +} + +CallSession::State CallSession::getPreviousState () const { + L_D(); + return d->prevState; +} + +const Address& CallSession::getToAddress () const { + L_D(); + d->toAddress = Address(d->op->getTo()); + return d->toAddress; +} + +CallSession::State CallSession::getTransferState () const { + L_D(); + return d->transferState; +} + +shared_ptr CallSession::getTransferTarget () const { + L_D(); + return d->transferTarget; +} + +string CallSession::getToHeader (const string &name) const { + L_D(); + return L_C_TO_STRING(sal_custom_header_find(d->op->getRecvCustomHeaders(), name.c_str())); +} + +// ----------------------------------------------------------------------------- + +string CallSession::getRemoteUserAgent () const { + L_D(); + if (d->op) + return d->op->getRemoteUserAgent(); + return string(); +} + +shared_ptr CallSession::getReplacedCallSession () const { + L_D(); + SalOp *replacedOp = d->op->getReplaces(); + if (!replacedOp) + return nullptr; + return reinterpret_cast(replacedOp->getUserPointer())->getSharedFromThis(); +} + +CallSessionParams * CallSession::getCurrentParams () const { + L_D(); + d->updateCurrentParams(); + return d->currentParams; +} + +// ----------------------------------------------------------------------------- + +const CallSessionParams * CallSession::getParams () const { + L_D(); + return d->params; +} + +// ----------------------------------------------------------------------------- + +bool CallSession::isEarlyState (CallSession::State state) { + switch (state) { + case CallSession::State::Idle: + case CallSession::State::OutgoingInit: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingProgress: + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::EarlyUpdatedByRemote: + case CallSession::State::EarlyUpdating: + return true; + default: + return false; + } +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/session/call-session.h b/src/conference/session/call-session.h new file mode 100644 index 000000000..63330f3d0 --- /dev/null +++ b/src/conference/session/call-session.h @@ -0,0 +1,115 @@ +/* + * call-session.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CALL_SESSION_H_ +#define _L_CALL_SESSION_H_ + +#include "object/object.h" +#include "address/address.h" +#include "conference/conference.h" +#include "conference/params/call-session-params.h" +#include "core/core-listener.h" +#include "sal/call-op.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallPrivate; +class CallSessionPrivate; +class Content; +class Core; + +class LINPHONE_PUBLIC CallSession : public Object, public CoreAccessor { + friend class Call; + friend class CallPrivate; + friend class ClientGroupChatRoom; + friend class ClientGroupChatRoomPrivate; + friend class Conference; + friend class CorePrivate; + friend class LocalConferenceCall; + friend class RemoteConferenceCall; + friend class ServerGroupChatRoom; + friend class ServerGroupChatRoomPrivate; + +public: + L_OVERRIDE_SHARED_FROM_THIS(CallSession); + + L_DECLARE_ENUM(State, L_ENUM_VALUES_CALL_SESSION_STATE); + + CallSession (const std::shared_ptr &core, const CallSessionParams *params, CallSessionListener *listener); + ~CallSession (); + + LinphoneStatus accept (const CallSessionParams *csp = nullptr); + LinphoneStatus acceptUpdate (const CallSessionParams *csp = nullptr); + virtual void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to); + LinphoneStatus decline (LinphoneReason reason); + LinphoneStatus decline (const LinphoneErrorInfo *ei); + LinphoneStatus declineNotAnswered (LinphoneReason reason); + virtual LinphoneStatus deferUpdate (); + bool hasTransferPending (); + virtual void initiateIncoming (); + virtual bool initiateOutgoing (); + virtual void iterate (time_t currentRealTime, bool oneSecondElapsed); + LinphoneStatus redirect (const std::string &redirectUri); + LinphoneStatus redirect (const Address &redirectAddr); + virtual void startIncomingNotification (bool notifyRinging = true); + virtual int startInvite (const Address *destination, const std::string &subject = "", const Content *content = nullptr); + LinphoneStatus terminate (const LinphoneErrorInfo *ei = nullptr); + LinphoneStatus transfer (const std::shared_ptr &dest); + LinphoneStatus transfer (const std::string &dest); + LinphoneStatus update (const CallSessionParams *csp, const std::string &subject = "", const Content *content = nullptr); + + CallSessionParams *getCurrentParams () const; + LinphoneCallDir getDirection () const; + const Address &getDiversionAddress () const; + int getDuration () const; + const LinphoneErrorInfo * getErrorInfo () const; + const Address &getLocalAddress () const; + LinphoneCallLog *getLog () const; + virtual const CallSessionParams *getParams () const; + LinphoneReason getReason () const; + std::shared_ptr getReferer () const; + std::string getReferTo () const; + const Address &getRemoteAddress () const; + std::string getRemoteContact () const; + const Address *getRemoteContactAddress () const; + const CallSessionParams *getRemoteParams (); + std::string getRemoteUserAgent () const; + std::shared_ptr getReplacedCallSession () const; + CallSession::State getState () const; + const Address &getToAddress () const; + CallSession::State getTransferState () const; + std::shared_ptr getTransferTarget () const; + std::string getToHeader (const std::string &name) const; + + static bool isEarlyState (CallSession::State state); + +protected: + explicit CallSession (CallSessionPrivate &p, const std::shared_ptr &core); + CallSession::State getPreviousState () const; + +private: + L_DECLARE_PRIVATE(CallSession); + L_DISABLE_COPY(CallSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CALL_SESSION_H_ diff --git a/src/conference/session/media-session-p.h b/src/conference/session/media-session-p.h new file mode 100644 index 000000000..1b65012a5 --- /dev/null +++ b/src/conference/session/media-session-p.h @@ -0,0 +1,341 @@ +/* + * media-session-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MEDIA_SESSION_P_H_ +#define _L_MEDIA_SESSION_P_H_ + +#include "call-session-p.h" + +#include "media-session.h" +#include "port-config.h" +#include "nat/ice-agent.h" +#include "nat/stun-client.h" + +#include "linphone/call_stats.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class MediaSessionPrivate : public CallSessionPrivate { +public: + static int resumeAfterFailedTransfer (void *userData, unsigned int); + static bool_t startPendingRefer (void *userData); + static void stunAuthRequestedCb (void *userData, const char *realm, const char *nonce, const char **username, const char **password, const char **ha1); + + void accepted () override; + void ackReceived (LinphoneHeaders *headers) override; + void dtmfReceived (char dtmf); + bool failure () override; + void pauseForTransfer (); + void pausedByRemote (); + void remoteRinging () override; + void replaceOp (SalCallOp *newOp) override; + int resumeAfterFailedTransfer (); + void resumed (); + void startPendingRefer (); + void telephoneEventReceived (int event); + void terminated () override; + void updated (bool isUpdate); + void updating (bool isUpdate) override; + + void enableSymmetricRtp (bool value); + void oglRender () const; + void sendVfu (); + + void clearIceCheckList (IceCheckList *cl); + void deactivateIce (); + void prepareStreamsForIceGathering (bool hasVideo); + void stopStreamsForIceGathering (); + + int getAf () const { return af; } + + bool getAudioMuted () const { return audioMuted; } + + MediaSessionParams *getCurrentParams () const { return static_cast(currentParams); } + MediaSessionParams *getParams () const { return static_cast(params); } + MediaSessionParams *getRemoteParams () const { return static_cast(remoteParams); } + void setCurrentParams (MediaSessionParams *msp); + void setParams (MediaSessionParams *msp); + void setRemoteParams (MediaSessionParams *msp); + + IceSession *getIceSession () const { return iceAgent ? iceAgent->getIceSession() : nullptr; } + + SalMediaDescription *getLocalDesc () const { return localDesc; } + + unsigned int getMediaStartCount () const; + MediaStream *getMediaStream (LinphoneStreamType type) const; + LinphoneNatPolicy *getNatPolicy () const { return natPolicy; } + + int getRtcpPort (LinphoneStreamType type) const; + int getRtpPort (LinphoneStreamType type) const; + LinphoneCallStats *getStats (LinphoneStreamType type) const; + int getStreamIndex (LinphoneStreamType type) const; + int getStreamIndex (MediaStream *ms) const; + SalCallOp * getOp () const { return op; } + MSWebCam *getVideoDevice () const; + void setAudioMuted (bool value) { audioMuted = value; } + + void initializeStreams (); + void stopStreams (); + + // Methods used by testers + void addLocalDescChangedFlag (int flag) { localDescChanged |= flag; } + belle_sip_source_t *getDtmfTimer () const { return dtmfTimer; } + const std::string &getDtmfSequence () const { return dtmfSequence; } + int getMainAudioStreamIndex () const { return mainAudioStreamIndex; } + int getMainTextStreamIndex () const { return mainTextStreamIndex; } + int getMainVideoStreamIndex () const { return mainVideoStreamIndex; } + SalMediaDescription *getResultDesc () const { return resultDesc; } + + // CoreListener + void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) override; + + // Call listener + void snapshotTakenCb(void *userdata, struct _MSFilter *f, unsigned int id, void *arg); + +private: + static OrtpJitterBufferAlgorithm jitterBufferNameToAlgo (const std::string &name); + +#ifdef VIDEO_ENABLED + static void videoStreamEventCb (void *userData, const MSFilter *f, const unsigned int eventId, const void *args); +#endif // ifdef VIDEO_ENABLED +#ifdef TEST_EXT_RENDERER + static void extRendererCb (void *userData, const MSPicture *local, const MSPicture *remote); +#endif // ifdef TEST_EXT_RENDERER + static void realTimeTextCharacterReceived (void *userData, MSFilter *f, unsigned int id, void *arg); + static int sendDtmf (void *data, unsigned int revents); + static float aggregateQualityRatings (float audioRating, float videoRating); + + std::shared_ptr getMe () const; + void setState (CallSession::State newState, const std::string &message) override; + + void computeStreamsIndexes (const SalMediaDescription *md); + void fixCallParams (SalMediaDescription *rmd); + void initializeParamsAccordingToIncomingCallParams () override; + void setCompatibleIncomingCallParams (SalMediaDescription *md); + void updateBiggestDesc (SalMediaDescription *md); + void updateRemoteSessionIdAndVer (); + + void initStats (LinphoneCallStats *stats, LinphoneStreamType type); + void notifyStatsUpdated (int streamIndex); + + OrtpEvQueue *getEventQueue (int streamIndex) const; + MediaStream *getMediaStream (int streamIndex) const; + + void fillMulticastMediaAddresses (); + int selectFixedPort (int streamIndex, std::pair portRange); + int selectRandomPort (int streamIndex, std::pair portRange); + void setPortConfig (int streamIndex, std::pair portRange); + void setPortConfigFromRtpSession (int streamIndex, RtpSession *session); + void setRandomPortConfig (int streamIndex); + + void discoverMtu (const Address &remoteAddr); + std::string getBindIpForStream (int streamIndex); + void getLocalIp (const Address &remoteAddr); + std::string getPublicIpForStream (int streamIndex); + void runStunTestsIfNeeded (); + void selectIncomingIpVersion (); + void selectOutgoingIpVersion (); + + void forceStreamsDirAccordingToState (SalMediaDescription *md); + bool generateB64CryptoKey (size_t keyLength, char *keyOut, size_t keyOutSize); + void makeLocalMediaDescription (); + int setupEncryptionKey (SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag); + void setupDtlsKeys (SalMediaDescription *md); + void setupEncryptionKeys (SalMediaDescription *md); + void setupRtcpFb (SalMediaDescription *md); + void setupRtcpXr (SalMediaDescription *md); + void setupZrtpHash (SalMediaDescription *md); + void transferAlreadyAssignedPayloadTypes (SalMediaDescription *oldMd, SalMediaDescription *md); + void updateLocalMediaDescriptionFromIce (); + + SalMulticastRole getMulticastRole (SalStreamType type); + void joinMulticastGroup (int streamIndex, MediaStream *ms); + + int findCryptoIndexFromTag (const SalSrtpCryptoAlgo crypto[], unsigned char tag); + void setDtlsFingerprint (MSMediaStreamSessions *sessions, const SalStreamDescription *sd, const SalStreamDescription *remote); + void setDtlsFingerprintOnAllStreams (); + void setupDtlsParams (MediaStream *ms); + void setZrtpCryptoTypesParameters (MSZrtpParams *params); + void startDtls (MSMediaStreamSessions *sessions, const SalStreamDescription *sd, const SalStreamDescription *remote); + void startDtlsOnAllStreams (); + void updateCryptoParameters (SalMediaDescription *oldMd, SalMediaDescription *newMd); + bool updateStreamCryptoParameters (const SalStreamDescription *localStreamDesc, SalStreamDescription *oldStream, SalStreamDescription *newStream, MediaStream *ms); + + int getIdealAudioBandwidth (const SalMediaDescription *md, const SalStreamDescription *desc); + int getVideoBandwidth (const SalMediaDescription *md, const SalStreamDescription *desc); + RtpProfile *makeProfile (const SalMediaDescription *md, const SalStreamDescription *desc, int *usedPt); + void unsetRtpProfile (int streamIndex); + void updateAllocatedAudioBandwidth (const PayloadType *pt, int maxbw); + + void applyJitterBufferParams (RtpSession *session, LinphoneStreamType type); + void clearEarlyMediaDestination (MediaStream *ms); + void clearEarlyMediaDestinations (); + void configureAdaptiveRateControl (MediaStream *ms, const OrtpPayloadType *pt, bool videoWillBeUsed); + void configureRtpSessionForRtcpFb (const SalStreamDescription *stream); + void configureRtpSessionForRtcpXr (SalStreamType type); + RtpSession *createAudioRtpIoSession (); + RtpSession *createVideoRtpIoSession (); + void freeResources (); + void handleIceEvents (OrtpEvent *ev); + void handleStreamEvents (int streamIndex); + void initializeAudioStream (); + void initializeTextStream (); + void initializeVideoStream (); + void prepareEarlyMediaForking (); + void postConfigureAudioStreams (bool muted); + void setSymmetricRtp (bool value); + void setupRingbackPlayer (); + void startAudioStream (CallSession::State targetState, bool videoWillBeUsed); + void startStreams (CallSession::State targetState); + void startTextStream (); + void startVideoStream (CallSession::State targetState); + void stopAudioStream (); + void stopTextStream (); + void stopVideoStream (); + void tryEarlyMediaForking (SalMediaDescription *md); + void updateFrozenPayloads (SalMediaDescription *result); + void updateStreams (SalMediaDescription *newMd, CallSession::State targetState); + void updateStreamsDestinations (SalMediaDescription *oldMd, SalMediaDescription *newMd); + + bool allStreamsAvpfEnabled () const; + bool allStreamsEncrypted () const; + bool atLeastOneStreamStarted () const; + void audioStreamAuthTokenReady (const std::string &authToken, bool verified); + void audioStreamEncryptionChanged (bool encrypted); + uint16_t getAvpfRrInterval () const; + unsigned int getNbActiveStreams () const; + bool isEncryptionMandatory () const; + int mediaParametersChanged (SalMediaDescription *oldMd, SalMediaDescription *newMd); + void propagateEncryptionChanged (); + + void fillLogStats (MediaStream *st); + void updateLocalStats (LinphoneCallStats *stats, MediaStream *stream) const; + void updateRtpStats (LinphoneCallStats *stats, int streamIndex); + + void executeBackgroundTasks (bool oneSecondElapsed); + void reportBandwidth (); + void reportBandwidthForStream (MediaStream *ms, LinphoneStreamType type); + + void abort (const std::string &errorMsg) override; + void handleIncomingReceivedStateInIncomingNotification () override; + bool isReadyForInvite () const override; + LinphoneStatus pause (); + int restartInvite () override; + void setTerminated () override; + LinphoneStatus startAcceptUpdate (CallSession::State nextState, const std::string &stateInfo) override; + LinphoneStatus startUpdate (const std::string &subject = "") override; + void terminate () override; + void updateCurrentParams () const override; + + void accept (const MediaSessionParams *params, bool wasRinging); + LinphoneStatus acceptUpdate (const CallSessionParams *csp, CallSession::State nextState, const std::string &stateInfo) override; + + void refreshSockets (); + void reinviteToRecoverFromConnectionLoss () override; + void repairByInviteWithReplaces () override; + +#ifdef VIDEO_ENABLED + void videoStreamEventCb (const MSFilter *f, const unsigned int eventId, const void *args); +#endif // ifdef VIDEO_ENABLED + void realTimeTextCharacterReceived (MSFilter *f, unsigned int id, void *arg); + int sendDtmf (); + + void stunAuthRequestedCb (const char *realm, const char *nonce, const char **username, const char **password, const char **ha1); +private: + static const std::string ecStateStore; + static const int ecStateMaxLen; + + std::weak_ptr me; + + AudioStream *audioStream = nullptr; + OrtpEvQueue *audioStreamEvQueue = nullptr; + LinphoneCallStats *audioStats = nullptr; + RtpProfile *audioProfile = nullptr; + RtpProfile *rtpIoAudioProfile = nullptr; + int mainAudioStreamIndex = LINPHONE_CALL_STATS_AUDIO; + + VideoStream *videoStream = nullptr; + OrtpEvQueue *videoStreamEvQueue = nullptr; + LinphoneCallStats *videoStats = nullptr; + RtpProfile *rtpIoVideoProfile = nullptr; + RtpProfile *videoProfile = nullptr; + int mainVideoStreamIndex = LINPHONE_CALL_STATS_VIDEO; + void *videoWindowId = nullptr; + bool cameraEnabled = true; + + TextStream *textStream = nullptr; + OrtpEvQueue *textStreamEvQueue = nullptr; + LinphoneCallStats *textStats = nullptr; + RtpProfile *textProfile = nullptr; + int mainTextStreamIndex = LINPHONE_CALL_STATS_TEXT; + + LinphoneNatPolicy *natPolicy = nullptr; + std::unique_ptr stunClient; + std::unique_ptr iceAgent; + + // The address family to prefer for RTP path, guessed from signaling path. + int af; + + std::string dtmfSequence; + belle_sip_source_t *dtmfTimer = nullptr; + + std::string mediaLocalIp; + PortConfig mediaPorts[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; + bool needMediaLocalIpRefresh = false; + + // The rtp, srtp, zrtp contexts for each stream. + MSMediaStreamSessions sessions[SAL_MEDIA_DESCRIPTION_MAX_STREAMS]; + + SalMediaDescription *localDesc = nullptr; + int localDescChanged = 0; + SalMediaDescription *biggestDesc = nullptr; + SalMediaDescription *resultDesc = nullptr; + bool expectMediaInAck = false; + unsigned int remoteSessionId = 0; + unsigned int remoteSessionVer = 0; + + std::string authToken; + bool authTokenVerified = false; + std::string dtlsCertificateFingerprint; + + unsigned int mediaStartCount = 0; + + // Upload bandwidth setting at the time the call is started. Used to detect if it changes during a call. + int upBandwidth = 0; + + // Upload bandwidth used by audio. + int audioBandwidth = 0; + + bool allMuted = false; + bool audioMuted = false; + bool automaticallyPaused = false; + bool pausedByApp = false; + bool recordActive = false; + bool incomingIceReinvitePending = false; + + std::string onHoldFile; + + L_DECLARE_PUBLIC(MediaSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MEDIA_SESSION_P_H_ diff --git a/src/conference/session/media-session.cpp b/src/conference/session/media-session.cpp new file mode 100644 index 000000000..f8216ca56 --- /dev/null +++ b/src/conference/session/media-session.cpp @@ -0,0 +1,4825 @@ +/* + * media-session.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "address/address-p.h" +#include "c-wrapper/c-wrapper.h" +#include "conference/session/media-session-p.h" +#include "call/call-p.h" +#include "conference/participant-p.h" +#include "conference/params/media-session-params-p.h" +#include "conference/session/media-session.h" +#include "core/core-p.h" +#include "sal/sal.h" +#include "utils/payload-type-handler.h" + +#include "logger/logger.h" + +#include "linphone/core.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "private.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +#define STR_REASSIGN(dest, src) { \ + if (dest) \ + ms_free(dest); \ + dest = src; \ +} + +inline OrtpRtcpXrStatSummaryFlag operator|(OrtpRtcpXrStatSummaryFlag a, OrtpRtcpXrStatSummaryFlag b) { + return static_cast(static_cast(a) | static_cast(b)); +} + +// ============================================================================= + +const string MediaSessionPrivate::ecStateStore = ".linphone.ecstate"; +const int MediaSessionPrivate::ecStateMaxLen = 1048576; /* 1Mo */ + +// ============================================================================= + +void MediaSessionPrivate::stunAuthRequestedCb (void *userData, const char *realm, const char *nonce, const char **username, const char **password, const char **ha1) { + MediaSessionPrivate *msp = reinterpret_cast(userData); + msp->stunAuthRequestedCb(realm, nonce, username, password, ha1); +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::accepted () { + L_Q(); + CallSessionPrivate::accepted(); + LinphoneTaskList tl; + linphone_task_list_init(&tl); + /* Reset the internal call update flag, so it doesn't risk to be copied and used in further re-INVITEs */ + getParams()->getPrivate()->setInternalCallUpdate(false); + SalMediaDescription *rmd = op->getRemoteMediaDescription(); + SalMediaDescription *md = op->getFinalMediaDescription(); + if (!md && (prevState == CallSession::State::OutgoingEarlyMedia) && resultDesc) { + lInfo() << "Using early media SDP since none was received with the 200 OK"; + md = resultDesc; + } + if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(q->getCore()->getCCore(), md))) + md = nullptr; + if (md) { + /* There is a valid SDP in the response, either offer or answer, and we're able to start/update the streams */ + if (rmd) { + /* Handle remote ICE attributes if any. */ + iceAgent->updateFromRemoteMediaDescription(localDesc, rmd, !op->isOfferer()); + } + CallSession::State nextState = CallSession::State::Idle; + string nextStateMsg; + switch (state) { + case CallSession::State::Resuming: + case CallSession::State::Connected: + if (referer) + notifyReferState(); + BCTBX_NO_BREAK; /* Intentional no break */ + case CallSession::State::Updating: + case CallSession::State::UpdatedByRemote: + if (!sal_media_description_has_dir(localDesc, SalStreamInactive) + && (sal_media_description_has_dir(md, SalStreamRecvOnly) || sal_media_description_has_dir(md, SalStreamInactive))) { + nextState = CallSession::State::PausedByRemote; + nextStateMsg = "Call paused by remote"; + } else { + if (!getParams()->getPrivate()->getInConference() && listener) + listener->onSetCurrentSession(q->getSharedFromThis()); + nextState = CallSession::State::StreamsRunning; + nextStateMsg = "Streams running"; + } + break; + case CallSession::State::EarlyUpdating: + nextState = prevState; + nextStateMsg = "Early update accepted"; + break; + case CallSession::State::Pausing: + /* When we entered the pausing state, we always reach the paused state whatever the content of the remote SDP is. + * Our streams are all send-only (with music), soundcard and camera are never used. */ + nextState = CallSession::State::Paused; + nextStateMsg = "Call paused"; + if (referPending) + linphone_task_list_add(&tl, &MediaSessionPrivate::startPendingRefer, q); + break; + default: + lError() << "accepted(): don't know what to do in state [" << Utils::toString(state) << "]"; + break; + } + + if (nextState == CallSession::State::Idle) + lError() << "BUG: nextState is not set in accepted(), current state is " << Utils::toString(state); + else { + updateRemoteSessionIdAndVer(); + iceAgent->updateIceStateInCallStats(); + updateStreams(md, nextState); + fixCallParams(rmd); + setState(nextState, nextStateMsg); + } + } else { /* Invalid or no SDP */ + switch (prevState) { + /* Send a bye only in case of early states */ + case CallSession::State::OutgoingInit: + case CallSession::State::OutgoingProgress: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::IncomingReceived: + case CallSession::State::IncomingEarlyMedia: + lError() << "Incompatible SDP answer received, need to abort the call"; + abort("Incompatible, check codecs or security settings..."); + break; + /* Otherwise we are able to resume previous state */ + default: + lError() << "Incompatible SDP answer received"; + switch(state) { + case CallSession::State::PausedByRemote: + case CallSession::State::Paused: + case CallSession::State::StreamsRunning: + break; + default: + lInfo() << "Incompatible SDP answer received, restoring previous state [" << Utils::toString(prevState) << "]"; + setState(prevState, "Incompatible media parameters."); + break; + } + break; + } + } + linphone_task_list_run(&tl); + linphone_task_list_free(&tl); +} + +void MediaSessionPrivate::ackReceived (LinphoneHeaders *headers) { + CallSessionPrivate::ackReceived(headers); + if (expectMediaInAck) { + switch (state) { + case CallSession::State::StreamsRunning: + case CallSession::State::PausedByRemote: + setState(CallSession::State::UpdatedByRemote, "UpdatedByRemote"); + break; + default: + break; + } + accepted(); + } +} + +void MediaSessionPrivate::dtmfReceived (char dtmf) { + L_Q(); + if (listener) + listener->onDtmfReceived(q->getSharedFromThis(), dtmf); +} + +bool MediaSessionPrivate::failure () { + L_Q(); + const SalErrorInfo *ei = op->getErrorInfo(); + switch (ei->reason) { + case SalReasonRedirect: + stopStreams(); + break; + case SalReasonUnsupportedContent: /* This is for compatibility: linphone sent 415 because of SDP offer answer failure */ + case SalReasonNotAcceptable: + lInfo() << "Outgoing CallSession [" << q << "] failed with SRTP and/or AVPF enabled"; + if ((state == CallSession::State::OutgoingInit) || (state == CallSession::State::OutgoingProgress) + || (state == CallSession::State::OutgoingRinging) /* Push notification case */ || (state == CallSession::State::OutgoingEarlyMedia)) { + for (int i = 0; i < localDesc->nb_streams; i++) { + if (!sal_stream_description_active(&localDesc->streams[i])) + continue; + if (getParams()->getMediaEncryption() == LinphoneMediaEncryptionSRTP) { + if (getParams()->avpfEnabled()) { + if (i == 0) + lInfo() << "Retrying CallSession [" << q << "] with SAVP"; + getParams()->enableAvpf(false); + restartInvite(); + return true; + } else if (!linphone_core_is_media_encryption_mandatory(q->getCore()->getCCore())) { + if (i == 0) + lInfo() << "Retrying CallSession [" << q << "] with AVP"; + getParams()->setMediaEncryption(LinphoneMediaEncryptionNone); + memset(localDesc->streams[i].crypto, 0, sizeof(localDesc->streams[i].crypto)); + restartInvite(); + return true; + } + } else if (getParams()->avpfEnabled()) { + if (i == 0) + lInfo() << "Retrying CallSession [" << q << "] with AVP"; + getParams()->enableAvpf(false); + restartInvite(); + return true; + } + } + } + break; + default: + break; + } + + bool stop = CallSessionPrivate::failure(); + if (stop) + return true; + + if (referer) { + // Schedule automatic resume of the call. This must be done only after the notifications are completed due to dialog serialization of requests + linphone_core_queue_task(q->getCore()->getCCore(), + &MediaSessionPrivate::resumeAfterFailedTransfer, referer.get(), + "Automatic CallSession resuming after failed transfer"); + } + + if (listener) + listener->onStopRingingIfNeeded(q->getSharedFromThis()); + stopStreams(); + return false; +} + +void MediaSessionPrivate::pauseForTransfer () { + L_Q(); + lInfo() << "Automatically pausing current MediaSession to accept transfer"; + q->pause(); + automaticallyPaused = true; +} + +void MediaSessionPrivate::pausedByRemote () { + L_Q(); + MediaSessionParams newParams(*getParams()); + if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "inactive_video_on_pause", 0)) + newParams.setVideoDirection(LinphoneMediaDirectionInactive); + acceptUpdate(&newParams, CallSession::State::PausedByRemote, "Call paused by remote"); +} + +void MediaSessionPrivate::remoteRinging () { + L_Q(); + /* Set privacy */ + getCurrentParams()->setPrivacy((LinphonePrivacyMask)op->getPrivacy()); + SalMediaDescription *md = op->getFinalMediaDescription(); + if (md) { + SalMediaDescription *rmd = op->getRemoteMediaDescription(); + /* Initialize the remote call params by invoking linphone_call_get_remote_params(). This is useful as the SDP may not be present in the 200Ok */ + q->getRemoteParams(); + /* Accept early media */ + if ((audioStream && audio_stream_started(audioStream)) +#ifdef VIDEO_ENABLED + || (videoStream && video_stream_started(videoStream)) +#endif + ) { + /* Streams already started */ + tryEarlyMediaForking(md); +#ifdef VIDEO_ENABLED + if (videoStream) + video_stream_send_vfu(videoStream); /* Request for iframe */ +#endif + return; + } + + setState(CallSession::State::OutgoingEarlyMedia, "Early media"); + if (listener) + listener->onStopRinging(q->getSharedFromThis()); + lInfo() << "Doing early media..."; + iceAgent->updateFromRemoteMediaDescription(localDesc, rmd, !op->isOfferer()); + updateStreams(md, state); + if ((q->getCurrentParams()->getAudioDirection() == LinphoneMediaDirectionInactive) && audioStream) { + if (listener) + listener->onStartRinging(q->getSharedFromThis()); + } + } else { + linphone_core_stop_dtmf_stream(q->getCore()->getCCore()); + if (state == CallSession::State::OutgoingEarlyMedia) { + /* Already doing early media */ + return; + } + if (listener) + listener->onStartRinging(q->getSharedFromThis()); + lInfo() << "Remote ringing..."; + setState(CallSession::State::OutgoingRinging, "Remote ringing"); + } +} + +void MediaSessionPrivate::replaceOp (SalCallOp *newOp) { + CallSessionPrivate::replaceOp(newOp); + updateStreams(newOp->getFinalMediaDescription(), state); +} + +int MediaSessionPrivate::resumeAfterFailedTransfer () { + L_Q(); + if (automaticallyPaused && (state == CallSession::State::Pausing)) + return BELLE_SIP_CONTINUE; // Was still in pausing state + if (automaticallyPaused && (state == CallSession::State::Paused)) { + if (op->isIdle()) + q->resume(); + else { + lInfo() << "MediaSessionPrivate::resumeAfterFailedTransfer(), op was busy"; + return BELLE_SIP_CONTINUE; + } + } + return BELLE_SIP_STOP; +} + +void MediaSessionPrivate::resumed () { + acceptUpdate(nullptr, CallSession::State::StreamsRunning, "Connected (streams running)"); +} + +void MediaSessionPrivate::startPendingRefer () { + L_Q(); + if (listener) + listener->onCallSessionStartReferred(q->getSharedFromThis()); +} + +void MediaSessionPrivate::telephoneEventReceived (int event) { + static char dtmfTab[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', 'A', 'B', 'C', 'D' }; + if ((event < 0) || (event > 15)) { + lWarning() << "Bad dtmf value " << event; + return; + } + dtmfReceived(dtmfTab[event]); +} + +void MediaSessionPrivate::terminated () { + stopStreams(); + CallSessionPrivate::terminated(); +} + +/* This callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session */ +void MediaSessionPrivate::updated (bool isUpdate) { + SalMediaDescription *rmd = op->getRemoteMediaDescription(); + switch (state) { + case CallSession::State::PausedByRemote: + if (sal_media_description_has_dir(rmd, SalStreamSendRecv) || sal_media_description_has_dir(rmd, SalStreamRecvOnly)) { + resumed(); + return; + } + break; + case CallSession::State::StreamsRunning: + case CallSession::State::Connected: + case CallSession::State::UpdatedByRemote: /* Can happen on UAC connectivity loss */ + if (sal_media_description_has_dir(rmd, SalStreamSendOnly) || sal_media_description_has_dir(rmd, SalStreamInactive)) { + pausedByRemote(); + return; + } + break; + default: + /* The other cases are handled in CallSessionPrivate::updated */ + break; + } + CallSessionPrivate::updated(isUpdate); +} + + + +void MediaSessionPrivate::updating (bool isUpdate) { + L_Q(); + SalMediaDescription *rmd = op->getRemoteMediaDescription(); + fixCallParams(rmd); + if (state != CallSession::State::Paused) { + /* Refresh the local description, but in paused state, we don't change anything. */ + if (!rmd && lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "sdp_200_ack_follow_video_policy", 0)) { + lInfo() << "Applying default policy for offering SDP on CallSession [" << q << "]"; + setParams(new MediaSessionParams()); + params->initDefault(q->getCore()); + } + makeLocalMediaDescription(); + op->setLocalMediaDescription(localDesc); + } + if (rmd) { + SalErrorInfo sei; + memset(&sei, 0, sizeof(sei)); + expectMediaInAck = false; + SalMediaDescription *md = op->getFinalMediaDescription(); + if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(q->getCore()->getCCore(), md))) { + sal_error_info_set(&sei, SalReasonNotAcceptable, "SIP", 0, nullptr, nullptr); + op->declineWithErrorInfo(&sei, nullptr); + sal_error_info_reset(&sei); + return; + } + SalMediaDescription *prevResultDesc = resultDesc; + if (isUpdate && prevResultDesc && md){ + int diff = sal_media_description_equals(prevResultDesc, md); + if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED | SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)) { + lWarning() << "Cannot accept this update, it is changing parameters that require user approval"; + sal_error_info_set(&sei, SalReasonUnknown, "SIP", 504, "Cannot change the session parameters without prompting the user", nullptr); + op->declineWithErrorInfo(&sei, nullptr); + sal_error_info_reset(&sei); + return; + } + } + updated(isUpdate); + } else { + /* Case of a reINVITE or UPDATE without SDP */ + expectMediaInAck = true; + op->accept(); /* Respond with an offer */ + /* Don't do anything else in this case, wait for the ACK to receive to notify the app */ + } +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::enableSymmetricRtp (bool value) { + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (sessions[i].rtp_session) + rtp_session_set_symmetric_rtp(sessions[i].rtp_session, value); + } +} + +void MediaSessionPrivate::oglRender () const { +#ifdef VIDEO_ENABLED + if (videoStream && videoStream->output && (ms_filter_get_id(videoStream->output) == MS_OGL_ID)) + ms_filter_call_method(videoStream->output, MS_OGL_RENDER, nullptr); +#endif +} + +void MediaSessionPrivate::sendVfu () { +#ifdef VIDEO_ENABLED + if (videoStream) + video_stream_send_vfu(videoStream); +#endif +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::clearIceCheckList (IceCheckList *cl) { + if (audioStream && audioStream->ms.ice_check_list == cl) + audioStream->ms.ice_check_list = nullptr; + if (videoStream && videoStream->ms.ice_check_list == cl) + videoStream->ms.ice_check_list = nullptr; + if (textStream && textStream->ms.ice_check_list == cl) + textStream->ms.ice_check_list = nullptr; +} + +void MediaSessionPrivate::deactivateIce () { + if (audioStream) + audioStream->ms.ice_check_list = nullptr; + if (videoStream) + videoStream->ms.ice_check_list = nullptr; + if (textStream) + textStream->ms.ice_check_list = nullptr; + _linphone_call_stats_set_ice_state(audioStats, LinphoneIceStateNotActivated); + _linphone_call_stats_set_ice_state(videoStats, LinphoneIceStateNotActivated); + _linphone_call_stats_set_ice_state(textStats, LinphoneIceStateNotActivated); + stopStreamsForIceGathering(); +} + +void MediaSessionPrivate::prepareStreamsForIceGathering (bool hasVideo) { + if (audioStream->ms.state == MSStreamInitialized) + audio_stream_prepare_sound(audioStream, nullptr, nullptr); +#ifdef VIDEO_ENABLED + if (hasVideo && videoStream && (videoStream->ms.state == MSStreamInitialized)) + video_stream_prepare_video(videoStream); +#endif + if (getParams()->realtimeTextEnabled() && (textStream->ms.state == MSStreamInitialized)) + text_stream_prepare_text(textStream); +} + +void MediaSessionPrivate::stopStreamsForIceGathering () { + if (audioStream && (audioStream->ms.state == MSStreamPreparing)) + audio_stream_unprepare_sound(audioStream); +#ifdef VIDEO_ENABLED + if (videoStream && (videoStream->ms.state == MSStreamPreparing)) + video_stream_unprepare_video(videoStream); +#endif + if (textStream && (textStream->ms.state == MSStreamPreparing)) + text_stream_unprepare_text(textStream); +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::setCurrentParams (MediaSessionParams *msp) { + if (currentParams) + delete currentParams; + currentParams = msp; +} + +void MediaSessionPrivate::setParams (MediaSessionParams *msp) { + if (params) + delete params; + params = msp; +} + +void MediaSessionPrivate::setRemoteParams (MediaSessionParams *msp) { + if (remoteParams) + delete remoteParams; + remoteParams = msp; +} + +MediaStream * MediaSessionPrivate::getMediaStream (LinphoneStreamType type) const { + switch (type) { + case LinphoneStreamTypeAudio: + return &audioStream->ms; + case LinphoneStreamTypeVideo: + return &videoStream->ms; + case LinphoneStreamTypeText: + return &textStream->ms; + case LinphoneStreamTypeUnknown: + default: + return nullptr; + } +} + +int MediaSessionPrivate::getRtcpPort (LinphoneStreamType type) const { + return mediaPorts[getStreamIndex(getMediaStream(type))].rtcpPort; +} + +int MediaSessionPrivate::getRtpPort (LinphoneStreamType type) const { + return mediaPorts[getStreamIndex(getMediaStream(type))].rtpPort; +} + +LinphoneCallStats * MediaSessionPrivate::getStats (LinphoneStreamType type) const { + switch (type) { + case LinphoneStreamTypeAudio: + return audioStats; + case LinphoneStreamTypeVideo: + return videoStats; + case LinphoneStreamTypeText: + return textStats; + case LinphoneStreamTypeUnknown: + default: + return nullptr; + } +} + +int MediaSessionPrivate::getStreamIndex (LinphoneStreamType type) const { + return getStreamIndex(getMediaStream(type)); +} + +int MediaSessionPrivate::getStreamIndex (MediaStream *ms) const { + if (ms == &audioStream->ms) + return mainAudioStreamIndex; + else if (ms == &videoStream->ms) + return mainVideoStreamIndex; + else if (ms == &textStream->ms) + return mainTextStreamIndex; + return -1; +} + +MSWebCam * MediaSessionPrivate::getVideoDevice () const { + L_Q(); + bool paused = (state == CallSession::State::Pausing) || (state == CallSession::State::Paused); + if (paused || allMuted || !cameraEnabled) +#ifdef VIDEO_ENABLED + return ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(q->getCore()->getCCore()->factory), + "StaticImage: Static picture"); +#else + return nullptr; +#endif + else + return q->getCore()->getCCore()->video_conf.device; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::initializeStreams () { + initializeAudioStream(); + initializeVideoStream(); + initializeTextStream(); +} + +void MediaSessionPrivate::stopStreams () { + L_Q(); + if (audioStream || videoStream || textStream) { + if (audioStream && videoStream) + audio_stream_unlink_video(audioStream, videoStream); + stopAudioStream(); + stopVideoStream(); + stopTextStream(); + if (q->getCore()->getCCore()->msevq) + ms_event_queue_skip(q->getCore()->getCCore()->msevq); + } + + if (audioProfile) { + rtp_profile_destroy(audioProfile); + audioProfile = nullptr; + unsetRtpProfile(mainAudioStreamIndex); + } + if (videoProfile) { + rtp_profile_destroy(videoProfile); + videoProfile = nullptr; + unsetRtpProfile(mainVideoStreamIndex); + } + if (textProfile) { + rtp_profile_destroy(textProfile); + textProfile = nullptr; + unsetRtpProfile(mainTextStreamIndex); + } + if (rtpIoAudioProfile) { + rtp_profile_destroy(rtpIoAudioProfile); + rtpIoAudioProfile = nullptr; + } + if (rtpIoVideoProfile) { + rtp_profile_destroy(rtpIoVideoProfile); + rtpIoVideoProfile = nullptr; + } + + q->getCore()->soundcardHintCheck(); +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + L_Q(); + if (mediaNetworkReachable) { + LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore()); + if (lp_config_get_int(config, "net", "recreate_sockets_when_network_is_up", 0)) + refreshSockets(); + } else { + setBroken(); + } + CallSessionPrivate::onNetworkReachable(sipNetworkReachable, mediaNetworkReachable); +} + +// ----------------------------------------------------------------------------- + +OrtpJitterBufferAlgorithm MediaSessionPrivate::jitterBufferNameToAlgo (const string &name) { + if (name == "basic") return OrtpJitterBufferBasic; + if (name == "rls") return OrtpJitterBufferRecursiveLeastSquare; + lError() << "Invalid jitter buffer algorithm: " << name; + return OrtpJitterBufferRecursiveLeastSquare; +} + +#ifdef VIDEO_ENABLED +void MediaSessionPrivate::videoStreamEventCb (void *userData, const MSFilter *f, const unsigned int eventId, const void *args) { + MediaSessionPrivate *msp = reinterpret_cast(userData); + msp->videoStreamEventCb(f, eventId, args); +} +#endif + +#ifdef TEST_EXT_RENDERER +void MediaSessionPrivate::extRendererCb (void *userData, const MSPicture *local, const MSPicture *remote) { + lInfo() << "extRendererCb, local buffer=" << local ? local->planes[0] : nullptr + << ", remote buffer=" << remote ? remote->planes[0] : nullptr); +} +#endif + +void MediaSessionPrivate::realTimeTextCharacterReceived (void *userData, MSFilter *f, unsigned int id, void *arg) { + MediaSessionPrivate *msp = reinterpret_cast(userData); + msp->realTimeTextCharacterReceived(f, id, arg); +} + +int MediaSessionPrivate::sendDtmf (void *data, unsigned int revents) { + MediaSession *session = reinterpret_cast(data); + return session->getPrivate()->sendDtmf(); +} + +// ----------------------------------------------------------------------------- + +float MediaSessionPrivate::aggregateQualityRatings (float audioRating, float videoRating) { + float result; + if ((audioRating < 0) && (videoRating < 0)) + result = -1; + else if (audioRating < 0) + result = videoRating * 5.0f; + else if (videoRating < 0) + result = audioRating * 5.0f; + else + result = audioRating * videoRating * 5.0f; + return result; +} + +// ----------------------------------------------------------------------------- + +shared_ptr MediaSessionPrivate::getMe () const { + shared_ptr participant = me.lock(); + if (!participant) { + lWarning() << "Unable to get valid Participant instance"; + throw std::bad_weak_ptr(); + } + return participant; +} + +void MediaSessionPrivate::setState (CallSession::State newState, const string &message) { + L_Q(); + + // Take a ref on the session otherwise it might get destroyed during the call to setState + shared_ptr sessionRef = q->getSharedFromThis(); + if ((newState != state) && (newState != CallSession::State::StreamsRunning)) + q->cancelDtmfs(); + CallSessionPrivate::setState(newState, message); + if (listener) + listener->onCallSessionStateChangedForReporting(q->getSharedFromThis()); + SalMediaDescription *rmd = nullptr; + switch (newState) { + case CallSession::State::UpdatedByRemote: + // Handle specifically the case of an incoming ICE-concluded reINVITE + lInfo() << "Checking for ICE reINVITE"; + rmd = op->getRemoteMediaDescription(); + if (iceAgent && rmd && iceAgent->checkIceReinviteNeedsDeferedResponse(rmd)) { + deferUpdate = true; + deferUpdateInternal = true; + incomingIceReinvitePending = true; + lInfo() << "CallSession [" << q << "]: ICE reinvite received, but one or more check-lists are not completed. Response will be sent later, when ICE has completed"; + } + break; + default: + break; + } +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::computeStreamsIndexes (const SalMediaDescription *md) { + bool audioFound = false; + bool videoFound = false; + bool textFound = false; + for (int i = 0; i < md->nb_streams; i++) { + if (md->streams[i].type == SalAudio) { + if (audioFound) + lInfo() << "audio stream index found: " << i << ", but main audio stream already set to " << mainAudioStreamIndex; + else { + mainAudioStreamIndex = i; + audioFound = true; + lInfo() << "audio stream index found: " << i << ", updating main audio stream index"; + } + /* Check that the default value of a another stream doesn't match the new one */ + if (i == mainVideoStreamIndex) { + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { + if (sal_stream_description_active(&md->streams[j])) + continue; + if ((j != mainVideoStreamIndex) && (j != mainTextStreamIndex)) { + lInfo() << i << " was used for video stream ; now using " << j; + mainVideoStreamIndex = j; + break; + } + } + } + if (i == mainTextStreamIndex) { + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { + if (sal_stream_description_active(&md->streams[j])) + continue; + if ((j != mainVideoStreamIndex) && (j != mainTextStreamIndex)) { + lInfo() << i << " was used for text stream ; now using " << j; + mainTextStreamIndex = j; + break; + } + } + } + } else if (md->streams[i].type == SalVideo) { + if (videoFound) + lInfo() << "video stream index found: " << i << ", but main video stream already set to " << mainVideoStreamIndex; + else { + mainVideoStreamIndex = i; + videoFound = true; + lInfo() << "video stream index found: " << i << ", updating main video stream index"; + } + /* Check that the default value of a another stream doesn't match the new one */ + if (i == mainAudioStreamIndex) { + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { + if (sal_stream_description_active(&md->streams[j])) + continue; + if ((j != mainAudioStreamIndex) && (j != mainTextStreamIndex)) { + lInfo() << i << " was used for audio stream ; now using " << j; + mainAudioStreamIndex = j; + break; + } + } + } + if (i == mainTextStreamIndex) { + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { + if (sal_stream_description_active(&md->streams[j])) + continue; + if ((j != mainAudioStreamIndex) && (j != mainTextStreamIndex)) { + lInfo() << i << " was used for text stream ; now using " << j; + mainTextStreamIndex = j; + break; + } + } + } + } else if (md->streams[i].type == SalText) { + if (textFound) + lInfo() << "text stream index found: " << i << ", but main text stream already set to " << mainTextStreamIndex; + else { + mainTextStreamIndex = i; + textFound = true; + lInfo() << "text stream index found: " << i << ", updating main text stream index"; + } + /* Check that the default value of a another stream doesn't match the new one */ + if (i == mainAudioStreamIndex) { + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { + if (sal_stream_description_active(&md->streams[j])) + continue; + if ((j != mainVideoStreamIndex) && (j != mainAudioStreamIndex)) { + lInfo() << i << " was used for audio stream ; now using " << j; + mainAudioStreamIndex = j; + break; + } + } + } + if (i == mainVideoStreamIndex) { + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; j++) { + if (sal_stream_description_active(&md->streams[j])) + continue; + if ((j != mainVideoStreamIndex) && (j != mainAudioStreamIndex)) { + lInfo() << i << " was used for video stream ; now using " << j; + mainVideoStreamIndex = j; + break; + } + } + } + } + } +} + +/* + * This method needs to be called at each incoming reINVITE, in order to adjust various local parameters to what is being offered by remote: + * - the stream indexes. + * - the video enablement parameter according to what is offered and our local policy. + * Fixing the params to proper values avoid request video by accident during internal call updates, pauses and resumes + */ +void MediaSessionPrivate::fixCallParams (SalMediaDescription *rmd) { + L_Q(); + if (rmd) { + computeStreamsIndexes(rmd); + updateBiggestDesc(rmd); + /* Why disabling implicit_rtcp_fb ? It is a local policy choice actually. It doesn't disturb to propose it again and again + * even if the other end apparently doesn't support it. + * The following line of code is causing trouble, while for example making an audio call, then adding video. + * Due to the 200Ok response of the audio-only offer where no rtcp-fb attribute is present, implicit_rtcp_fb is set to + * false, which is then preventing it to be eventually used when video is later added to the call. + * I did the choice of commenting it out. + */ + /*params.getPrivate()->enableImplicitRtcpFb(params.getPrivate()->implicitRtcpFbEnabled() & sal_media_description_has_implicit_avpf(rmd));*/ + } + const MediaSessionParams *rcp = q->getRemoteParams(); + if (rcp) { + if (getParams()->audioEnabled() && !rcp->audioEnabled()) { + lInfo() << "CallSession [" << q << "]: disabling audio in our call params because the remote doesn't want it"; + getParams()->enableAudio(false); + } + if (getParams()->videoEnabled() && !rcp->videoEnabled()) { + lInfo() << "CallSession [" << q << "]: disabling video in our call params because the remote doesn't want it"; + getParams()->enableVideo(false); + } + if (rcp->videoEnabled() && q->getCore()->getCCore()->video_policy.automatically_accept && linphone_core_video_enabled(q->getCore()->getCCore()) && !getParams()->videoEnabled()) { + lInfo() << "CallSession [" << q << "]: re-enabling video in our call params because the remote wants it and the policy allows to automatically accept"; + getParams()->enableVideo(true); + } + if (rcp->realtimeTextEnabled() && !getParams()->realtimeTextEnabled()) + getParams()->enableRealtimeText(true); + } +} + +void MediaSessionPrivate::initializeParamsAccordingToIncomingCallParams () { + L_Q(); + CallSessionPrivate::initializeParamsAccordingToIncomingCallParams(); + getCurrentParams()->getPrivate()->setUpdateCallWhenIceCompleted(getParams()->getPrivate()->getUpdateCallWhenIceCompleted()); + getParams()->enableVideo(linphone_core_video_enabled(q->getCore()->getCCore()) && q->getCore()->getCCore()->video_policy.automatically_accept); + SalMediaDescription *md = op->getRemoteMediaDescription(); + if (md) { + /* It is licit to receive an INVITE without SDP, in this case WE choose the media parameters according to policy */ + setCompatibleIncomingCallParams(md); + /* Set multicast role & address if any */ + if (!op->isOfferer()) { + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (md->streams[i].dir == SalStreamInactive) + continue; + if ((md->streams[i].rtp_addr[0] != '\0') && ms_is_multicast(md->streams[i].rtp_addr)) { + md->streams[i].multicast_role = SalMulticastReceiver; + mediaPorts[i].multicastIp = md->streams[i].rtp_addr; + } + } + } + } +} + +/** + * Fix call parameters on incoming call to eg. enable AVPF if the incoming call propose it and it is not enabled locally. + */ +void MediaSessionPrivate::setCompatibleIncomingCallParams (SalMediaDescription *md) { + L_Q(); + /* Handle AVPF, SRTP and DTLS */ + getParams()->enableAvpf(!!sal_media_description_has_avpf(md)); + if (destProxy) + getParams()->setAvpfRrInterval(static_cast(linphone_proxy_config_get_avpf_rr_interval(destProxy) * 1000)); + else + getParams()->setAvpfRrInterval(static_cast(linphone_core_get_avpf_rr_interval(q->getCore()->getCCore()) * 1000)); + if (sal_media_description_has_zrtp(md) && linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP)) + getParams()->setMediaEncryption(LinphoneMediaEncryptionZRTP); + else if (sal_media_description_has_dtls(md) && media_stream_dtls_supported()) + getParams()->setMediaEncryption(LinphoneMediaEncryptionDTLS); + else if (sal_media_description_has_srtp(md) && ms_srtp_supported()) + getParams()->setMediaEncryption(LinphoneMediaEncryptionSRTP); + else if (getParams()->getMediaEncryption() != LinphoneMediaEncryptionZRTP) + getParams()->setMediaEncryption(LinphoneMediaEncryptionNone); + /* In case of nat64, even ipv4 addresses are reachable from v6. Should be enhanced to manage stream by stream connectivity (I.E v6 or v4) */ + /*if (!sal_media_description_has_ipv6(md)){ + lInfo() << "The remote SDP doesn't seem to offer any IPv6 connectivity, so disabling IPv6 for this call"; + af = AF_INET; + }*/ + fixCallParams(md); +} + +void MediaSessionPrivate::updateBiggestDesc (SalMediaDescription *md) { + if (!biggestDesc || (md->nb_streams > biggestDesc->nb_streams)) { + /* We have been offered and now are ready to proceed, or we added a new stream, + * store the media description to remember the mapping of calls */ + if (biggestDesc) { + sal_media_description_unref(biggestDesc); + biggestDesc = nullptr; + } + biggestDesc = sal_media_description_ref(md); + } +} + +void MediaSessionPrivate::updateRemoteSessionIdAndVer () { + SalMediaDescription *desc = op->getRemoteMediaDescription(); + if (desc) { + remoteSessionId = desc->session_id; + remoteSessionVer = desc->session_ver; + } +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::initStats (LinphoneCallStats *stats, LinphoneStreamType type) { + _linphone_call_stats_set_type(stats, type); + _linphone_call_stats_set_received_rtcp(stats, nullptr); + _linphone_call_stats_set_sent_rtcp(stats, nullptr); + _linphone_call_stats_set_ice_state(stats, LinphoneIceStateNotActivated); +} + +void MediaSessionPrivate::notifyStatsUpdated (int streamIndex) { + L_Q(); + LinphoneCallStats *stats = nullptr; + if (streamIndex == mainAudioStreamIndex) + stats = audioStats; + else if (streamIndex == mainVideoStreamIndex) + stats = videoStats; + else if (streamIndex == mainTextStreamIndex) + stats = textStats; + else + return; + if (_linphone_call_stats_get_updated(stats)) { + switch (_linphone_call_stats_get_updated(stats)) { + case LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE: + case LINPHONE_CALL_STATS_SENT_RTCP_UPDATE: + if (listener) { + listener->onRtcpUpdateForReporting(q->getSharedFromThis(), + (streamIndex == mainAudioStreamIndex) + ? SalAudio + : (streamIndex == mainVideoStreamIndex) ? SalVideo : SalText + ); + } + break; + default: + break; + } + if (listener) + listener->onStatsUpdated(q->getSharedFromThis(), stats); + _linphone_call_stats_set_updated(stats, 0); + } +} + +// ----------------------------------------------------------------------------- + +OrtpEvQueue * MediaSessionPrivate::getEventQueue (int streamIndex) const { + if (streamIndex == mainAudioStreamIndex) + return audioStreamEvQueue; + if (streamIndex == mainVideoStreamIndex) + return videoStreamEvQueue; + if (streamIndex == mainTextStreamIndex) + return textStreamEvQueue; + lError() << "getEventQueue(): no stream index " << streamIndex; + return nullptr; +} + +unsigned int MediaSessionPrivate::getMediaStartCount () const { + return mediaStartCount; +} + +MediaStream * MediaSessionPrivate::getMediaStream (int streamIndex) const { + if (streamIndex == mainAudioStreamIndex) + return &audioStream->ms; + if (streamIndex == mainVideoStreamIndex) + return &videoStream->ms; + if (streamIndex == mainTextStreamIndex) + return &textStream->ms; + lError() << "getMediaStream(): no stream index " << streamIndex; + return nullptr; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::fillMulticastMediaAddresses () { + L_Q(); + if (getParams()->audioMulticastEnabled()) + mediaPorts[mainAudioStreamIndex].multicastIp = linphone_core_get_audio_multicast_addr(q->getCore()->getCCore()); + else + mediaPorts[mainAudioStreamIndex].multicastIp.clear(); + if (getParams()->videoMulticastEnabled()) + mediaPorts[mainVideoStreamIndex].multicastIp = linphone_core_get_video_multicast_addr(q->getCore()->getCCore()); + else + mediaPorts[mainVideoStreamIndex].multicastIp.clear(); +} + +int MediaSessionPrivate::selectFixedPort (int streamIndex, pair portRange) { + L_Q(); + for (int triedPort = portRange.first; triedPort < (portRange.first + 100); triedPort += 2) { + bool alreadyUsed = false; + for (const bctbx_list_t *elem = linphone_core_get_calls(q->getCore()->getCCore()); elem != nullptr; elem = bctbx_list_next(elem)) { + LinphoneCall *lcall = reinterpret_cast(bctbx_list_get_data(elem)); + shared_ptr session = static_pointer_cast(L_GET_CPP_PTR_FROM_C_OBJECT(lcall)->getPrivate()->getActiveSession()); + int existingPort = session->getPrivate()->mediaPorts[streamIndex].rtpPort; + if (existingPort == triedPort) { + alreadyUsed = true; + break; + } + } + if (!alreadyUsed) + return triedPort; + } + + lError() << "Could not find any free port !"; + return -1; +} + +int MediaSessionPrivate::selectRandomPort (int streamIndex, pair portRange) { + L_Q(); + for (int nbTries = 0; nbTries < 100; nbTries++) { + bool alreadyUsed = false; + unsigned int rangeSize = static_cast(portRange.second - portRange.first); + unsigned int randomInRangeSize = ortp_random() % rangeSize; + unsigned int mask = 1; + unsigned int realRandom = randomInRangeSize + static_cast(portRange.first); + int triedPort = static_cast(realRandom & ~mask); + if (triedPort < portRange.first) triedPort = portRange.first + 2; + for (const bctbx_list_t *elem = linphone_core_get_calls(q->getCore()->getCCore()); elem != nullptr; elem = bctbx_list_next(elem)) { + LinphoneCall *lcall = reinterpret_cast(bctbx_list_get_data(elem)); + shared_ptr session = static_pointer_cast(L_GET_CPP_PTR_FROM_C_OBJECT(lcall)->getPrivate()->getActiveSession()); + int existingPort = session->getPrivate()->mediaPorts[streamIndex].rtpPort; + if (existingPort == triedPort) { + alreadyUsed = true; + break; + } + } + if (!alreadyUsed) + return triedPort; + } + + lError() << "Could not find any free port!"; + return -1; +} + +void MediaSessionPrivate::setPortConfig(int streamIndex, pair portRange) { + if ((portRange.first <= 0) && (portRange.second <= 0)) { + setRandomPortConfig(streamIndex); + } else { + if (portRange.first == portRange.second) { + /* Fixed port */ + int port = selectFixedPort(streamIndex, portRange); + if (port == -1) { + setRandomPortConfig(streamIndex); + return; + } + mediaPorts[streamIndex].rtpPort = port; + } else { + /* Select random port in the specified range */ + mediaPorts[streamIndex].rtpPort = selectRandomPort(streamIndex, portRange); + } + mediaPorts[streamIndex].rtcpPort = mediaPorts[streamIndex].rtpPort + 1; + } +} + +void MediaSessionPrivate::setPortConfigFromRtpSession (int streamIndex, RtpSession *session) { + mediaPorts[streamIndex].rtpPort = rtp_session_get_local_port(session); + mediaPorts[streamIndex].rtcpPort = rtp_session_get_local_rtcp_port(session); +} + +void MediaSessionPrivate::setRandomPortConfig (int streamIndex) { + mediaPorts[streamIndex].rtpPort = -1; + mediaPorts[streamIndex].rtcpPort = -1; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::discoverMtu (const Address &remoteAddr) { + L_Q(); + if (q->getCore()->getCCore()->net_conf.mtu == 0) { + /* Attempt to discover mtu */ + int mtu = ms_discover_mtu(remoteAddr.getDomain().c_str()); + if (mtu > 0) { + ms_factory_set_mtu(q->getCore()->getCCore()->factory, mtu); + lInfo() << "Discovered mtu is " << mtu << ", RTP payload max size is " << ms_factory_get_payload_max_size(q->getCore()->getCCore()->factory); + } + } +} + +string MediaSessionPrivate::getBindIpForStream (int streamIndex) { + L_Q(); + string bindIp = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", ""); + PortConfig *pc = &mediaPorts[streamIndex]; + if (!pc->multicastIp.empty()){ + if (direction == LinphoneCallOutgoing) { + /* As multicast sender, we must decide a local interface to use to send multicast, and bind to it */ + char multicastBindIp[LINPHONE_IPADDR_SIZE]; + memset(multicastBindIp, 0, sizeof(multicastBindIp)); + linphone_core_get_local_ip_for((pc->multicastIp.find_first_of(':') == string::npos) ? AF_INET : AF_INET6, nullptr, multicastBindIp); + bindIp = pc->multicastBindIp = multicastBindIp; + } else { + /* Otherwise we shall use an address family of the same family of the multicast address, because + * dual stack socket and multicast don't work well on Mac OS (linux is OK, as usual). */ + bindIp = (pc->multicastIp.find_first_of(':') == string::npos) ? "0.0.0.0" : "::0"; + } + } + return bindIp; +} + +/** + * Fill the local ip that routes to the internet according to the destination, or guess it by other special means. + */ +void MediaSessionPrivate::getLocalIp (const Address &remoteAddr) { + L_Q(); + // Next, sometime, override from config + const char *ip = linphone_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "bind_address", nullptr); + if (ip) { + mediaLocalIp = ip; + return; + } + + // If a known proxy was identified for this call, then we may have a chance to take the local ip address + // from the socket that connects to this proxy + if (destProxy && destProxy->op) { + ip = destProxy->op->getLocalAddress(nullptr); + if (ip) { + if (strchr(ip, ':') && (af == AF_INET)) { + // Case where we've decided to use IPv4 in selectOutgoingIpVersion(), but the signaling local ip address is IPv6. + // We'll use the default media localip + } else { + lInfo() << "Found media local-ip from signaling."; + mediaLocalIp = ip; + return; + } + } + } + + // In last resort, attempt to find the local ip that routes to destination if given as an IP address, + // or the default route (dest is empty) + string dest; + if (!destProxy) { + struct addrinfo hints; + struct addrinfo *res = nullptr; + string host(remoteAddr.getDomain()); + int err; + + if (host[0] == '[') + host = host.substr(1, host.size() - 2); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_flags = AI_NUMERICHOST; + err = getaddrinfo(host.c_str(), nullptr, &hints, &res); + if (err == 0) + dest = host; // The remote address host part is real ip address, use it + if (res) + freeaddrinfo(res); + } + + if (!dest.empty() || mediaLocalIp.empty() || needMediaLocalIpRefresh) { + needMediaLocalIpRefresh = false; + mediaLocalIp.reserve(LINPHONE_IPADDR_SIZE); + linphone_core_get_local_ip(q->getCore()->getCCore(), af, dest.c_str(), &mediaLocalIp[0]); + } +} + +string MediaSessionPrivate::getPublicIpForStream (int streamIndex) { + if (!mediaPorts[streamIndex].multicastIp.empty()) + return mediaPorts[streamIndex].multicastIp; + return mediaLocalIp; +} + +void MediaSessionPrivate::runStunTestsIfNeeded () { + L_Q(); + if (linphone_nat_policy_stun_enabled(natPolicy) && !(linphone_nat_policy_ice_enabled(natPolicy) || linphone_nat_policy_turn_enabled(natPolicy))) { + stunClient = makeUnique(q->getCore()); + int ret = stunClient->run(mediaPorts[mainAudioStreamIndex].rtpPort, mediaPorts[mainVideoStreamIndex].rtpPort, mediaPorts[mainTextStreamIndex].rtpPort); + if (ret >= 0) + pingTime = ret; + } +} + +/* + * Select IP version to use for advertising local addresses of RTP streams, for an incoming call. + * If the call is received through a know proxy that is IPv6, use IPv6. + * Otherwise check the remote contact address. + * If later the resulting media description tells that we have to send IPv4, it won't be a problem because the RTP sockets + * are dual stack. + */ +void MediaSessionPrivate::selectIncomingIpVersion () { + L_Q(); + if (linphone_core_ipv6_enabled(q->getCore()->getCCore())) { + if (destProxy && destProxy->op) + af = destProxy->op->getAddressFamily(); + else + af = op->getAddressFamily(); + } else + af = AF_INET; +} + +/* + * Choose IP version we are going to use for RTP streams IP address advertised in SDP. + * The algorithm is as follows: + * - if ipv6 is disabled at the core level, it is always AF_INET + * - Otherwise, if the call is done through a known proxy config, then use the information obtained during REGISTER + * - Otherwise if the destination address for the call is an IPv6 address, use IPv6. + * to know if IPv6 is supported by the server. +**/ +void MediaSessionPrivate::selectOutgoingIpVersion () { + L_Q(); + char ipv4[LINPHONE_IPADDR_SIZE]; + char ipv6[LINPHONE_IPADDR_SIZE]; + bool haveIpv6 = false; + bool haveIpv4 = false; + + af = AF_UNSPEC; + if (linphone_core_get_local_ip_for(AF_INET, nullptr, ipv4) == 0) + haveIpv4 = true; + if (linphone_core_ipv6_enabled(q->getCore()->getCCore())) { + const LinphoneAddress *to = linphone_call_log_get_to_address(log); + + if (linphone_core_get_local_ip_for(AF_INET6, nullptr, ipv6) == 0) + haveIpv6 = true; + if (destProxy && destProxy->op) { + // We can determine from the proxy connection whether IPv6 works - this is the most reliable + af = destProxy->op->getAddressFamily(); + } else if (sal_address_is_ipv6(L_GET_PRIVATE_FROM_C_OBJECT(to)->getInternalAddress())) { + af = AF_INET6; + } + + if (!linphone_config_get_bool(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "prefer_ipv6", TRUE) && haveIpv4) { + // This is the case where IPv4 is to be prefered if both are available + af = AF_INET; // We'll use IPv4 + lInfo() << "prefer_ipv6 is set to false, as both IP versions are available we are going to use IPv4"; + } + if (af == AF_UNSPEC) + af = haveIpv6 ? AF_INET6 : AF_INET; + } else { + af = AF_INET; + } + // Fill the media_localip default value since we have it here + mediaLocalIp = (af == AF_INET6) ? ipv6 : ipv4; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::forceStreamsDirAccordingToState (SalMediaDescription *md) { + L_Q(); + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + SalStreamDescription *sd = &md->streams[i]; + switch (state) { + case CallSession::State::Pausing: + case CallSession::State::Paused: + if (sd->dir != SalStreamInactive) { + sd->dir = SalStreamSendOnly; + if ((sd->type == SalVideo) && lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "inactive_video_on_pause", 0)) + sd->dir = SalStreamInactive; + } + break; + default: + break; + } + /* Reflect the stream directions in the call params */ + if (i == mainAudioStreamIndex) + getCurrentParams()->setAudioDirection(MediaSessionParamsPrivate::salStreamDirToMediaDirection(sd->dir)); + else if (i == mainVideoStreamIndex) + getCurrentParams()->setVideoDirection(MediaSessionParamsPrivate::salStreamDirToMediaDirection(sd->dir)); + } +} + +bool MediaSessionPrivate::generateB64CryptoKey (size_t keyLength, char *keyOut, size_t keyOutSize) { + uint8_t *tmp = (uint8_t *)ms_malloc0(keyLength); + if (!sal_get_random_bytes(tmp, keyLength)) { + lError() << "Failed to generate random key"; + ms_free(tmp); + return false; + } + size_t b64Size = b64::b64_encode((const char *)tmp, keyLength, nullptr, 0); + if (b64Size == 0) { + lError() << "Failed to get b64 result size"; + ms_free(tmp); + return false; + } + if (b64Size >= keyOutSize) { + lError() << "Insufficient room for writing base64 SRTP key"; + ms_free(tmp); + return false; + } + b64Size = b64::b64_encode((const char *)tmp, keyLength, keyOut, keyOutSize); + if (b64Size == 0) { + lError() << "Failed to b64 encode key"; + ms_free(tmp); + return false; + } + keyOut[b64Size] = '\0'; + ms_free(tmp); + return true; +} + +void MediaSessionPrivate::makeLocalMediaDescription () { + L_Q(); + int maxIndex = 0; + bool rtcpMux = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "rtcp_mux", 0); + SalMediaDescription *md = sal_media_description_new(); + SalMediaDescription *oldMd = localDesc; + + /* Multicast is only set in case of outgoing call */ + if (direction == LinphoneCallOutgoing) { + if (getParams()->audioMulticastEnabled()) { + md->streams[mainAudioStreamIndex].ttl = linphone_core_get_audio_multicast_ttl(q->getCore()->getCCore()); + md->streams[mainAudioStreamIndex].multicast_role = SalMulticastSender; + } + if (getParams()->videoMulticastEnabled()) { + md->streams[mainVideoStreamIndex].ttl = linphone_core_get_video_multicast_ttl(q->getCore()->getCCore()); + md->streams[mainVideoStreamIndex].multicast_role = SalMulticastSender; + } + } + + getParams()->getPrivate()->adaptToNetwork(q->getCore()->getCCore(), pingTime); + + string subject = q->getParams()->getSessionName(); + if (!subject.empty()) + strncpy(md->name, subject.c_str(), sizeof(md->name)); + md->session_id = (oldMd ? oldMd->session_id : (rand() & 0xfff)); + md->session_ver = (oldMd ? (oldMd->session_ver + 1) : (rand() & 0xfff)); + md->nb_streams = (biggestDesc ? biggestDesc->nb_streams : 1); + + /* Re-check local ip address each time we make a new offer, because it may change in case of network reconnection */ + { + LinphoneAddress *address = (direction == LinphoneCallOutgoing ? log->to : log->from); + getLocalIp(*L_GET_CPP_PTR_FROM_C_OBJECT(address)); + } + + strncpy(md->addr, mediaLocalIp.c_str(), sizeof(md->addr)); + LinphoneAddress *addr = nullptr; + if (destProxy) { + addr = linphone_address_clone(linphone_proxy_config_get_identity_address(destProxy)); + } else { + addr = linphone_address_new(linphone_core_get_identity(q->getCore()->getCCore())); + } + if (linphone_address_get_username(addr)) /* Might be null in case of identity without userinfo */ + strncpy(md->username, linphone_address_get_username(addr), sizeof(md->username)); + linphone_address_unref(addr); + + int bandwidth = getParams()->getPrivate()->getDownBandwidth(); + if (bandwidth) + md->bandwidth = bandwidth; + else + md->bandwidth = linphone_core_get_download_bandwidth(q->getCore()->getCCore()); + + SalCustomSdpAttribute *customSdpAttributes = getParams()->getPrivate()->getCustomSdpAttributes(); + if (customSdpAttributes) + md->custom_sdp_attributes = sal_custom_sdp_attribute_clone(customSdpAttributes); + + PayloadTypeHandler pth(q->getCore()); + + bctbx_list_t *l = pth.makeCodecsList(SalAudio, getParams()->getAudioBandwidthLimit(), -1, + oldMd ? oldMd->streams[mainAudioStreamIndex].already_assigned_payloads : nullptr); + if (l && getParams()->audioEnabled()) { + strncpy(md->streams[mainAudioStreamIndex].rtp_addr, getPublicIpForStream(mainAudioStreamIndex).c_str(), sizeof(md->streams[mainAudioStreamIndex].rtp_addr)); + strncpy(md->streams[mainAudioStreamIndex].rtcp_addr, getPublicIpForStream(mainAudioStreamIndex).c_str(), sizeof(md->streams[mainAudioStreamIndex].rtcp_addr)); + strncpy(md->streams[mainAudioStreamIndex].name, "Audio", sizeof(md->streams[mainAudioStreamIndex].name) - 1); + md->streams[mainAudioStreamIndex].rtp_port = mediaPorts[mainAudioStreamIndex].rtpPort; + md->streams[mainAudioStreamIndex].rtcp_port = mediaPorts[mainAudioStreamIndex].rtcpPort; + md->streams[mainAudioStreamIndex].proto = getParams()->getMediaProto(); + md->streams[mainAudioStreamIndex].dir = getParams()->getPrivate()->getSalAudioDirection(); + md->streams[mainAudioStreamIndex].type = SalAudio; + md->streams[mainAudioStreamIndex].rtcp_mux = rtcpMux; + int downPtime = getParams()->getPrivate()->getDownPtime(); + if (downPtime) + md->streams[mainAudioStreamIndex].ptime = downPtime; + else + md->streams[mainAudioStreamIndex].ptime = linphone_core_get_download_ptime(q->getCore()->getCCore()); + md->streams[mainAudioStreamIndex].max_rate = pth.getMaxCodecSampleRate(l); + md->streams[mainAudioStreamIndex].payloads = l; + if (audioStream && audioStream->ms.sessions.rtp_session) { + md->streams[mainAudioStreamIndex].rtp_ssrc = rtp_session_get_send_ssrc(audioStream->ms.sessions.rtp_session); + strncpy(md->streams[mainAudioStreamIndex].rtcp_cname, getMe()->getAddress().asString().c_str(), sizeof(md->streams[mainAudioStreamIndex].rtcp_cname)); + } + else + lWarning() << "Cannot get audio local ssrc for CallSession [" << q << "]"; + if (mainAudioStreamIndex > maxIndex) + maxIndex = mainAudioStreamIndex; + } else { + lInfo() << "Don't put audio stream on local offer for CallSession [" << q << "]"; + md->streams[mainAudioStreamIndex].dir = SalStreamInactive; + if(l) + l = bctbx_list_free_with_data(l, (bctbx_list_free_func)payload_type_destroy); + } + SalCustomSdpAttribute *sdpMediaAttributes = getParams()->getPrivate()->getCustomSdpMediaAttributes(LinphoneStreamTypeAudio); + if (sdpMediaAttributes) + md->streams[mainAudioStreamIndex].custom_sdp_attributes = sal_custom_sdp_attribute_clone(sdpMediaAttributes); + + md->streams[mainVideoStreamIndex].proto = md->streams[mainAudioStreamIndex].proto; + md->streams[mainVideoStreamIndex].dir = getParams()->getPrivate()->getSalVideoDirection(); + md->streams[mainVideoStreamIndex].type = SalVideo; + md->streams[mainVideoStreamIndex].rtcp_mux = rtcpMux; + strncpy(md->streams[mainVideoStreamIndex].name, "Video", sizeof(md->streams[mainVideoStreamIndex].name) - 1); + + l = pth.makeCodecsList(SalVideo, 0, -1, + oldMd ? oldMd->streams[mainVideoStreamIndex].already_assigned_payloads : nullptr); + if (l && getParams()->videoEnabled()){ + strncpy(md->streams[mainVideoStreamIndex].rtp_addr, getPublicIpForStream(mainVideoStreamIndex).c_str(), sizeof(md->streams[mainVideoStreamIndex].rtp_addr)); + strncpy(md->streams[mainVideoStreamIndex].rtcp_addr, getPublicIpForStream(mainVideoStreamIndex).c_str(), sizeof(md->streams[mainVideoStreamIndex].rtcp_addr)); + md->streams[mainVideoStreamIndex].rtp_port = mediaPorts[mainVideoStreamIndex].rtpPort; + md->streams[mainVideoStreamIndex].rtcp_port = mediaPorts[mainVideoStreamIndex].rtcpPort; + md->streams[mainVideoStreamIndex].payloads = l; + if (videoStream && videoStream->ms.sessions.rtp_session) { + md->streams[mainVideoStreamIndex].rtp_ssrc = rtp_session_get_send_ssrc(videoStream->ms.sessions.rtp_session); + strncpy(md->streams[mainVideoStreamIndex].rtcp_cname, getMe()->getAddress().asString().c_str(), sizeof(md->streams[mainVideoStreamIndex].rtcp_cname)); + } else + lWarning() << "Cannot get video local ssrc for CallSession [" << q << "]"; + if (mainVideoStreamIndex > maxIndex) + maxIndex = mainVideoStreamIndex; + } else { + lInfo() << "Don't put video stream on local offer for CallSession [" << q << "]"; + md->streams[mainVideoStreamIndex].dir = SalStreamInactive; + if(l) + l = bctbx_list_free_with_data(l, (bctbx_list_free_func)payload_type_destroy); + } + sdpMediaAttributes = getParams()->getPrivate()->getCustomSdpMediaAttributes(LinphoneStreamTypeVideo); + if (sdpMediaAttributes) + md->streams[mainVideoStreamIndex].custom_sdp_attributes = sal_custom_sdp_attribute_clone(sdpMediaAttributes); + + md->streams[mainTextStreamIndex].proto = md->streams[mainAudioStreamIndex].proto; + md->streams[mainTextStreamIndex].dir = SalStreamSendRecv; + md->streams[mainTextStreamIndex].type = SalText; + md->streams[mainTextStreamIndex].rtcp_mux = rtcpMux; + strncpy(md->streams[mainTextStreamIndex].name, "Text", sizeof(md->streams[mainTextStreamIndex].name) - 1); + if (getParams()->realtimeTextEnabled()) { + strncpy(md->streams[mainTextStreamIndex].rtp_addr, getPublicIpForStream(mainTextStreamIndex).c_str(), sizeof(md->streams[mainTextStreamIndex].rtp_addr)); + strncpy(md->streams[mainTextStreamIndex].rtcp_addr, getPublicIpForStream(mainTextStreamIndex).c_str(), sizeof(md->streams[mainTextStreamIndex].rtcp_addr)); + + md->streams[mainTextStreamIndex].rtp_port = mediaPorts[mainTextStreamIndex].rtpPort; + md->streams[mainTextStreamIndex].rtcp_port = mediaPorts[mainTextStreamIndex].rtcpPort; + + l = pth.makeCodecsList(SalText, 0, -1, + oldMd ? oldMd->streams[mainTextStreamIndex].already_assigned_payloads : nullptr); + md->streams[mainTextStreamIndex].payloads = l; + if (textStream && textStream->ms.sessions.rtp_session) { + md->streams[mainTextStreamIndex].rtp_ssrc = rtp_session_get_send_ssrc(textStream->ms.sessions.rtp_session); + strncpy(md->streams[mainTextStreamIndex].rtcp_cname, getMe()->getAddress().asString().c_str(), sizeof(md->streams[mainTextStreamIndex].rtcp_cname)); + } else + lWarning() << "Cannot get text local ssrc for CallSession [" << q << "]"; + if (mainTextStreamIndex > maxIndex) + maxIndex = mainTextStreamIndex; + } else { + lInfo() << "Don't put text stream on local offer for CallSession [" << q << "]"; + md->streams[mainTextStreamIndex].dir = SalStreamInactive; + } + sdpMediaAttributes = getParams()->getPrivate()->getCustomSdpMediaAttributes(LinphoneStreamTypeText); + if (sdpMediaAttributes) + md->streams[mainTextStreamIndex].custom_sdp_attributes = sal_custom_sdp_attribute_clone(sdpMediaAttributes); + + md->nb_streams = MAX(md->nb_streams, maxIndex + 1); + + /* Deactivate unused streams */ + for (int i = md->nb_streams; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (md->streams[i].rtp_port == 0) { + md->streams[i].dir = SalStreamInactive; + if (biggestDesc && (i < biggestDesc->nb_streams)) { + md->streams[i].proto = biggestDesc->streams[i].proto; + md->streams[i].type = biggestDesc->streams[i].type; + } + } + } + setupEncryptionKeys(md); + setupDtlsKeys(md); + setupZrtpHash(md); + setupRtcpFb(md); + setupRtcpXr(md); + if (stunClient) + stunClient->updateMediaDescription(md); + localDesc = md; + updateLocalMediaDescriptionFromIce(); + if (oldMd) { + transferAlreadyAssignedPayloadTypes(oldMd, md); + localDescChanged = sal_media_description_equals(md, oldMd); + sal_media_description_unref(oldMd); + if (getParams()->getPrivate()->getInternalCallUpdate()) { + /* + * An internal call update (ICE reINVITE) is not expected to modify the actual media stream parameters. + * However, the localDesc may change between first INVITE and ICE reINVITE, for example if the remote party has declined a video stream. + * We use the internalCallUpdate flag to prevent trigger an unnecessary media restart. + */ + localDescChanged = 0; + } + } + forceStreamsDirAccordingToState(md); +} + +void MediaSessionPrivate::setupDtlsKeys (SalMediaDescription *md) { + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&md->streams[i])) + continue; + /* If media encryption is set to DTLS check presence of fingerprint in the call which shall have been set at stream init + * but it may have failed when retrieving certificate resulting in no fingerprint present and then DTLS not usable */ + if (sal_stream_description_has_dtls(&md->streams[i])) { + /* Get the self fingerprint from call (it's computed at stream init) */ + strncpy(md->streams[i].dtls_fingerprint, dtlsCertificateFingerprint.c_str(), sizeof(md->streams[i].dtls_fingerprint)); + /* If we are offering, SDP will have actpass setup attribute when role is unset, if we are responding the result mediadescription will be set to SalDtlsRoleIsClient */ + md->streams[i].dtls_role = SalDtlsRoleUnset; + } else { + md->streams[i].dtls_fingerprint[0] = '\0'; + md->streams[i].dtls_role = SalDtlsRoleInvalid; + } + } +} + +int MediaSessionPrivate::setupEncryptionKey (SalSrtpCryptoAlgo *crypto, MSCryptoSuite suite, unsigned int tag) { + crypto->tag = tag; + crypto->algo = suite; + size_t keylen = 0; + switch (suite) { + case MS_AES_128_SHA1_80: + case MS_AES_128_SHA1_32: + case MS_AES_128_NO_AUTH: + case MS_NO_CIPHER_SHA1_80: /* Not sure for this one */ + keylen = 30; + break; + case MS_AES_256_SHA1_80: + case MS_AES_CM_256_SHA1_80: + case MS_AES_256_SHA1_32: + keylen = 46; + break; + case MS_CRYPTO_SUITE_INVALID: + break; + } + if ((keylen == 0) || !generateB64CryptoKey(keylen, crypto->master_key, SAL_SRTP_KEY_SIZE)) { + lError() << "Could not generate SRTP key"; + crypto->algo = MS_CRYPTO_SUITE_INVALID; + return -1; + } + return 0; +} + +void MediaSessionPrivate::setupRtcpFb (SalMediaDescription *md) { + L_Q(); + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&md->streams[i])) + continue; + md->streams[i].rtcp_fb.generic_nack_enabled = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "rtcp_fb_generic_nack_enabled", 0); + md->streams[i].rtcp_fb.tmmbr_enabled = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "rtcp_fb_tmmbr_enabled", 1); + md->streams[i].implicit_rtcp_fb = getParams()->getPrivate()->implicitRtcpFbEnabled(); + for (const bctbx_list_t *it = md->streams[i].payloads; it != nullptr; it = bctbx_list_next(it)) { + OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(it)); + PayloadTypeAvpfParams avpf_params; + if (!getParams()->avpfEnabled() && !getParams()->getPrivate()->implicitRtcpFbEnabled()) { + payload_type_unset_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); + memset(&avpf_params, 0, sizeof(avpf_params)); + } else { + payload_type_set_flag(pt, PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED); + avpf_params = payload_type_get_avpf_params(pt); + avpf_params.trr_interval = getParams()->getAvpfRrInterval(); + } + payload_type_set_avpf_params(pt, avpf_params); + } + } +} + +void MediaSessionPrivate::setupRtcpXr (SalMediaDescription *md) { + L_Q(); + md->rtcp_xr.enabled = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "rtcp_xr_enabled", 1); + if (md->rtcp_xr.enabled) { + const char *rcvr_rtt_mode = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "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(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "rtcp_xr_rcvr_rtt_max_size", 10000); + md->rtcp_xr.stat_summary_enabled = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "rtcp_xr_stat_summary_enabled", 1); + if (md->rtcp_xr.stat_summary_enabled) + md->rtcp_xr.stat_summary_flags = OrtpRtcpXrStatSummaryLoss | OrtpRtcpXrStatSummaryDup | OrtpRtcpXrStatSummaryJitt | OrtpRtcpXrStatSummaryTTL; + md->rtcp_xr.voip_metrics_enabled = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "rtp", "rtcp_xr_voip_metrics_enabled", 1); + } + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&md->streams[i])) + continue; + memcpy(&md->streams[i].rtcp_xr, &md->rtcp_xr, sizeof(md->streams[i].rtcp_xr)); + } +} + +void MediaSessionPrivate::setupZrtpHash (SalMediaDescription *md) { + L_Q(); + if (linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP)) { + /* Set the hello hash for all streams */ + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&md->streams[i])) + continue; + if (sessions[i].zrtp_context) { + ms_zrtp_getHelloHash(sessions[i].zrtp_context, md->streams[i].zrtphash, 128); + /* Turn on the flag to use it if ZRTP is set */ + md->streams[i].haveZrtpHash = (getParams()->getMediaEncryption() == LinphoneMediaEncryptionZRTP); + } else + md->streams[i].haveZrtpHash = 0; + } + } +} + +void MediaSessionPrivate::setupEncryptionKeys (SalMediaDescription *md) { + L_Q(); + SalMediaDescription *oldMd = localDesc; + bool keepSrtpKeys = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "keep_srtp_keys", 1); + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&md->streams[i])) + continue; + if (sal_stream_description_has_srtp(&md->streams[i])) { + if (keepSrtpKeys && oldMd && sal_stream_description_active(&oldMd->streams[i]) && sal_stream_description_has_srtp(&oldMd->streams[i])) { + lInfo() << "Keeping same crypto keys"; + for (int j = 0; j < SAL_CRYPTO_ALGO_MAX; j++) { + memcpy(&md->streams[i].crypto[j], &oldMd->streams[i].crypto[j], sizeof(SalSrtpCryptoAlgo)); + } + } else { + const MSCryptoSuite *suites = linphone_core_get_srtp_crypto_suites(q->getCore()->getCCore()); + for (int j = 0; (suites != nullptr) && (suites[j] != MS_CRYPTO_SUITE_INVALID) && (j < SAL_CRYPTO_ALGO_MAX); j++) { + setupEncryptionKey(&md->streams[i].crypto[j], suites[j], static_cast(j) + 1); + } + } + } + } +} + +void MediaSessionPrivate::transferAlreadyAssignedPayloadTypes (SalMediaDescription *oldMd, SalMediaDescription *md) { + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + md->streams[i].already_assigned_payloads = oldMd->streams[i].already_assigned_payloads; + oldMd->streams[i].already_assigned_payloads = nullptr; + } +} + +void MediaSessionPrivate::updateLocalMediaDescriptionFromIce () { + iceAgent->updateLocalMediaDescriptionFromIce(localDesc); + iceAgent->updateIceStateInCallStats(); +} + +// ----------------------------------------------------------------------------- + +SalMulticastRole MediaSessionPrivate::getMulticastRole (SalStreamType type) { + L_Q(); + SalMulticastRole multicastRole = SalMulticastInactive; + if (op) { + SalStreamDescription *streamDesc = nullptr; + SalMediaDescription *remoteDesc = op->getRemoteMediaDescription(); + if (!localDesc && !remoteDesc && (direction == LinphoneCallOutgoing)) { + /* Well using call dir */ + if (((type == SalAudio) && getParams()->audioMulticastEnabled()) + || ((type == SalVideo) && getParams()->videoMulticastEnabled())) + multicastRole = SalMulticastSender; + } else if (localDesc && (!remoteDesc || op->isOfferer())) { + streamDesc = sal_media_description_find_best_stream(localDesc, type); + } else if (!op->isOfferer() && remoteDesc) { + streamDesc = sal_media_description_find_best_stream(remoteDesc, type); + } + + if (streamDesc) + multicastRole = streamDesc->multicast_role; + } + lInfo() << "CallSession [" << q << "], stream type [" << sal_stream_type_to_string(type) << "], multicast role is [" + << sal_multicast_role_to_string(multicastRole) << "]"; + return multicastRole; +} + +void MediaSessionPrivate::joinMulticastGroup (int streamIndex, MediaStream *ms) { + L_Q(); + if (!mediaPorts[streamIndex].multicastIp.empty()) + media_stream_join_multicast_group(ms, mediaPorts[streamIndex].multicastIp.c_str()); + else + lError() << "Cannot join multicast group if multicast ip is not set for call [" << q << "]"; +} + +// ----------------------------------------------------------------------------- + +int MediaSessionPrivate::findCryptoIndexFromTag (const SalSrtpCryptoAlgo crypto[], unsigned char tag) { + for (int i = 0; i < SAL_CRYPTO_ALGO_MAX; i++) { + if (crypto[i].tag == tag) + return i; + } + return -1; +} + +void MediaSessionPrivate::setDtlsFingerprint (MSMediaStreamSessions *sessions, const SalStreamDescription *sd, const SalStreamDescription *remote) { + if (sal_stream_description_has_dtls(sd)) { + if (sd->dtls_role == SalDtlsRoleInvalid) + lWarning() << "Unable to start DTLS engine on stream session [" << sessions << "], Dtls role in resulting media description is invalid"; + else { /* If DTLS is available at both end points */ + /* Give the peer certificate fingerprint to dtls context */ + ms_dtls_srtp_set_peer_fingerprint(sessions->dtls_context, remote->dtls_fingerprint); + } + } +} + +void MediaSessionPrivate::setDtlsFingerprintOnAllStreams () { + SalMediaDescription *remote = op->getRemoteMediaDescription(); + SalMediaDescription *result = op->getFinalMediaDescription(); + if (!remote || !result) { + /* This can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */ + return; + } + if (audioStream && (media_stream_get_state(&audioStream->ms) == MSStreamStarted)) + setDtlsFingerprint(&audioStream->ms.sessions, sal_media_description_find_best_stream(result, SalAudio), sal_media_description_find_best_stream(remote, SalAudio)); +#if VIDEO_ENABLED + if (videoStream && (media_stream_get_state(&videoStream->ms) == MSStreamStarted)) + setDtlsFingerprint(&videoStream->ms.sessions, sal_media_description_find_best_stream(result, SalVideo), sal_media_description_find_best_stream(remote, SalVideo)); +#endif + if (textStream && (media_stream_get_state(&textStream->ms) == MSStreamStarted)) + setDtlsFingerprint(&textStream->ms.sessions, sal_media_description_find_best_stream(result, SalText), sal_media_description_find_best_stream(remote, SalText)); +} + +void MediaSessionPrivate::setupDtlsParams (MediaStream *ms) { + L_Q(); + if (getParams()->getMediaEncryption() == LinphoneMediaEncryptionDTLS) { + MSDtlsSrtpParams dtlsParams; + memset(&dtlsParams, 0, sizeof(MSDtlsSrtpParams)); + /* TODO : search for a certificate with CNAME=sip uri(retrieved from variable me) or default : linphone-dtls-default-identity */ + /* This will parse the directory to find a matching fingerprint or generate it if not found */ + /* returned string must be freed */ + char *certificate = nullptr; + char *key = nullptr; + char *fingerprint = nullptr; + sal_certificates_chain_parse_directory(&certificate, &key, &fingerprint, + linphone_core_get_user_certificates_path(q->getCore()->getCCore()), "linphone-dtls-default-identity", SAL_CERTIFICATE_RAW_FORMAT_PEM, true, true); + if (fingerprint) { + dtlsCertificateFingerprint = fingerprint; + ms_free(fingerprint); + } + if (key && certificate) { + dtlsParams.pem_certificate = certificate; + dtlsParams.pem_pkey = key; + dtlsParams.role = MSDtlsSrtpRoleUnset; /* Default is unset, then check if we have a result SalMediaDescription */ + media_stream_enable_dtls(ms, &dtlsParams); + ms_free(certificate); + ms_free(key); + } else { + lError() << "Unable to retrieve or generate DTLS certificate and key - DTLS disabled"; + /* TODO : check if encryption forced, if yes, stop call */ + } + } +} + +void MediaSessionPrivate::setZrtpCryptoTypesParameters (MSZrtpParams *params) { + L_Q(); + if (!params) + return; + + const MSCryptoSuite *srtpSuites = linphone_core_get_srtp_crypto_suites(q->getCore()->getCCore()); + if (srtpSuites) { + for(int i = 0; (srtpSuites[i] != MS_CRYPTO_SUITE_INVALID) && (i < SAL_CRYPTO_ALGO_MAX) && (i < MS_MAX_ZRTP_CRYPTO_TYPES); i++) { + switch (srtpSuites[i]) { + case MS_AES_128_SHA1_32: + params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1; + params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS32; + break; + case MS_AES_128_NO_AUTH: + params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1; + break; + case MS_NO_CIPHER_SHA1_80: + params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80; + break; + case MS_AES_128_SHA1_80: + params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES1; + params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80; + break; + case MS_AES_CM_256_SHA1_80: + lWarning() << "Deprecated crypto suite MS_AES_CM_256_SHA1_80, use MS_AES_256_SHA1_80 instead"; + BCTBX_NO_BREAK; + case MS_AES_256_SHA1_80: + params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES3; + params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS80; + break; + case MS_AES_256_SHA1_32: + params->ciphers[params->ciphersCount++] = MS_ZRTP_CIPHER_AES3; + params->authTags[params->authTagsCount++] = MS_ZRTP_AUTHTAG_HS32; + break; + case MS_CRYPTO_SUITE_INVALID: + break; + } + } + } + + /* linphone_core_get_srtp_crypto_suites is used to determine sensible defaults; here each can be overridden */ + MsZrtpCryptoTypesCount ciphersCount = linphone_core_get_zrtp_cipher_suites(q->getCore()->getCCore(), params->ciphers); /* if not present in config file, params->ciphers is not modified */ + if (ciphersCount != 0) /* Use zrtp_cipher_suites config only when present, keep config from srtp_crypto_suite otherwise */ + params->ciphersCount = ciphersCount; + params->hashesCount = linphone_core_get_zrtp_hash_suites(q->getCore()->getCCore(), params->hashes); + MsZrtpCryptoTypesCount authTagsCount = linphone_core_get_zrtp_auth_suites(q->getCore()->getCCore(), params->authTags); /* If not present in config file, params->authTags is not modified */ + if (authTagsCount != 0) + params->authTagsCount = authTagsCount; /* Use zrtp_auth_suites config only when present, keep config from srtp_crypto_suite otherwise */ + params->sasTypesCount = linphone_core_get_zrtp_sas_suites(q->getCore()->getCCore(), params->sasTypes); + params->keyAgreementsCount = linphone_core_get_zrtp_key_agreement_suites(q->getCore()->getCCore(), params->keyAgreements); +} + +void MediaSessionPrivate::startDtls (MSMediaStreamSessions *sessions, const SalStreamDescription *sd, const SalStreamDescription *remote) { + if (sal_stream_description_has_dtls(sd)) { + if (sd->dtls_role == SalDtlsRoleInvalid) + lWarning() << "Unable to start DTLS engine on stream session [" << sessions << "], Dtls role in resulting media description is invalid"; + else { /* If DTLS is available at both end points */ + /* Give the peer certificate fingerprint to dtls context */ + ms_dtls_srtp_set_peer_fingerprint(sessions->dtls_context, remote->dtls_fingerprint); + ms_dtls_srtp_set_role(sessions->dtls_context, (sd->dtls_role == SalDtlsRoleIsClient) ? MSDtlsSrtpRoleIsClient : MSDtlsSrtpRoleIsServer); /* Set the role to client */ + ms_dtls_srtp_start(sessions->dtls_context); /* Then start the engine, it will send the DTLS client Hello */ + } + } +} + +void MediaSessionPrivate::startDtlsOnAllStreams () { + SalMediaDescription *remote = op->getRemoteMediaDescription(); + SalMediaDescription *result = op->getFinalMediaDescription(); + if (!remote || !result) { + /* This can happen in some tricky cases (early-media without SDP in the 200). In that case, simply skip DTLS code */ + return; + } + if (audioStream && (media_stream_get_state(&audioStream->ms) == MSStreamStarted)) + startDtls(&audioStream->ms.sessions, sal_media_description_find_best_stream(result, SalAudio), sal_media_description_find_best_stream(remote, SalAudio)); +#if VIDEO_ENABLED + if (videoStream && (media_stream_get_state(&videoStream->ms) == MSStreamStarted)) + startDtls(&videoStream->ms.sessions, sal_media_description_find_best_stream(result, SalVideo), sal_media_description_find_best_stream(remote, SalVideo)); +#endif + if (textStream && (media_stream_get_state(&textStream->ms) == MSStreamStarted)) + startDtls(&textStream->ms.sessions, sal_media_description_find_best_stream(result, SalText), sal_media_description_find_best_stream(remote, SalText)); +} + +void MediaSessionPrivate::updateCryptoParameters (SalMediaDescription *oldMd, SalMediaDescription *newMd) { + const SalStreamDescription *localStreamDesc = sal_media_description_find_secure_stream_of_type(localDesc, SalAudio); + SalStreamDescription *oldStream = sal_media_description_find_secure_stream_of_type(oldMd, SalAudio); + SalStreamDescription *newStream = sal_media_description_find_secure_stream_of_type(newMd, SalAudio); + if (audioStream && localStreamDesc && oldStream && newStream) + updateStreamCryptoParameters(localStreamDesc, oldStream, newStream, &audioStream->ms); +#ifdef VIDEO_ENABLED + localStreamDesc = sal_media_description_find_secure_stream_of_type(localDesc, SalVideo); + oldStream = sal_media_description_find_secure_stream_of_type(oldMd, SalVideo); + newStream = sal_media_description_find_secure_stream_of_type(newMd, SalVideo); + if (videoStream && localStreamDesc && oldStream && newStream) + updateStreamCryptoParameters(localStreamDesc, oldStream, newStream, &videoStream->ms); +#endif + localStreamDesc = sal_media_description_find_secure_stream_of_type(localDesc, SalText); + oldStream = sal_media_description_find_secure_stream_of_type(oldMd, SalText); + newStream = sal_media_description_find_secure_stream_of_type(newMd, SalText); + if (textStream && localStreamDesc && oldStream && newStream) + updateStreamCryptoParameters(localStreamDesc, oldStream, newStream, &textStream->ms); + startDtlsOnAllStreams(); +} + +bool MediaSessionPrivate::updateStreamCryptoParameters (const SalStreamDescription *localStreamDesc, SalStreamDescription *oldStream, SalStreamDescription *newStream, MediaStream *ms) { + int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast(newStream->crypto_local_tag)); + if (cryptoIdx >= 0) { + if (localDescChanged & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) + ms_media_stream_sessions_set_srtp_send_key_b64(&ms->sessions, newStream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key); + if (strcmp(oldStream->crypto[0].master_key, newStream->crypto[0].master_key) != 0) + ms_media_stream_sessions_set_srtp_recv_key_b64(&ms->sessions, newStream->crypto[0].algo, newStream->crypto[0].master_key); + return true; + } else + lWarning() << "Failed to find local crypto algo with tag: " << newStream->crypto_local_tag; + return false; +} + +// ----------------------------------------------------------------------------- + +int MediaSessionPrivate::getIdealAudioBandwidth (const SalMediaDescription *md, const SalStreamDescription *desc) { + L_Q(); + int remoteBandwidth = 0; + if (desc->bandwidth > 0) + remoteBandwidth = desc->bandwidth; + else if (md->bandwidth > 0) { + /* Case where b=AS is given globally, not per stream */ + remoteBandwidth = md->bandwidth; + } + int uploadBandwidth = 0; + bool forced = false; + if (getParams()->getPrivate()->getUpBandwidth() > 0) { + forced = true; + uploadBandwidth = getParams()->getPrivate()->getUpBandwidth(); + } else + uploadBandwidth = linphone_core_get_upload_bandwidth(q->getCore()->getCCore()); + uploadBandwidth = PayloadTypeHandler::getMinBandwidth(uploadBandwidth, remoteBandwidth); + if (!linphone_core_media_description_contains_video_stream(md) || forced) + return uploadBandwidth; + if (PayloadTypeHandler::bandwidthIsGreater(uploadBandwidth, 512)) + uploadBandwidth = 100; + else if (PayloadTypeHandler::bandwidthIsGreater(uploadBandwidth, 256)) + uploadBandwidth = 64; + else if (PayloadTypeHandler::bandwidthIsGreater(uploadBandwidth, 128)) + uploadBandwidth = 40; + else if (PayloadTypeHandler::bandwidthIsGreater(uploadBandwidth, 0)) + uploadBandwidth = 24; + return uploadBandwidth; +} + +int MediaSessionPrivate::getVideoBandwidth (const SalMediaDescription *md, const SalStreamDescription *desc) { + L_Q(); + int remoteBandwidth = 0; + if (desc->bandwidth > 0) + remoteBandwidth = desc->bandwidth; + else if (md->bandwidth > 0) { + /* Case where b=AS is given globally, not per stream */ + remoteBandwidth = PayloadTypeHandler::getRemainingBandwidthForVideo(md->bandwidth, audioBandwidth); + } + return PayloadTypeHandler::getMinBandwidth(PayloadTypeHandler::getRemainingBandwidthForVideo(linphone_core_get_upload_bandwidth(q->getCore()->getCCore()), audioBandwidth), remoteBandwidth); +} + +RtpProfile * MediaSessionPrivate::makeProfile (const SalMediaDescription *md, const SalStreamDescription *desc, int *usedPt) { + L_Q(); + *usedPt = -1; + int bandwidth = 0; + if (desc->type == SalAudio) + bandwidth = getIdealAudioBandwidth(md, desc); + else if (desc->type == SalVideo) + bandwidth = getVideoBandwidth(md, desc); + + bool first = true; + RtpProfile *profile = rtp_profile_new("Call profile"); + for (const bctbx_list_t *elem = desc->payloads; elem != nullptr; elem = bctbx_list_next(elem)) { + OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(elem)); + /* Make a copy of the payload type, so that we left the ones from the SalStreamDescription unchanged. + * If the SalStreamDescription is freed, this will have no impact on the running streams. */ + pt = payload_type_clone(pt); + int upPtime = 0; + if ((pt->flags & PAYLOAD_TYPE_FLAG_CAN_SEND) && first) { + /* First codec in list is the selected one */ + if (desc->type == SalAudio) { + updateAllocatedAudioBandwidth(pt, bandwidth); + bandwidth = audioBandwidth; + upPtime = getParams()->getPrivate()->getUpPtime(); + if (!upPtime) + upPtime = linphone_core_get_upload_ptime(q->getCore()->getCCore()); + } + first = false; + } + if (*usedPt == -1) { + /* Don't select telephone-event as a payload type */ + if (strcasecmp(pt->mime_type, "telephone-event") != 0) + *usedPt = payload_type_get_number(pt); + } + if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE) { + lInfo() << "Payload type [" << pt->mime_type << "/" << pt->clock_rate << "] has explicit bitrate [" << (pt->normal_bitrate / 1000) << "] kbit/s"; + pt->normal_bitrate = PayloadTypeHandler::getMinBandwidth(pt->normal_bitrate, bandwidth * 1000); + } else + pt->normal_bitrate = bandwidth * 1000; + if (desc->ptime > 0) + upPtime = desc->ptime; + if (upPtime > 0) { + ostringstream os; + os << "ptime=" << upPtime; + payload_type_append_send_fmtp(pt, os.str().c_str()); + } + int number = payload_type_get_number(pt); + if (rtp_profile_get_payload(profile, number)) + lWarning() << "A payload type with number " << number << " already exists in profile!"; + else + rtp_profile_set_payload(profile, number, pt); + } + return profile; +} + +void MediaSessionPrivate::unsetRtpProfile (int streamIndex) { + if (sessions[streamIndex].rtp_session) + rtp_session_set_profile(sessions[streamIndex].rtp_session, &av_profile); +} + +void MediaSessionPrivate::updateAllocatedAudioBandwidth (const PayloadType *pt, int maxbw) { + L_Q(); + audioBandwidth = PayloadTypeHandler::getAudioPayloadTypeBandwidth(pt, maxbw); + lInfo() << "Audio bandwidth for CallSession [" << q << "] is " << audioBandwidth; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::applyJitterBufferParams (RtpSession *session, LinphoneStreamType type) { + L_Q(); + LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore()); + JBParameters params; + rtp_session_get_jitter_buffer_params(session, ¶ms); + params.min_size = lp_config_get_int(config, "rtp", "jitter_buffer_min_size", 40); + params.max_size = lp_config_get_int(config, "rtp", "jitter_buffer_max_size", 500); + params.max_packets = params.max_size * 200 / 1000; /* Allow 200 packet per seconds, quite large */ + const char *algo = lp_config_get_string(config, "rtp", "jitter_buffer_algorithm", "rls"); + params.buffer_algorithm = jitterBufferNameToAlgo(algo ? algo : ""); + params.refresh_ms = lp_config_get_int(config, "rtp", "jitter_buffer_refresh_period", 5000); + params.ramp_refresh_ms = lp_config_get_int(config, "rtp", "jitter_buffer_ramp_refresh_period", 5000); + params.ramp_step_ms = lp_config_get_int(config, "rtp", "jitter_buffer_ramp_step", 20); + params.ramp_threshold = lp_config_get_int(config, "rtp", "jitter_buffer_ramp_threshold", 70); + + switch (type) { + case LinphoneStreamTypeAudio: + case LinphoneStreamTypeText: /* Let's use the same params for text as for audio */ + params.nom_size = linphone_core_get_audio_jittcomp(q->getCore()->getCCore()); + params.adaptive = linphone_core_audio_adaptive_jittcomp_enabled(q->getCore()->getCCore()); + break; + case LinphoneStreamTypeVideo: + params.nom_size = linphone_core_get_video_jittcomp(q->getCore()->getCCore()); + params.adaptive = linphone_core_video_adaptive_jittcomp_enabled(q->getCore()->getCCore()); + break; + case LinphoneStreamTypeUnknown: + lFatal() << "applyJitterBufferParams: should not happen"; + break; + } + params.enabled = params.nom_size > 0; + if (params.enabled) { + if (params.min_size > params.nom_size) + params.min_size = params.nom_size; + if (params.max_size < params.nom_size) + params.max_size = params.nom_size; + } + rtp_session_set_jitter_buffer_params(session, ¶ms); +} + +void MediaSessionPrivate::clearEarlyMediaDestination (MediaStream *ms) { + L_Q(); + RtpSession *session = ms->sessions.rtp_session; + rtp_session_clear_aux_remote_addr(session); + /* Restore symmetric rtp if ICE is not used */ + if (!iceAgent->hasSession()) + rtp_session_set_symmetric_rtp(session, linphone_core_symmetric_rtp_enabled(q->getCore()->getCCore())); +} + +void MediaSessionPrivate::clearEarlyMediaDestinations () { + if (audioStream) + clearEarlyMediaDestination(&audioStream->ms); + if (videoStream) + clearEarlyMediaDestination(&videoStream->ms); +} + +void MediaSessionPrivate::configureAdaptiveRateControl (MediaStream *ms, const OrtpPayloadType *pt, bool videoWillBeUsed) { + L_Q(); + bool enabled = !!linphone_core_adaptive_rate_control_enabled(q->getCore()->getCCore()); + if (!enabled) { + media_stream_enable_adaptive_bitrate_control(ms, false); + return; + } + bool isAdvanced = true; + string algo = linphone_core_get_adaptive_rate_algorithm(q->getCore()->getCCore()); + if (algo == "basic") + isAdvanced = false; + else if (algo == "advanced") + isAdvanced = true; + if (isAdvanced) { + /* We can't use media_stream_avpf_enabled() here because the active PayloadType is not set yet in the MediaStream */ + if (!pt || !(pt->flags & PAYLOAD_TYPE_RTCP_FEEDBACK_ENABLED)) { + lWarning() << "CallSession [" << q << "] - advanced adaptive rate control requested but avpf is not activated in this stream. Reverting to basic rate control instead"; + isAdvanced = false; + } else + lInfo() << "CallSession [" << q << "] - setting up advanced rate control"; + } + if (isAdvanced) { + ms_bandwidth_controller_add_stream(q->getCore()->getCCore()->bw_controller, ms); + media_stream_enable_adaptive_bitrate_control(ms, false); + } else { + media_stream_set_adaptive_bitrate_algorithm(ms, MSQosAnalyzerAlgorithmSimple); + if ((ms->type == MSAudio) && videoWillBeUsed) { + /* If this is an audio stream but video is going to be used, there is no need to perform + * basic rate control on the audio stream, just the video stream. */ + enabled = false; + } + media_stream_enable_adaptive_bitrate_control(ms, enabled); + } +} + +void MediaSessionPrivate::configureRtpSessionForRtcpFb (const SalStreamDescription *stream) { + RtpSession *session = nullptr; + if (stream->type == SalAudio) + session = audioStream->ms.sessions.rtp_session; + else if (stream->type == SalVideo) + session = videoStream->ms.sessions.rtp_session; + else + return; /* Do nothing for streams that are not audio or video */ + if (stream->rtcp_fb.generic_nack_enabled) + rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, true); + else + rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_GENERIC_NACK, false); + if (stream->rtcp_fb.tmmbr_enabled) + rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, true); + else + rtp_session_enable_avpf_feature(session, ORTP_AVPF_FEATURE_TMMBR, false); +} + +void MediaSessionPrivate::configureRtpSessionForRtcpXr (SalStreamType type) { + SalMediaDescription *remote = op->getRemoteMediaDescription(); + if (!remote) + return; + const SalStreamDescription *localStream = sal_media_description_find_best_stream(localDesc, type); + if (!localStream) + return; + const SalStreamDescription *remoteStream = sal_media_description_find_best_stream(remote, type); + if (!remoteStream) + return; + OrtpRtcpXrConfiguration currentConfig; + const OrtpRtcpXrConfiguration *remoteConfig = &remoteStream->rtcp_xr; + if (localStream->dir == SalStreamInactive) + return; + else if (localStream->dir == SalStreamRecvOnly) { + /* Use local config for unilateral parameters and remote config for collaborative parameters */ + memcpy(¤tConfig, &localStream->rtcp_xr, sizeof(currentConfig)); + currentConfig.rcvr_rtt_mode = remoteConfig->rcvr_rtt_mode; + currentConfig.rcvr_rtt_max_size = remoteConfig->rcvr_rtt_max_size; + } else + memcpy(¤tConfig, remoteConfig, sizeof(currentConfig)); + RtpSession *session = nullptr; + if (type == SalAudio) { + session = audioStream->ms.sessions.rtp_session; + } else if (type == SalVideo) { + session = videoStream->ms.sessions.rtp_session; + } else if (type == SalText) { + session = textStream->ms.sessions.rtp_session; + } + rtp_session_configure_rtcp_xr(session, ¤tConfig); +} + +RtpSession * MediaSessionPrivate::createAudioRtpIoSession () { + L_Q(); + LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore()); + const char *rtpmap = lp_config_get_string(config, "sound", "rtp_map", "pcmu/8000/1"); + OrtpPayloadType *pt = rtp_profile_get_payload_from_rtpmap(audioProfile, rtpmap); + if (!pt) + return nullptr; + rtpIoAudioProfile = rtp_profile_new("RTP IO audio profile"); + int ptnum = lp_config_get_int(config, "sound", "rtp_ptnum", 0); + rtp_profile_set_payload(rtpIoAudioProfile, ptnum, payload_type_clone(pt)); + const char *localIp = lp_config_get_string(config, "sound", "rtp_local_addr", "127.0.0.1"); + int localPort = lp_config_get_int(config, "sound", "rtp_local_port", 17076); + RtpSession *rtpSession = ms_create_duplex_rtp_session(localIp, localPort, -1, ms_factory_get_mtu(q->getCore()->getCCore()->factory)); + rtp_session_set_profile(rtpSession, rtpIoAudioProfile); + const char *remoteIp = lp_config_get_string(config, "sound", "rtp_remote_addr", "127.0.0.1"); + int remotePort = lp_config_get_int(config, "sound", "rtp_remote_port", 17078); + rtp_session_set_remote_addr_and_port(rtpSession, remoteIp, remotePort, -1); + rtp_session_enable_rtcp(rtpSession, false); + rtp_session_set_payload_type(rtpSession, ptnum); + int jittcomp = lp_config_get_int(config, "sound", "rtp_jittcomp", 0); /* 0 means no jitter buffer */ + rtp_session_set_jitter_compensation(rtpSession, jittcomp); + rtp_session_enable_jitter_buffer(rtpSession, (jittcomp > 0)); + bool symmetric = !!lp_config_get_int(config, "sound", "rtp_symmetric", 0); + rtp_session_set_symmetric_rtp(rtpSession, symmetric); + return rtpSession; +} + +RtpSession * MediaSessionPrivate::createVideoRtpIoSession () { +#ifdef VIDEO_ENABLED + L_Q(); + LinphoneConfig *config = linphone_core_get_config(q->getCore()->getCCore()); + const char *rtpmap = lp_config_get_string(config, "video", "rtp_map", "vp8/90000/1"); + OrtpPayloadType *pt = rtp_profile_get_payload_from_rtpmap(videoProfile, rtpmap); + if (!pt) + return nullptr; + rtpIoVideoProfile = rtp_profile_new("RTP IO video profile"); + int ptnum = lp_config_get_int(config, "video", "rtp_ptnum", 0); + rtp_profile_set_payload(rtpIoVideoProfile, ptnum, payload_type_clone(pt)); + const char *localIp = lp_config_get_string(config, "video", "rtp_local_addr", "127.0.0.1"); + int localPort = lp_config_get_int(config, "video", "rtp_local_port", 19076); + RtpSession *rtpSession = ms_create_duplex_rtp_session(localIp, localPort, -1, ms_factory_get_mtu(q->getCore()->getCCore()->factory)); + rtp_session_set_profile(rtpSession, rtpIoVideoProfile); + const char *remoteIp = lp_config_get_string(config, "video", "rtp_remote_addr", "127.0.0.1"); + int remotePort = lp_config_get_int(config, "video", "rtp_remote_port", 19078); + rtp_session_set_remote_addr_and_port(rtpSession, remoteIp, remotePort, -1); + rtp_session_enable_rtcp(rtpSession, false); + rtp_session_set_payload_type(rtpSession, ptnum); + rtp_session_set_symmetric_rtp(rtpSession, linphone_config_get_bool(config, "video", "rtp_symmetric", FALSE)); + int jittcomp = lp_config_get_int(config, "video", "rtp_jittcomp", 0); /* 0 means no jitter buffer */ + rtp_session_set_jitter_compensation(rtpSession, jittcomp); + rtp_session_enable_jitter_buffer(rtpSession, (jittcomp > 0)); + return rtpSession; +#else + return nullptr; +#endif +} + +/* + * Frees the media resources of the call. + * This has to be done at the earliest, unlike signaling resources that sometimes need to be kept a bit more longer. + * It is called by setTerminated() (for termination of calls signaled to the application), or directly by the destructor of the session + * if it was never notified to the application. + */ +void MediaSessionPrivate::freeResources () { + stopStreams(); + iceAgent->deleteSession(); + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) + ms_media_stream_sessions_uninit(&sessions[i]); + _linphone_call_stats_uninit(audioStats); + _linphone_call_stats_uninit(videoStats); + _linphone_call_stats_uninit(textStats); +} + +void MediaSessionPrivate::handleIceEvents (OrtpEvent *ev) { + L_Q(); + OrtpEventType evt = ortp_event_get_type(ev); + OrtpEventData *evd = ortp_event_get_data(ev); + if (evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) { + if (iceAgent->hasCompletedCheckList()) { + /* The ICE session has succeeded, so perform a call update */ + if (iceAgent->isControlling() && q->getCurrentParams()->getPrivate()->getUpdateCallWhenIceCompleted()) { + MediaSessionParams newParams(*getParams()); + newParams.getPrivate()->setInternalCallUpdate(true); + q->update(&newParams); + }else if (!iceAgent->isControlling() && incomingIceReinvitePending){ + q->acceptUpdate(nullptr); + incomingIceReinvitePending = false; + } + startDtlsOnAllStreams(); + } + iceAgent->updateIceStateInCallStats(); + } else if (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) { + if (!evd->info.ice_processing_successful) + lWarning() << "No STUN answer from [" << linphone_core_get_stun_server(q->getCore()->getCCore()) << "], continuing without STUN"; + iceAgent->gatheringFinished(); + switch (state) { + case CallSession::State::Updating: + startUpdate(); + break; + case CallSession::State::UpdatedByRemote: + startAcceptUpdate(prevState, Utils::toString(prevState)); + break; + case CallSession::State::OutgoingInit: + stopStreamsForIceGathering(); + if (isReadyForInvite()) + q->startInvite(nullptr, ""); + break; + case CallSession::State::Idle: + stopStreamsForIceGathering(); + updateLocalMediaDescriptionFromIce(); + op->setLocalMediaDescription(localDesc); + deferIncomingNotification = false; + startIncomingNotification(); + break; + default: + break; + } + } else if (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) { + if (state == CallSession::State::UpdatedByRemote) { + startAcceptUpdate(prevState, Utils::toString(prevState)); + iceAgent->updateIceStateInCallStats(); + } + } else if (evt == ORTP_EVENT_ICE_RESTART_NEEDED) { + iceAgent->restartSession(IR_Controlling); + q->update(getCurrentParams()); + } +} + +void MediaSessionPrivate::handleStreamEvents (int streamIndex) { + L_Q(); + MediaStream *ms = (streamIndex == mainAudioStreamIndex) ? &audioStream->ms : + (streamIndex == mainVideoStreamIndex ? &videoStream->ms : &textStream->ms); + if (ms) { + /* Ensure there is no dangling ICE check list */ + if (!iceAgent->hasSession()) + media_stream_set_ice_check_list(ms, nullptr); + switch(ms->type){ + case MSAudio: + audio_stream_iterate((AudioStream *)ms); + break; + case MSVideo: +#ifdef VIDEO_ENABLED + video_stream_iterate((VideoStream *)ms); +#endif + break; + case MSText: + text_stream_iterate((TextStream *)ms); + break; + default: + lError() << "handleStreamEvents(): unsupported stream type"; + return; + } + } + OrtpEvQueue *evq; + OrtpEvent *ev; + /* Yes the event queue has to be taken at each iteration, because ice events may perform operations re-creating the streams */ + while ((evq = getEventQueue(streamIndex)) && (ev = ortp_ev_queue_get(evq))) { + LinphoneCallStats *stats = nullptr; + if (streamIndex == mainAudioStreamIndex) + stats = audioStats; + else if (streamIndex == mainVideoStreamIndex) + stats = videoStats; + else + stats = textStats; + + OrtpEventType evt = ortp_event_get_type(ev); + OrtpEventData *evd = ortp_event_get_data(ev); + + /*This MUST be done before any call to "linphone_call_stats_fill" since it has ownership over evd->packet*/ + if (evt == ORTP_EVENT_RTCP_PACKET_RECEIVED) { + do { + if (evd->packet && rtcp_is_RTPFB(evd->packet)) { + if (rtcp_RTPFB_get_type(evd->packet) == RTCP_RTPFB_TMMBR) { + listener->onTmmbrReceived(q->getSharedFromThis(), streamIndex, (int)rtcp_RTPFB_tmmbr_get_max_bitrate(evd->packet)); + } + } + } while (rtcp_next_packet(evd->packet)); + rtcp_rewind(evd->packet); + } + + /* And yes the MediaStream must be taken at each iteration, because it may have changed due to the handling of events + * in this loop*/ + ms = getMediaStream(streamIndex); + if (ms) + linphone_call_stats_fill(stats, ms, ev); + notifyStatsUpdated(streamIndex); + if (evt == ORTP_EVENT_ZRTP_ENCRYPTION_CHANGED) { + if (streamIndex == mainAudioStreamIndex) + audioStreamEncryptionChanged(!!evd->info.zrtp_stream_encrypted); + else if (streamIndex == mainVideoStreamIndex) + propagateEncryptionChanged(); + } else if (evt == ORTP_EVENT_ZRTP_SAS_READY) { + if (streamIndex == mainAudioStreamIndex) + audioStreamAuthTokenReady(evd->info.zrtp_info.sas, !!evd->info.zrtp_info.verified); + } else if (evt == ORTP_EVENT_DTLS_ENCRYPTION_CHANGED) { + if (streamIndex == mainAudioStreamIndex) + audioStreamEncryptionChanged(!!evd->info.dtls_stream_encrypted); + else if (streamIndex == mainVideoStreamIndex) + propagateEncryptionChanged(); + } else if ((evt == ORTP_EVENT_ICE_SESSION_PROCESSING_FINISHED) || (evt == ORTP_EVENT_ICE_GATHERING_FINISHED) + || (evt == ORTP_EVENT_ICE_LOSING_PAIRS_COMPLETED) || (evt == ORTP_EVENT_ICE_RESTART_NEEDED)) { + if (ms) + handleIceEvents(ev); + } else if (evt == ORTP_EVENT_TELEPHONE_EVENT) { + telephoneEventReceived(evd->info.telephone_event); + } else if (evt == ORTP_EVENT_NEW_VIDEO_BANDWIDTH_ESTIMATION_AVAILABLE) { + lInfo() << "Video bandwidth estimation is " << (int)(evd->info.video_bandwidth_available / 1000.) << " kbit/s"; + /* If this event happens then it should be a video stream */ + if (streamIndex == mainVideoStreamIndex) + linphone_call_stats_set_estimated_download_bandwidth(stats, (float)(evd->info.video_bandwidth_available*1e-3)); + } + ortp_event_destroy(ev); + } +} + +void MediaSessionPrivate::initializeAudioStream () { + L_Q(); + if (audioStream) + return; + if (!sessions[mainAudioStreamIndex].rtp_session) { + SalMulticastRole multicastRole = getMulticastRole(SalAudio); + SalMediaDescription *remoteDesc = nullptr; + SalStreamDescription *streamDesc = nullptr; + if (op) + remoteDesc = op->getRemoteMediaDescription(); + if (remoteDesc) + streamDesc = sal_media_description_find_best_stream(remoteDesc, SalAudio); + + audioStream = audio_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainAudioStreamIndex)), + (multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainAudioStreamIndex].rtpPort, + (multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainAudioStreamIndex].rtcpPort); + if (multicastRole == SalMulticastReceiver) + joinMulticastGroup(mainAudioStreamIndex, &audioStream->ms); + rtp_session_enable_network_simulation(audioStream->ms.sessions.rtp_session, &q->getCore()->getCCore()->net_conf.netsim_params); + applyJitterBufferParams(audioStream->ms.sessions.rtp_session, LinphoneStreamTypeAudio); + string userAgent = linphone_core_get_user_agent(q->getCore()->getCCore()); + audio_stream_set_rtcp_information(audioStream, getMe()->getAddress().asString().c_str(), userAgent.c_str()); + rtp_session_set_symmetric_rtp(audioStream->ms.sessions.rtp_session, linphone_core_symmetric_rtp_enabled(q->getCore()->getCCore())); + setupDtlsParams(&audioStream->ms); + + /* Initialize zrtp even if we didn't explicitely set it, just in case peer offers it */ + if (linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP)) { + LinphoneAddress *peerAddr = (direction == LinphoneCallIncoming) ? log->from : log->to; + LinphoneAddress *selfAddr = (direction == LinphoneCallIncoming) ? log->to : log->from; + char *peerUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(peerAddr) + , linphone_address_get_username(peerAddr) + , linphone_address_get_domain(peerAddr)); + char *selfUri = ms_strdup_printf("%s:%s@%s" , linphone_address_get_scheme(selfAddr) + , linphone_address_get_username(selfAddr) + , linphone_address_get_domain(selfAddr)); + MSZrtpParams params; + memset(¶ms, 0, sizeof(MSZrtpParams)); + /* media encryption of current params will be set later when zrtp is activated */ + params.zidCacheDB = linphone_core_get_zrtp_cache_db(q->getCore()->getCCore()); + params.peerUri = peerUri; + params.selfUri = selfUri; + /* Get key lifespan from config file, default is 0:forever valid */ + params.limeKeyTimeSpan = bctbx_time_string_to_sec(lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "sip", "lime_key_validity", "0")); + setZrtpCryptoTypesParameters(¶ms); + audio_stream_enable_zrtp(audioStream, ¶ms); + if (peerUri) + ms_free(peerUri); + if (selfUri) + ms_free(selfUri); + } + + media_stream_reclaim_sessions(&audioStream->ms, &sessions[mainAudioStreamIndex]); + } else { + audioStream = audio_stream_new_with_sessions(q->getCore()->getCCore()->factory, &sessions[mainAudioStreamIndex]); + } + + if (mediaPorts[mainAudioStreamIndex].rtpPort == -1) + setPortConfigFromRtpSession(mainAudioStreamIndex, audioStream->ms.sessions.rtp_session); + int dscp = linphone_core_get_audio_dscp(q->getCore()->getCCore()); + if (dscp != -1) + audio_stream_set_dscp(audioStream, dscp); + if (linphone_core_echo_limiter_enabled(q->getCore()->getCCore())) { + string type = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "sound", "el_type", "mic"); + if (type == "mic") + audio_stream_enable_echo_limiter(audioStream, ELControlMic); + else if (type == "full") + 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 */ + string location = lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "sound", "eq_location", "hp"); + audioStream->eq_loc = (location == "mic") ? MSEqualizerMic : MSEqualizerHP; + lInfo() << "Equalizer location: " << location; + + audio_stream_enable_gain_control(audioStream, true); + if (linphone_core_echo_cancellation_enabled(q->getCore()->getCCore())) { + int len = lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "ec_tail_len", 0); + int delay = lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "ec_delay", 0); + int framesize = lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "ec_framesize", 0); + audio_stream_set_echo_canceller_params(audioStream, len, delay, framesize); + if (audioStream->ec) { + char *statestr=reinterpret_cast(ms_malloc0(ecStateMaxLen)); + if (lp_config_relative_file_exists(linphone_core_get_config(q->getCore()->getCCore()), ecStateStore.c_str()) + && (lp_config_read_relative_file(linphone_core_get_config(q->getCore()->getCCore()), ecStateStore.c_str(), statestr, ecStateMaxLen) == 0)) { + ms_filter_call_method(audioStream->ec, MS_ECHO_CANCELLER_SET_STATE_STRING, statestr); + } + ms_free(statestr); + } + } + audio_stream_enable_automatic_gain_control(audioStream, linphone_core_agc_enabled(q->getCore()->getCCore())); + bool_t enabled = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "noisegate", 0); + audio_stream_enable_noise_gate(audioStream, enabled); + audio_stream_set_features(audioStream, linphone_core_get_audio_features(q->getCore()->getCCore())); + + if (q->getCore()->getCCore()->rtptf) { + RtpTransport *meta_rtp; + RtpTransport *meta_rtcp; + rtp_session_get_transports(audioStream->ms.sessions.rtp_session, &meta_rtp, &meta_rtcp); + if (!meta_rtp_transport_get_endpoint(meta_rtp)) { + lInfo() << "CallSession [" << q << "] using custom audio RTP transport endpoint"; + meta_rtp_transport_set_endpoint(meta_rtp, q->getCore()->getCCore()->rtptf->audio_rtp_func(q->getCore()->getCCore()->rtptf->audio_rtp_func_data, mediaPorts[mainAudioStreamIndex].rtpPort)); + } + if (!meta_rtp_transport_get_endpoint(meta_rtcp)) + meta_rtp_transport_set_endpoint(meta_rtcp, q->getCore()->getCCore()->rtptf->audio_rtcp_func(q->getCore()->getCCore()->rtptf->audio_rtcp_func_data, mediaPorts[mainAudioStreamIndex].rtcpPort)); + } + + audioStreamEvQueue = ortp_ev_queue_new(); + rtp_session_register_event_queue(audioStream->ms.sessions.rtp_session, audioStreamEvQueue); + iceAgent->prepareIceForStream(&audioStream->ms, false); +} + +void MediaSessionPrivate::initializeTextStream () { + L_Q(); + if (textStream) + return; + if (!sessions[mainTextStreamIndex].rtp_session) { + SalMulticastRole multicastRole = getMulticastRole(SalText); + SalMediaDescription *remoteDesc = nullptr; + SalStreamDescription *streamDesc = nullptr; + if (op) + remoteDesc = op->getRemoteMediaDescription(); + if (remoteDesc) + streamDesc = sal_media_description_find_best_stream(remoteDesc, SalText); + + textStream = text_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainTextStreamIndex)), + (multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainTextStreamIndex].rtpPort, + (multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainTextStreamIndex].rtcpPort); + if (multicastRole == SalMulticastReceiver) + joinMulticastGroup(mainTextStreamIndex, &textStream->ms); + rtp_session_enable_network_simulation(textStream->ms.sessions.rtp_session, &q->getCore()->getCCore()->net_conf.netsim_params); + applyJitterBufferParams(textStream->ms.sessions.rtp_session, LinphoneStreamTypeText); + rtp_session_set_symmetric_rtp(textStream->ms.sessions.rtp_session, linphone_core_symmetric_rtp_enabled(q->getCore()->getCCore())); + setupDtlsParams(&textStream->ms); + media_stream_reclaim_sessions(&textStream->ms, &sessions[mainTextStreamIndex]); + } else + textStream = text_stream_new_with_sessions(q->getCore()->getCCore()->factory, &sessions[mainTextStreamIndex]); + if (mediaPorts[mainTextStreamIndex].rtpPort == -1) + setPortConfigFromRtpSession(mainTextStreamIndex, textStream->ms.sessions.rtp_session); + + if (q->getCore()->getCCore()->rtptf) { + RtpTransport *meta_rtp; + RtpTransport *meta_rtcp; + rtp_session_get_transports(textStream->ms.sessions.rtp_session, &meta_rtp, &meta_rtcp); + if (!meta_rtp_transport_get_endpoint(meta_rtp)) + meta_rtp_transport_set_endpoint(meta_rtp, q->getCore()->getCCore()->rtptf->audio_rtp_func(q->getCore()->getCCore()->rtptf->audio_rtp_func_data, mediaPorts[mainTextStreamIndex].rtpPort)); + if (!meta_rtp_transport_get_endpoint(meta_rtcp)) + meta_rtp_transport_set_endpoint(meta_rtcp, q->getCore()->getCCore()->rtptf->audio_rtcp_func(q->getCore()->getCCore()->rtptf->audio_rtcp_func_data, mediaPorts[mainTextStreamIndex].rtcpPort)); + } + + textStreamEvQueue = ortp_ev_queue_new(); + rtp_session_register_event_queue(textStream->ms.sessions.rtp_session, textStreamEvQueue); + iceAgent->prepareIceForStream(&textStream->ms, false); +} + +void MediaSessionPrivate::initializeVideoStream () { +#ifdef VIDEO_ENABLED + L_Q(); + if (videoStream) + return; + if (!sessions[mainVideoStreamIndex].rtp_session) { + SalMulticastRole multicastRole = getMulticastRole(SalVideo); + SalMediaDescription *remoteDesc = nullptr; + SalStreamDescription *streamDesc = nullptr; + if (op) + remoteDesc = op->getRemoteMediaDescription(); + if (remoteDesc) + streamDesc = sal_media_description_find_best_stream(remoteDesc, SalVideo); + + videoStream = video_stream_new2(q->getCore()->getCCore()->factory, L_STRING_TO_C(getBindIpForStream(mainVideoStreamIndex)), + (multicastRole == SalMulticastReceiver) ? streamDesc->rtp_port : mediaPorts[mainVideoStreamIndex].rtpPort, + (multicastRole == SalMulticastReceiver) ? 0 /* Disabled for now */ : mediaPorts[mainVideoStreamIndex].rtcpPort); + if (multicastRole == SalMulticastReceiver) + joinMulticastGroup(mainVideoStreamIndex, &videoStream->ms); + rtp_session_enable_network_simulation(videoStream->ms.sessions.rtp_session, &q->getCore()->getCCore()->net_conf.netsim_params); + applyJitterBufferParams(videoStream->ms.sessions.rtp_session, LinphoneStreamTypeVideo); + string userAgent = linphone_core_get_user_agent(q->getCore()->getCCore()); + video_stream_set_rtcp_information(videoStream, getMe()->getAddress().asString().c_str(), userAgent.c_str()); + rtp_session_set_symmetric_rtp(videoStream->ms.sessions.rtp_session, linphone_core_symmetric_rtp_enabled(q->getCore()->getCCore())); + setupDtlsParams(&videoStream->ms); + /* Initialize zrtp even if we didn't explicitely set it, just in case peer offers it */ + if (linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP)) + video_stream_enable_zrtp(videoStream, audioStream); + + media_stream_reclaim_sessions(&videoStream->ms, &sessions[mainVideoStreamIndex]); + } else + videoStream = video_stream_new_with_sessions(q->getCore()->getCCore()->factory, &sessions[mainVideoStreamIndex]); + + if (mediaPorts[mainVideoStreamIndex].rtpPort == -1) + setPortConfigFromRtpSession(mainVideoStreamIndex, videoStream->ms.sessions.rtp_session); + int dscp = linphone_core_get_video_dscp(q->getCore()->getCCore()); + if (dscp!=-1) + video_stream_set_dscp(videoStream, dscp); + video_stream_enable_display_filter_auto_rotate( + videoStream, + !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "video", "display_filter_auto_rotate", 0) + ); + int videoRecvBufSize = lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "video", "recv_buf_size", 0); + if (videoRecvBufSize > 0) + rtp_session_set_recv_buf_size(videoStream->ms.sessions.rtp_session, videoRecvBufSize); + + const char *displayFilter = linphone_core_get_video_display_filter(q->getCore()->getCCore()); + if (displayFilter) + video_stream_set_display_filter_name(videoStream, displayFilter); + video_stream_set_event_callback(videoStream, videoStreamEventCb, this); + + if (q->getCore()->getCCore()->rtptf) { + RtpTransport *meta_rtp; + RtpTransport *meta_rtcp; + rtp_session_get_transports(videoStream->ms.sessions.rtp_session, &meta_rtp, &meta_rtcp); + if (!meta_rtp_transport_get_endpoint(meta_rtp)) { + lInfo() << "CallSession [" << q << "] using custom video RTP transport endpoint"; + meta_rtp_transport_set_endpoint(meta_rtp, q->getCore()->getCCore()->rtptf->video_rtp_func(q->getCore()->getCCore()->rtptf->video_rtp_func_data, mediaPorts[mainVideoStreamIndex].rtpPort)); + } + if (!meta_rtp_transport_get_endpoint(meta_rtcp)) + meta_rtp_transport_set_endpoint(meta_rtcp, q->getCore()->getCCore()->rtptf->video_rtcp_func(q->getCore()->getCCore()->rtptf->video_rtcp_func_data, mediaPorts[mainVideoStreamIndex].rtcpPort)); + } + videoStreamEvQueue = ortp_ev_queue_new(); + rtp_session_register_event_queue(videoStream->ms.sessions.rtp_session, videoStreamEvQueue); + iceAgent->prepareIceForStream(&videoStream->ms, false); +#ifdef TEST_EXT_RENDERER + video_stream_set_render_callback(videoStream, extRendererCb, nullptr); +#endif +#else + videoStream = nullptr; +#endif +} + +void MediaSessionPrivate::prepareEarlyMediaForking () { + /* We need to disable symmetric rtp otherwise our outgoing streams will be switching permanently between the multiple destinations */ + if (audioStream) + rtp_session_set_symmetric_rtp(audioStream->ms.sessions.rtp_session, false); + if (videoStream) + rtp_session_set_symmetric_rtp(videoStream->ms.sessions.rtp_session, false); +} + +void MediaSessionPrivate::postConfigureAudioStreams (bool muted) { + L_Q(); + q->getCore()->getPrivate()->postConfigureAudioStream(audioStream, muted); + if (linphone_core_dtmf_received_has_listener(q->getCore()->getCCore())) + audio_stream_play_received_dtmfs(audioStream, false); + if (recordActive) + q->startRecording(); +} + +void MediaSessionPrivate::setSymmetricRtp (bool value) { + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + MSMediaStreamSessions *mss = &sessions[i]; + if (mss->rtp_session) + rtp_session_set_symmetric_rtp(mss->rtp_session, value); + } +} + +void MediaSessionPrivate::setupRingbackPlayer () { + L_Q(); + int pauseTime = 3000; + audio_stream_play(audioStream, q->getCore()->getCCore()->sound_conf.ringback_tone); + ms_filter_call_method(audioStream->soundread, MS_FILE_PLAYER_LOOP, &pauseTime); +} + +void MediaSessionPrivate::startAudioStream (CallSession::State targetState, bool videoWillBeUsed) { + L_Q(); + const SalStreamDescription *stream = sal_media_description_find_best_stream(resultDesc, SalAudio); + if (stream && (stream->dir != SalStreamInactive) && (stream->rtp_port != 0)) { + int usedPt = -1; + onHoldFile = ""; + audioProfile = makeProfile(resultDesc, stream, &usedPt); + if (usedPt == -1) + lWarning() << "No audio stream accepted?"; + else { + const char *rtpAddr = (stream->rtp_addr[0] != '\0') ? stream->rtp_addr : resultDesc->addr; + bool isMulticast = !!ms_is_multicast(rtpAddr); + bool ok = true; + getCurrentParams()->getPrivate()->setUsedAudioCodec(rtp_profile_get_payload(audioProfile, usedPt)); + getCurrentParams()->enableAudio(true); + MSSndCard *playcard = q->getCore()->getCCore()->sound_conf.lsd_card ? q->getCore()->getCCore()->sound_conf.lsd_card : q->getCore()->getCCore()->sound_conf.play_sndcard; + if (!playcard) + lWarning() << "No card defined for playback!"; + MSSndCard *captcard = q->getCore()->getCCore()->sound_conf.capt_sndcard; + if (!captcard) + lWarning() << "No card defined for capture!"; + string playfile = L_C_TO_STRING(q->getCore()->getCCore()->play_file); + string recfile = L_C_TO_STRING(q->getCore()->getCCore()->rec_file); + /* Don't use file or soundcard capture when placed in recv-only mode */ + if ((stream->rtp_port == 0) || (stream->dir == SalStreamRecvOnly) || ((stream->multicast_role == SalMulticastReceiver) && isMulticast)) { + captcard = nullptr; + playfile = ""; + } + if (targetState == CallSession::State::Paused) { + // In paused state, we never use soundcard + playcard = captcard = nullptr; + recfile = ""; + // And we will eventually play "playfile" if set by the user + } + if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) { + captcard = nullptr; + playfile = ""; /* It is setup later */ + if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "send_ringback_without_playback", 0) == 1) { + playcard = nullptr; + recfile = ""; + } + } + // If playfile are supplied don't use soundcards + bool useRtpIo = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "rtp_io", false); + bool useRtpIoEnableLocalOutput = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sound", "rtp_io_enable_local_output", false); + if (q->getCore()->getCCore()->use_files || (useRtpIo && !useRtpIoEnableLocalOutput)) { + captcard = playcard = nullptr; + } + if (getParams()->getPrivate()->getInConference()) { + // First create the graph without soundcard resources + captcard = playcard = nullptr; + } + if (listener && !listener->areSoundResourcesAvailable(q->getSharedFromThis())) { + lInfo() << "Sound resources are used by another CallSession, not using soundcard"; + captcard = playcard = nullptr; + } + + if (playcard) { + ms_snd_card_set_stream_type(playcard, MS_SND_CARD_STREAM_VOICE); + } + media_stream_set_max_network_bitrate(&audioStream->ms, linphone_core_get_upload_bandwidth(q->getCore()->getCCore()) * 1000); + bool useEc = captcard && linphone_core_echo_cancellation_enabled(q->getCore()->getCCore()); + audio_stream_enable_echo_canceller(audioStream, useEc); + 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); + rtp_session_enable_rtcp_mux(audioStream->ms.sessions.rtp_session, stream->rtcp_mux); + if (!getParams()->getPrivate()->getInConference() && !getParams()->getRecordFilePath().empty()) { + audio_stream_mixed_record_open(audioStream, getParams()->getRecordFilePath().c_str()); + getCurrentParams()->setRecordFilePath(getParams()->getRecordFilePath()); + } + // Valid local tags are > 0 + if (sal_stream_description_has_srtp(stream)) { + const SalStreamDescription *localStreamDesc = sal_media_description_find_stream(localDesc, stream->proto, SalAudio); + int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast(stream->crypto_local_tag)); + if (cryptoIdx >= 0) { + ms_media_stream_sessions_set_srtp_recv_key_b64(&audioStream->ms.sessions, stream->crypto[0].algo, stream->crypto[0].master_key); + ms_media_stream_sessions_set_srtp_send_key_b64(&audioStream->ms.sessions, stream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key); + } else + lWarning() << "Failed to find local crypto algo with tag: " << stream->crypto_local_tag; + } + configureRtpSessionForRtcpFb(stream); + configureRtpSessionForRtcpXr(SalAudio); + configureAdaptiveRateControl(&audioStream->ms, getCurrentParams()->getUsedAudioCodec(), videoWillBeUsed); + if (isMulticast) + rtp_session_set_multicast_ttl(audioStream->ms.sessions.rtp_session, stream->ttl); + MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER; + if (useRtpIo) { + if (useRtpIoEnableLocalOutput) { + io.input.type = MSResourceRtp; + io.input.session = createAudioRtpIoSession(); + if (playcard) { + io.output.type = MSResourceSoundcard; + io.output.soundcard = playcard; + } else { + io.output.type = MSResourceFile; + io.output.file = recfile.empty() ? nullptr : recfile.c_str(); + } + } else { + io.input.type = io.output.type = MSResourceRtp; + io.input.session = io.output.session = createAudioRtpIoSession(); + } + if (!io.input.session) + ok = false; + } else { + if (playcard) { + io.output.type = MSResourceSoundcard; + io.output.soundcard = playcard; + } else { + io.output.type = MSResourceFile; + io.output.file = recfile.empty() ? nullptr : recfile.c_str(); + } + if (captcard) { + io.input.type = MSResourceSoundcard; + io.input.soundcard = captcard; + } else { + io.input.type = MSResourceFile; + onHoldFile = playfile; + io.input.file = nullptr; /* We prefer to use the remote_play api, that allows to play multimedia files */ + } + } + if (ok) { + int err = audio_stream_start_from_io(audioStream, audioProfile, rtpAddr, stream->rtp_port, + (stream->rtcp_addr[0] != '\0') ? stream->rtcp_addr : resultDesc->addr, + (linphone_core_rtcp_enabled(q->getCore()->getCCore()) && !isMulticast) ? (stream->rtcp_port ? stream->rtcp_port : stream->rtp_port + 1) : 0, + usedPt, &io); + if (err == 0) + postConfigureAudioStreams((allMuted || audioMuted) && (listener && !listener->isPlayingRingbackTone(q->getSharedFromThis()))); + } + ms_media_stream_sessions_set_encryption_mandatory(&audioStream->ms.sessions, isEncryptionMandatory()); + if ((targetState == CallSession::State::Paused) && !captcard && !playfile.empty()) { + int pauseTime = 500; + ms_filter_call_method(audioStream->soundread, MS_FILE_PLAYER_LOOP, &pauseTime); + } + if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) + setupRingbackPlayer(); + if (getParams()->getPrivate()->getInConference() && listener) { + // Transform the graph to connect it to the conference filter + bool mute = (stream->dir == SalStreamRecvOnly); + listener->onCallSessionConferenceStreamStarting(q->getSharedFromThis(), mute); + } + getCurrentParams()->getPrivate()->setInConference(getParams()->getPrivate()->getInConference()); + getCurrentParams()->enableLowBandwidth(getParams()->lowBandwidthEnabled()); + // Start ZRTP engine if needed : set here or remote have a zrtp-hash attribute + SalMediaDescription *remote = op->getRemoteMediaDescription(); + const SalStreamDescription *remoteStream = sal_media_description_find_best_stream(remote, SalAudio); + if (linphone_core_media_encryption_supported(q->getCore()->getCCore(), LinphoneMediaEncryptionZRTP) + && ((getParams()->getMediaEncryption() == LinphoneMediaEncryptionZRTP) || (remoteStream->haveZrtpHash == 1))) { + audio_stream_start_zrtp(audioStream); + if (remoteStream->haveZrtpHash == 1) { + int retval = ms_zrtp_setPeerHelloHash(audioStream->ms.sessions.zrtp_context, (uint8_t *)remoteStream->zrtphash, strlen((const char *)(remoteStream->zrtphash))); + if (retval != 0) + lError() << "Zrtp hash mismatch 0x" << hex << retval; + } + } + } + } +} + +void MediaSessionPrivate::startStreams (CallSession::State targetState) { + L_Q(); + switch (targetState) { + case CallSession::State::IncomingEarlyMedia: + if (listener) + listener->onRingbackToneRequested(q->getSharedFromThis(), true); + BCTBX_NO_BREAK; + case CallSession::State::OutgoingEarlyMedia: + if (!getParams()->earlyMediaSendingEnabled()) + allMuted = true; + break; + default: + if (listener) + listener->onRingbackToneRequested(q->getSharedFromThis(), false); + allMuted = false; + break; + } + + getCurrentParams()->getPrivate()->setUsedAudioCodec(nullptr); + getCurrentParams()->getPrivate()->setUsedVideoCodec(nullptr); + getCurrentParams()->getPrivate()->setUsedRealtimeTextCodec(nullptr); + + if (!audioStream && !videoStream) { + lFatal() << "startStreams() called without prior init!"; + return; + } + if (iceAgent->hasSession()) { + /* If there is an ICE session when we are about to start streams, then ICE will conduct the media path checking and authentication properly. + * Symmetric RTP must be turned off */ + setSymmetricRtp(false); + } + + mediaStartCount++; + bool videoWillBeUsed = false; +#if defined(VIDEO_ENABLED) + const SalStreamDescription *vstream = sal_media_description_find_best_stream(resultDesc, SalVideo); + if (vstream && (vstream->dir != SalStreamInactive) && vstream->payloads) { + /* When video is used, do not make adaptive rate control on audio, it is stupid */ + videoWillBeUsed = true; + } +#endif + lInfo() << "startStreams() CallSession=[" << q << "] local upload_bandwidth=[" << linphone_core_get_upload_bandwidth(q->getCore()->getCCore()) + << "] kbit/s; local download_bandwidth=[" << linphone_core_get_download_bandwidth(q->getCore()->getCCore()) << "] kbit/s"; + getCurrentParams()->enableAudio(false); + if (audioStream) + startAudioStream(targetState, videoWillBeUsed); + else + lWarning() << "startStreams(): no audio stream!"; + getCurrentParams()->enableVideo(false); + if (videoStream) { + if (audioStream) + audio_stream_link_video(audioStream, videoStream); + startVideoStream(targetState); + } + /* The on-hold file is to be played once both audio and video are ready */ + if (!onHoldFile.empty() && !getParams()->getPrivate()->getInConference() && audioStream) { + MSFilter *player = audio_stream_open_remote_play(audioStream, onHoldFile.c_str()); + if (player) { + int pauseTime = 500; + ms_filter_call_method(player, MS_PLAYER_SET_LOOP, &pauseTime); + ms_filter_call_method_noarg(player, MS_PLAYER_START); + } + } + upBandwidth = linphone_core_get_upload_bandwidth(q->getCore()->getCCore()); + if (getParams()->realtimeTextEnabled()) + startTextStream(); + + setDtlsFingerprintOnAllStreams(); + if (!iceAgent->hasCompleted()) { + if (getParams()->getMediaEncryption() == LinphoneMediaEncryptionDTLS) { + getCurrentParams()->getPrivate()->setUpdateCallWhenIceCompleted(false); + lInfo() << "Disabling update call when ice completed on call [" << q << "]"; + } + iceAgent->startConnectivityChecks(); + } else { + /* Should not start dtls until ice is completed */ + startDtlsOnAllStreams(); + } +} + +void MediaSessionPrivate::startTextStream () { + L_Q(); + const SalStreamDescription *tstream = sal_media_description_find_best_stream(resultDesc, SalText); + if (tstream && (tstream->dir != SalStreamInactive) && (tstream->rtp_port != 0)) { + const char *rtpAddr = tstream->rtp_addr[0] != '\0' ? tstream->rtp_addr : resultDesc->addr; + const char *rtcpAddr = tstream->rtcp_addr[0] != '\0' ? tstream->rtcp_addr : resultDesc->addr; + const SalStreamDescription *localStreamDesc = sal_media_description_find_stream(localDesc, tstream->proto, SalText); + int usedPt = -1; + textProfile = makeProfile(resultDesc, tstream, &usedPt); + if (usedPt == -1) + lWarning() << "No text stream accepted"; + else { + getCurrentParams()->getPrivate()->setUsedRealtimeTextCodec(rtp_profile_get_payload(textProfile, usedPt)); + getCurrentParams()->enableRealtimeText(true); + if (sal_stream_description_has_srtp(tstream)) { + int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast(tstream->crypto_local_tag)); + if (cryptoIdx >= 0) { + ms_media_stream_sessions_set_srtp_recv_key_b64(&textStream->ms.sessions, tstream->crypto[0].algo, tstream->crypto[0].master_key); + ms_media_stream_sessions_set_srtp_send_key_b64(&textStream->ms.sessions, tstream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key); + } + } + configureRtpSessionForRtcpFb(tstream); + configureRtpSessionForRtcpXr(SalText); + rtp_session_enable_rtcp_mux(textStream->ms.sessions.rtp_session, tstream->rtcp_mux); + bool isMulticast = !!ms_is_multicast(rtpAddr); + if (isMulticast) + rtp_session_set_multicast_ttl(textStream->ms.sessions.rtp_session, tstream->ttl); + text_stream_start(textStream, textProfile, rtpAddr, tstream->rtp_port, rtcpAddr, + (linphone_core_rtcp_enabled(q->getCore()->getCCore()) && !isMulticast) ? (tstream->rtcp_port ? tstream->rtcp_port : tstream->rtp_port + 1) : 0, usedPt); + ms_filter_add_notify_callback(textStream->rttsink, realTimeTextCharacterReceived, this, false); + ms_media_stream_sessions_set_encryption_mandatory(&textStream->ms.sessions, isEncryptionMandatory()); + } + } else + lInfo() << "No valid text stream defined"; +} + +void MediaSessionPrivate::startVideoStream (CallSession::State targetState) { +#ifdef VIDEO_ENABLED + L_Q(); + bool reusedPreview = false; + /* Shutdown preview */ + MSFilter *source = nullptr; + if (q->getCore()->getCCore()->previewstream) { + if (q->getCore()->getCCore()->video_conf.reuse_preview_source) + source = video_preview_stop_reuse_source(q->getCore()->getCCore()->previewstream); + else + video_preview_stop(q->getCore()->getCCore()->previewstream); + q->getCore()->getCCore()->previewstream = nullptr; + } + const SalStreamDescription *vstream = sal_media_description_find_best_stream(resultDesc, SalVideo); + if (vstream && (vstream->dir != SalStreamInactive) && (vstream->rtp_port != 0)) { + int usedPt = -1; + videoProfile = makeProfile(resultDesc, vstream, &usedPt); + if (usedPt == -1) + lWarning() << "No video stream accepted"; + else { + getCurrentParams()->getPrivate()->setUsedVideoCodec(rtp_profile_get_payload(videoProfile, usedPt)); + getCurrentParams()->enableVideo(true); + rtp_session_enable_rtcp_mux(videoStream->ms.sessions.rtp_session, vstream->rtcp_mux); + media_stream_set_max_network_bitrate(&videoStream->ms, linphone_core_get_upload_bandwidth(q->getCore()->getCCore()) * 1000); + if (q->getCore()->getCCore()->video_conf.preview_vsize.width != 0) + video_stream_set_preview_size(videoStream, q->getCore()->getCCore()->video_conf.preview_vsize); + video_stream_set_fps(videoStream, linphone_core_get_preferred_framerate(q->getCore()->getCCore())); + if (lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "video", "nowebcam_uses_normal_fps", 0)) + videoStream->staticimage_webcam_fps_optimization = false; + const LinphoneVideoDefinition *vdef = linphone_core_get_preferred_video_definition(q->getCore()->getCCore()); + MSVideoSize vsize; + vsize.width = static_cast(linphone_video_definition_get_width(vdef)); + vsize.height = static_cast(linphone_video_definition_get_height(vdef)); + video_stream_set_sent_video_size(videoStream, vsize); + video_stream_enable_self_view(videoStream, q->getCore()->getCCore()->video_conf.selfview); + if (videoWindowId) + video_stream_set_native_window_id(videoStream, videoWindowId); + else if (q->getCore()->getCCore()->video_window_id) + video_stream_set_native_window_id(videoStream, q->getCore()->getCCore()->video_window_id); + if (q->getCore()->getCCore()->preview_window_id) + video_stream_set_native_preview_window_id(videoStream, q->getCore()->getCCore()->preview_window_id); + video_stream_use_preview_video_window(videoStream, q->getCore()->getCCore()->use_preview_window); + const char *rtpAddr = (vstream->rtp_addr[0] != '\0') ? vstream->rtp_addr : resultDesc->addr; + const char *rtcpAddr = (vstream->rtcp_addr[0] != '\0') ? vstream->rtcp_addr : resultDesc->addr; + bool isMulticast = !!ms_is_multicast(rtpAddr); + MediaStreamDir dir = MediaStreamSendRecv; + bool isActive = true; + if (isMulticast) { + if (vstream->multicast_role == SalMulticastReceiver) + dir = MediaStreamRecvOnly; + else + dir = MediaStreamSendOnly; + } else if ((vstream->dir == SalStreamSendOnly) && q->getCore()->getCCore()->video_conf.capture) + dir = MediaStreamSendOnly; + else if ((vstream->dir == SalStreamRecvOnly) && q->getCore()->getCCore()->video_conf.display) + dir = MediaStreamRecvOnly; + else if (vstream->dir == SalStreamSendRecv) { + if (q->getCore()->getCCore()->video_conf.display && q->getCore()->getCCore()->video_conf.capture) + dir = MediaStreamSendRecv; + else if (q->getCore()->getCCore()->video_conf.display) + dir = MediaStreamRecvOnly; + else + dir = MediaStreamSendOnly; + } else { + lWarning() << "Video stream is inactive"; + /* Either inactive or incompatible with local capabilities */ + isActive = false; + } + MSWebCam *cam = getVideoDevice(); + if (isActive) { + if (sal_stream_description_has_srtp(vstream)) { + const SalStreamDescription *localStreamDesc = sal_media_description_find_stream(localDesc, vstream->proto, SalVideo); + int cryptoIdx = findCryptoIndexFromTag(localStreamDesc->crypto, static_cast(vstream->crypto_local_tag)); + if (cryptoIdx >= 0) { + ms_media_stream_sessions_set_srtp_recv_key_b64(&videoStream->ms.sessions, vstream->crypto[0].algo, vstream->crypto[0].master_key); + ms_media_stream_sessions_set_srtp_send_key_b64(&videoStream->ms.sessions, vstream->crypto[0].algo, localStreamDesc->crypto[cryptoIdx].master_key); + } + } + configureRtpSessionForRtcpFb(vstream); + configureRtpSessionForRtcpXr(SalVideo); + configureAdaptiveRateControl(&videoStream->ms, getCurrentParams()->getUsedVideoCodec(), true); + log->video_enabled = true; + video_stream_set_direction(videoStream, dir); + lInfo() << "startVideoStream: device_rotation=" << q->getCore()->getCCore()->device_rotation; + video_stream_set_device_rotation(videoStream, q->getCore()->getCCore()->device_rotation); + video_stream_set_freeze_on_error(videoStream, !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "video", "freeze_on_error", 1)); + if (isMulticast) + rtp_session_set_multicast_ttl(videoStream->ms.sessions.rtp_session, vstream->ttl); + video_stream_use_video_preset(videoStream, lp_config_get_string(linphone_core_get_config(q->getCore()->getCCore()), "video", "preset", nullptr)); + if (q->getCore()->getCCore()->video_conf.reuse_preview_source && source) { + lInfo() << "video_stream_start_with_source kept: " << source; + video_stream_start_with_source(videoStream, videoProfile, rtpAddr, vstream->rtp_port, rtcpAddr, + linphone_core_rtcp_enabled(q->getCore()->getCCore()) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port + 1) : 0, + usedPt, -1, cam, source); + reusedPreview = true; + } else { + bool ok = true; + MSMediaStreamIO io = MS_MEDIA_STREAM_IO_INITIALIZER; + if (linphone_config_get_bool(linphone_core_get_config(q->getCore()->getCCore()), "video", "rtp_io", FALSE)) { + io.input.type = io.output.type = MSResourceRtp; + io.input.session = io.output.session = createVideoRtpIoSession(); + if (!io.input.session) { + ok = false; + lWarning() << "Cannot create video RTP IO session"; + } + } else { + io.input.type = MSResourceCamera; + io.input.camera = cam; + io.output.type = MSResourceDefault; + } + if (ok) { + video_stream_start_from_io(videoStream, videoProfile, rtpAddr, vstream->rtp_port, rtcpAddr, + (linphone_core_rtcp_enabled(q->getCore()->getCCore()) && !isMulticast) ? (vstream->rtcp_port ? vstream->rtcp_port : vstream->rtp_port + 1) : 0, + usedPt, &io); + } + } + ms_media_stream_sessions_set_encryption_mandatory(&videoStream->ms.sessions, isEncryptionMandatory()); + if (listener) + listener->onResetFirstVideoFrameDecoded(q->getSharedFromThis()); + /* Start ZRTP engine if needed : set here or remote have a zrtp-hash attribute */ + SalMediaDescription *remote = op->getRemoteMediaDescription(); + const SalStreamDescription *remoteStream = sal_media_description_find_best_stream(remote, SalVideo); + if ((getParams()->getMediaEncryption() == LinphoneMediaEncryptionZRTP) || (remoteStream->haveZrtpHash == 1)) { + /* Audio stream is already encrypted and video stream is active */ + if (media_stream_secured(&audioStream->ms) && (media_stream_get_state(&videoStream->ms) == MSStreamStarted)) { + video_stream_start_zrtp(videoStream); + if (remoteStream->haveZrtpHash == 1) { + int retval = ms_zrtp_setPeerHelloHash(videoStream->ms.sessions.zrtp_context, (uint8_t *)remoteStream->zrtphash, strlen((const char *)(remoteStream->zrtphash))); + if (retval != 0) + lError() << "Video stream ZRTP hash mismatch 0x" << hex << retval; + } + } + } + } + } + } else + lInfo() << "No valid video stream defined"; + if (!reusedPreview && source) { + /* Destroy not-reused source filter */ + lWarning() << "Video preview (" << source << ") not reused: destroying it"; + ms_filter_destroy(source); + } +#endif +} + +void MediaSessionPrivate::stopAudioStream () { + L_Q(); + if (audioStream) { + if (listener) + listener->onUpdateMediaInfoForReporting(q->getSharedFromThis(), LINPHONE_CALL_STATS_AUDIO); + media_stream_reclaim_sessions(&audioStream->ms, &sessions[mainAudioStreamIndex]); + if (audioStream->ec) { + char *stateStr = nullptr; + ms_filter_call_method(audioStream->ec, MS_ECHO_CANCELLER_GET_STATE_STRING, &stateStr); + if (stateStr) { + lInfo() << "Writing echo canceler state, " << (int)strlen(stateStr) << " bytes"; + lp_config_write_relative_file(linphone_core_get_config(q->getCore()->getCCore()), ecStateStore.c_str(), stateStr); + } + } + audio_stream_get_local_rtp_stats(audioStream, &log->local_stats); + fillLogStats(&audioStream->ms); + if (listener) + listener->onCallSessionConferenceStreamStopping(q->getSharedFromThis()); + ms_bandwidth_controller_remove_stream(q->getCore()->getCCore()->bw_controller, &audioStream->ms); + audio_stream_stop(audioStream); + updateRtpStats(audioStats, mainAudioStreamIndex); + audioStream = nullptr; + handleStreamEvents(mainAudioStreamIndex); + rtp_session_unregister_event_queue(sessions[mainAudioStreamIndex].rtp_session, audioStreamEvQueue); + ortp_ev_queue_flush(audioStreamEvQueue); + ortp_ev_queue_destroy(audioStreamEvQueue); + audioStreamEvQueue = nullptr; + + getCurrentParams()->getPrivate()->setUsedAudioCodec(nullptr); + } +} + +void MediaSessionPrivate::stopTextStream () { + L_Q(); + if (textStream) { + if (listener) + listener->onUpdateMediaInfoForReporting(q->getSharedFromThis(), LINPHONE_CALL_STATS_TEXT); + media_stream_reclaim_sessions(&textStream->ms, &sessions[mainTextStreamIndex]); + fillLogStats(&textStream->ms); + text_stream_stop(textStream); + updateRtpStats(textStats, mainTextStreamIndex); + textStream = nullptr; + handleStreamEvents(mainTextStreamIndex); + rtp_session_unregister_event_queue(sessions[mainTextStreamIndex].rtp_session, textStreamEvQueue); + ortp_ev_queue_flush(textStreamEvQueue); + ortp_ev_queue_destroy(textStreamEvQueue); + textStreamEvQueue = nullptr; + getCurrentParams()->getPrivate()->setUsedRealtimeTextCodec(nullptr); + } +} + +void MediaSessionPrivate::stopVideoStream () { +#ifdef VIDEO_ENABLED + L_Q(); + if (videoStream) { + if (listener) + listener->onUpdateMediaInfoForReporting(q->getSharedFromThis(), LINPHONE_CALL_STATS_VIDEO); + media_stream_reclaim_sessions(&videoStream->ms, &sessions[mainVideoStreamIndex]); + fillLogStats(&videoStream->ms); + ms_bandwidth_controller_remove_stream(q->getCore()->getCCore()->bw_controller, &videoStream->ms); + video_stream_stop(videoStream); + updateRtpStats(videoStats, mainVideoStreamIndex); + videoStream = nullptr; + handleStreamEvents(mainVideoStreamIndex); + rtp_session_unregister_event_queue(sessions[mainVideoStreamIndex].rtp_session, videoStreamEvQueue); + ortp_ev_queue_flush(videoStreamEvQueue); + ortp_ev_queue_destroy(videoStreamEvQueue); + videoStreamEvQueue = nullptr; + getCurrentParams()->getPrivate()->setUsedVideoCodec(nullptr); + } +#endif +} + +void MediaSessionPrivate::tryEarlyMediaForking (SalMediaDescription *md) { + L_Q(); + lInfo() << "Early media response received from another branch, checking if media can be forked to this new destination"; + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&resultDesc->streams[i])) + continue; + SalStreamDescription *refStream = &resultDesc->streams[i]; + SalStreamDescription *newStream = &md->streams[i]; + if ((refStream->type == newStream->type) && refStream->payloads && newStream->payloads) { + OrtpPayloadType *refpt = reinterpret_cast(refStream->payloads->data); + OrtpPayloadType *newpt = reinterpret_cast(newStream->payloads->data); + if ((strcmp(refpt->mime_type, newpt->mime_type) == 0) && (refpt->clock_rate == newpt->clock_rate) + && (payload_type_get_number(refpt) == payload_type_get_number(newpt))) { + MediaStream *ms = nullptr; + if (refStream->type == SalAudio) + ms = &audioStream->ms; + else if (refStream->type == SalVideo) + ms = &videoStream->ms; + if (ms) { + RtpSession *session = ms->sessions.rtp_session; + const char *rtpAddr = (newStream->rtp_addr[0] != '\0') ? newStream->rtp_addr : md->addr; + const char *rtcpAddr = (newStream->rtcp_addr[0] != '\0') ? newStream->rtcp_addr : md->addr; + if (ms_is_multicast(rtpAddr)) + lInfo() << "Multicast addr [" << rtpAddr << "/" << newStream->rtp_port << "] does not need auxiliary rtp's destination for CallSession [" << q << "]"; + else + rtp_session_add_aux_remote_addr_full(session, rtpAddr, newStream->rtp_port, rtcpAddr, newStream->rtcp_port); + } + } + } + } +} + +void MediaSessionPrivate::updateFrozenPayloads (SalMediaDescription *result) { + L_Q(); + for (int i = 0; i < result->nb_streams; i++) { + for (bctbx_list_t *elem = result->streams[i].payloads; elem != nullptr; elem = bctbx_list_next(elem)) { + OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(elem)); + if (PayloadTypeHandler::isPayloadTypeNumberAvailable(localDesc->streams[i].already_assigned_payloads, payload_type_get_number(pt), nullptr)) { + /* New codec, needs to be added to the list */ + localDesc->streams[i].already_assigned_payloads = bctbx_list_append(localDesc->streams[i].already_assigned_payloads, payload_type_clone(pt)); + lInfo() << "CallSession[" << q << "] : payload type " << payload_type_get_number(pt) << " " << pt->mime_type << "/" << pt->clock_rate + << " fmtp=" << L_C_TO_STRING(pt->recv_fmtp) << " added to frozen list"; + } + } + } +} + +void MediaSessionPrivate::updateStreams (SalMediaDescription *newMd, CallSession::State targetState) { + L_Q(); + if (!((state == CallSession::State::IncomingEarlyMedia) && linphone_core_get_ring_during_incoming_early_media(q->getCore()->getCCore()))) + linphone_core_stop_ringing(q->getCore()->getCCore()); + if (!newMd) { + lError() << "updateStreams() called with null media description"; + return; + } + updateBiggestDesc(localDesc); + sal_media_description_ref(newMd); + SalMediaDescription *oldMd = resultDesc; + resultDesc = newMd; + if ((audioStream && (audioStream->ms.state == MSStreamStarted)) || (videoStream && (videoStream->ms.state == MSStreamStarted))) { + clearEarlyMediaDestinations(); + + /* We already started media: check if we really need to restart it */ + int mdChanged = 0; + if (oldMd) { + mdChanged = mediaParametersChanged(oldMd, newMd); + /* Might not be mandatory to restart stream for each ice restart as it leads bad user experience, specially in video. See 0002495 for better background on this */ + if (mdChanged & (SAL_MEDIA_DESCRIPTION_CODEC_CHANGED + | SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED + | SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED + | SAL_MEDIA_DESCRIPTION_ICE_RESTART_DETECTED + | SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION)) + lInfo() << "Media descriptions are different, need to restart the streams"; + else if (listener && listener->isPlayingRingbackTone(q->getSharedFromThis())) + lInfo() << "Playing ringback tone, will restart the streams"; + else { + if (allMuted && (targetState == CallSession::State::StreamsRunning)) { + lInfo() << "Early media finished, unmuting inputs..."; + /* We were in early media, now we want to enable real media */ + allMuted = false; + if (audioStream) + linphone_core_enable_mic(q->getCore()->getCCore(), linphone_core_mic_enabled(q->getCore()->getCCore())); +#ifdef VIDEO_ENABLED + if (videoStream && cameraEnabled) + q->enableCamera(q->cameraEnabled()); +#endif + } + if (mdChanged == SAL_MEDIA_DESCRIPTION_UNCHANGED) { + /* FIXME ZRTP, might be restarted in any cases? */ + lInfo() << "No need to restart streams, SDP is unchanged"; + if (oldMd) + sal_media_description_unref(oldMd); + return; + } else { + if (mdChanged & SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED) { + lInfo() << "Network parameters have changed, update them"; + updateStreamsDestinations(oldMd, newMd); + } + if (mdChanged & SAL_MEDIA_DESCRIPTION_CRYPTO_KEYS_CHANGED) { + lInfo() << "Crypto parameters have changed, update them"; + updateCryptoParameters(oldMd, newMd); + } + if (oldMd) + sal_media_description_unref(oldMd); + return; + } + } + } + stopStreams(); + if (mdChanged & SAL_MEDIA_DESCRIPTION_NETWORK_XXXCAST_CHANGED) { + lInfo() << "Media ip type has changed, destroying sessions context on CallSession [" << q << "]"; + ms_media_stream_sessions_uninit(&sessions[mainAudioStreamIndex]); + ms_media_stream_sessions_uninit(&sessions[mainVideoStreamIndex]); + ms_media_stream_sessions_uninit(&sessions[mainTextStreamIndex]); + } + initializeStreams(); + } + + if (!audioStream) { + /* This happens after pausing the call locally. The streams are destroyed and then we wait the 200Ok to recreate them */ + initializeStreams(); + } + + if (getParams()->earlyMediaSendingEnabled() && (state == CallSession::State::OutgoingEarlyMedia)) + prepareEarlyMediaForking(); + startStreams(targetState); + if ((state == CallSession::State::Pausing) && pausedByApp && (q->getCore()->getCallCount() == 1)) + linphone_core_play_named_tone(q->getCore()->getCCore(), LinphoneToneCallOnHold); + updateFrozenPayloads(newMd); + + if (oldMd) + sal_media_description_unref(oldMd); +} + +void MediaSessionPrivate::updateStreamsDestinations (SalMediaDescription *oldMd, SalMediaDescription *newMd) { + SalStreamDescription *newAudioDesc = nullptr; + + #ifdef VIDEO_ENABLED + SalStreamDescription *newVideoDesc = nullptr; + #endif + + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&newMd->streams[i])) + continue; + if (newMd->streams[i].type == SalAudio) + newAudioDesc = &newMd->streams[i]; + + #ifdef VIDEO_ENABLED + else if (newMd->streams[i].type == SalVideo) + newVideoDesc = &newMd->streams[i]; + #endif + } + if (audioStream && newAudioDesc) { + const char *rtpAddr = (newAudioDesc->rtp_addr[0] != '\0') ? newAudioDesc->rtp_addr : newMd->addr; + const char *rtcpAddr = (newAudioDesc->rtcp_addr[0] != '\0') ? newAudioDesc->rtcp_addr : newMd->addr; + lInfo() << "Change audio stream destination: RTP=" << rtpAddr << ":" << newAudioDesc->rtp_port << " RTCP=" << rtcpAddr << ":" << newAudioDesc->rtcp_port; + rtp_session_set_remote_addr_full(audioStream->ms.sessions.rtp_session, rtpAddr, newAudioDesc->rtp_port, rtcpAddr, newAudioDesc->rtcp_port); + } +#ifdef VIDEO_ENABLED + if (videoStream && newVideoDesc) { + const char *rtpAddr = (newVideoDesc->rtp_addr[0] != '\0') ? newVideoDesc->rtp_addr : newMd->addr; + const char *rtcpAddr = (newVideoDesc->rtcp_addr[0] != '\0') ? newVideoDesc->rtcp_addr : newMd->addr; + lInfo() << "Change video stream destination: RTP=" << rtpAddr << ":" << newVideoDesc->rtp_port << " RTCP=" << rtcpAddr << ":" << newVideoDesc->rtcp_port; + rtp_session_set_remote_addr_full(videoStream->ms.sessions.rtp_session, rtpAddr, newVideoDesc->rtp_port, rtcpAddr, newVideoDesc->rtcp_port); + } +#endif +} + +// ----------------------------------------------------------------------------- + +bool MediaSessionPrivate::allStreamsAvpfEnabled () const { + int nbActiveStreams = 0; + int nbAvpfEnabledStreams = 0; + if (audioStream && media_stream_get_state(&audioStream->ms) == MSStreamStarted) { + nbActiveStreams++; + if (media_stream_avpf_enabled(&audioStream->ms)) + nbAvpfEnabledStreams++; + } + if (videoStream && media_stream_get_state(&videoStream->ms) == MSStreamStarted) { + nbActiveStreams++; + if (media_stream_avpf_enabled(&videoStream->ms)) + nbAvpfEnabledStreams++; + } + return (nbActiveStreams > 0) && (nbActiveStreams == nbAvpfEnabledStreams); +} + +bool MediaSessionPrivate::allStreamsEncrypted () const { + int numberOfEncryptedStreams = 0; + int numberOfActiveStreams = 0; + if (audioStream && (media_stream_get_state(&audioStream->ms) == MSStreamStarted)) { + numberOfActiveStreams++; + if (media_stream_secured(&audioStream->ms)) + numberOfEncryptedStreams++; + } + if (videoStream && (media_stream_get_state(&videoStream->ms) == MSStreamStarted)) { + numberOfActiveStreams++; + if (media_stream_secured(&videoStream->ms)) + numberOfEncryptedStreams++; + } + if (textStream && (media_stream_get_state(&textStream->ms) == MSStreamStarted)) { + numberOfActiveStreams++; + if (media_stream_secured(&textStream->ms)) + numberOfEncryptedStreams++; + } + return (numberOfActiveStreams > 0) && (numberOfActiveStreams == numberOfEncryptedStreams); +} + +bool MediaSessionPrivate::atLeastOneStreamStarted () const { + return (audioStream && (media_stream_get_state(&audioStream->ms) == MSStreamStarted)) + || (videoStream && (media_stream_get_state(&videoStream->ms) == MSStreamStarted)) + || (textStream && (media_stream_get_state(&textStream->ms) == MSStreamStarted)); +} + +void MediaSessionPrivate::audioStreamAuthTokenReady (const string &authToken, bool verified) { + this->authToken = authToken; + authTokenVerified = verified; + lInfo() << "Authentication token is " << authToken << "(" << (verified ? "verified" : "unverified") << ")"; +} + +void MediaSessionPrivate::audioStreamEncryptionChanged (bool encrypted) { + propagateEncryptionChanged(); + + #ifdef VIDEO_ENABLED + L_Q(); + /* Enable video encryption */ + if ((getParams()->getMediaEncryption() == LinphoneMediaEncryptionZRTP) && q->getCurrentParams()->videoEnabled()) { + lInfo() << "Trying to start ZRTP encryption on video stream"; + video_stream_start_zrtp(videoStream); + } + #endif +} + +uint16_t MediaSessionPrivate::getAvpfRrInterval () const { + uint16_t rrInterval = 0; + if (audioStream && (media_stream_get_state(&audioStream->ms) == MSStreamStarted)) { + uint16_t streamRrInterval = media_stream_get_avpf_rr_interval(&audioStream->ms); + if (streamRrInterval > rrInterval) rrInterval = streamRrInterval; + } + if (videoStream && (media_stream_get_state(&videoStream->ms) == MSStreamStarted)) { + uint16_t streamRrInterval = media_stream_get_avpf_rr_interval(&videoStream->ms); + if (streamRrInterval > rrInterval) rrInterval = streamRrInterval; + } + return rrInterval; +} + +unsigned int MediaSessionPrivate::getNbActiveStreams () const { + SalMediaDescription *md = nullptr; + if (op) + md = op->getRemoteMediaDescription(); + if (!md) + return 0; + return sal_media_description_nb_active_streams_of_type(md, SalAudio) + sal_media_description_nb_active_streams_of_type(md, SalVideo) + sal_media_description_nb_active_streams_of_type(md, SalText); +} + +bool MediaSessionPrivate::isEncryptionMandatory () const { + L_Q(); + if (getParams()->getMediaEncryption() == LinphoneMediaEncryptionDTLS) { + lInfo() << "Forced encryption mandatory on CallSession [" << q << "] due to SRTP-DTLS"; + return true; + } + return getParams()->mandatoryMediaEncryptionEnabled(); +} + +int MediaSessionPrivate::mediaParametersChanged (SalMediaDescription *oldMd, SalMediaDescription *newMd) { + L_Q(); + if (getParams()->getPrivate()->getInConference() != getCurrentParams()->getPrivate()->getInConference()) + return SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION; + if (upBandwidth != linphone_core_get_upload_bandwidth(q->getCore()->getCCore())) + return SAL_MEDIA_DESCRIPTION_FORCE_STREAM_RECONSTRUCTION; + if (localDescChanged) { + char *differences = sal_media_description_print_differences(localDescChanged); + lInfo() << "Local description has changed: " << differences; + ms_free(differences); + } + int otherDescChanged = sal_media_description_equals(oldMd, newMd); + if (otherDescChanged) { + char *differences = sal_media_description_print_differences(otherDescChanged); + lInfo() << "Other description has changed: " << differences; + ms_free(differences); + } + return localDescChanged | otherDescChanged; +} + +void MediaSessionPrivate::propagateEncryptionChanged () { + L_Q(); + if (!allStreamsEncrypted()) { + lInfo() << "Some streams are not encrypted"; + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionNone); + if (listener) + listener->onEncryptionChanged(q->getSharedFromThis(), false, authToken); + } else { + if (!authToken.empty()) { + /* ZRTP only is using auth_token */ + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionZRTP); + } else { + /* Otherwise it must be DTLS as SDES doesn't go through this function */ + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionDTLS); + } + lInfo() << "All streams are encrypted, key exchanged using " + << ((q->getCurrentParams()->getMediaEncryption() == LinphoneMediaEncryptionZRTP) ? "ZRTP" + : (q->getCurrentParams()->getMediaEncryption() == LinphoneMediaEncryptionDTLS) ? "DTLS" : "Unknown mechanism"); + if (listener) + listener->onEncryptionChanged(q->getSharedFromThis(), true, authToken); +#ifdef VIDEO_ENABLED + if (isEncryptionMandatory() && videoStream && media_stream_started(&videoStream->ms)) { + /* Nothing could have been sent yet so generating key frame */ + video_stream_send_vfu(videoStream); + } +#endif + } +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::fillLogStats (MediaStream *st) { + float quality = media_stream_get_average_quality_rating(st); + if (quality >= 0) { + if (static_cast(log->quality) == -1) + log->quality = quality; + else + log->quality *= quality / 5.0f; + } +} + +void MediaSessionPrivate::updateRtpStats (LinphoneCallStats *stats, int streamIndex) { + if (sessions[streamIndex].rtp_session) { + const rtp_stats_t *rtpStats = rtp_session_get_stats(sessions[streamIndex].rtp_session); + if (rtpStats) + _linphone_call_stats_set_rtp_stats(stats, rtpStats); + } +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::executeBackgroundTasks (bool oneSecondElapsed) { + L_Q(); + switch (state) { + case CallSession::State::StreamsRunning: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::PausedByRemote: + case CallSession::State::Paused: + if (oneSecondElapsed) { + float audioLoad = 0.f; + float videoLoad = 0.f; + float textLoad = 0.f; + if (audioStream && audioStream->ms.sessions.ticker) + audioLoad = ms_ticker_get_average_load(audioStream->ms.sessions.ticker); + if (videoStream && videoStream->ms.sessions.ticker) + videoLoad = ms_ticker_get_average_load(videoStream->ms.sessions.ticker); + if (textStream && textStream->ms.sessions.ticker) + textLoad = ms_ticker_get_average_load(textStream->ms.sessions.ticker); + reportBandwidth(); + lInfo() << "Thread processing load: audio=" << audioLoad << "\tvideo=" << videoLoad << "\ttext=" << textLoad; + } + break; + default: + /* No stats for other states */ + break; + } + + handleStreamEvents(mainAudioStreamIndex); + handleStreamEvents(mainVideoStreamIndex); + handleStreamEvents(mainTextStreamIndex); + + if (listener) + listener->onNoMediaTimeoutCheck(q->getSharedFromThis(), oneSecondElapsed); +} + +void MediaSessionPrivate::reportBandwidth () { + L_Q(); + reportBandwidthForStream(&audioStream->ms, LinphoneStreamTypeAudio); + reportBandwidthForStream(&videoStream->ms, LinphoneStreamTypeVideo); + reportBandwidthForStream(&textStream->ms, LinphoneStreamTypeText); + + lInfo() << "Bandwidth usage for CallSession [" << q << "]:\n" << fixed << setprecision(2) << + "\tRTP audio=[d=" << linphone_call_stats_get_download_bandwidth(audioStats) << ",u=" << linphone_call_stats_get_upload_bandwidth(audioStats) << + "], video=[d=" << linphone_call_stats_get_download_bandwidth(videoStats) << ",u=" << linphone_call_stats_get_upload_bandwidth(videoStats) << ",ed=" << linphone_call_stats_get_estimated_download_bandwidth(videoStats) << + "], text=[d=" << linphone_call_stats_get_download_bandwidth(textStats) << ",u=" << linphone_call_stats_get_upload_bandwidth(textStats) << "] kbits/sec\n" << + "\tRTCP audio=[d=" << linphone_call_stats_get_rtcp_download_bandwidth(audioStats) << ",u=" << linphone_call_stats_get_rtcp_upload_bandwidth(audioStats) << + "], video=[d=" << linphone_call_stats_get_rtcp_download_bandwidth(videoStats) << ",u=" << linphone_call_stats_get_rtcp_upload_bandwidth(videoStats) << + "], text=[d=" << linphone_call_stats_get_rtcp_download_bandwidth(textStats) << ",u=" << linphone_call_stats_get_rtcp_upload_bandwidth(textStats) << "] kbits/sec"; +} + +void MediaSessionPrivate::reportBandwidthForStream (MediaStream *ms, LinphoneStreamType type) { + L_Q(); + LinphoneCallStats *stats = nullptr; + if (type == LinphoneStreamTypeAudio) { + stats = audioStats; + } else if (type == LinphoneStreamTypeVideo) { + stats = videoStats; + } else if (type == LinphoneStreamTypeText) { + stats = textStats; + } else + return; + + bool active = ms ? (media_stream_get_state(ms) == MSStreamStarted) : false; + _linphone_call_stats_set_download_bandwidth(stats, active ? (float)(media_stream_get_down_bw(ms) * 1e-3) : 0.f); + _linphone_call_stats_set_upload_bandwidth(stats, active ? (float)(media_stream_get_up_bw(ms) * 1e-3) : 0.f); + _linphone_call_stats_set_rtcp_download_bandwidth(stats, active ? (float)(media_stream_get_rtcp_down_bw(ms) * 1e-3) : 0.f); + _linphone_call_stats_set_rtcp_upload_bandwidth(stats, active ? (float)(media_stream_get_rtcp_up_bw(ms) * 1e-3) : 0.f); + _linphone_call_stats_set_ip_family_of_remote(stats, + active ? (ortp_stream_is_ipv6(&ms->sessions.rtp_session->rtp.gs) ? LinphoneAddressFamilyInet6 : LinphoneAddressFamilyInet) : LinphoneAddressFamilyUnspec); + + if (q->getCore()->getCCore()->send_call_stats_periodical_updates) { + if (active) + linphone_call_stats_update(stats, ms); + _linphone_call_stats_set_updated(stats, _linphone_call_stats_get_updated(stats) | LINPHONE_CALL_STATS_PERIODICAL_UPDATE); + if (listener) + listener->onStatsUpdated(q->getSharedFromThis(), stats); + _linphone_call_stats_set_updated(stats, 0); + } +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::abort (const string &errorMsg) { + L_Q(); + if (listener) + listener->onStopRinging(q->getSharedFromThis()); + stopStreams(); + CallSessionPrivate::abort(errorMsg); +} + +void MediaSessionPrivate::handleIncomingReceivedStateInIncomingNotification () { + L_Q(); + /* Try to be best-effort in giving real local or routable contact address for 100Rel case */ + setContactOp(); + bool proposeEarlyMedia = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "incoming_calls_early_media", false); + if (proposeEarlyMedia) + q->acceptEarlyMedia(); + else + op->notifyRinging(false); + if (op->getReplaces() && !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "auto_answer_replacing_calls", 1)) + q->accept(); +} + +bool MediaSessionPrivate::isReadyForInvite () const { + bool callSessionReady = CallSessionPrivate::isReadyForInvite(); + bool iceReady = false; + if (iceAgent->hasSession()) { + if (iceAgent->candidatesGathered()) + iceReady = true; + } else + iceReady = true; + return callSessionReady && iceReady; +} + +LinphoneStatus MediaSessionPrivate::pause () { + L_Q(); + if ((state != CallSession::State::StreamsRunning) && (state != CallSession::State::PausedByRemote)) { + lWarning() << "Cannot pause this MediaSession, it is not active"; + return -1; + } + string subject; + if (sal_media_description_has_dir(resultDesc, SalStreamSendRecv)) + subject = "Call on hold"; + else if (sal_media_description_has_dir(resultDesc, SalStreamRecvOnly)) + subject = "Call on hold for me too"; + else { + lError() << "No reason to pause this call, it is already paused or inactive"; + return -1; + } + broken = false; + setState(CallSession::State::Pausing, "Pausing call"); + makeLocalMediaDescription(); + op->setLocalMediaDescription(localDesc); + op->update(subject.c_str(), false); + if (listener) + listener->onResetCurrentSession(q->getSharedFromThis()); + if (audioStream || videoStream || textStream) + stopStreams(); + pausedByApp = false; + return 0; +} + +int MediaSessionPrivate::restartInvite () { + stopStreams(); + initializeStreams(); + return CallSessionPrivate::restartInvite(); +} + +void MediaSessionPrivate::setTerminated () { + freeResources(); + CallSessionPrivate::setTerminated(); +} + +LinphoneStatus MediaSessionPrivate::startAcceptUpdate (CallSession::State nextState, const string &stateInfo) { + if (iceAgent->hasSession() && (iceAgent->getNbLosingPairs() > 0)) { + /* Defer the sending of the answer until there are no losing pairs left */ + return 0; + } + makeLocalMediaDescription(); + updateRemoteSessionIdAndVer(); + op->setLocalMediaDescription(localDesc); + op->accept(); + SalMediaDescription *md = op->getFinalMediaDescription(); + iceAgent->stopIceForInactiveStreams(md); + if (md && !sal_media_description_empty(md)) + updateStreams(md, nextState); + setState(nextState, stateInfo); + return 0; +} + +LinphoneStatus MediaSessionPrivate::startUpdate (const string &subject) { + L_Q(); + fillMulticastMediaAddresses(); + if (!getParams()->getPrivate()->getNoUserConsent()) + makeLocalMediaDescription(); + if (!q->getCore()->getCCore()->sip_conf.sdp_200_ack) + op->setLocalMediaDescription(localDesc); + else + op->setLocalMediaDescription(nullptr); + LinphoneStatus result = CallSessionPrivate::startUpdate(subject); + if (q->getCore()->getCCore()->sip_conf.sdp_200_ack) { + /* We are NOT offering, set local media description after sending the call so that we are ready to + * process the remote offer when it will arrive. */ + op->setLocalMediaDescription(localDesc); + } + return result; +} + +void MediaSessionPrivate::terminate () { + L_Q(); + if (listener) + listener->onStopRingingIfNeeded(q->getSharedFromThis()); + + stopStreams(); + CallSessionPrivate::terminate(); +} + +void MediaSessionPrivate::updateCurrentParams () const { + CallSessionPrivate::updateCurrentParams(); + + LinphoneVideoDefinition *vdef = linphone_video_definition_new(MS_VIDEO_SIZE_UNKNOWN_W, MS_VIDEO_SIZE_UNKNOWN_H, nullptr); + getCurrentParams()->getPrivate()->setSentVideoDefinition(vdef); + getCurrentParams()->getPrivate()->setReceivedVideoDefinition(vdef); + linphone_video_definition_unref(vdef); +#ifdef VIDEO_ENABLED + if (videoStream) { + MSVideoSize vsize = video_stream_get_sent_video_size(videoStream); + vdef = linphone_video_definition_new(static_cast(vsize.width), static_cast(vsize.height), nullptr); + getCurrentParams()->getPrivate()->setSentVideoDefinition(vdef); + linphone_video_definition_unref(vdef); + vsize = video_stream_get_received_video_size(videoStream); + vdef = linphone_video_definition_new(static_cast(vsize.width), static_cast(vsize.height), nullptr); + getCurrentParams()->getPrivate()->setReceivedVideoDefinition(vdef); + linphone_video_definition_unref(vdef); + getCurrentParams()->getPrivate()->setSentFps(video_stream_get_sent_framerate(videoStream)); + getCurrentParams()->getPrivate()->setReceivedFps(video_stream_get_received_framerate(videoStream)); + } +#endif + + /* REVISITED + * Previous code was buggy. + * Relying on the mediastream's state (added by jehan: only) to know the current encryption is unreliable. + * For (added by jehan: both DTLS and) ZRTP it is though necessary. + * But for all others the current_params->media_encryption state should reflect (added by jehan: both) what is agreed by the offer/answer + * mechanism (added by jehan: and encryption status from media which is much stronger than only result of offer/answer ) + * Typically there can be inactive streams for which the media layer has no idea of whether they are encrypted or not. + */ + + switch (getParams()->getMediaEncryption()) { + case LinphoneMediaEncryptionZRTP: + if (atLeastOneStreamStarted()) { + if (allStreamsEncrypted() && !authToken.empty()) + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionZRTP); + else { + /* To avoid too many traces */ + lDebug() << "Encryption was requested to be " << linphone_media_encryption_to_string(getParams()->getMediaEncryption()) + << ", but isn't effective (allStreamsEncrypted=" << allStreamsEncrypted() << ", auth_token=" << authToken << ")"; + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionNone); + } + } /* else don't update the state if all streams are shutdown */ + break; + case LinphoneMediaEncryptionDTLS: + case LinphoneMediaEncryptionSRTP: + if (atLeastOneStreamStarted()) { + if ((getNbActiveStreams() == 0) || allStreamsEncrypted()) + getCurrentParams()->setMediaEncryption(getParams()->getMediaEncryption()); + else { + /* To avoid to many traces */ + lDebug() << "Encryption was requested to be " << linphone_media_encryption_to_string(getParams()->getMediaEncryption()) + << ", but isn't effective (allStreamsEncrypted=" << allStreamsEncrypted() << ")"; + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionNone); + } + } /* else don't update the state if all streams are shutdown */ + break; + case LinphoneMediaEncryptionNone: + /* Check if we actually switched to ZRTP */ + if (atLeastOneStreamStarted() && allStreamsEncrypted() && !authToken.empty()) + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionZRTP); + else + getCurrentParams()->setMediaEncryption(LinphoneMediaEncryptionNone); + break; + } + SalMediaDescription *md = resultDesc; + getCurrentParams()->enableAvpf(allStreamsAvpfEnabled() && sal_media_description_has_avpf(md)); + if (getCurrentParams()->avpfEnabled()) + getCurrentParams()->setAvpfRrInterval(getAvpfRrInterval()); + else + getCurrentParams()->setAvpfRrInterval(0); + if (md) { + SalStreamDescription *sd = sal_media_description_find_best_stream(md, SalAudio); + getCurrentParams()->setAudioDirection(sd ? MediaSessionParamsPrivate::salStreamDirToMediaDirection(sd->dir) : LinphoneMediaDirectionInactive); + if (getCurrentParams()->getAudioDirection() != LinphoneMediaDirectionInactive) { + const char *rtpAddr = (sd->rtp_addr[0] != '\0') ? sd->rtp_addr : md->addr; + getCurrentParams()->enableAudioMulticast(!!ms_is_multicast(rtpAddr)); + } else + getCurrentParams()->enableAudioMulticast(false); + sd = sal_media_description_find_best_stream(md, SalVideo); + getCurrentParams()->getPrivate()->enableImplicitRtcpFb(sd && sal_stream_description_has_implicit_avpf(sd)); + getCurrentParams()->setVideoDirection(sd ? MediaSessionParamsPrivate::salStreamDirToMediaDirection(sd->dir) : LinphoneMediaDirectionInactive); + if (getCurrentParams()->getVideoDirection() != LinphoneMediaDirectionInactive) { + const char *rtpAddr = (sd->rtp_addr[0] != '\0') ? sd->rtp_addr : md->addr; + getCurrentParams()->enableVideoMulticast(!!ms_is_multicast(rtpAddr)); + } else + getCurrentParams()->enableVideoMulticast(false); + } +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::accept (const MediaSessionParams *msp, bool wasRinging) { + L_Q(); + if (msp) { + setParams(new MediaSessionParams(*msp)); + iceAgent->prepare(localDesc, true, false /*we don't allow gathering now, it must have been done before*/); + makeLocalMediaDescription(); + op->setLocalMediaDescription(localDesc); + } + + updateRemoteSessionIdAndVer(); + + /* Give a chance a set card prefered sampling frequency */ + if (localDesc->streams[0].max_rate > 0) { + lInfo() << "Configuring prefered card sampling rate to [" << localDesc->streams[0].max_rate << "]"; + if (q->getCore()->getCCore()->sound_conf.play_sndcard) + ms_snd_card_set_preferred_sample_rate(q->getCore()->getCCore()->sound_conf.play_sndcard, localDesc->streams[0].max_rate); + if (q->getCore()->getCCore()->sound_conf.capt_sndcard) + ms_snd_card_set_preferred_sample_rate(q->getCore()->getCCore()->sound_conf.capt_sndcard, localDesc->streams[0].max_rate); + } + + LinphoneCore *lc = q->getCore()->getCCore(); + if (!wasRinging && (audioStream->ms.state == MSStreamInitialized) && !lc->use_files) { + audio_stream_prepare_sound(audioStream, lc->sound_conf.play_sndcard, lc->sound_conf.capt_sndcard); + } + + CallSessionPrivate::accept(nullptr); + + SalMediaDescription *newMd = op->getFinalMediaDescription(); + iceAgent->stopIceForInactiveStreams(newMd); + if (newMd) { + updateStreams(newMd, CallSession::State::StreamsRunning); + setState(CallSession::State::StreamsRunning, "Connected (streams running)"); + } else + expectMediaInAck = true; +} + +LinphoneStatus MediaSessionPrivate::acceptUpdate (const CallSessionParams *csp, CallSession::State nextState, const string &stateInfo) { + L_Q(); + SalMediaDescription *desc = op->getRemoteMediaDescription(); + bool keepSdpVersion = !!lp_config_get_int(linphone_core_get_config(q->getCore()->getCCore()), "sip", "keep_sdp_version", 0); + if (keepSdpVersion && (desc->session_id == remoteSessionId) && (desc->session_ver == remoteSessionVer)) { + /* Remote has sent an INVITE with the same SDP as before, so send a 200 OK with the same SDP as before. */ + lWarning() << "SDP version has not changed, send same SDP as before"; + op->accept(); + setState(nextState, stateInfo); + return 0; + } + if (csp) + setParams(new MediaSessionParams(*static_cast(csp))); + else { + if (!op->isOfferer()) { + /* Reset call params for multicast because this param is only relevant when offering */ + getParams()->enableAudioMulticast(false); + getParams()->enableVideoMulticast(false); + } + } + if (getParams()->videoEnabled() && !linphone_core_video_enabled(q->getCore()->getCCore())) { + lWarning() << "Requested video but video support is globally disabled. Refusing video"; + getParams()->enableVideo(false); + } + if (q->getCurrentParams()->getPrivate()->getInConference()) { + lWarning() << "Video isn't supported in conference"; + getParams()->enableVideo(false); + } + /* Update multicast params according to call params */ + fillMulticastMediaAddresses(); + iceAgent->checkSession(IR_Controlled, true); + initializeStreams(); /* So that video stream is initialized if necessary */ + if (iceAgent->prepare(localDesc, true)) + return 0; /* Deferred until completion of ICE gathering */ + startAcceptUpdate(nextState, stateInfo); + return 0; +} + +// ----------------------------------------------------------------------------- + +void MediaSessionPrivate::refreshSockets () { + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + MSMediaStreamSessions *mss = &sessions[i]; + if (mss->rtp_session) + rtp_session_refresh_sockets(mss->rtp_session); + } +} + +void MediaSessionPrivate::reinviteToRecoverFromConnectionLoss () { + L_Q(); + lInfo() << "MediaSession [" << q << "] is going to be updated (reINVITE) in order to recover from lost connectivity"; + if (iceAgent->hasSession()) + iceAgent->resetSession(IR_Controlling); + q->update(getParams()); +} + +void MediaSessionPrivate::repairByInviteWithReplaces () { + if ((state == CallSession::State::IncomingEarlyMedia) || (state == CallSession::State::OutgoingEarlyMedia)) { + stopStreams(); + initializeStreams(); + } + CallSessionPrivate::repairByInviteWithReplaces(); +} + +// ----------------------------------------------------------------------------- + +#ifdef VIDEO_ENABLED +void MediaSessionPrivate::videoStreamEventCb (const MSFilter *f, const unsigned int eventId, const void *args) { + L_Q(); + switch (eventId) { + case MS_VIDEO_DECODER_DECODING_ERRORS: + lWarning() << "MS_VIDEO_DECODER_DECODING_ERRORS"; + if (videoStream && video_stream_is_decoding_error_to_be_reported(videoStream, 5000)) { + video_stream_decoding_error_reported(videoStream); + q->sendVfuRequest(); + } + break; + case MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS: + lInfo() << "MS_VIDEO_DECODER_RECOVERED_FROM_ERRORS"; + if (videoStream) + video_stream_decoding_error_recovered(videoStream); + break; + case MS_VIDEO_DECODER_FIRST_IMAGE_DECODED: + lInfo() << "First video frame decoded successfully"; + if (listener) + listener->onFirstVideoFrameDecoded(q->getSharedFromThis()); + break; + case MS_VIDEO_DECODER_SEND_PLI: + case MS_VIDEO_DECODER_SEND_SLI: + case MS_VIDEO_DECODER_SEND_RPSI: + /* Handled internally by mediastreamer2 */ + break; + default: + lWarning() << "Unhandled event " << eventId; + break; + } +} +#endif + +void MediaSessionPrivate::realTimeTextCharacterReceived (MSFilter *f, unsigned int id, void *arg) { + L_Q(); + if (id == MS_RTT_4103_RECEIVED_CHAR) { + RealtimeTextReceivedCharacter *data = reinterpret_cast(arg); + if (listener) + listener->onRealTimeTextCharacterReceived(q->getSharedFromThis(), data); + } +} + +int MediaSessionPrivate::sendDtmf () { + L_Q(); + LinphoneCore *lc = q->getCore()->getCCore(); + // By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO + if (linphone_core_get_use_rfc2833_for_dtmf(lc) || !linphone_core_get_use_info_for_dtmf(lc)) { + // In Band DTMF + if (audioStream) + audio_stream_send_dtmf(audioStream, dtmfSequence.front()); + else { + lError() << "Cannot send RFC2833 DTMF when we are not in communication"; + return FALSE; + } + } + if (linphone_core_get_use_info_for_dtmf(lc)) { + // Out of Band DTMF (use INFO method) + op->sendDtmf(dtmfSequence.front()); + } + + dtmfSequence.erase(0, 1); + // Continue only if the dtmf sequence is not empty + if (!dtmfSequence.empty()) + return TRUE; + else { + q->cancelDtmfs(); + return FALSE; + } +} + +// ----------------------------------------------------------------------------- + +int MediaSessionPrivate::resumeAfterFailedTransfer (void *userData, unsigned int) { + MediaSession *session = reinterpret_cast(userData); + return session->getPrivate()->resumeAfterFailedTransfer(); +} + +bool_t MediaSessionPrivate::startPendingRefer (void *userData) { + MediaSession *session = reinterpret_cast(userData); + session->getPrivate()->startPendingRefer(); + return TRUE; +} + +void MediaSessionPrivate::stunAuthRequestedCb (const char *realm, const char *nonce, const char **username, const char **password, const char **ha1) { + L_Q(); + /* Get the username from the nat policy or the proxy config */ + LinphoneProxyConfig *proxy = nullptr; + if (destProxy) + proxy = destProxy; + else + proxy = linphone_core_get_default_proxy_config(q->getCore()->getCCore()); + if (!proxy) + return; + const char * user = nullptr; + LinphoneNatPolicy *proxyNatPolicy = linphone_proxy_config_get_nat_policy(proxy); + if (proxyNatPolicy) + user = linphone_nat_policy_get_stun_server_username(proxyNatPolicy); + else if (natPolicy) + user = linphone_nat_policy_get_stun_server_username(natPolicy); + if (!user) { + /* If the username has not been found in the nat_policy, take the username from the currently used proxy config */ + const LinphoneAddress *addr = linphone_proxy_config_get_identity_address(proxy); + if (!addr) + return; + user = linphone_address_get_username(addr); + } + if (!user) + return; + + const LinphoneAuthInfo *authInfo = linphone_core_find_auth_info(q->getCore()->getCCore(), realm, user, nullptr); + if (!authInfo) { + lWarning() << "No auth info found for STUN auth request"; + return; + } + const char *hash = linphone_auth_info_get_ha1(authInfo); + if (hash) + *ha1 = hash; + else + *password = linphone_auth_info_get_passwd(authInfo); + *username = user; +} + +// ============================================================================= + +MediaSession::MediaSession (const shared_ptr &core, shared_ptr me, const CallSessionParams *params, CallSessionListener *listener) + : CallSession(*new MediaSessionPrivate, core) { + L_D(); + d->me = me; + d->listener = listener; + + if (params) + d->setParams(new MediaSessionParams(*(reinterpret_cast(params)))); + else + d->setParams(new MediaSessionParams()); + d->setCurrentParams(new MediaSessionParams()); + + d->audioStats = _linphone_call_stats_new(); + d->initStats(d->audioStats, LinphoneStreamTypeAudio); + d->videoStats = _linphone_call_stats_new(); + d->initStats(d->videoStats, LinphoneStreamTypeVideo); + d->textStats = _linphone_call_stats_new(); + d->initStats(d->textStats, LinphoneStreamTypeText); + + int minPort, maxPort; + linphone_core_get_audio_port_range(getCore()->getCCore(), &minPort, &maxPort); + d->setPortConfig(d->mainAudioStreamIndex, make_pair(minPort, maxPort)); + linphone_core_get_video_port_range(getCore()->getCCore(), &minPort, &maxPort); + d->setPortConfig(d->mainVideoStreamIndex, make_pair(minPort, maxPort)); + linphone_core_get_text_port_range(getCore()->getCCore(), &minPort, &maxPort); + d->setPortConfig(d->mainTextStreamIndex, make_pair(minPort, maxPort)); + + memset(d->sessions, 0, sizeof(d->sessions)); + d->iceAgent = makeUnique(*this); + + lInfo() << "New MediaSession [" << this << "] initialized (LinphoneCore version: " << linphone_core_get_version() << ")"; +} + +MediaSession::~MediaSession () { + L_D(); + cancelDtmfs(); + if (d->audioStream || d->videoStream) + d->freeResources(); + if (d->audioStats) + linphone_call_stats_unref(d->audioStats); + if (d->videoStats) + linphone_call_stats_unref(d->videoStats); + if (d->textStats) + linphone_call_stats_unref(d->textStats); + if (d->natPolicy) + linphone_nat_policy_unref(d->natPolicy); + if (d->localDesc) + sal_media_description_unref(d->localDesc); + if (d->biggestDesc) + sal_media_description_unref(d->biggestDesc); + if (d->resultDesc) + sal_media_description_unref(d->resultDesc); +} + +// ----------------------------------------------------------------------------- + +LinphoneStatus MediaSession::accept (const MediaSessionParams *msp) { + L_D(); + LinphoneStatus result = d->checkForAcceptation(); + if (result < 0) return result; + + bool wasRinging = false; + if (d->listener) + wasRinging = d->listener->onCallSessionAccepted(getSharedFromThis()); + + d->accept(msp, wasRinging); + lInfo() << "CallSession accepted"; + return 0; +} + +LinphoneStatus MediaSession::acceptEarlyMedia (const MediaSessionParams *msp) { + L_D(); + if (d->state != CallSession::State::IncomingReceived) { + lError() << "Bad state " << Utils::toString(d->state) << " for MediaSession::acceptEarlyMedia()"; + return -1; + } + /* Try to be best-effort in giving real local or routable contact address for 100Rel case */ + d->setContactOp(); + /* If parameters are passed, update the media description */ + if (msp) { + d->setParams(new MediaSessionParams(*msp)); + d->makeLocalMediaDescription(); + d->op->setLocalMediaDescription(d->localDesc); + d->op->setSentCustomHeaders(d->getParams()->getPrivate()->getCustomHeaders()); + } + d->op->notifyRinging(true); + d->setState(CallSession::State::IncomingEarlyMedia, "Incoming call early media"); + SalMediaDescription *md = d->op->getFinalMediaDescription(); + if (md) + d->updateStreams(md, d->state); + return 0; +} + +LinphoneStatus MediaSession::acceptUpdate (const MediaSessionParams *msp) { + L_D(); + if (d->expectMediaInAck) { + lError() << "MediaSession::acceptUpdate() is not possible during a late offer incoming reINVITE (INVITE without SDP)"; + return -1; + } + return CallSession::acceptUpdate(msp); +} + +void MediaSession::cancelDtmfs () { + L_D(); + if (!d->dtmfTimer) + return; + + getCore()->getCCore()->sal->cancelTimer(d->dtmfTimer); + belle_sip_object_unref(d->dtmfTimer); + d->dtmfTimer = nullptr; + d->dtmfSequence.clear(); +} + +void MediaSession::configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) { + L_D(); + CallSession::configure (direction, cfg, op, from, to); + + if (d->destProxy) + d->natPolicy = linphone_proxy_config_get_nat_policy(d->destProxy); + if (!d->natPolicy) + d->natPolicy = linphone_core_get_nat_policy(getCore()->getCCore()); + linphone_nat_policy_ref(d->natPolicy); + + if (direction == LinphoneCallOutgoing) { + d->selectOutgoingIpVersion(); + d->getLocalIp(to); + d->initializeStreams(); // Reserve the sockets immediately + d->getCurrentParams()->getPrivate()->setUpdateCallWhenIceCompleted(d->getParams()->getPrivate()->getUpdateCallWhenIceCompleted()); + d->fillMulticastMediaAddresses(); + if (d->natPolicy && linphone_nat_policy_ice_enabled(d->natPolicy)) + d->iceAgent->checkSession(IR_Controlling, false); + d->runStunTestsIfNeeded(); + d->discoverMtu(to); + } else if (direction == LinphoneCallIncoming) { + d->selectIncomingIpVersion(); + /* Note that the choice of IP version for streams is later refined by setCompatibleIncomingCallParams() when examining the + * remote offer, if any. If the remote offer contains IPv4 addresses, we should propose IPv4 as well. */ + Address cleanedFrom = from; + cleanedFrom.clean(); + d->getLocalIp(cleanedFrom); + d->setParams(new MediaSessionParams()); + d->params->initDefault(getCore()); + d->initializeParamsAccordingToIncomingCallParams(); + SalMediaDescription *md = d->op->getRemoteMediaDescription(); + if (d->natPolicy && linphone_nat_policy_ice_enabled(d->natPolicy)) { + if (md) { + /* Create the ice session now if ICE is required */ + d->iceAgent->checkSession(IR_Controlled, false); + } else { + linphone_nat_policy_unref(d->natPolicy); + d->natPolicy = nullptr; + lWarning() << "ICE not supported for incoming INVITE without SDP"; + } + } + d->initializeStreams(); // Reserve the sockets immediately + if (d->natPolicy) + d->runStunTestsIfNeeded(); + d->discoverMtu(cleanedFrom); + } +} + +LinphoneStatus MediaSession::deferUpdate () { + L_D(); + if (d->state != CallSession::State::UpdatedByRemote) { + lError() << "MediaSession::deferUpdate() not done in state CallSession::State::UpdatedByRemote"; + return -1; + } + if (d->expectMediaInAck) { + lError() << "MediaSession::deferUpdate() is not possible during a late offer incoming reINVITE (INVITE without SDP)"; + return -1; + } + d->deferUpdate = true; + return 0; +} + +void MediaSession::initiateIncoming () { + L_D(); + CallSession::initiateIncoming(); + d->initializeStreams(); + if (d->natPolicy) { + if (linphone_nat_policy_ice_enabled(d->natPolicy)) + d->deferIncomingNotification = d->iceAgent->prepare(d->localDesc, true); + } +} + +bool MediaSession::initiateOutgoing () { + L_D(); + bool defer = CallSession::initiateOutgoing(); + d->initializeStreams(); + if (linphone_nat_policy_ice_enabled(d->natPolicy)) { + if (getCore()->getCCore()->sip_conf.sdp_200_ack) + lWarning() << "ICE is not supported when sending INVITE without SDP"; + else { + /* Defer the start of the call after the ICE gathering process */ + defer |= d->iceAgent->prepare(d->localDesc, false); + } + } + return defer; +} + +void MediaSession::iterate (time_t currentRealTime, bool oneSecondElapsed) { + L_D(); + d->executeBackgroundTasks(oneSecondElapsed); + CallSession::iterate(currentRealTime, oneSecondElapsed); +} + +LinphoneStatus MediaSession::pause () { + L_D(); + LinphoneStatus result = d->pause(); + if (result == 0) + d->pausedByApp = true; + return result; +} + +LinphoneStatus MediaSession::resume () { + L_D(); + if (d->state != CallSession::State::Paused) { + lWarning() << "we cannot resume a call that has not been established and paused before"; + return -1; + } + if (!d->getParams()->getPrivate()->getInConference()) { + if (linphone_core_sound_resources_locked(getCore()->getCCore())) { + lWarning() << "Cannot resume MediaSession " << this << " because another call is locking the sound resources"; + return -1; + } + linphone_core_preempt_sound_resources(getCore()->getCCore()); + lInfo() << "Resuming MediaSession " << this; + } + d->automaticallyPaused = false; + d->broken = false; + /* Stop playing music immediately. If remote side is a conference it + * prevents the participants to hear it while the 200OK comes back. */ + if (d->audioStream) + audio_stream_play(d->audioStream, nullptr); + d->makeLocalMediaDescription(); + sal_media_description_set_dir(d->localDesc, SalStreamSendRecv); + if (!getCore()->getCCore()->sip_conf.sdp_200_ack) + d->op->setLocalMediaDescription(d->localDesc); + else + d->op->setLocalMediaDescription(nullptr); + string subject = "Call resuming"; + if (d->getParams()->getPrivate()->getInConference() && !getCurrentParams()->getPrivate()->getInConference()) + subject = "Conference"; + if (d->op->update(subject.c_str(), false) != 0) + return -1; + d->setState(CallSession::State::Resuming,"Resuming"); + if (!d->getParams()->getPrivate()->getInConference() && d->listener) + d->listener->onSetCurrentSession(getSharedFromThis()); + if (getCore()->getCCore()->sip_conf.sdp_200_ack) { + /* We are NOT offering, set local media description after sending the call so that we are ready to + * process the remote offer when it will arrive. */ + d->op->setLocalMediaDescription(d->localDesc); + } + return 0; +} + +LinphoneStatus MediaSession::sendDtmf (char dtmf) { + L_D(); + d->dtmfSequence = dtmf; + d->sendDtmf(); + return 0; +} + +LinphoneStatus MediaSession::sendDtmfs (const std::string &dtmfs) { + L_D(); + if (d->dtmfTimer) { + lWarning() << "MediaSession::sendDtmfs(): a DTMF sequence is already in place, canceling DTMF sequence"; + return -2; + } + if (!dtmfs.empty()) { + int delayMs = lp_config_get_int(linphone_core_get_config(getCore()->getCCore()), "net", "dtmf_delay_ms", 200); + if (delayMs < 0) + delayMs = 0; + d->dtmfSequence = dtmfs; + d->dtmfTimer = getCore()->getCCore()->sal->createTimer(MediaSessionPrivate::sendDtmf, this, static_cast(delayMs), "DTMF sequence timer"); + } + return 0; +} + +void MediaSession::sendVfuRequest () { +#ifdef VIDEO_ENABLED + L_D(); + MediaSessionParams *curParams = getCurrentParams(); + + if ((curParams->avpfEnabled() || curParams->getPrivate()->implicitRtcpFbEnabled()) + && d->videoStream && media_stream_get_state(&d->videoStream->ms) == MSStreamStarted) { // || sal_media_description_has_implicit_avpf((const SalMediaDescription *)call->resultdesc) + lInfo() << "Request Full Intra Request on CallSession [" << this << "]"; + video_stream_send_fir(d->videoStream); + } else if (getCore()->getCCore()->sip_conf.vfu_with_info) { + lInfo() << "Request SIP INFO FIR on CallSession [" << this << "]"; + if (d->state == CallSession::State::StreamsRunning) + d->op->sendVfuRequest(); + } else + lInfo() << "vfu request using sip disabled from config [sip,vfu_with_info]"; +#endif +} + +void MediaSession::startIncomingNotification (bool notifyRinging) { + L_D(); + d->makeLocalMediaDescription(); + d->op->setLocalMediaDescription(d->localDesc); + SalMediaDescription *md = d->op->getFinalMediaDescription(); + if (md) { + if (sal_media_description_empty(md) || linphone_core_incompatible_security(getCore()->getCCore(), md)) { + LinphoneErrorInfo *ei = linphone_error_info_new(); + linphone_error_info_set(ei, nullptr, LinphoneReasonNotAcceptable, 488, "Not acceptable here", nullptr); + if (d->listener) + d->listener->onCallSessionEarlyFailed(getSharedFromThis(), ei); + d->op->decline(SalReasonNotAcceptable, nullptr); + return; + } + } + + CallSession::startIncomingNotification(notifyRinging); +} + +int MediaSession::startInvite (const Address *destination, const string &subject, const Content *content) { + L_D(); + linphone_core_stop_dtmf_stream(getCore()->getCCore()); + d->makeLocalMediaDescription(); + if (!getCore()->getCCore()->ringstream && getCore()->getCCore()->sound_conf.play_sndcard && getCore()->getCCore()->sound_conf.capt_sndcard) { + /* Give a chance to set card prefered sampling frequency */ + if (d->localDesc->streams[0].max_rate > 0) + ms_snd_card_set_preferred_sample_rate(getCore()->getCCore()->sound_conf.play_sndcard, d->localDesc->streams[0].max_rate); + if (!getCore()->getCCore()->use_files) + audio_stream_prepare_sound(d->audioStream, getCore()->getCCore()->sound_conf.play_sndcard, getCore()->getCCore()->sound_conf.capt_sndcard); + } + if (!getCore()->getCCore()->sip_conf.sdp_200_ack) { + /* We are offering, set local media description before sending the call */ + d->op->setLocalMediaDescription(d->localDesc); + } + + int result = CallSession::startInvite(destination, subject, content); + if (result < 0) { + if (d->state == CallSession::State::Error) + d->stopStreams(); + return result; + } + if (getCore()->getCCore()->sip_conf.sdp_200_ack) { + /* We are NOT offering, set local media description after sending the call so that we are ready to + process the remote offer when it will arrive. */ + d->op->setLocalMediaDescription(d->localDesc); + } + return result; +} + +void MediaSession::startRecording () { + L_D(); + if (d->getParams()->getRecordFilePath().empty()) { + lError() << "MediaSession::startRecording(): no output file specified. Use MediaSessionParams::setRecordFilePath()"; + return; + } + if (d->audioStream && !d->getParams()->getPrivate()->getInConference()) + audio_stream_mixed_record_start(d->audioStream); + d->recordActive = true; +} + +void MediaSession::stopRecording () { + L_D(); + if (d->audioStream && !d->getParams()->getPrivate()->getInConference()) + audio_stream_mixed_record_stop(d->audioStream); + d->recordActive = false; +} + +void MediaSession::terminateBecauseOfLostMedia () { + L_D(); + d->nonOpError = true; + linphone_error_info_set(d->ei, nullptr, LinphoneReasonIOError, 503, "Media lost", nullptr); + terminate(); +} + +LinphoneStatus MediaSession::update (const MediaSessionParams *msp, const string &subject) { + L_D(); + CallSession::State nextState; + CallSession::State initialState = d->state; + LinphoneStatus result = 0; + if (!d->isUpdateAllowed(nextState)) + return -1; + if (d->getCurrentParams() == msp) + lWarning() << "CallSession::update() is given the current params, this is probably not what you intend to do!"; + d->iceAgent->checkSession(IR_Controlling, true); + if (msp) { + d->broken = false; + d->setState(nextState, "Updating call"); + d->setParams(new MediaSessionParams(*msp)); + if (d->iceAgent->prepare(d->localDesc, false)) { + lInfo() << "Defer CallSession update to gather ICE candidates"; + return 0; + } + result = d->startUpdate(subject); + if (result && (d->state != initialState)) { + /* Restore initial state */ + d->setState(initialState, "Restore initial state"); + } + } else { +#ifdef VIDEO_ENABLED + if (d->videoStream && (d->state == CallSession::State::StreamsRunning)) { + const LinphoneVideoDefinition *vdef = linphone_core_get_preferred_video_definition(getCore()->getCCore()); + MSVideoSize vsize; + vsize.width = static_cast(linphone_video_definition_get_width(vdef)); + vsize.height = static_cast(linphone_video_definition_get_height(vdef)); + video_stream_set_sent_video_size(d->videoStream, vsize); + video_stream_set_fps(d->videoStream, linphone_core_get_preferred_framerate(getCore()->getCCore())); + if (d->cameraEnabled && (d->videoStream->cam != getCore()->getCCore()->video_conf.device)) + video_stream_change_camera(d->videoStream, getCore()->getCCore()->video_conf.device); + else + video_stream_update_video_params(d->videoStream); + } +#endif + } + return result; +} + +// ----------------------------------------------------------------------------- + +void MediaSession::requestNotifyNextVideoFrameDecoded () { + L_D(); + if (d->videoStream && d->videoStream->ms.decoder) + ms_filter_call_method_noarg(d->videoStream->ms.decoder, MS_VIDEO_DECODER_RESET_FIRST_IMAGE_NOTIFICATION); +} + +void MediaSessionPrivate::snapshotTakenCb(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { +#ifdef VIDEO_ENABLED + L_Q(); + if (id == MS_JPEG_WRITER_SNAPSHOT_TAKEN) { + const char *filepath = (const char *) arg; + listener->onSnapshotTaken(q->getSharedFromThis(), filepath); + } +#endif +} + +#ifdef VIDEO_ENABLED +static void snapshot_taken(void *userdata, struct _MSFilter *f, unsigned int id, void *arg) { + MediaSessionPrivate *d = (MediaSessionPrivate *)userdata; + d->snapshotTakenCb(userdata, f, id, arg); +} +#endif + +LinphoneStatus MediaSession::takePreviewSnapshot (const string& file) { +#ifdef VIDEO_ENABLED + L_D(); + if (d->videoStream && d->videoStream->local_jpegwriter) { + ms_filter_clear_notify_callback(d->videoStream->jpegwriter); + const char *filepath = file.empty() ? nullptr : file.c_str(); + ms_filter_add_notify_callback(d->videoStream->local_jpegwriter, snapshot_taken, d, TRUE); + return ms_filter_call_method(d->videoStream->local_jpegwriter, MS_JPEG_WRITER_TAKE_SNAPSHOT, (void *)filepath); + } + lWarning() << "Cannot take local snapshot: no currently running video stream on this call"; +#endif + return -1; +} + +LinphoneStatus MediaSession::takeVideoSnapshot (const string& file) { +#ifdef VIDEO_ENABLED + L_D(); + if (d->videoStream && d->videoStream->jpegwriter) { + ms_filter_clear_notify_callback(d->videoStream->jpegwriter); + const char *filepath = file.empty() ? nullptr : file.c_str(); + ms_filter_add_notify_callback(d->videoStream->jpegwriter, snapshot_taken, d, TRUE); + return ms_filter_call_method(d->videoStream->jpegwriter, MS_JPEG_WRITER_TAKE_SNAPSHOT, (void *)filepath); + } + lWarning() << "Cannot take snapshot: no currently running video stream on this call"; +#endif + return -1; +} + +void MediaSession::zoomVideo (float zoomFactor, float *cx, float *cy) { + zoomVideo(zoomFactor, *cx, *cy); +} + +void MediaSession::zoomVideo (float zoomFactor, float cx, float cy) { + L_D(); + if (d->videoStream && d->videoStream->output) { + if (zoomFactor < 1) + zoomFactor = 1; + float halfsize = 0.5f * 1.0f / zoomFactor; + if ((cx - halfsize) < 0) + cx = 0 + halfsize; + if ((cx + halfsize) > 1) + cx = 1 - halfsize; + if ((cy - halfsize) < 0) + cy = 0 + halfsize; + if ((cy + halfsize) > 1) + cy = 1 - halfsize; + float zoom[3] = { zoomFactor, cx, cy }; + ms_filter_call_method(d->videoStream->output, MS_VIDEO_DISPLAY_ZOOM, &zoom); + } else + lWarning() << "Could not apply zoom: video output wasn't activated"; +} + +// ----------------------------------------------------------------------------- + +bool MediaSession::cameraEnabled () const { + L_D(); + return d->cameraEnabled; +} + +bool MediaSession::echoCancellationEnabled () const { + L_D(); + if (!d->audioStream || !d->audioStream->ec) + return !!linphone_core_echo_cancellation_enabled(getCore()->getCCore()); + + bool val; + ms_filter_call_method(d->audioStream->ec, MS_ECHO_CANCELLER_GET_BYPASS_MODE, &val); + return !val; +} + +bool MediaSession::echoLimiterEnabled () const { + L_D(); + if (d->audioStream) + return d->audioStream->el_type !=ELInactive; + return !!linphone_core_echo_limiter_enabled(getCore()->getCCore()); +} + +void MediaSession::enableCamera (bool value) { +#ifdef VIDEO_ENABLED + L_D(); + d->cameraEnabled = value; + switch (d->state) { + case CallSession::State::StreamsRunning: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::Connected: + if (d->videoStream && video_stream_started(d->videoStream) && (video_stream_get_camera(d->videoStream) != d->getVideoDevice())) { + string currentCam = video_stream_get_camera(d->videoStream) ? ms_web_cam_get_name(video_stream_get_camera(d->videoStream)) : "NULL"; + string newCam = d->getVideoDevice() ? ms_web_cam_get_name(d->getVideoDevice()) : "NULL"; + lInfo() << "Switching video cam from [" << currentCam << "] to [" << newCam << "] on CallSession [" << this << "]"; + video_stream_change_camera(d->videoStream, d->getVideoDevice()); + } + break; + default: + break; + } +#endif +} + +void MediaSession::enableEchoCancellation (bool value) { + L_D(); + if (d->audioStream && d->audioStream->ec) { + bool bypassMode = !value; + ms_filter_call_method(d->audioStream->ec, MS_ECHO_CANCELLER_SET_BYPASS_MODE, &bypassMode); + } +} + +void MediaSession::enableEchoLimiter (bool value) { + L_D(); + if (d->audioStream) { + if (value) { + string type = lp_config_get_string(linphone_core_get_config(getCore()->getCCore()), "sound", "el_type", "mic"); + if (type == "mic") + audio_stream_enable_echo_limiter(d->audioStream, ELControlMic); + else if (type == "full") + audio_stream_enable_echo_limiter(d->audioStream, ELControlFull); + } else + audio_stream_enable_echo_limiter(d->audioStream, ELInactive); + } +} + +bool MediaSession::getAllMuted () const { + L_D(); + return d->allMuted; +} + +LinphoneCallStats * MediaSession::getAudioStats () const { + return getStats(LinphoneStreamTypeAudio); +} + +string MediaSession::getAuthenticationToken () const { + L_D(); + return d->authToken; +} + +bool MediaSession::getAuthenticationTokenVerified () const { + L_D(); + return d->authTokenVerified; +} + +float MediaSession::getAverageQuality () const { + L_D(); + float audioRating = -1.f; + float videoRating = -1.f; + if (d->audioStream) + audioRating = media_stream_get_average_quality_rating(&d->audioStream->ms) / 5.0f; + if (d->videoStream) + videoRating = media_stream_get_average_quality_rating(&d->videoStream->ms) / 5.0f; + return MediaSessionPrivate::aggregateQualityRatings(audioRating, videoRating); +} + +MediaSessionParams * MediaSession::getCurrentParams () const { + L_D(); + d->updateCurrentParams(); + return d->getCurrentParams(); +} + +float MediaSession::getCurrentQuality () const { + L_D(); + float audioRating = -1.f; + float videoRating = -1.f; + if (d->audioStream) + audioRating = media_stream_get_quality_rating(&d->audioStream->ms) / 5.0f; + if (d->videoStream) + videoRating = media_stream_get_quality_rating(&d->videoStream->ms) / 5.0f; + return MediaSessionPrivate::aggregateQualityRatings(audioRating, videoRating); +} + +const MediaSessionParams * MediaSession::getMediaParams () const { + L_D(); + return d->getParams(); +} + +RtpTransport * MediaSession::getMetaRtcpTransport (int streamIndex) const { + L_D(); + if ((streamIndex < 0) || (streamIndex >= getStreamCount())) + return nullptr; + RtpTransport *metaRtp; + RtpTransport *metaRtcp; + rtp_session_get_transports(d->sessions[streamIndex].rtp_session, &metaRtp, &metaRtcp); + return metaRtcp; +} + +RtpTransport * MediaSession::getMetaRtpTransport (int streamIndex) const { + L_D(); + if ((streamIndex < 0) || (streamIndex >= getStreamCount())) + return nullptr; + RtpTransport *metaRtp; + RtpTransport *metaRtcp; + rtp_session_get_transports(d->sessions[streamIndex].rtp_session, &metaRtp, &metaRtcp); + return metaRtp; +} + +float MediaSession::getMicrophoneVolumeGain () const { + L_D(); + if (d->audioStream) + return audio_stream_get_sound_card_input_gain(d->audioStream); + else { + lError() << "Could not get record volume: no audio stream"; + return -1.0f; + } +} + +void * MediaSession::getNativeVideoWindowId () const { + L_D(); + if (d->videoWindowId) { + /* The video id was previously set by the app */ + return d->videoWindowId; + } +#ifdef VIDEO_ENABLED + else if (d->videoStream) { + /* It was not set but we want to get the one automatically created by mediastreamer2 (desktop versions only) */ + return video_stream_get_native_window_id(d->videoStream); + } +#endif + return nullptr; +} + +const CallSessionParams * MediaSession::getParams () const { + L_D(); + return d->params; +} + +float MediaSession::getPlayVolume () const { + L_D(); + if (d->audioStream && d->audioStream->volrecv) { + float vol = 0; + ms_filter_call_method(d->audioStream->volrecv, MS_VOLUME_GET, &vol); + return vol; + } + return LINPHONE_VOLUME_DB_LOWEST; +} + +float MediaSession::getRecordVolume () const { + L_D(); + if (d->audioStream && d->audioStream->volsend && !d->audioMuted && (d->state == CallSession::State::StreamsRunning)) { + float vol = 0; + ms_filter_call_method(d->audioStream->volsend, MS_VOLUME_GET, &vol); + return vol; + } + return LINPHONE_VOLUME_DB_LOWEST; +} + +const MediaSessionParams * MediaSession::getRemoteParams () { + L_D(); + if (d->op){ + SalMediaDescription *md = d->op->getRemoteMediaDescription(); + if (md) { + d->setRemoteParams(new MediaSessionParams()); + unsigned int nbAudioStreams = sal_media_description_nb_active_streams_of_type(md, SalAudio); + for (unsigned int i = 0; i < nbAudioStreams; i++) { + SalStreamDescription *sd = sal_media_description_get_active_stream_of_type(md, SalAudio, i); + if (sal_stream_description_has_srtp(sd)) + d->getRemoteParams()->setMediaEncryption(LinphoneMediaEncryptionSRTP); + } + unsigned int nbVideoStreams = sal_media_description_nb_active_streams_of_type(md, SalVideo); + for (unsigned int i = 0; i < nbVideoStreams; i++) { + SalStreamDescription *sd = sal_media_description_get_active_stream_of_type(md, SalVideo, i); + if (sal_stream_description_active(sd)) + d->getRemoteParams()->enableVideo(true); + if (sal_stream_description_has_srtp(sd)) + d->getRemoteParams()->setMediaEncryption(LinphoneMediaEncryptionSRTP); + } + unsigned int nbTextStreams = sal_media_description_nb_active_streams_of_type(md, SalText); + for (unsigned int i = 0; i < nbTextStreams; i++) { + SalStreamDescription *sd = sal_media_description_get_active_stream_of_type(md, SalText, i); + if (sal_stream_description_has_srtp(sd)) + d->getRemoteParams()->setMediaEncryption(LinphoneMediaEncryptionSRTP); + d->getRemoteParams()->enableRealtimeText(true); + } + if (!d->getRemoteParams()->videoEnabled()) { + if ((md->bandwidth > 0) && (md->bandwidth <= linphone_core_get_edge_bw(getCore()->getCCore()))) + d->getRemoteParams()->enableLowBandwidth(true); + } + if (md->name[0] != '\0') + d->getRemoteParams()->setSessionName(md->name); + + d->getRemoteParams()->getPrivate()->setCustomSdpAttributes(md->custom_sdp_attributes); + d->getRemoteParams()->getPrivate()->setCustomSdpMediaAttributes(LinphoneStreamTypeAudio, md->streams[d->mainAudioStreamIndex].custom_sdp_attributes); + d->getRemoteParams()->getPrivate()->setCustomSdpMediaAttributes(LinphoneStreamTypeVideo, md->streams[d->mainVideoStreamIndex].custom_sdp_attributes); + d->getRemoteParams()->getPrivate()->setCustomSdpMediaAttributes(LinphoneStreamTypeText, md->streams[d->mainTextStreamIndex].custom_sdp_attributes); + } + const SalCustomHeader *ch = d->op->getRecvCustomHeaders(); + if (ch) { + /* Instanciate a remote_params only if a SIP message was received before (custom headers indicates this) */ + if (!d->remoteParams) + d->setRemoteParams(new MediaSessionParams()); + d->getRemoteParams()->getPrivate()->setCustomHeaders(ch); + } + return d->getRemoteParams(); + } + return nullptr; +} + +float MediaSession::getSpeakerVolumeGain () const { + L_D(); + if (d->audioStream) + return audio_stream_get_sound_card_output_gain(d->audioStream); + else { + lError() << "Could not get playback volume: no audio stream"; + return -1.0f; + } +} + +LinphoneCallStats * MediaSession::getStats (LinphoneStreamType type) const { + L_D(); + if (type == LinphoneStreamTypeUnknown) + return nullptr; + LinphoneCallStats *stats = nullptr; + LinphoneCallStats *statsCopy = _linphone_call_stats_new(); + if (type == LinphoneStreamTypeAudio) + stats = d->audioStats; + else if (type == LinphoneStreamTypeVideo) + stats = d->videoStats; + else if (type == LinphoneStreamTypeText) + stats = d->textStats; + MediaStream *ms = d->getMediaStream(type); + if (ms && stats) + linphone_call_stats_update(stats, ms); + _linphone_call_stats_clone(statsCopy, stats); + return statsCopy; +} + +int MediaSession::getStreamCount () const { + /* TODO: Revisit when multiple media streams will be implemented */ +#ifdef VIDEO_ENABLED + if (getCurrentParams()->realtimeTextEnabled()) + return 3; + return 2; +#else + if (getCurrentParams()->realtimeTextEnabled()) + return 2; + return 1; +#endif +} + +MSFormatType MediaSession::getStreamType (int streamIndex) const { + L_D(); + /* TODO: Revisit when multiple media streams will be implemented */ + if (streamIndex == d->mainVideoStreamIndex) + return MSVideo; + else if (streamIndex == d->mainTextStreamIndex) + return MSText; + else if (streamIndex == d->mainAudioStreamIndex) + return MSAudio; + return MSUnknownMedia; +} + +LinphoneCallStats * MediaSession::getTextStats () const { + return getStats(LinphoneStreamTypeText); +} + +LinphoneCallStats * MediaSession::getVideoStats () const { + return getStats(LinphoneStreamTypeVideo); +} + +bool MediaSession::mediaInProgress () const { + L_D(); + if ((linphone_call_stats_get_ice_state(d->audioStats) == LinphoneIceStateInProgress) + || (linphone_call_stats_get_ice_state(d->videoStats) == LinphoneIceStateInProgress) + || (linphone_call_stats_get_ice_state(d->textStats) == LinphoneIceStateInProgress)) + return true; + /* TODO: could check zrtp state */ + return false; +} + +void MediaSession::setAudioRoute (LinphoneAudioRoute route) { + L_D(); + if (d->audioStream) + audio_stream_set_audio_route(d->audioStream, (MSAudioRoute)route); +} + +void MediaSession::setAuthenticationTokenVerified (bool value) { + L_D(); + if (!d->audioStream || !media_stream_started(&d->audioStream->ms)) { + lError() << "MediaSession::setAuthenticationTokenVerified(): No audio stream or not started"; + return; + } + if (!d->audioStream->ms.sessions.zrtp_context) { + lError() << "MediaSession::setAuthenticationTokenVerified(): No zrtp context"; + return; + } + if (!d->authTokenVerified && value) + ms_zrtp_sas_verified(d->audioStream->ms.sessions.zrtp_context); + else if (d->authTokenVerified && !value) + ms_zrtp_sas_reset_verified(d->audioStream->ms.sessions.zrtp_context); + d->authTokenVerified = value; + d->propagateEncryptionChanged(); +} + +void MediaSession::setMicrophoneVolumeGain (float value) { + L_D(); + if(d->audioStream) + audio_stream_set_sound_card_input_gain(d->audioStream, value); + else + lError() << "Could not set record volume: no audio stream"; +} + +void MediaSession::setNativeVideoWindowId (void *id) { + L_D(); + d->videoWindowId = id; +#ifdef VIDEO_ENABLED + if (d->videoStream) + video_stream_set_native_window_id(d->videoStream, id); +#endif +} + +void MediaSession::setParams (const MediaSessionParams *msp) { + L_D(); + if ((d->state == CallSession::State::OutgoingInit) || (d->state == CallSession::State::IncomingReceived)) + d->setParams(msp ? new MediaSessionParams(*msp) : nullptr); + else + lError() << "MediaSession::setParams(): Invalid state %s", Utils::toString(d->state); +} + +void MediaSession::setSpeakerVolumeGain (float value) { + L_D(); + if (d->audioStream) + audio_stream_set_sound_card_output_gain(d->audioStream, value); + else + lError() << "Could not set playback volume: no audio stream"; +} + +LINPHONE_END_NAMESPACE diff --git a/src/conference/session/media-session.h b/src/conference/session/media-session.h new file mode 100644 index 000000000..8236c4f8a --- /dev/null +++ b/src/conference/session/media-session.h @@ -0,0 +1,115 @@ +/* + * media-session.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MEDIA_SESSION_H_ +#define _L_MEDIA_SESSION_H_ + +#include "call-session.h" +#include "conference/params/media-session-params.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CallPrivate; +class Core; +class IceAgent; +class MediaSessionPrivate; +class Participant; + +class LINPHONE_PUBLIC MediaSession : public CallSession { + friend class Call; + friend class CallPrivate; + friend class IceAgent; + +public: + MediaSession (const std::shared_ptr &core, std::shared_ptr me, const CallSessionParams *params, CallSessionListener *listener); + ~MediaSession (); + + LinphoneStatus accept (const MediaSessionParams *msp = nullptr); + LinphoneStatus acceptEarlyMedia (const MediaSessionParams *msp = nullptr); + LinphoneStatus acceptUpdate (const MediaSessionParams *msp); + void cancelDtmfs (); + void configure (LinphoneCallDir direction, LinphoneProxyConfig *cfg, SalCallOp *op, const Address &from, const Address &to) override; + LinphoneStatus deferUpdate () override; + void initiateIncoming () override; + bool initiateOutgoing () override; + void iterate (time_t currentRealTime, bool oneSecondElapsed) override; + LinphoneStatus pause (); + LinphoneStatus resume (); + LinphoneStatus sendDtmf (char dtmf); + LinphoneStatus sendDtmfs (const std::string &dtmfs); + void sendVfuRequest (); + void startIncomingNotification (bool notifyRinging = true) override; + int startInvite (const Address *destination, const std::string &subject = "", const Content *content = nullptr) override; + void startRecording (); + void stopRecording (); + void terminateBecauseOfLostMedia (); + LinphoneStatus update (const MediaSessionParams *msp, const std::string &subject = ""); + + void requestNotifyNextVideoFrameDecoded (); + LinphoneStatus takePreviewSnapshot (const std::string& file); + LinphoneStatus takeVideoSnapshot (const std::string& file); + void zoomVideo (float zoomFactor, float *cx, float *cy); + void zoomVideo (float zoomFactor, float cx, float cy); + + bool cameraEnabled () const; + bool echoCancellationEnabled () const; + bool echoLimiterEnabled () const; + void enableCamera (bool value); + void enableEchoCancellation (bool value); + void enableEchoLimiter (bool value); + bool getAllMuted () const; + LinphoneCallStats * getAudioStats () const; + std::string getAuthenticationToken () const; + bool getAuthenticationTokenVerified () const; + float getAverageQuality () const; + MediaSessionParams *getCurrentParams () const; + float getCurrentQuality () const; + const MediaSessionParams *getMediaParams () const; + RtpTransport * getMetaRtcpTransport (int streamIndex) const; + RtpTransport * getMetaRtpTransport (int streamIndex) const; + float getMicrophoneVolumeGain () const; + void * getNativeVideoWindowId () const; + const CallSessionParams *getParams () const override; + float getPlayVolume () const; + float getRecordVolume () const; + const MediaSessionParams *getRemoteParams (); + float getSpeakerVolumeGain () const; + LinphoneCallStats * getStats (LinphoneStreamType type) const; + int getStreamCount () const; + MSFormatType getStreamType (int streamIndex) const; + LinphoneCallStats * getTextStats () const; + LinphoneCallStats * getVideoStats () const; + bool mediaInProgress () const; + void setAudioRoute (LinphoneAudioRoute route); + void setAuthenticationTokenVerified (bool value); + void setMicrophoneVolumeGain (float value); + void setNativeVideoWindowId (void *id); + void setParams (const MediaSessionParams *msp); + void setSpeakerVolumeGain (float value); + +private: + L_DECLARE_PRIVATE(MediaSession); + L_DISABLE_COPY(MediaSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MEDIA_SESSION_H_ diff --git a/src/conference/session/port-config.h b/src/conference/session/port-config.h new file mode 100644 index 000000000..1bebccf13 --- /dev/null +++ b/src/conference/session/port-config.h @@ -0,0 +1,40 @@ +/* + * port-config.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PORT_CONFIG_H_ +#define _L_PORT_CONFIG_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +struct PortConfig { + std::string multicastIp; + std::string multicastBindIp; + int rtpPort = -1; + int rtcpPort = -1; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PORT_CONFIG_H_ diff --git a/src/containers/lru-cache.h b/src/containers/lru-cache.h new file mode 100644 index 000000000..5bab2c5f1 --- /dev/null +++ b/src/containers/lru-cache.h @@ -0,0 +1,107 @@ +/* + * lru-cache.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_LRU_CACHE_H_ +#define _L_LRU_CACHE_H_ + +#include +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +template +class LruCache { +public: + LruCache (int capacity = DefaultCapacity) : mCapacity(capacity) { + if (capacity < MinCapacity) + capacity = MinCapacity; + } + + int getCapacity () const { + return mCapacity; + } + + int getSize () const { + return int(mKeyToPair.size()); + } + + Value *operator[] (const Key &key) { + auto it = mKeyToPair.find(key); + return it == mKeyToPair.end() ? nullptr : &it->second.second; + } + + const Value *operator[] (const Key &key) const { + auto it = mKeyToPair.find(key); + return it == mKeyToPair.cend() ? nullptr : &it->second.second; + } + + void insert (const Key &key, const Value &value) { + auto it = mKeyToPair.find(key); + if (it != mKeyToPair.end()) + mKeys.erase(it->second.first); + else if (int(mKeyToPair.size()) == mCapacity) { + Key lastKey = mKeys.back(); + mKeys.pop_back(); + mKeyToPair.erase(lastKey); + } + + mKeys.push_front(key); + mKeyToPair.insert({ key, { mKeys.begin(), value } }); + } + + void insert (const Key &key, Value &&value) { + auto it = mKeyToPair.find(key); + if (it != mKeyToPair.end()) + mKeys.erase(it->second.first); + else if (int(mKeyToPair.size()) == mCapacity) { + Key lastKey = mKeys.back(); + mKeys.pop_back(); + mKeyToPair.erase(lastKey); + } + + mKeys.push_front(key); + mKeyToPair.insert({ key, std::make_pair(mKeys.begin(), std::move(value)) }); + } + + void clear () { + mKeyToPair.clear(); + mKeys.clear(); + } + + static constexpr int MinCapacity = 10; + static constexpr int DefaultCapacity = 1000; + +private: + using Pair = std::pair::iterator, Value>; + + const int mCapacity; + + // See: https://stackoverflow.com/questions/16781886/can-we-store-unordered-maptiterator + // Do not store iterator key. + std::list mKeys; + std::unordered_map mKeyToPair; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_LRU_CACHE_H_ diff --git a/src/content/content-disposition.cpp b/src/content/content-disposition.cpp new file mode 100644 index 000000000..b7c6c9f16 --- /dev/null +++ b/src/content/content-disposition.cpp @@ -0,0 +1,111 @@ +/* + * content-disposition.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "content-disposition.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class ContentDispositionPrivate : public ClonableObjectPrivate { +public: + string disposition; + string parameter; +}; + +// ----------------------------------------------------------------------------- + +const ContentDisposition ContentDisposition::Notification("notification"); +const ContentDisposition ContentDisposition::RecipientList("recipient-list"); +const ContentDisposition ContentDisposition::RecipientListHistory("recipient-list-history; handling=optional"); + +// ----------------------------------------------------------------------------- + +ContentDisposition::ContentDisposition (const string &disposition) : ClonableObject(*new ContentDispositionPrivate) { + L_D(); + size_t posParam = disposition.find(";"); + d->disposition = Utils::trim(disposition.substr(0, posParam)); + if (posParam != string::npos) + setParameter(Utils::trim(disposition.substr(posParam + 1))); +} + +ContentDisposition::ContentDisposition (const ContentDisposition &other) + : ContentDisposition(other.asString()) {} + +ContentDisposition &ContentDisposition::operator= (const ContentDisposition &other) { + L_D(); + if (this != &other) { + d->disposition = other.getPrivate()->disposition; + setParameter(other.getParameter()); + } + return *this; +} + +bool ContentDisposition::weakEqual (const ContentDisposition &other) const { + L_D(); + return d->disposition == other.getPrivate()->disposition; +} + +bool ContentDisposition::operator== (const ContentDisposition &other) const { + return weakEqual(other) && (getParameter() == other.getParameter()); +} + +bool ContentDisposition::operator!= (const ContentDisposition &other) const { + return !(*this == other); +} + +bool ContentDisposition::isEmpty () const { + L_D(); + return d->disposition.empty(); +} + +bool ContentDisposition::isValid () const { + L_D(); + return !d->disposition.empty(); +} + +const string &ContentDisposition::getParameter () const { + L_D(); + return d->parameter; +} + +void ContentDisposition::setParameter (const string ¶meter) { + L_D(); + d->parameter = parameter; +} + +string ContentDisposition::asString () const { + L_D(); + if (isValid()) { + string asString = d->disposition; + if (!d->parameter.empty()) + asString += ";" + d->parameter; + return asString; + } + return ""; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/content-disposition.h b/src/content/content-disposition.h new file mode 100644 index 000000000..e01b289bb --- /dev/null +++ b/src/content/content-disposition.h @@ -0,0 +1,65 @@ +/* + * content-disposition.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONTENT_DISPOSITION_H_ +#define _L_CONTENT_DISPOSITION_H_ + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ContentDispositionPrivate; + +class LINPHONE_PUBLIC ContentDisposition : public ClonableObject { +public: + explicit ContentDisposition (const std::string &contentDisposition = ""); + ContentDisposition (const ContentDisposition &other); + + ContentDisposition &operator= (const ContentDisposition &other); + + bool weakEqual (const ContentDisposition &other) const; + bool operator== (const ContentDisposition &other) const; + bool operator!= (const ContentDisposition &other) const; + + // Delete these operators to prevent putting complicated content-disposition strings + // in the code. Instead define static const ContentDisposition objects below. + bool operator== (const std::string &other) const = delete; + bool operator!= (const std::string &other) const = delete; + + bool isEmpty () const; + bool isValid () const; + + const std::string &getParameter () const; + void setParameter (const std::string ¶meter); + + std::string asString () const; + + static const ContentDisposition Notification; + static const ContentDisposition RecipientList; + static const ContentDisposition RecipientListHistory; + +private: + L_DECLARE_PRIVATE(ContentDisposition); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONTENT_DISPOSITION_H_ diff --git a/src/content/content-manager.cpp b/src/content/content-manager.cpp new file mode 100644 index 000000000..e63e6ff19 --- /dev/null +++ b/src/content/content-manager.cpp @@ -0,0 +1,91 @@ +/* + * content-manager.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "c-wrapper/c-wrapper.h" + +#include "linphone/api/c-content.h" + +#include "content-disposition.h" +#include "content-manager.h" +#include "content-type.h" +#include "content/content.h" +#include "content/header/header-param.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +list ContentManager::multipartToContentList (const Content &content) { + LinphoneContent *cContent = L_GET_C_BACK_PTR(&content); + SalBodyHandler *sbh = sal_body_handler_from_content(cContent); + + list contents; + for (const belle_sip_list_t *parts = sal_body_handler_get_parts(sbh); parts; parts = parts->next) { + SalBodyHandler *part = (SalBodyHandler *)parts->data; + LinphoneContent *cContent = linphone_content_from_sal_body_handler(part, false); + Content *cppContent = L_GET_CPP_PTR_FROM_C_OBJECT(cContent); + if (content.getContentDisposition().isValid()) + cppContent->setContentDisposition(content.getContentDisposition()); + contents.push_back(*cppContent); + linphone_content_unref(cContent); + } + + sal_body_handler_unref(sbh); + return contents; +} + +Content ContentManager::contentListToMultipart (const list &contents, const string &boundary) { + belle_sip_multipart_body_handler_t *mpbh = belle_sip_multipart_body_handler_new( + nullptr, nullptr, nullptr, boundary.c_str() + ); + mpbh = (belle_sip_multipart_body_handler_t *)belle_sip_object_ref(mpbh); + + ContentDisposition disposition; + for (Content *content : contents) { + // Is this content-disposition stuff generic or only valid for notification content-disposition? + if (content->getContentDisposition().isValid()) + disposition = content->getContentDisposition(); + + LinphoneContent *cContent = L_GET_C_BACK_PTR(content); + SalBodyHandler *sbh = sal_body_handler_from_content(cContent, false); + belle_sip_multipart_body_handler_add_part(mpbh, BELLE_SIP_BODY_HANDLER(sbh)); + } + + SalBodyHandler *sbh = (SalBodyHandler *)mpbh; + sal_body_handler_set_type(sbh, ContentType::Multipart.getType().c_str()); + sal_body_handler_set_subtype(sbh, ContentType::Multipart.getSubType().c_str()); + sal_body_handler_set_content_type_parameter(sbh, "boundary", boundary.c_str()); + + LinphoneContent *cContent = linphone_content_from_sal_body_handler(sbh); + belle_sip_object_unref(mpbh); + + Content content = *L_GET_CPP_PTR_FROM_C_OBJECT(cContent); + if (disposition.isValid()) + content.setContentDisposition(disposition); + linphone_content_unref(cContent); + return content; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/content-manager.h b/src/content/content-manager.h new file mode 100644 index 000000000..deeb62f57 --- /dev/null +++ b/src/content/content-manager.h @@ -0,0 +1,44 @@ +/* + * content-manager.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONTENT_MANAGER_H_ +#define _L_CONTENT_MANAGER_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Content; + +namespace { + constexpr const char MultipartBoundary[] = "---------------------------14737809831466499882746641449"; +} + +namespace ContentManager { + LINPHONE_PUBLIC std::list multipartToContentList (const Content &content); + LINPHONE_PUBLIC Content contentListToMultipart (const std::list &contents, const std::string &boundary = MultipartBoundary); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONTENT_MANAGER_H_ diff --git a/src/content/content-p.h b/src/content/content-p.h new file mode 100644 index 000000000..b32d61ef4 --- /dev/null +++ b/src/content/content-p.h @@ -0,0 +1,49 @@ +/* + * content-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONTENT_P_H_ +#define _L_CONTENT_P_H_ + +#include "content-disposition.h" +#include "content-type.h" +#include "content.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Header; + +class ContentPrivate : public ClonableObjectPrivate { +private: + std::vector body; + ContentType contentType; + ContentDisposition contentDisposition; + std::string contentEncoding; + std::list
headers; + + const std::list>::const_iterator findHeader (const std::string &headerName) const; + + L_DECLARE_PUBLIC(Content); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONTENT_P_H_ diff --git a/src/content/content-type.cpp b/src/content/content-type.cpp new file mode 100644 index 000000000..29913d57e --- /dev/null +++ b/src/content/content-type.cpp @@ -0,0 +1,218 @@ +/* + * content-type.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "content-type.h" +#include "header/header-p.h" +#include "header/header-param.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class ContentTypePrivate : public HeaderPrivate { +public: + string type; + string subType; +}; + +// ----------------------------------------------------------------------------- + +const ContentType ContentType::ConferenceInfo("application/conference-info+xml"); +const ContentType ContentType::Cpim("message/cpim"); +const ContentType ContentType::ExternalBody("message/external-body"); +const ContentType ContentType::FileTransfer("application/vnd.gsma.rcs-ft-http+xml"); +const ContentType ContentType::Imdn("message/imdn+xml"); +const ContentType ContentType::ImIsComposing("application/im-iscomposing+xml"); +const ContentType ContentType::Multipart("multipart/mixed"); +const ContentType ContentType::PlainText("text/plain"); +const ContentType ContentType::ResourceLists("application/resource-lists+xml"); +const ContentType ContentType::Rlmi("application/rlmi+xml"); +const ContentType ContentType::Sdp("application/sdp"); + +// ----------------------------------------------------------------------------- + +ContentType::ContentType (const string &contentType) : Header(*new ContentTypePrivate) { + L_D(); + + size_t pos = contentType.find('/'); + size_t posParam = contentType.find(";"); + size_t end = contentType.length(); + if (pos == string::npos) + return; + + if (setType(Utils::trim(contentType.substr(0, pos)))) { + if (posParam != string::npos) + end = posParam; + if (!setSubType(Utils::trim(contentType.substr(pos + 1, end - (pos + 1))))) + d->type.clear(); + } + + if (posParam != string::npos) { + string params = contentType.substr(posParam + 1); + string token; + do { + posParam = params.find(";"); + if (posParam == string::npos) { + token = params; + } else { + token = params.substr(0, posParam); + } + addParameter(HeaderParam(token)); + params.erase(0, posParam + 1); + } while (posParam != std::string::npos); + } +} + +ContentType::ContentType (const string &type, const string &subType) : Header(*new ContentTypePrivate) { + L_D(); + + if (setType(type) && !setSubType(subType)) + d->type.clear(); +} + +ContentType::ContentType ( + const string &type, + const string &subType, + const HeaderParam ¶meter +) : Header(*new ContentTypePrivate) { + L_D(); + + if (setType(type) && !setSubType(subType)) + d->type.clear(); + addParameter(parameter); +} + +ContentType::ContentType ( + const string &type, + const string &subType, + const std::list ¶meters +) : Header(*new ContentTypePrivate) { + L_D(); + + if (setType(type) && !setSubType(subType)) + d->type.clear(); + addParameters(parameters); +} + +ContentType::ContentType (const ContentType &other) : ContentType(other.getType(), other.getSubType(), other.getParameters()) {} + +ContentType &ContentType::operator= (const ContentType &other) { + if (this != &other) { + setType(other.getType()); + setSubType(other.getSubType()); + cleanParameters(); + addParameters(other.getParameters()); + } + + return *this; +} + +bool ContentType::weakEqual (const ContentType &other) const { + return (getType() == other.getType()) && (getSubType() == other.getSubType()); +} + +bool ContentType::operator== (const ContentType &other) const { + if (!weakEqual(other)) + return false; + if (getParameters().size() != other.getParameters().size()) + return false; + for (const auto ¶m : getParameters()) { + auto it = other.findParameter(param.getName()); + if (it == other.getParameters().cend()) + return false; + if (it->getValue() != param.getValue()) + return false; + } + return true; +} + +bool ContentType::operator!= (const ContentType &other) const { + return !(*this == other); +} + +const string &ContentType::getType () const { + L_D(); + return d->type; +} + +bool ContentType::setType (const string &type) { + L_D(); + if (type.find('/') == string::npos) { + d->type = Utils::stringToLower(type); + setValue(d->type + "/" + d->subType); + return true; + } + return false; +} + +const string &ContentType::getSubType () const { + L_D(); + return d->subType; +} + +bool ContentType::setSubType (const string &subType) { + L_D(); + if (subType.find('/') == string::npos) { + d->subType = Utils::stringToLower(subType); + setValue(d->type + "/" + d->subType); + return true; + } + return false; +} + +bool ContentType::isEmpty () const { + L_D(); + return d->type.empty() && d->subType.empty(); +} + +bool ContentType::isValid () const { + L_D(); + return !d->type.empty() && !d->subType.empty(); +} + +bool ContentType::isMultipart() const { + return getType() == "multipart"; +} + +bool ContentType::isFile () const { + // TODO Remove when not needed anymore in step 2.1 of maindb + return isFile(*this); +} + +bool ContentType::isFile (const ContentType &contentType) { + // TODO Remove when not needed anymore in step 2.1 of maindb + return contentType != FileTransfer && + contentType != PlainText && + contentType != ExternalBody && + contentType != Imdn && + contentType != ImIsComposing && + contentType != ResourceLists && + contentType != Rlmi && + contentType != Sdp && + contentType != Cpim && + contentType != ConferenceInfo; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/content-type.h b/src/content/content-type.h new file mode 100644 index 000000000..ae802952b --- /dev/null +++ b/src/content/content-type.h @@ -0,0 +1,84 @@ +/* + * content-type.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONTENT_TYPE_H_ +#define _L_CONTENT_TYPE_H_ + +#include "object/clonable-object.h" +#include "header/header.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ContentTypePrivate; +class HeaderParam; + +class LINPHONE_PUBLIC ContentType : public Header { +public: + explicit ContentType (const std::string &contentType = ""); + ContentType (const std::string &type, const std::string &subType); + ContentType (const std::string &type, const std::string &subType, const HeaderParam ¶meter); + ContentType (const std::string &type, const std::string &subType, const std::list ¶meters); + ContentType (const ContentType &other); + + ContentType &operator= (const ContentType &other); + + bool weakEqual (const ContentType &other) const; + bool operator== (const ContentType &other) const; + bool operator!= (const ContentType &other) const; + + // Delete these operators to prevent putting complicated content-type strings + // in the code. Instead define static const ContentType objects below. + bool operator== (const std::string &other) const = delete; + bool operator!= (const std::string &other) const = delete; + + bool isEmpty () const; + bool isValid () const; + bool isFile () const; + + const std::string &getType () const; + bool setType (const std::string &type); + + const std::string &getSubType () const; + bool setSubType (const std::string &subType); + + bool isMultipart() const; + + static bool isFile (const ContentType &contentType); + + static const ContentType ConferenceInfo; + static const ContentType Cpim; + static const ContentType ExternalBody; + static const ContentType FileTransfer; + static const ContentType Imdn; + static const ContentType ImIsComposing; + static const ContentType Multipart; + static const ContentType PlainText; + static const ContentType ResourceLists; + static const ContentType Rlmi; + static const ContentType Sdp; + +private: + L_DECLARE_PRIVATE(ContentType); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONTENT_TYPE_H_ diff --git a/src/content/content.cpp b/src/content/content.cpp index 2003b1613..631d94351 100644 --- a/src/content/content.cpp +++ b/src/content/content.cpp @@ -1,11 +1,11 @@ /* * content.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,25 +13,227 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "object/object-p.h" +// TODO: Remove me later. +#include "linphone/core.h" -#include "content.h" +#include "linphone/utils/algorithm.h" +#include "linphone/utils/utils.h" + +#include "content-p.h" +#include "content-type.h" +#include "header/header.h" // ============================================================================= +using namespace std; + LINPHONE_BEGIN_NAMESPACE -class ContentPrivate : public ObjectPrivate { -private: +// ============================================================================= - L_DECLARE_PUBLIC(Content); -}; +Content::Content () : ClonableObject(*new ContentPrivate) {} -// ----------------------------------------------------------------------------- +Content::Content (const Content &other) : ClonableObject(*new ContentPrivate), AppDataContainer(other) { + L_D(); + d->body = other.getBody(); + d->contentType = other.getContentType(); + d->contentDisposition = other.getContentDisposition(); + d->contentEncoding = other.getContentEncoding(); + d->headers = other.getHeaders(); +} -Content::Content (ContentPrivate &p) : Object(p) {} +Content::Content (Content &&other) : ClonableObject(*new ContentPrivate), AppDataContainer(move(other)) { + L_D(); + ContentPrivate *dOther = other.getPrivate(); + d->body = move(dOther->body); + d->contentType = move(dOther->contentType); + d->contentDisposition = move(dOther->contentDisposition); + d->contentEncoding = move(dOther->contentEncoding); + d->headers = move(dOther->headers); +} + +Content::Content (ContentPrivate &p) : ClonableObject(p) {} + +Content::~Content () { + L_D(); + /* + * Fills the body with zeros before releasing since it may contain + * private data like cipher keys or decoded messages. + */ + d->body.assign(d->body.size(), 0); +} + +Content &Content::operator= (const Content &other) { + L_D(); + if (this != &other) { + AppDataContainer::operator=(other); + d->body = other.getBody(); + d->contentType = other.getContentType(); + d->contentDisposition = other.getContentDisposition(); + d->contentEncoding = other.getContentEncoding(); + d->headers = other.getHeaders(); + } + return *this; +} + +Content &Content::operator= (Content &&other) { + L_D(); + AppDataContainer::operator=(move(other)); + ContentPrivate *dOther = other.getPrivate(); + d->body = move(dOther->body); + d->contentType = move(dOther->contentType); + d->contentDisposition = move(dOther->contentDisposition); + d->contentEncoding = move(dOther->contentEncoding); + d->headers = move(dOther->headers); + return *this; +} + +bool Content::operator== (const Content &other) const { + L_D(); + return d->contentType == other.getContentType() && + d->body == other.getBody() && + d->contentDisposition == other.getContentDisposition() && + d->contentEncoding == other.getContentEncoding() && + d->headers == other.getHeaders(); +} + +const ContentType &Content::getContentType () const { + L_D(); + return d->contentType; +} + +void Content::setContentType (const ContentType &contentType) { + L_D(); + d->contentType = contentType; +} + +const ContentDisposition &Content::getContentDisposition () const { + L_D(); + return d->contentDisposition; +} + +void Content::setContentDisposition (const ContentDisposition &contentDisposition) { + L_D(); + d->contentDisposition = contentDisposition; +} + +const string &Content::getContentEncoding () const { + L_D(); + return d->contentEncoding; +} + +void Content::setContentEncoding (const string &contentEncoding) { + L_D(); + d->contentEncoding = contentEncoding; +} + +const vector &Content::getBody () const { + L_D(); + return d->body; +} + +string Content::getBodyAsString () const { + L_D(); + return Utils::utf8ToLocale(string(d->body.begin(), d->body.end())); +} + +string Content::getBodyAsUtf8String () const { + L_D(); + return string(d->body.begin(), d->body.end()); +} + +void Content::setBody (const vector &body) { + L_D(); + d->body = body; +} + +void Content::setBody (vector &&body) { + L_D(); + d->body = move(body); +} + +void Content::setBody (const string &body) { + L_D(); + string toUtf8 = Utils::localeToUtf8(body); + d->body = vector(toUtf8.cbegin(), toUtf8.cend()); +} + +void Content::setBody (const void *buffer, size_t size) { + L_D(); + const char *start = static_cast(buffer); + d->body = vector(start, start + size); +} + +void Content::setBodyFromUtf8 (const string &body) { + L_D(); + d->body = vector(body.cbegin(), body.cend()); +} + +size_t Content::getSize () const { + L_D(); + return d->body.size(); +} + +bool Content::isEmpty () const { + return getSize() == 0; +} + +bool Content::isValid () const { + L_D(); + return d->contentType.isValid() || (d->contentType.isEmpty() && d->body.empty()); +} + +bool Content::isFile () const { + return false; +} + +bool Content::isFileTransfer () const { + return false; +} + +void Content::addHeader (const string &headerName, const string &headerValue) { + L_D(); + removeHeader(headerName); + Header header = Header(headerName, headerValue); + d->headers.push_back(header); +} + +void Content::addHeader (const Header &header) { + L_D(); + removeHeader(header.getName()); + d->headers.push_back(header); +} + +const list
&Content::getHeaders () const { + L_D(); + return d->headers; +} + +const Header &Content::getHeader (const string &headerName) const { + L_D(); + list
::const_iterator it = findHeader(headerName); + if (it != d->headers.cend()) { + return *it; + } + return Utils::getEmptyConstRefObject
(); +} + +void Content::removeHeader (const string &headerName) { + L_D(); + auto it = findHeader(headerName); + if (it != d->headers.cend()) + d->headers.remove(*it); +} + +list
::const_iterator Content::findHeader (const string &headerName) const { + L_D(); + return findIf(d->headers, [&headerName](const Header &header) { + return header.getName() == headerName; + }); +} LINPHONE_END_NAMESPACE diff --git a/src/content/content.h b/src/content/content.h index fa59de1e7..3c29d3a1a 100644 --- a/src/content/content.h +++ b/src/content/content.h @@ -1,11 +1,11 @@ /* * content.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,33 +13,84 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CONTENT_H_ -#define _CONTENT_H_ +#ifndef _L_CONTENT_H_ +#define _L_CONTENT_H_ -#include "object/object.h" +#include +#include + +#include "object/app-data-container.h" +#include "object/clonable-object.h" // ============================================================================= +L_DECL_C_STRUCT(LinphoneContent); + LINPHONE_BEGIN_NAMESPACE +class ContentDisposition; +class ContentType; class ContentPrivate; +class Header; -class LINPHONE_PUBLIC Content : public Object { - friend class Core; - +class LINPHONE_PUBLIC Content : public ClonableObject, public AppDataContainer { public: - // Nothing for the moment. + Content (); + Content (const Content &other); + Content (Content &&other); + ~Content (); + + Content &operator= (const Content &other); + Content &operator= (Content &&other); + + bool operator== (const Content &other) const; + + const ContentType &getContentType () const; + void setContentType (const ContentType &contentType); + + const ContentDisposition &getContentDisposition () const; + void setContentDisposition (const ContentDisposition &contentDisposition); + + const std::string &getContentEncoding () const; + void setContentEncoding (const std::string &contentEncoding); + + const std::vector &getBody () const; + std::string getBodyAsString () const; + std::string getBodyAsUtf8String () const; + + void setBody (const std::vector &body); + void setBody (std::vector &&body); + void setBody (const std::string &body); + void setBody (const void *buffer, size_t size); + void setBodyFromUtf8 (const std::string &body); + + size_t getSize () const; + + bool isValid () const; + + bool isEmpty () const; + + virtual bool isFile () const; + virtual bool isFileTransfer () const; + + const std::list
&getHeaders () const; + const Header &getHeader (const std::string &headerName) const; + void addHeader (const std::string &headerName, const std::string &headerValue); + void addHeader (const Header &header); + void removeHeader (const std::string &headerName); + std::list
::const_iterator findHeader (const std::string &headerName) const; + +protected: + explicit Content (ContentPrivate &p); private: - Content (ContentPrivate &p); - L_DECLARE_PRIVATE(Content); - L_DISABLE_COPY(Content); }; LINPHONE_END_NAMESPACE -#endif // ifndef _CONTENT_H_ +#endif // ifndef _L_CONTENT_H_ diff --git a/src/content/file-content.cpp b/src/content/file-content.cpp new file mode 100644 index 000000000..b4a0ef0fb --- /dev/null +++ b/src/content/file-content.cpp @@ -0,0 +1,124 @@ +/* + * file-content.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// TODO: Remove me later. +#include "linphone/core.h" + +#include "content-p.h" +#include "file-content.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class FileContentPrivate : public ContentPrivate { +public: + string fileName; + string filePath; + size_t fileSize = 0; +}; + +// ----------------------------------------------------------------------------- + +FileContent::FileContent () : Content(*new FileContentPrivate) {} + +FileContent::FileContent (const FileContent &other) : Content(*new FileContentPrivate) { + L_D(); + d->fileName = other.getFileName(); + d->filePath = other.getFilePath(); + d->fileSize = other.getFileSize(); +} + +FileContent::FileContent (FileContent &&other) : Content(*new FileContentPrivate) { + L_D(); + d->fileName = move(other.getPrivate()->fileName); + d->filePath = move(other.getPrivate()->filePath); + d->fileSize = move(other.getPrivate()->fileSize); +} + +FileContent &FileContent::operator= (const FileContent &other) { + L_D(); + Content::operator=(other); + d->fileName = other.getFileName(); + d->filePath = other.getFilePath(); + d->fileSize = other.getFileSize(); + + return *this; +} + +FileContent &FileContent::operator= (FileContent &&other) { + L_D(); + Content::operator=(move(other)); + d->fileName = move(other.getPrivate()->fileName); + d->filePath = move(other.getPrivate()->filePath); + d->fileSize = move(other.getPrivate()->fileSize); + return *this; +} + +bool FileContent::operator== (const FileContent &other) const { + L_D(); + return Content::operator==(other) && + d->fileName == other.getFileName() && + d->filePath == other.getFilePath() && + d->fileSize == other.getFileSize(); +} + +void FileContent::setFileSize (size_t size) { + L_D(); + d->fileSize = size; +} + +size_t FileContent::getFileSize () const { + L_D(); + return d->fileSize; +} + +void FileContent::setFileName (const string &name) { + L_D(); + d->fileName = name; +} + +const string &FileContent::getFileName () const { + L_D(); + return d->fileName; +} + +void FileContent::setFilePath (const string &path) { + L_D(); + d->filePath = path; +} + +const string &FileContent::getFilePath () const { + L_D(); + return d->filePath; +} + +bool FileContent::isFile () const { + return true; +} + +bool FileContent::isFileTransfer () const { + return false; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/file-content.h b/src/content/file-content.h new file mode 100644 index 000000000..081a5898a --- /dev/null +++ b/src/content/file-content.h @@ -0,0 +1,60 @@ +/* + * file-content.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_FILE_CONTENT_H_ +#define _L_FILE_CONTENT_H_ + +#include "content.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class FileContentPrivate; + +class LINPHONE_PUBLIC FileContent : public Content { +public: + FileContent (); + FileContent (const FileContent &other); + FileContent (FileContent &&other); + + FileContent &operator= (const FileContent &other); + FileContent &operator= (FileContent &&other); + + bool operator== (const FileContent &other) const; + + void setFileSize (size_t size); + size_t getFileSize () const; + + void setFileName (const std::string &name); + const std::string &getFileName () const; + + void setFilePath (const std::string &path); + const std::string &getFilePath () const; + + bool isFile () const override; + bool isFileTransfer () const override; + +private: + L_DECLARE_PRIVATE(FileContent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_FILE_CONTENT_H_ diff --git a/src/content/file-transfer-content.cpp b/src/content/file-transfer-content.cpp new file mode 100644 index 000000000..8bf22f7a0 --- /dev/null +++ b/src/content/file-transfer-content.cpp @@ -0,0 +1,180 @@ +/* + * file-transfer-content.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// TODO: Remove me later. +#include "linphone/core.h" + +#include "content-p.h" +#include "file-transfer-content.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class FileTransferContentPrivate : public ContentPrivate { +public: + string fileName; + string fileUrl; + string filePath; + FileContent *fileContent = nullptr; + size_t fileSize = 0; + std::vector fileKey; +}; + +// ----------------------------------------------------------------------------- + +FileTransferContent::FileTransferContent () : Content(*new FileTransferContentPrivate) { + setContentType(ContentType::FileTransfer); +} + +FileTransferContent::FileTransferContent (const FileTransferContent &other) : Content(*new FileTransferContentPrivate) { + L_D(); + d->fileName = other.getFileName(); + d->fileUrl = other.getFileUrl(); + d->filePath = other.getFilePath(); + d->fileContent = other.getFileContent(); + d->fileSize = other.getFileSize(); + d->fileKey = other.getFileKey(); +} + +FileTransferContent::FileTransferContent (FileTransferContent &&other) : Content(*new FileTransferContentPrivate) { + L_D(); + d->fileName = move(other.getPrivate()->fileName); + d->fileUrl = move(other.getPrivate()->fileUrl); + d->filePath = move(other.getPrivate()->filePath); + d->fileContent = move(other.getPrivate()->fileContent); + d->fileSize = move(other.getPrivate()->fileSize); + d->fileKey = move(other.getPrivate()->fileKey); +} + +FileTransferContent &FileTransferContent::operator= (const FileTransferContent &other) { + L_D(); + if (this != &other) { + Content::operator=(other); + d->fileName = other.getFileName(); + d->fileUrl = other.getFileUrl(); + d->filePath = other.getFilePath(); + d->fileContent = other.getFileContent(); + d->fileSize = other.getFileSize(); + d->fileKey = other.getFileKey(); + } + + return *this; +} + +FileTransferContent &FileTransferContent::operator= (FileTransferContent &&other) { + L_D(); + Content::operator=(move(other)); + d->fileName = move(other.getPrivate()->fileName); + d->fileUrl = move(other.getPrivate()->fileUrl); + d->filePath = move(other.getPrivate()->filePath); + d->fileContent = move(other.getPrivate()->fileContent); + d->fileSize = move(other.getPrivate()->fileSize); + d->fileKey = move(other.getPrivate()->fileKey); + + return *this; +} + +bool FileTransferContent::operator== (const FileTransferContent &other) const { + L_D(); + return Content::operator==(other) && + d->fileName == other.getFileName() && + d->fileUrl == other.getFileUrl() && + d->filePath == other.getFilePath() && + d->fileSize == other.getFileSize(); +} + +void FileTransferContent::setFileName (const string &name) { + L_D(); + d->fileName = name; +} + +const string &FileTransferContent::getFileName () const { + L_D(); + return d->fileName; +} + +void FileTransferContent::setFileUrl (const string &url) { + L_D(); + d->fileUrl = url; +} + +const string &FileTransferContent::getFileUrl () const { + L_D(); + return d->fileUrl; +} + +void FileTransferContent::setFilePath (const string &path) { + L_D(); + d->filePath = path; +} + +const string &FileTransferContent::getFilePath () const { + L_D(); + return d->filePath; +} + +void FileTransferContent::setFileContent (FileContent *content) { + L_D(); + d->fileContent = content; +} + +FileContent *FileTransferContent::getFileContent () const { + L_D(); + return d->fileContent; +} + +void FileTransferContent::setFileSize (size_t size) { + L_D(); + d->fileSize = size; +} + +size_t FileTransferContent::getFileSize () const { + L_D(); + return d->fileSize; +} + +void FileTransferContent::setFileKey (const char *key, size_t size) { + L_D(); + d->fileKey = vector(key, key + size); +} + +const vector &FileTransferContent::getFileKey () const { + L_D(); + return d->fileKey; +} + +size_t FileTransferContent::getFileKeySize() const { + L_D(); + return d->fileKey.size(); +} + +bool FileTransferContent::isFile () const { + return false; +} + +bool FileTransferContent::isFileTransfer () const { + return true; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/file-transfer-content.h b/src/content/file-transfer-content.h new file mode 100644 index 000000000..4ae07867b --- /dev/null +++ b/src/content/file-transfer-content.h @@ -0,0 +1,73 @@ +/* + * file-transfer-content.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_FILE_TRANSFER_CONTENT_H_ +#define _L_FILE_TRANSFER_CONTENT_H_ + +#include + +#include "content.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class FileContent; +class FileTransferContentPrivate; + +class LINPHONE_PUBLIC FileTransferContent : public Content { +public: + FileTransferContent (); + FileTransferContent (const FileTransferContent &other); + FileTransferContent (FileTransferContent &&other); + + FileTransferContent &operator= (const FileTransferContent &other); + FileTransferContent &operator= (FileTransferContent &&other); + + bool operator== (const FileTransferContent &other) const; + + void setFileName (const std::string &name); + const std::string &getFileName () const; + + void setFileUrl (const std::string &url); + const std::string &getFileUrl () const; + + void setFilePath (const std::string &path); + const std::string &getFilePath () const; + + void setFileContent (FileContent *content); + FileContent *getFileContent () const; + + void setFileSize (size_t size); + size_t getFileSize () const; + + void setFileKey (const char *key, size_t size); + const std::vector &getFileKey () const; + size_t getFileKeySize() const; + + bool isFile () const override; + bool isFileTransfer () const override; + +private: + L_DECLARE_PRIVATE(FileTransferContent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_FILE_TRANSFER_CONTENT_H_ diff --git a/src/content/header/header-p.h b/src/content/header/header-p.h new file mode 100644 index 000000000..fd4663efe --- /dev/null +++ b/src/content/header/header-p.h @@ -0,0 +1,43 @@ +/* + * header-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_HEADER_P_H_ +#define _L_HEADER_P_H_ + +#include + +#include "object/clonable-object-p.h" + +#include "header.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class HeaderPrivate : public ClonableObjectPrivate { +private: + std::string name; + std::string value; + std::list parameters; + L_DECLARE_PUBLIC(Header); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_HEADER_P_H_ \ No newline at end of file diff --git a/src/content/header/header-param.cpp b/src/content/header/header-param.cpp new file mode 100644 index 000000000..9605a2f84 --- /dev/null +++ b/src/content/header/header-param.cpp @@ -0,0 +1,108 @@ +/* + * header-param.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "header-param.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class HeaderParamPrivate : public ClonableObjectPrivate { +public: + string name; + string value; +}; + +// ----------------------------------------------------------------------------- + +HeaderParam::HeaderParam (const string ¶m) : ClonableObject(*new HeaderParamPrivate) { + size_t pos = param.find("="); + size_t end = param.length(); + + if (pos == string::npos) { + setName(param); + } else { + setName(param.substr(0, pos)); + setValue(param.substr(pos + 1, end - (pos + 1))); + } +} + +HeaderParam::HeaderParam (const string &name, const string &value) : ClonableObject(*new HeaderParamPrivate) { + setName(name); + setValue(value); +} + +HeaderParam::HeaderParam (const HeaderParam &other) : HeaderParam(other.getName(), other.getValue()) {} + +HeaderParam &HeaderParam::operator= (const HeaderParam &other) { + if (this != &other) { + setName(other.getName()); + setValue(other.getValue()); + } + + return *this; +} + +bool HeaderParam::operator== (const HeaderParam &other) const { + return getName() == other.getName() && + getValue() == other.getValue(); +} + +bool HeaderParam::operator!= (const HeaderParam &other) const { + return !(*this == other); +} + +const string &HeaderParam::getName () const { + L_D(); + return d->name; +} + +bool HeaderParam::setName (const string &name) { + L_D(); + d->name = name; + return true; +} + +const string &HeaderParam::getValue () const { + L_D(); + return d->value; +} + +bool HeaderParam::setValue (const string &value) { + L_D(); + d->value = value; + return true; +} + +string HeaderParam::asString () const { + L_D(); + string asString = ";" + d->name; + if (!d->value.empty()) + asString += "=" + d->value; + return asString; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/header/header-param.h b/src/content/header/header-param.h new file mode 100644 index 000000000..a9471b486 --- /dev/null +++ b/src/content/header/header-param.h @@ -0,0 +1,61 @@ +/* + * header-param.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_HEADER_PARAM_H_ +#define _L_HEADER_PARAM_H_ + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class HeaderParamPrivate; + +class LINPHONE_PUBLIC HeaderParam : public ClonableObject { +public: + explicit HeaderParam (const std::string &header = ""); + HeaderParam (const std::string &name, const std::string &value); + HeaderParam (const HeaderParam &other); + + HeaderParam &operator= (const HeaderParam &other); + + bool operator== (const HeaderParam &other) const; + bool operator!= (const HeaderParam &other) const; + + // Delete these operators to prevent putting complicated content-type strings + // in the code. Instead define static const HeaderParam objects below. + bool operator== (const std::string &other) const = delete; + bool operator!= (const std::string &other) const = delete; + + const std::string &getName () const; + bool setName (const std::string &name); + + const std::string &getValue () const; + bool setValue (const std::string &value); + + std::string asString () const; + +private: + L_DECLARE_PRIVATE(HeaderParam); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_HEADER_PARAM_H_ diff --git a/src/content/header/header.cpp b/src/content/header/header.cpp new file mode 100644 index 000000000..519ae2db3 --- /dev/null +++ b/src/content/header/header.cpp @@ -0,0 +1,183 @@ +/* + * header.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/utils.h" +#include "linphone/utils/algorithm.h" + +#include "header-p.h" +#include "header-param.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +Header::Header(HeaderPrivate &p) : ClonableObject(p) {} + +Header::Header() : ClonableObject(*new HeaderPrivate) {} + +Header::Header (const string &name, const string &value) : ClonableObject(*new HeaderPrivate) { + setName(name); + + size_t posParam = value.find(";"); + if (posParam == string::npos) { + setValue(value); + return; + } + + string parsedValue = value.substr(0, posParam); + string params = value.substr(posParam + 1); + string token; + do { + posParam = params.find(";"); + if (posParam == string::npos) { + token = params; + } else { + token = params.substr(0, posParam); + } + addParameter(HeaderParam(token)); + params.erase(0, posParam + 1); + } while (posParam != std::string::npos); + + setValue(parsedValue); +} + +Header::Header (const string &name, const string &value, const list ¶ms) : Header(name, value) { + addParameters(params); +} + +Header::Header (const Header &other) : Header(other.getName(), other.getValue(), other.getParameters()) {} + +Header &Header::operator= (const Header &other) { + if (this != &other) { + setName(other.getName()); + setValue(other.getValue()); + cleanParameters(); + addParameters(other.getParameters()); + } + + return *this; +} + +bool Header::operator== (const Header &other) const { + return getName() == other.getName() && + getValue() == other.getValue(); +} + +bool Header::operator!= (const Header &other) const { + return !(*this == other); +} + +void Header::setName (const string &name) { + L_D(); + d->name = name; +} + +string Header::getName () const { + L_D(); + return d->name; +} + +void Header::setValue (const string &value) { + L_D(); + d->value = value; +} + +string Header::getValue () const { + L_D(); + return d->value; +} + +void Header::cleanParameters () { + L_D(); + d->parameters.clear(); +} + +const list &Header::getParameters () const { + L_D(); + return d->parameters; +} + +void Header::addParameter (const string ¶mName, const string ¶mValue) { + addParameter(HeaderParam(paramName, paramValue)); +} + +void Header::addParameter (const HeaderParam ¶m) { + L_D(); + removeParameter(param); + d->parameters.push_back(param); +} + +void Header::addParameters(const list ¶ms) { + for (auto it = std::begin(params); it!=std::end(params); ++it) { + HeaderParam param = *it; + addParameter(param.getName(), param.getValue()); + } +} + +void Header::removeParameter (const string ¶mName) { + L_D(); + auto it = findParameter(paramName); + if (it != d->parameters.cend()) + d->parameters.remove(*it); +} + +void Header::removeParameter (const HeaderParam ¶m) { + removeParameter(param.getName()); +} + +list::const_iterator Header::findParameter (const string ¶mName) const { + L_D(); + return findIf(d->parameters, [¶mName](const HeaderParam ¶m) { + return param.getName() == paramName; + }); +} + +const HeaderParam &Header::getParameter (const string ¶mName) const { + L_D(); + list::const_iterator it = findParameter(paramName); + if (it != d->parameters.cend()) { + return *it; + } + return Utils::getEmptyConstRefObject(); +} + +string Header::asString () const { + stringstream asString; + if (!getName().empty()) { + asString << getName() << ":"; + } + asString << getValue(); + for (const auto ¶m : getParameters()) { + asString << param.asString(); + } + return asString.str(); +} + +ostream &operator<< (ostream &os, const Header& header) { + os << header.asString(); + return os; +} + +LINPHONE_END_NAMESPACE diff --git a/src/content/header/header.h b/src/content/header/header.h new file mode 100644 index 000000000..e0541538a --- /dev/null +++ b/src/content/header/header.h @@ -0,0 +1,75 @@ +/* + * header.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_HEADER_H_ +#define _L_HEADER_H_ + +#include + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class HeaderPrivate; +class HeaderParam; + +class LINPHONE_PUBLIC Header : public ClonableObject { +public: + Header (); + Header (const std::string &name, const std::string &value); + Header (const std::string &name, const std::string &value, const std::list ¶ms); + Header (const Header &other); + + Header &operator= (const Header &other); + + bool operator== (const Header &other) const; + bool operator!= (const Header &other) const; + + void setName (const std::string &name); + std::string getName () const; + + void setValue (const std::string &value); + std::string getValue () const; + + void cleanParameters (); + const std::list &getParameters () const; + void addParameter (const std::string ¶mName, const std::string ¶mValue); + void addParameter (const HeaderParam ¶m); + void addParameters(const std::list ¶ms); + void removeParameter (const std::string ¶mName); + void removeParameter (const HeaderParam ¶m); + std::list::const_iterator findParameter (const std::string ¶mName) const; + const HeaderParam &getParameter (const std::string ¶mName) const; + + std::string asString () const; + + LINPHONE_PUBLIC friend std::ostream &operator<< (std::ostream &os, const Header &header); + +protected: + explicit Header (HeaderPrivate &p); + +private: + L_DECLARE_PRIVATE(Header); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_HEADER_H_ diff --git a/src/core/core-accessor.cpp b/src/core/core-accessor.cpp new file mode 100644 index 000000000..92c26a7c6 --- /dev/null +++ b/src/core/core-accessor.cpp @@ -0,0 +1,65 @@ +/* + * core-accessor.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "logger/logger.h" + +#include "core-accessor.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class CoreAccessorPrivate { +public: + weak_ptr core; +}; + +// ----------------------------------------------------------------------------- + +CoreAccessor::CoreAccessor (const shared_ptr &core) { + L_ASSERT(core); + mPrivate = new CoreAccessorPrivate(); + mPrivate->core = core; +} + +CoreAccessor::CoreAccessor (const shared_ptr &&core) { + L_ASSERT(core); + mPrivate = new CoreAccessorPrivate(); + mPrivate->core = move(core); +} + +CoreAccessor::~CoreAccessor () { + delete mPrivate; +} + +shared_ptr CoreAccessor::getCore () const { + L_D(); + + shared_ptr core = d->core.lock(); + if (!core) { + lWarning() << "Unable to get valid core instance."; + throw bad_weak_ptr(); + } + + return core; +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/core-accessor.h b/src/core/core-accessor.h new file mode 100644 index 000000000..0461e253c --- /dev/null +++ b/src/core/core-accessor.h @@ -0,0 +1,52 @@ +/* + * core-accessor.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CORE_ACCESSOR_H_ +#define _L_CORE_ACCESSOR_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Core; +class CoreAccessorPrivate; + +// Decorator to get a valid core instance. +class LINPHONE_PUBLIC CoreAccessor { +public: + CoreAccessor (const std::shared_ptr &core); + CoreAccessor (const std::shared_ptr &&core); + + virtual ~CoreAccessor () = 0; + + // Returns a valid core instance. Or throw one std::bad_weak_ptr exception if core is destroyed. + std::shared_ptr getCore () const; + +private: + CoreAccessorPrivate *mPrivate = nullptr; + + L_DISABLE_COPY(CoreAccessor); + L_DECLARE_PRIVATE(CoreAccessor); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CORE_ACCESSOR_H_ diff --git a/src/core/core-call.cpp b/src/core/core-call.cpp new file mode 100644 index 000000000..119db552b --- /dev/null +++ b/src/core/core-call.cpp @@ -0,0 +1,322 @@ +/* + * core-call.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "core-p.h" +#include "call/call-p.h" +#include "conference/session/call-session-p.h" +#include "logger/logger.h" + +// TODO: Remove me later. +#include "c-wrapper/c-wrapper.h" +#include "conference_private.h" + +#include + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +int CorePrivate::addCall (const shared_ptr &call) { + L_Q(); + L_ASSERT(call); + if (!canWeAddCall()) + return -1; + if (!hasCalls()) + notifySoundcardUsage(true); + calls.push_back(call); + linphone_core_notify_call_created(q->getCCore(), L_GET_C_BACK_PTR(call)); + return 0; +} + +bool CorePrivate::canWeAddCall () const { + L_Q(); + if (q->getCallCount() < static_cast(q->getCCore()->max_calls)) + return true; + lInfo() << "Maximum amount of simultaneous calls reached!"; + return false; +} + +bool CorePrivate::inviteReplacesABrokenCall (SalCallOp *op) { + CallSession *replacedSession = nullptr; + SalCallOp *replacedOp = op->getReplaces(); + if (replacedOp) + replacedSession = reinterpret_cast(replacedOp->getUserPointer()); + for (const auto &call : calls) { + shared_ptr session = call->getPrivate()->getActiveSession(); + if (session + && ((session->getPrivate()->isBroken() && op->compareOp(session->getPrivate()->getOp())) + || (replacedSession == session.get() && op->getFrom() == replacedOp->getFrom() && op->getTo() == replacedOp->getTo()) + )) { + session->getPrivate()->replaceOp(op); + return true; + } + } + + return false; +} + +bool CorePrivate::isAlreadyInCallWithAddress (const Address &addr) const { + for (const auto &call : calls) { + if (call->getRemoteAddress().weakEqual(addr)) + return true; + } + return false; +} + +void CorePrivate::iterateCalls (time_t currentRealTime, bool oneSecondElapsed) const { + // Make a copy of the list af calls because it may be altered during calls to the Call::iterate method + list> savedCalls(calls); + for (const auto &call : savedCalls) { + call->getPrivate()->iterate(currentRealTime, oneSecondElapsed); + } +} + +void CorePrivate::notifySoundcardUsage (bool used) { + L_Q(); + MSSndCard *card = q->getCCore()->sound_conf.capt_sndcard; + if (card && (ms_snd_card_get_capabilities(card) & MS_SND_CARD_CAP_IS_SLOW)) + ms_snd_card_set_usage_hint(card, used); +} + +int CorePrivate::removeCall (const shared_ptr &call) { + L_ASSERT(call); + auto iter = find(calls.begin(), calls.end(), call); + if (iter == calls.end()) { + lWarning() << "Could not find the call to remove"; + return -1; + } + calls.erase(iter); + return 0; +} + +void CorePrivate::unsetVideoWindowId (bool preview, void *id) { +#ifdef VIDEO_ENABLED + for (const auto &call : calls) { + VideoStream *vstream = reinterpret_cast(call->getPrivate()->getMediaStream(LinphoneStreamTypeVideo)); + if (vstream) { + if (preview) + video_stream_set_native_preview_window_id(vstream, id); + else + video_stream_set_native_window_id(vstream, id); + } + } +#endif +} + +// ----------------------------------------------------------------------------- + +void CorePrivate::parameterizeEqualizer (AudioStream *stream) { + L_Q(); + LinphoneConfig *config = linphone_core_get_config(q->getCCore()); + const char *eqActive = lp_config_get_string(config, "sound", "eq_active", nullptr); + if (eqActive) + lWarning() << "'eq_active' linphonerc parameter has no effect anymore. Please use 'mic_eq_active' or 'spk_eq_active' instead"; + const char *eqGains = lp_config_get_string(config, "sound", "eq_gains", nullptr); + if(eqGains) + lWarning() << "'eq_gains' linphonerc parameter has no effect anymore. Please use 'mic_eq_gains' or 'spk_eq_gains' instead"; + if (stream->mic_equalizer) { + MSFilter *f = stream->mic_equalizer; + bool enabled = !!lp_config_get_int(config, "sound", "mic_eq_active", 0); + ms_filter_call_method(f, MS_EQUALIZER_SET_ACTIVE, &enabled); + const char *gains = lp_config_get_string(config, "sound", "mic_eq_gains", nullptr); + if (enabled && gains) { + bctbx_list_t *gainsList = ms_parse_equalizer_string(gains); + for (bctbx_list_t *it = gainsList; it; it = bctbx_list_next(it)) { + MSEqualizerGain *g = reinterpret_cast(bctbx_list_get_data(it)); + lInfo() << "Read microphone equalizer gains: " << g->frequency << "(~" << g->width << ") --> " << g->gain; + ms_filter_call_method(f, MS_EQUALIZER_SET_GAIN, g); + } + if (gainsList) + bctbx_list_free_with_data(gainsList, ms_free); + } + } + if (stream->spk_equalizer) { + MSFilter *f = stream->spk_equalizer; + bool enabled = !!lp_config_get_int(config, "sound", "spk_eq_active", 0); + ms_filter_call_method(f, MS_EQUALIZER_SET_ACTIVE, &enabled); + const char *gains = lp_config_get_string(config, "sound", "spk_eq_gains", nullptr); + if (enabled && gains) { + bctbx_list_t *gainsList = ms_parse_equalizer_string(gains); + for (bctbx_list_t *it = gainsList; it; it = bctbx_list_next(it)) { + MSEqualizerGain *g = reinterpret_cast(bctbx_list_get_data(it)); + lInfo() << "Read speaker equalizer gains: " << g->frequency << "(~" << g->width << ") --> " << g->gain; + ms_filter_call_method(f, MS_EQUALIZER_SET_GAIN, g); + } + if (gainsList) + bctbx_list_free_with_data(gainsList, ms_free); + } + } +} + +void CorePrivate::postConfigureAudioStream (AudioStream *stream, bool muted) { + L_Q(); + float micGain = q->getCCore()->sound_conf.soft_mic_lev; + if (muted) + audio_stream_set_mic_gain(stream, 0); + else + audio_stream_set_mic_gain_db(stream, micGain); + float recvGain = q->getCCore()->sound_conf.soft_play_lev; + if (static_cast(recvGain)) + setPlaybackGainDb(stream, recvGain); + LinphoneConfig *config = linphone_core_get_config(q->getCCore()); + float ngThres = lp_config_get_float(config, "sound", "ng_thres", 0.05f); + float ngFloorGain = lp_config_get_float(config, "sound", "ng_floorgain", 0); + if (stream->volsend) { + int dcRemoval = lp_config_get_int(config, "sound", "dc_removal", 0); + ms_filter_call_method(stream->volsend, MS_VOLUME_REMOVE_DC, &dcRemoval); + float speed = lp_config_get_float(config, "sound", "el_speed", -1); + float thres = lp_config_get_float(config, "sound", "el_thres", -1); + float force = lp_config_get_float(config, "sound", "el_force", -1); + int sustain = lp_config_get_int(config, "sound", "el_sustain", -1); + float transmitThres = lp_config_get_float(config, "sound", "el_transmit_thres", -1); + if (static_cast(speed) == -1) + speed = 0.03f; + if (static_cast(force) == -1) + force = 25; + MSFilter *f = stream->volsend; + ms_filter_call_method(f, MS_VOLUME_SET_EA_SPEED, &speed); + ms_filter_call_method(f, MS_VOLUME_SET_EA_FORCE, &force); + if (static_cast(thres) != -1) + ms_filter_call_method(f, MS_VOLUME_SET_EA_THRESHOLD, &thres); + if (static_cast(sustain) != -1) + ms_filter_call_method(f, MS_VOLUME_SET_EA_SUSTAIN, &sustain); + if (static_cast(transmitThres) != -1) + ms_filter_call_method(f, MS_VOLUME_SET_EA_TRANSMIT_THRESHOLD, &transmitThres); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_THRESHOLD, &ngThres); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_FLOORGAIN, &ngFloorGain); + } + if (stream->volrecv) { + /* Parameters for a limited noise-gate effect, using echo limiter threshold */ + float floorGain = (float)(1 / pow(10, micGain / 10)); + int spkAgc = lp_config_get_int(config, "sound", "speaker_agc_enabled", 0); + MSFilter *f = stream->volrecv; + ms_filter_call_method(f, MS_VOLUME_ENABLE_AGC, &spkAgc); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_THRESHOLD, &ngThres); + ms_filter_call_method(f, MS_VOLUME_SET_NOISE_GATE_FLOORGAIN, &floorGain); + } + parameterizeEqualizer(stream); +} + +void CorePrivate::setPlaybackGainDb (AudioStream *stream, float gain) { + if (stream->volrecv) + ms_filter_call_method(stream->volrecv, MS_VOLUME_SET_DB_GAIN, &gain); + else + lWarning() << "Could not apply playback gain: gain control wasn't activated"; +} + +// ============================================================================= + +bool Core::areSoundResourcesLocked () const { + L_D(); + for (const auto &call : d->calls) { + if (call->mediaInProgress()) + return true; + switch (call->getState()) { + case CallSession::State::OutgoingInit: + case CallSession::State::OutgoingProgress: + case CallSession::State::OutgoingRinging: + case CallSession::State::OutgoingEarlyMedia: + case CallSession::State::Connected: + case CallSession::State::Referred: + case CallSession::State::IncomingEarlyMedia: + case CallSession::State::Updating: + lInfo() << "Call " << call << " is locking sound resources"; + return true; + default: + break; + } + } + return false; +} + +shared_ptr Core::getCallByRemoteAddress (const Address &addr) const { + L_D(); + for (const auto &call : d->calls) { + if (call->getRemoteAddress().weakEqual(addr)) + return call; + } + return nullptr; +} + +const list> &Core::getCalls () const { + L_D(); + return d->calls; +} + +unsigned int Core::getCallCount () const { + L_D(); + return static_cast(d->calls.size()); +} + +shared_ptr Core::getCurrentCall () const { + L_D(); + return d->currentCall; +} + +LinphoneStatus Core::pauseAllCalls () { + L_D(); + for (const auto &call : d->calls) { + if ((call->getState() == CallSession::State::StreamsRunning) || (call->getState() == CallSession::State::PausedByRemote)) + call->pause(); + } + return 0; +} + +void Core::soundcardHintCheck () { + L_D(); + bool noNeedForSound = true; + // Check if the remaining calls are paused + for (const auto &call : d->calls) { + if ((call->getState() != CallSession::State::Pausing) + && (call->getState() != CallSession::State::Paused) + && (call->getState() != CallSession::State::End) + && (call->getState() != CallSession::State::Error)) { + noNeedForSound = false; + break; + } + } + // If no more calls or all calls are paused, we can free the soundcard + LinphoneConfig *config = linphone_core_get_config(L_GET_C_BACK_PTR(this)); + bool useRtpIo = !!lp_config_get_int(config, "sound", "rtp_io", FALSE); + bool useRtpIoEnableLocalOutput = !!lp_config_get_int(config, "sound", "rtp_io_enable_local_output", FALSE); + + LinphoneConference *conf_ctx = getCCore()->conf_ctx; + if (conf_ctx && linphone_conference_get_size(conf_ctx) >= 1) return; + + if ((!d->hasCalls() || noNeedForSound) + && (!L_GET_C_BACK_PTR(getSharedFromThis())->use_files && (!useRtpIo || (useRtpIo && useRtpIoEnableLocalOutput)))) { + lInfo() << "Notifying soundcard that we don't need it anymore for calls"; + d->notifySoundcardUsage(false); + } +} + +LinphoneStatus Core::terminateAllCalls () { + L_D(); + while (!d->calls.empty()) { + d->calls.front()->terminate(); + } + return 0; +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/core-chat-room.cpp b/src/core/core-chat-room.cpp new file mode 100644 index 000000000..c4282c6b6 --- /dev/null +++ b/src/core/core-chat-room.cpp @@ -0,0 +1,336 @@ +/* + * core-chat-room.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "address/identity-address.h" +#include "chat/chat-room/basic-chat-room.h" +#include "chat/chat-room/basic-to-client-group-chat-room.h" +#include "chat/chat-room/chat-room-p.h" +#include "chat/chat-room/client-group-chat-room-p.h" +#include "chat/chat-room/client-group-to-basic-chat-room.h" +#include "chat/chat-room/real-time-text-chat-room.h" +#include "conference/participant.h" +#include "core-p.h" +#include "logger/logger.h" + +// TODO: Remove me later. +#include "c-wrapper/c-wrapper.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- +// Helpers. +// ----------------------------------------------------------------------------- + +// Return the better local address to talk with peer address. +static IdentityAddress getDefaultLocalAddress (const shared_ptr &core, const IdentityAddress &peerAddress) { + LinphoneCore *cCore = core->getCCore(); + + LinphoneAddress *cPeerAddress = linphone_address_new(peerAddress.asString().c_str()); + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(cCore, cPeerAddress); + linphone_address_unref(cPeerAddress); + + IdentityAddress localAddress; + if (proxy) { + char *identity = linphone_address_as_string(linphone_proxy_config_get_identity_address(proxy)); + localAddress = IdentityAddress(identity); + bctbx_free(identity); + } else + localAddress = IdentityAddress(linphone_core_get_primary_contact(cCore)); + + return localAddress; +} + +// ----------------------------------------------------------------------------- + +shared_ptr CorePrivate::createBasicChatRoom ( + const ChatRoomId &chatRoomId, + ChatRoom::CapabilitiesMask capabilities +) { + L_Q(); + + shared_ptr chatRoom; + + if (capabilities & ChatRoom::Capabilities::RealTimeText) + chatRoom.reset(new RealTimeTextChatRoom(q->getSharedFromThis(), chatRoomId)); + else { + BasicChatRoom *basicChatRoom = new BasicChatRoom(q->getSharedFromThis(), chatRoomId); + LinphoneAddress *lAddr = linphone_address_new(chatRoomId.getLocalAddress().asString().c_str()); + LinphoneProxyConfig *proxy = linphone_core_lookup_known_proxy(q->getCCore(), lAddr); + linphone_address_unref(lAddr); + const char *conferenceFactoryUri = nullptr; + if (proxy) + conferenceFactoryUri = linphone_proxy_config_get_conference_factory_uri(proxy); + if ( + capabilities & ChatRoom::Capabilities::Migratable && + conferenceFactoryUri && + linphone_config_get_bool(linphone_core_get_config(q->getCCore()), + "misc", "enable_basic_to_client_group_chat_room_migration", FALSE) + ) + chatRoom.reset(new BasicToClientGroupChatRoom(shared_ptr(basicChatRoom))); + else + chatRoom.reset(basicChatRoom); + } + + AbstractChatRoomPrivate *dChatRoom = chatRoom->getPrivate(); + dChatRoom->setState(ChatRoom::State::Instantiated); + dChatRoom->setState(ChatRoom::State::Created); + + return chatRoom; +} + +shared_ptr CorePrivate::createClientGroupChatRoom (const string &subject, const string &uri, const Content &content, bool fallback) { + L_Q(); + + string usedUri; + string from; + { + LinphoneProxyConfig *proxy = nullptr; + if (uri.empty()) { + proxy = linphone_core_get_default_proxy_config(q->getCCore()); + if (!proxy) + return nullptr; + const char *conferenceFactoryUri = linphone_proxy_config_get_conference_factory_uri(proxy); + if (!conferenceFactoryUri) + return nullptr; + usedUri = conferenceFactoryUri; + } else { + LinphoneAddress *addr = linphone_address_new(uri.c_str()); + proxy = linphone_core_lookup_known_proxy(q->getCCore(), addr); + linphone_address_unref(addr); + usedUri = uri; + } + if (proxy) { + const LinphoneAddress *contactAddr = linphone_proxy_config_get_contact(proxy); + if (contactAddr) { + char *cFrom = linphone_address_as_string(contactAddr); + from = string(cFrom); + bctbx_free(cFrom); + } else + from = L_GET_CPP_PTR_FROM_C_OBJECT(linphone_proxy_config_get_identity_address(proxy))->asString(); + } + } + + shared_ptr chatRoom; + { + shared_ptr clientGroupChatRoom = make_shared( + q->getSharedFromThis(), usedUri, IdentityAddress(from), subject, content + ); + ClientGroupChatRoomPrivate *dClientGroupChatRoom = clientGroupChatRoom->getPrivate(); + + if (fallback) { + // Create a ClientGroupToBasicChatRoom to handle fallback from ClientGroupChatRoom to BasicGroupChatRoom if + // only one participant is invited and that it does not support group chat + chatRoom = make_shared(clientGroupChatRoom); + dClientGroupChatRoom->setCallSessionListener(chatRoom->getPrivate()); + dClientGroupChatRoom->setChatRoomListener(chatRoom->getPrivate()); + } else + chatRoom = clientGroupChatRoom; + } + chatRoom->getPrivate()->setState(ChatRoom::State::Instantiated); + + noCreatedClientGroupChatRooms[chatRoom.get()] = chatRoom; + + return chatRoom; +} + +void CorePrivate::insertChatRoom (const shared_ptr &chatRoom) { + L_ASSERT(chatRoom); + + const ChatRoomId &chatRoomId = chatRoom->getChatRoomId(); + auto it = chatRoomsById.find(chatRoomId); + // Chat room not exist or yes but with the same pointer! + L_ASSERT(it == chatRoomsById.end() || it->second == chatRoom); + if (it == chatRoomsById.end()) { + // Remove chat room from workaround cache. + noCreatedClientGroupChatRooms.erase(chatRoom.get()); + + chatRooms.push_back(chatRoom); + chatRoomsById[chatRoomId] = chatRoom; + } +} + +void CorePrivate::insertChatRoomWithDb (const shared_ptr &chatRoom, unsigned int notifyId) { + L_ASSERT(chatRoom->getState() == ChatRoom::State::Created); + mainDb->insertChatRoom(chatRoom, notifyId); +} + +void CorePrivate::loadChatRooms () { + chatRooms.clear(); + chatRoomsById.clear(); + for (auto &chatRoom : mainDb->getChatRooms()) { + insertChatRoom(chatRoom); + chatRoom->getPrivate()->sendDeliveryNotifications(); + } +} + +void CorePrivate::replaceChatRoom (const shared_ptr &replacedChatRoom, const shared_ptr &newChatRoom) { + const ChatRoomId &replacedChatRoomId = replacedChatRoom->getChatRoomId(); + const ChatRoomId &newChatRoomId = newChatRoom->getChatRoomId(); + if (replacedChatRoom->getCapabilities() & ChatRoom::Capabilities::Proxy) { + chatRooms.remove(newChatRoom); + chatRoomsById.erase(newChatRoomId); + chatRoomsById[newChatRoomId] = replacedChatRoom; + } else { + chatRooms.remove(replacedChatRoom); + chatRoomsById.erase(replacedChatRoomId); + chatRoomsById[newChatRoomId] = newChatRoom; + } +} + +// ----------------------------------------------------------------------------- + +const list> &Core::getChatRooms () const { + L_D(); + return d->chatRooms; +} + +shared_ptr Core::findChatRoom (const ChatRoomId &chatRoomId) const { + L_D(); + + auto it = d->chatRoomsById.find(chatRoomId); + if (it != d->chatRoomsById.cend()) + return it->second; + + lInfo() << "Unable to find chat room in RAM: " << chatRoomId << "."; + return nullptr; +} + +list> Core::findChatRooms (const IdentityAddress &peerAddress) const { + L_D(); + + list> output; + copy_if( + d->chatRooms.begin(), d->chatRooms.end(), + back_inserter(output), [&peerAddress](const shared_ptr &chatRoom) { + return chatRoom->getPeerAddress() == peerAddress; + } + ); + + return output; +} + +shared_ptr Core::findOneToOneChatRoom ( + const IdentityAddress &localAddress, + const IdentityAddress &participantAddress +) const { + L_D(); + for (const auto &chatRoom : d->chatRooms) { + const IdentityAddress &curLocalAddress = chatRoom->getLocalAddress(); + ChatRoom::CapabilitiesMask capabilities = chatRoom->getCapabilities(); + + // We are looking for a one to one chatroom + // Do not return a group chat room that everyone except one person has left + if (!(capabilities & ChatRoom::Capabilities::OneToOne)) + continue; + + // One to one client group chat room + // The only participant's address must match the participantAddress argument + if ( + (capabilities & ChatRoom::Capabilities::Conference) && + !chatRoom->getParticipants().empty() && + localAddress == curLocalAddress && + participantAddress.getAddressWithoutGruu() == chatRoom->getParticipants().front()->getAddress() + ) + return chatRoom; + + // One to one basic chat room (addresses without gruu) + // The peer address must match the participantAddress argument + if ( + (capabilities & ChatRoom::Capabilities::Basic) && + localAddress.getAddressWithoutGruu() == curLocalAddress.getAddressWithoutGruu() && + participantAddress.getAddressWithoutGruu() == chatRoom->getPeerAddress().getAddressWithoutGruu() + ) + return chatRoom; + } + return nullptr; +} + +shared_ptr Core::createClientGroupChatRoom (const string &subject, bool fallback) { + L_D(); + return d->createClientGroupChatRoom(subject, "", Content(), fallback); +} + +shared_ptr Core::getOrCreateBasicChatRoom (const ChatRoomId &chatRoomId, bool isRtt) { + L_D(); + + shared_ptr chatRoom = findChatRoom(chatRoomId); + if (chatRoom) + return chatRoom; + + chatRoom = d->createBasicChatRoom(chatRoomId, + isRtt ? ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::RealTimeText) : ChatRoom::CapabilitiesMask() + ); + d->insertChatRoom(chatRoom); + d->insertChatRoomWithDb(chatRoom); + + return chatRoom; +} + +shared_ptr Core::getOrCreateBasicChatRoom (const IdentityAddress &peerAddress, bool isRtt) { + L_D(); + + list> chatRooms = findChatRooms(peerAddress); + if (!chatRooms.empty()) + return chatRooms.front(); + + shared_ptr chatRoom = d->createBasicChatRoom( + ChatRoomId(peerAddress, getDefaultLocalAddress(getSharedFromThis(), peerAddress)), + isRtt ? ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::RealTimeText) : ChatRoom::CapabilitiesMask() + ); + d->insertChatRoom(chatRoom); + d->insertChatRoomWithDb(chatRoom); + + return chatRoom; +} + +shared_ptr Core::getOrCreateBasicChatRoomFromUri (const string &peerAddress, bool isRtt) { + LinphoneAddress *address = linphone_core_interpret_url(getCCore(), L_STRING_TO_C(peerAddress)); + if (!address) { + lError() << "Cannot make a valid address with: `" << peerAddress << "`."; + return nullptr; + } + + shared_ptr chatRoom = getOrCreateBasicChatRoom(*L_GET_CPP_PTR_FROM_C_OBJECT(address), isRtt); + linphone_address_unref(address); + return chatRoom; +} + +void Core::deleteChatRoom (const shared_ptr &chatRoom) { + CorePrivate *d = chatRoom->getCore()->getPrivate(); + + d->noCreatedClientGroupChatRooms.erase(chatRoom.get()); + const ChatRoomId &chatRoomId = chatRoom->getChatRoomId(); + auto chatRoomsByIdIt = d->chatRoomsById.find(chatRoomId); + if (chatRoomsByIdIt != d->chatRoomsById.end()) { + auto chatRoomsIt = find(d->chatRooms.begin(), d->chatRooms.end(), chatRoom); + L_ASSERT(chatRoomsIt != d->chatRooms.end()); + d->chatRooms.erase(chatRoomsIt); + d->chatRoomsById.erase(chatRoomsByIdIt); + d->mainDb->deleteChatRoom(chatRoomId); + } +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/core-listener.h b/src/core/core-listener.h new file mode 100644 index 000000000..53784f59e --- /dev/null +++ b/src/core/core-listener.h @@ -0,0 +1,42 @@ +/* + * core-listener.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CORE_LISTENER_H_ +#define _L_CORE_LISTENER_H_ + +#include "linphone/types.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CoreListener { +public: + virtual ~CoreListener () = default; + + virtual void onGlobalStateChanged (LinphoneGlobalState state) {} + virtual void onNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) {} + virtual void onRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message) {} + virtual void onEnteringBackground () {} + virtual void onEnteringForeground () {} +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CORE_LISTENER_H_ diff --git a/src/core/core-p.h b/src/core/core-p.h new file mode 100644 index 000000000..d740ff4be --- /dev/null +++ b/src/core/core-p.h @@ -0,0 +1,96 @@ +/* + * core-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CORE_P_H_ +#define _L_CORE_P_H_ + +#include "chat/chat-room/abstract-chat-room.h" +#include "core.h" +#include "db/main-db.h" +#include "object/object-p.h" +#include "sal/call-op.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class CoreListener; +class LocalConferenceListEventHandler; +class RemoteConferenceListEventHandler; + +class CorePrivate : public ObjectPrivate { +public: + void init (); + void registerListener (CoreListener *listener); + void unregisterListener (CoreListener *listener); + void uninit (); + + void notifyGlobalStateChanged (LinphoneGlobalState state); + void notifyNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable); + void notifyRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const std::string &message); + void notifyEnteringBackground (); + void notifyEnteringForeground (); + + int addCall (const std::shared_ptr &call); + bool canWeAddCall () const; + bool hasCalls () const { return !calls.empty(); } + bool inviteReplacesABrokenCall (SalCallOp *op); + bool isAlreadyInCallWithAddress (const Address &addr) const; + void iterateCalls (time_t currentRealTime, bool oneSecondElapsed) const; + void notifySoundcardUsage (bool used); + int removeCall (const std::shared_ptr &call); + void setCurrentCall (const std::shared_ptr &call) { currentCall = call; } + void unsetVideoWindowId (bool preview, void *id); + + void parameterizeEqualizer (AudioStream *stream); + void postConfigureAudioStream (AudioStream *stream, bool muted); + void setPlaybackGainDb (AudioStream *stream, float gain); + + void loadChatRooms (); + void insertChatRoom (const std::shared_ptr &chatRoom); + void insertChatRoomWithDb (const std::shared_ptr &chatRoom, unsigned int notifyId = 0); + std::shared_ptr createBasicChatRoom (const ChatRoomId &chatRoomId, AbstractChatRoom::CapabilitiesMask capabilities); + std::shared_ptr createClientGroupChatRoom (const std::string &subject, const std::string &uri = "", const Content &content = Content(), bool fallback = true); + void replaceChatRoom (const std::shared_ptr &replacedChatRoom, const std::shared_ptr &newChatRoom); + + std::unique_ptr mainDb; + std::unique_ptr remoteListEventHandler; + std::unique_ptr localListEventHandler; + +private: + bool isInBackground = false; + + std::list listeners; + + std::list> calls; + std::shared_ptr currentCall; + + std::list> chatRooms; + + std::unordered_map> chatRoomsById; + + // Ugly cache to deal with C code. + std::unordered_map> noCreatedClientGroupChatRooms; + + L_DECLARE_PUBLIC(Core); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CORE_P_H_ diff --git a/src/core/core.cpp b/src/core/core.cpp index 2d4e9696e..834d74d45 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -1,11 +1,11 @@ /* * core.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,24 +13,176 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "object/object-p.h" +#include +#include -#include "core.h" +//#include "linphone/utils/general.h" + +#include "address/address-p.h" +#include "call/call.h" +#include "conference/handlers/local-conference-list-event-handler.h" +#include "conference/handlers/remote-conference-list-event-handler.h" +#include "core/core-listener.h" +#include "core/core-p.h" +#include "logger/logger.h" +#include "paths/paths.h" + +// TODO: Remove me later. +#include "c-wrapper/c-wrapper.h" +#include "private.h" + +#define LINPHONE_DB "linphone.db" // ============================================================================= +using namespace std; + LINPHONE_BEGIN_NAMESPACE -class CorePrivate : public ObjectPrivate { -public: - // TODO. -}; +void CorePrivate::init () { + L_Q(); + mainDb.reset(new MainDb(q->getSharedFromThis())); + remoteListEventHandler = makeUnique(q->getSharedFromThis()); + localListEventHandler = makeUnique(q->getSharedFromThis()); + + AbstractDb::Backend backend; + string uri = L_C_TO_STRING(lp_config_get_string(linphone_core_get_config(L_GET_C_BACK_PTR(q)), "storage", "uri", nullptr)); + if (!uri.empty()) + backend = strcmp(lp_config_get_string(linphone_core_get_config(L_GET_C_BACK_PTR(q)), "storage", "backend", nullptr), "mysql") == 0 + ? MainDb::Mysql + : MainDb::Sqlite3; + else { + backend = AbstractDb::Sqlite3; + uri = q->getDataPath() + LINPHONE_DB; + } + + lInfo() << "Opening linphone database: " << uri; + if (!mainDb->connect(backend, uri)) + lFatal() << "Unable to open linphone database."; + + loadChatRooms(); +} + +void CorePrivate::registerListener (CoreListener *listener) { + listeners.push_back(listener); +} + +void CorePrivate::unregisterListener (CoreListener *listener) { + listeners.remove(listener); +} + +void CorePrivate::uninit () { + L_Q(); + while (!calls.empty()) { + calls.front()->terminate(); + linphone_core_iterate(L_GET_C_BACK_PTR(q)); + ms_usleep(10000); + } + + chatRooms.clear(); + chatRoomsById.clear(); + noCreatedClientGroupChatRooms.clear(); + + remoteListEventHandler = nullptr; + localListEventHandler = nullptr; + + AddressPrivate::clearSipAddressesCache(); +} // ----------------------------------------------------------------------------- -Core::Core (CorePrivate &p) : Object(p) {} +void CorePrivate::notifyGlobalStateChanged (LinphoneGlobalState state) { + auto listenersCopy = listeners; // Allow removable of a listener in its own call + for (const auto &listener : listenersCopy) + listener->onGlobalStateChanged(state); +} + +void CorePrivate::notifyNetworkReachable (bool sipNetworkReachable, bool mediaNetworkReachable) { + auto listenersCopy = listeners; // Allow removable of a listener in its own call + for (const auto &listener : listenersCopy) + listener->onNetworkReachable(sipNetworkReachable, mediaNetworkReachable); +} + +void CorePrivate::notifyRegistrationStateChanged (LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const string &message) { + auto listenersCopy = listeners; // Allow removable of a listener in its own call + for (const auto &listener : listenersCopy) + listener->onRegistrationStateChanged(cfg, state, message); +} + +void CorePrivate::notifyEnteringBackground () { + if (isInBackground) + return; + + isInBackground = true; + auto listenersCopy = listeners; // Allow removable of a listener in its own call + for (const auto &listener : listenersCopy) + listener->onEnteringBackground(); +} + +void CorePrivate::notifyEnteringForeground () { + if (!isInBackground) + return; + + isInBackground = false; + auto listenersCopy = listeners; // Allow removable of a listener in its own call + for (const auto &listener : listenersCopy) + listener->onEnteringForeground(); +} + +// ============================================================================= + +Core::Core () : Object(*new CorePrivate) { + xercesc::XMLPlatformUtils::Initialize(); +} + +Core::~Core () { + lInfo() << "Destroying core: " << this; + xercesc::XMLPlatformUtils::Terminate(); +} + +shared_ptr Core::create (LinphoneCore *cCore) { + // Do not use `make_shared` => Private constructor. + shared_ptr core = shared_ptr(new Core); + L_SET_CPP_PTR_FROM_C_OBJECT(cCore, core); + return core; +} + +// --------------------------------------------------------------------------- +// Application lifecycle. +// --------------------------------------------------------------------------- + +void Core::enterBackground () { + L_D(); + d->notifyEnteringBackground(); +} + +void Core::enterForeground () { + L_D(); + d->notifyEnteringForeground(); +} + +// --------------------------------------------------------------------------- +// C-Core. +// --------------------------------------------------------------------------- + +LinphoneCore *Core::getCCore () const { + return L_GET_C_BACK_PTR(this); +} + +// ----------------------------------------------------------------------------- +// Paths. +// ----------------------------------------------------------------------------- + +string Core::getDataPath() const { + return Paths::getPath(Paths::Data, static_cast(L_GET_C_BACK_PTR(this)->platform_helper)); +} + +string Core::getConfigPath() const { + return Paths::getPath(Paths::Config, static_cast(L_GET_C_BACK_PTR(this)->platform_helper)); +} LINPHONE_END_NAMESPACE diff --git a/src/core/core.h b/src/core/core.h index 1d4874c31..ba9356e55 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -1,11 +1,11 @@ /* * core.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,26 +13,129 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CORE_H_ -#define _CORE_H_ +#ifndef _L_CORE_H_ +#define _L_CORE_H_ + +#include #include "object/object.h" +#include "linphone/types.h" + // ============================================================================= +L_DECL_C_STRUCT(LinphoneCore); + LINPHONE_BEGIN_NAMESPACE +class Address; +class Call; +class ChatRoomId; class CorePrivate; +class IdentityAddress; +class AbstractChatRoom; class LINPHONE_PUBLIC Core : public Object { + friend class BasicToClientGroupChatRoom; + friend class BasicToClientGroupChatRoomPrivate; + friend class CallPrivate; + friend class CallSession; + friend class ChatMessage; + friend class ChatMessagePrivate; + friend class ChatRoom; + friend class ChatRoomPrivate; + friend class ClientGroupChatRoom; + friend class ClientGroupChatRoomPrivate; + friend class ClientGroupToBasicChatRoomPrivate; + friend class Imdn; + friend class LocalConferenceEventHandlerPrivate; + friend class MainDb; + friend class MainDbChatMessageKey; + friend class MainDbEventKey; + friend class MediaSessionPrivate; + friend class RealTimeTextChatRoomPrivate; + friend class RemoteConferenceEventHandler; + friend class RemoteConferenceListEventHandler; + friend class ServerGroupChatRoom; + friend class ServerGroupChatRoomPrivate; + public: - // Nothing for the moment. + L_OVERRIDE_SHARED_FROM_THIS(Core); + + ~Core (); + + // Return a new Core instance. Entry point of Linphone. + static std::shared_ptr create (LinphoneCore *cCore); + + // --------------------------------------------------------------------------- + // Application lifecycle. + // --------------------------------------------------------------------------- + + void enterBackground (); + void enterForeground (); + + // --------------------------------------------------------------------------- + // C-Core. + // --------------------------------------------------------------------------- + + // TODO: Remove me later. + LinphoneCore *getCCore () const; + + // --------------------------------------------------------------------------- + // Call. + // --------------------------------------------------------------------------- + + bool areSoundResourcesLocked () const; + std::shared_ptr getCallByRemoteAddress (const Address &addr) const; + const std::list> &getCalls () const; + unsigned int getCallCount () const; + std::shared_ptr getCurrentCall () const; + LinphoneStatus pauseAllCalls (); + void soundcardHintCheck (); + LinphoneStatus terminateAllCalls (); + + // --------------------------------------------------------------------------- + // ChatRoom. + // --------------------------------------------------------------------------- + + const std::list> &getChatRooms () const; + + std::shared_ptr findChatRoom (const ChatRoomId &chatRoomId) const; + std::list> findChatRooms (const IdentityAddress &peerAddress) const; + + std::shared_ptr findOneToOneChatRoom ( + const IdentityAddress &localAddress, + const IdentityAddress &participantAddress + ) const; + + std::shared_ptr createClientGroupChatRoom (const std::string &subject, bool fallback = true); + std::shared_ptr createClientGroupChatRoom ( + const std::string &subject, + const IdentityAddress &localAddress + ); + + std::shared_ptr getOrCreateBasicChatRoom (const ChatRoomId &chatRoomId, bool isRtt = false); + + // TODO: Remove me in the future, a chatroom is identified by a local and peer address now! + std::shared_ptr getOrCreateBasicChatRoom (const IdentityAddress &peerAddress, bool isRtt = false); + + std::shared_ptr getOrCreateBasicChatRoomFromUri (const std::string &uri, bool isRtt = false); + + static void deleteChatRoom (const std::shared_ptr &chatRoom); + + // --------------------------------------------------------------------------- + // Paths. + // --------------------------------------------------------------------------- + + std::string getDataPath() const; + std::string getConfigPath() const; private: - Core (CorePrivate &p); + Core (); L_DECLARE_PRIVATE(Core); L_DISABLE_COPY(Core); @@ -40,4 +143,4 @@ private: LINPHONE_END_NAMESPACE -#endif // ifndef _CORE_H_ +#endif // ifndef _L_CORE_H_ diff --git a/src/core/paths/paths-android.cpp b/src/core/paths/paths-android.cpp new file mode 100644 index 000000000..72ffa0bd8 --- /dev/null +++ b/src/core/paths/paths-android.cpp @@ -0,0 +1,44 @@ +/* + * paths-android.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "core/platform-helpers/platform-helpers.h" + +#include "paths-android.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +string SysPaths::getDataPath (PlatformHelpers *platformHelpers) { + if (!platformHelpers) + return ""; + return platformHelpers->getDataPath(); +} + +string SysPaths::getConfigPath (PlatformHelpers *platformHelpers) { + if (!platformHelpers) + return ""; + return platformHelpers->getConfigPath(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/paths/paths-android.h b/src/core/paths/paths-android.h new file mode 100644 index 000000000..828c5147b --- /dev/null +++ b/src/core/paths/paths-android.h @@ -0,0 +1,40 @@ +/* + * paths-android.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PATHS_ANDROID_H_ +#define _L_PATHS_ANDROID_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class PlatformHelpers; + +namespace SysPaths { + LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers); + LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PATHS_ANDROID_H_ diff --git a/src/core/paths/paths-apple.h b/src/core/paths/paths-apple.h new file mode 100644 index 000000000..fd1c8f6eb --- /dev/null +++ b/src/core/paths/paths-apple.h @@ -0,0 +1,40 @@ +/* + * paths-apple.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PATHS_APPLE_H_ +#define _L_PATHS_APPLE_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class PlatformHelpers; + +namespace SysPaths { + LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers); + LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PATHS_APPLE_H_ diff --git a/src/core/paths/paths-apple.mm b/src/core/paths/paths-apple.mm new file mode 100644 index 000000000..94c0e886b --- /dev/null +++ b/src/core/paths/paths-apple.mm @@ -0,0 +1,66 @@ +/* + * paths-apple.mm + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#import + +#import "logger/logger.h" + +#import "paths-apple.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +std::string SysPaths::getDataPath (PlatformHelpers *) { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); + NSString *writablePath = [paths objectAtIndex:0]; + NSString *fullPath = [writablePath stringByAppendingString:@"/linphone/"]; + if (![[NSFileManager defaultManager] fileExistsAtPath:fullPath]) { + NSError *error; + lInfo() << "Data path " << fullPath.UTF8String << " does not exist, creating it."; + if (![[NSFileManager defaultManager] createDirectoryAtPath:fullPath + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + lError() << "Create data path directory error: " << error.description; + } + } + + return fullPath.UTF8String; +} + +std::string SysPaths::getConfigPath (PlatformHelpers *) { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); + NSString *configPath = [paths objectAtIndex:0]; + NSString *fullPath = [configPath stringByAppendingString:@"/Preferences/linphone/"]; + if (![[NSFileManager defaultManager] fileExistsAtPath:fullPath]) { + NSError *error; + lInfo() << "Config path " << fullPath.UTF8String << " does not exist, creating it."; + if (![[NSFileManager defaultManager] createDirectoryAtPath:fullPath + withIntermediateDirectories:YES + attributes:nil + error:&error]) { + lError() << "Create config path directory error: " << error.description; + } + } + + return fullPath.UTF8String; +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/paths/paths-linux.cpp b/src/core/paths/paths-linux.cpp new file mode 100644 index 000000000..09bd962b5 --- /dev/null +++ b/src/core/paths/paths-linux.cpp @@ -0,0 +1,51 @@ +/* + * paths-linux.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "logger/logger.h" + +#include "paths-linux.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +static string getBaseDirectory () { + static string base; + if (base.empty()) { + char *dir = getenv("HOME"); + if (!dir) + lFatal() << "Unable to get home directory."; + base = dir; + } + return base; +} + +string SysPaths::getDataPath (PlatformHelpers *) { + static string dataPath = getBaseDirectory() + "/.local/share/linphone/"; + return dataPath; +} + +string SysPaths::getConfigPath (PlatformHelpers *) { + static string configPath = getBaseDirectory() + "/.config/linphone/"; + return configPath; +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/paths/paths-linux.h b/src/core/paths/paths-linux.h new file mode 100644 index 000000000..d5bc59977 --- /dev/null +++ b/src/core/paths/paths-linux.h @@ -0,0 +1,40 @@ +/* + * paths-linux.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PATHS_LINUX_H_ +#define _L_PATHS_LINUX_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class PlatformHelpers; + +namespace SysPaths { + LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers); + LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PATHS_LINUX_H_ diff --git a/src/core/paths/paths-windows.cpp b/src/core/paths/paths-windows.cpp new file mode 100644 index 000000000..65b6ba26c --- /dev/null +++ b/src/core/paths/paths-windows.cpp @@ -0,0 +1,61 @@ +/* + * paths-windows.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#pragma comment(lib, "comsuppw.lib") +#pragma comment(lib, "kernel32.lib") + +#include "core/platform-helpers/platform-helpers.h" + +#include "paths-windows.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +static string getPath (const GUID &id) { + string strPath; + + LPWSTR path; + if (SHGetKnownFolderPath(id, KF_FLAG_DONT_VERIFY, 0, &path) == S_OK) { + strPath = _bstr_t(path); + replace(strPath.begin(), strPath.end(), '\\', '/'); + CoTaskMemFree(path); + } + + return strPath.append("/linphone/"); +} + + +string SysPaths::getDataPath (PlatformHelpers *) { + static string dataPath = getPath(FOLDERID_LocalAppData); + return dataPath; +} + +string SysPaths::getConfigPath (PlatformHelpers *platformHelpers) { + // Yes, same path. + return getDataPath(platformHelpers); +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/paths/paths-windows.h b/src/core/paths/paths-windows.h new file mode 100644 index 000000000..1ee9d92f7 --- /dev/null +++ b/src/core/paths/paths-windows.h @@ -0,0 +1,40 @@ +/* + * paths-windws.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PATHS_WINDOWS_H_ +#define _L_PATHS_WINDOWS_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class PlatformHelpers; + +namespace SysPaths { + LINPHONE_PUBLIC std::string getDataPath (PlatformHelpers *platformHelpers); + LINPHONE_PUBLIC std::string getConfigPath (PlatformHelpers *platformHelpers); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PATHS_WINDOWS_H_ diff --git a/src/core/paths/paths.cpp b/src/core/paths/paths.cpp new file mode 100644 index 000000000..3f5dd2374 --- /dev/null +++ b/src/core/paths/paths.cpp @@ -0,0 +1,53 @@ +/* + * utils.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "core/platform-helpers/platform-helpers.h" +#include "paths.h" + +#ifdef __APPLE__ + #include "paths-apple.h" +#elif defined(__ANDROID__) + #include "paths-android.h" +#elif defined(_WIN32) + #include "paths-windows.h" +#elif defined(__linux) + #include "paths-linux.h" +#else + #error "Unsupported system." +#endif // ifdef __APPLE__ + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +string Paths::getPath (Paths::Type type, PlatformHelpers *platformHelpers) { + switch (type) { + case Data: + return SysPaths::getDataPath(platformHelpers); + case Config: + return SysPaths::getConfigPath(platformHelpers); + } + + L_ASSERT(false); + return ""; +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/paths/paths.h b/src/core/paths/paths.h new file mode 100644 index 000000000..f7fdf9b5b --- /dev/null +++ b/src/core/paths/paths.h @@ -0,0 +1,43 @@ +/* + * paths.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PATHS_H_ +#define _L_PATHS_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class PlatformHelpers; +namespace Paths { + enum Type { + Data, + Config + }; + + LINPHONE_PUBLIC std::string getPath (Type type, PlatformHelpers *platformHelpers); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PATHS_H_ diff --git a/src/core/platform-helpers/android-platform-helpers.cpp b/src/core/platform-helpers/android-platform-helpers.cpp new file mode 100644 index 000000000..bf9e7a991 --- /dev/null +++ b/src/core/platform-helpers/android-platform-helpers.cpp @@ -0,0 +1,232 @@ +/* + * android-platform-helpers.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "platform-helpers.h" +#include "logger/logger.h" + +// TODO: Remove me later. +#include "private.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class AndroidPlatformHelpers : public PlatformHelpers { +public: + AndroidPlatformHelpers (LinphoneCore *lc, void *systemContext); + ~AndroidPlatformHelpers (); + + void setDnsServers () override; + void acquireWifiLock () override; + void releaseWifiLock () override; + void acquireMcastLock () override; + void releaseMcastLock () override; + void acquireCpuLock () override; + void releaseCpuLock () override; + string getDataPath () override; + string getConfigPath () override; + +private: + int callVoidMethod (jmethodID id); + static jmethodID getMethodId (JNIEnv *env, jclass klass, const char *method, const char *signature); + string getNativeLibraryDir(); + jobject mJavaHelper; + jmethodID mWifiLockAcquireId; + jmethodID mWifiLockReleaseId; + jmethodID mMcastLockAcquireId; + jmethodID mMcastLockReleaseId; + jmethodID mCpuLockAcquireId; + jmethodID mCpuLockReleaseId; + jmethodID mGetDnsServersId; + jmethodID mGetPowerManagerId; + jmethodID mGetDataPathId; + jmethodID mGetConfigPathId; + jmethodID mGetNativeLibraryDirId; +}; + +static const char *GetStringUTFChars (JNIEnv *env, jstring string) { + const char *cstring = string ? env->GetStringUTFChars(string, nullptr) : nullptr; + return cstring; +} + +static void ReleaseStringUTFChars (JNIEnv *env, jstring string, const char *cstring) { + if (string) env->ReleaseStringUTFChars(string, cstring); +} + +jmethodID AndroidPlatformHelpers::getMethodId (JNIEnv *env, jclass klass, const char *method, const char *signature) { + jmethodID id = env->GetMethodID(klass, method, signature); + if (id == 0) + lFatal() << "Could not find java method: `" << method << ", " << signature << "`."; + return id; +} + +AndroidPlatformHelpers::AndroidPlatformHelpers (LinphoneCore *lc, void *systemContext) : PlatformHelpers(lc) { + JNIEnv *env = ms_get_jni_env(); + jclass klass = env->FindClass("org/linphone/core/tools/AndroidPlatformHelper"); + if (!klass) + lFatal() << "Could not find java AndroidPlatformHelper class."; + + jmethodID ctor = env->GetMethodID(klass, "", "(Ljava/lang/Object;)V"); + mJavaHelper = env->NewObject(klass, ctor, (jobject)systemContext); + if (!mJavaHelper) { + lError() << "Could not instanciate AndroidPlatformHelper object."; + return; + } + mJavaHelper = (jobject)env->NewGlobalRef(mJavaHelper); + + mWifiLockAcquireId = getMethodId(env, klass, "acquireWifiLock", "()V"); + mWifiLockReleaseId = getMethodId(env, klass, "releaseWifiLock", "()V"); + mMcastLockAcquireId = getMethodId(env, klass, "acquireMcastLock", "()V"); + mMcastLockReleaseId = getMethodId(env, klass, "releaseMcastLock", "()V"); + mCpuLockAcquireId = getMethodId(env, klass, "acquireCpuLock", "()V"); + mCpuLockReleaseId = getMethodId(env, klass, "releaseCpuLock", "()V"); + mGetDnsServersId = getMethodId(env, klass, "getDnsServers", "()[Ljava/lang/String;"); + mGetPowerManagerId = getMethodId(env, klass, "getPowerManager", "()Ljava/lang/Object;"); + mGetDataPathId = getMethodId(env, klass, "getDataPath", "()Ljava/lang/String;"); + mGetConfigPathId = getMethodId(env, klass, "getConfigPath", "()Ljava/lang/String;"); + mGetNativeLibraryDirId = getMethodId(env, klass, "getNativeLibraryDir", "()Ljava/lang/String;"); + + jobject pm = env->CallObjectMethod(mJavaHelper, mGetPowerManagerId); + belle_sip_wake_lock_init(env, pm); + + linphone_factory_set_top_resources_dir(linphone_factory_get() , getDataPath().append("share").c_str()); + linphone_factory_set_msplugins_dir(linphone_factory_get(), getNativeLibraryDir().c_str()); + lInfo() << "AndroidPlatformHelpers is fully initialised."; +} + +AndroidPlatformHelpers::~AndroidPlatformHelpers () { + if (mJavaHelper) { + JNIEnv *env = ms_get_jni_env(); + belle_sip_wake_lock_uninit(env); + env->DeleteGlobalRef(mJavaHelper); + mJavaHelper = nullptr; + } + lInfo() << "AndroidPlatformHelpers has been destroyed."; +} + +void AndroidPlatformHelpers::setDnsServers () { + if (!mJavaHelper || linphone_core_get_dns_set_by_app(mCore)) { + lError() << "AndroidPlatformHelpers' mJavaHelper is null."; + return; + } + JNIEnv *env = ms_get_jni_env(); + if (env && mJavaHelper) { + jobjectArray jservers = (jobjectArray)env->CallObjectMethod(mJavaHelper, mGetDnsServersId); + bctbx_list_t *l = nullptr; + if (env->ExceptionCheck()) { + env->ExceptionClear(); + lError() << "AndroidPlatformHelpers::setDnsServers() exception."; + return; + } + if (jservers != nullptr) { + int count = env->GetArrayLength(jservers); + + for (int i = 0; i < count; i++) { + jstring jserver = (jstring)env->GetObjectArrayElement(jservers, i); + const char *str = env->GetStringUTFChars(jserver, nullptr); + if (str) { + lInfo() << "AndroidPlatformHelpers found DNS server " << str; + l = bctbx_list_append(l, ms_strdup(str)); + env->ReleaseStringUTFChars(jserver, str); + } + } + } else { + lError() << "AndroidPlatformHelpers::setDnsServers() failed to get DNS servers list"; + } + linphone_core_set_dns_servers(mCore, l); + bctbx_list_free_with_data(l, ms_free); + } +} + +void AndroidPlatformHelpers::acquireWifiLock () { + callVoidMethod(mWifiLockAcquireId); +} + +void AndroidPlatformHelpers::releaseWifiLock () { + callVoidMethod(mWifiLockReleaseId); +} + +void AndroidPlatformHelpers::acquireMcastLock () { + callVoidMethod(mMcastLockAcquireId); +} + +void AndroidPlatformHelpers::releaseMcastLock () { + callVoidMethod(mMcastLockReleaseId); +} + +void AndroidPlatformHelpers::acquireCpuLock () { + callVoidMethod(mCpuLockAcquireId); +} + +void AndroidPlatformHelpers::releaseCpuLock () { + callVoidMethod(mCpuLockReleaseId); +} + +string AndroidPlatformHelpers::getDataPath () { + JNIEnv *env = ms_get_jni_env(); + jstring jdata_path = (jstring)env->CallObjectMethod(mJavaHelper, mGetDataPathId); + const char *data_path = GetStringUTFChars(env, jdata_path); + string dataPath = data_path; + ReleaseStringUTFChars(env, jdata_path, data_path); + return dataPath + "/"; +} + +string AndroidPlatformHelpers::getNativeLibraryDir () { + JNIEnv *env = ms_get_jni_env(); + string libPath; + jstring jlib_path = (jstring)env->CallObjectMethod(mJavaHelper, mGetNativeLibraryDirId); + if (jlib_path){ + const char *lib_path = GetStringUTFChars(env, jlib_path); + libPath = lib_path; + ReleaseStringUTFChars(env, jlib_path, lib_path); + } + return libPath; +} + +string AndroidPlatformHelpers::getConfigPath () { + JNIEnv *env = ms_get_jni_env(); + jstring jconfig_path = (jstring)env->CallObjectMethod(mJavaHelper, mGetConfigPathId); + const char *config_path = GetStringUTFChars(env, jconfig_path); + string configPath = config_path; + ReleaseStringUTFChars(env, jconfig_path, config_path); + return configPath + "/"; +} + +int AndroidPlatformHelpers::callVoidMethod (jmethodID id) { + JNIEnv *env = ms_get_jni_env(); + if (env && mJavaHelper) { + env->CallVoidMethod(mJavaHelper, id); + if (env->ExceptionCheck()) { + env->ExceptionClear(); + return -1; + } else + return 0; + } else + return -1; +} + +PlatformHelpers *createAndroidPlatformHelpers (LinphoneCore *lc, void *systemContext) { + return new AndroidPlatformHelpers(lc, systemContext); +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/platform-helpers/ios-platform-helpers.cpp b/src/core/platform-helpers/ios-platform-helpers.cpp new file mode 100644 index 000000000..57d14b21f --- /dev/null +++ b/src/core/platform-helpers/ios-platform-helpers.cpp @@ -0,0 +1,149 @@ +/* +linphone +Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifdef __APPLE__ +#include "TargetConditionals.h" +#endif +#if TARGET_OS_IPHONE + +#include + +#include + +#include "linphone/utils/general.h" +#include "linphone/utils/utils.h" + +#include "logger/logger.h" +#include "platform-helpers.h" + +// TODO: Remove me +#include "private.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class IosPlatformHelpers : public PlatformHelpers { +public: + IosPlatformHelpers (LinphoneCore *lc, void *system_context); + ~IosPlatformHelpers () = default; + + void setDnsServers () override {} + void acquireWifiLock () override {} + void releaseWifiLock () override {} + void acquireMcastLock () override {} + void releaseMcastLock () override {} + void acquireCpuLock () override; + void releaseCpuLock () override; + string getDataPath () override {return Utils::getEmptyConstRefObject();} + string getConfigPath () override {return Utils::getEmptyConstRefObject();} + +private: + void bgTaskTimeout (); + static void sBgTaskTimeout (void *data); + static std::string directoryForResource (CFStringRef framework, CFStringRef resource); + + long int mCpuLockTaskId; + int mCpuLockCount; +}; + +// ============================================================================= + +IosPlatformHelpers::IosPlatformHelpers (LinphoneCore *lc, void *system_context) : PlatformHelpers(lc) { + mCpuLockCount = 0; + mCpuLockTaskId = 0; + + std::string cpimPath = directoryForResource(CFSTR("org.linphone.linphone"), CFSTR("cpim_grammar")); + std::string vcardPath = directoryForResource(CFSTR("org.linphone.belcard"), CFSTR("vcard_grammar")); + if (!cpimPath.empty()) + belr::GrammarLoader::get().addPath(cpimPath); + else + lError() << "IosPlatformHelpers did not find cpim grammar resource directory..."; + + if (!vcardPath.empty()) + belr::GrammarLoader::get().addPath(vcardPath); + else + lError() << "IosPlatformHelpers did not find vcard grammar resource directory..."; + + lInfo() << "IosPlatformHelpers is fully initialised."; +} + +// ----------------------------------------------------------------------------- + +void IosPlatformHelpers::bgTaskTimeout () { + lError() << "IosPlatformHelpers: the system requests that the cpu lock is released now."; + if (mCpuLockTaskId != 0) { + belle_sip_end_background_task(static_cast(mCpuLockTaskId)); + mCpuLockTaskId = 0; + } +} + +void IosPlatformHelpers::sBgTaskTimeout (void *data) { + IosPlatformHelpers *zis = static_cast(data); + zis->bgTaskTimeout(); +} + +// ----------------------------------------------------------------------------- + +void IosPlatformHelpers::acquireCpuLock () { + // on iOS, cpu lock is implemented by a long running task and it is abstracted by belle-sip, so let's use belle-sip directly. + if (mCpuLockCount == 0) + mCpuLockTaskId = static_cast(belle_sip_begin_background_task("Liblinphone cpu lock", sBgTaskTimeout, this)); + + mCpuLockCount++; +} + +void IosPlatformHelpers::releaseCpuLock () { + mCpuLockCount--; + if (mCpuLockCount != 0) + return; + + if (mCpuLockTaskId == 0) { + lError() << "IosPlatformHelpers::releaseCpuLock(): too late, the lock has been released already by the system."; + return; + } + + belle_sip_end_background_task(static_cast(mCpuLockTaskId)); + mCpuLockTaskId = 0; +} + +std::string IosPlatformHelpers::directoryForResource (CFStringRef framework, CFStringRef resource) { + CFBundleRef bundle = CFBundleGetBundleWithIdentifier(framework); + CFURLRef grammarUrl = CFBundleCopyResourceURL(bundle, resource, nullptr, nullptr); + CFURLRef grammarUrlDirectory = CFURLCreateCopyDeletingLastPathComponent(nullptr, grammarUrl); + CFStringRef grammarPath = CFURLCopyFileSystemPath(grammarUrlDirectory, kCFURLPOSIXPathStyle); + CFStringEncoding encodingMethod = CFStringGetSystemEncoding(); + std::string path(CFStringGetCStringPtr(grammarPath, encodingMethod)); + CFRelease(grammarUrl); + CFRelease(grammarPath); + CFRelease(grammarUrlDirectory); + return path; +} + +// ----------------------------------------------------------------------------- + +PlatformHelpers *createIosPlatformHelpers (LinphoneCore *lc, void *system_context) { + return new IosPlatformHelpers(lc, system_context); +} + +LINPHONE_END_NAMESPACE + +#endif diff --git a/src/core/platform-helpers/platform-helpers.cpp b/src/core/platform-helpers/platform-helpers.cpp new file mode 100644 index 000000000..851ee48d5 --- /dev/null +++ b/src/core/platform-helpers/platform-helpers.cpp @@ -0,0 +1,52 @@ +/* + * platform-helpers.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "platform-helpers.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +StubbedPlatformHelpers::StubbedPlatformHelpers (LinphoneCore *lc) : PlatformHelpers(lc) {} + +void StubbedPlatformHelpers::setDnsServers () {} + +void StubbedPlatformHelpers::acquireWifiLock () {} + +void StubbedPlatformHelpers::releaseWifiLock () {} + +void StubbedPlatformHelpers::acquireMcastLock () {} + +void StubbedPlatformHelpers::releaseMcastLock () {} + +void StubbedPlatformHelpers::acquireCpuLock () {} + +void StubbedPlatformHelpers::releaseCpuLock () {} + +string StubbedPlatformHelpers::getDataPath () { + return ""; +} + +string StubbedPlatformHelpers::getConfigPath () { + return ""; +} + +LINPHONE_END_NAMESPACE diff --git a/src/core/platform-helpers/platform-helpers.h b/src/core/platform-helpers/platform-helpers.h new file mode 100644 index 000000000..6a55c8756 --- /dev/null +++ b/src/core/platform-helpers/platform-helpers.h @@ -0,0 +1,79 @@ +/* + * platform-helpers.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PLATFORM_HELPERS_H_ +#define _L_PLATFORM_HELPERS_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +L_DECL_C_STRUCT(LinphoneCore); + +LINPHONE_BEGIN_NAMESPACE + +/** + * This interface aims at abstracting some features offered by the platform, most often mobile platforms. + * A per platform implementation is to be made to implement these features, if available on the platform. + */ +class PlatformHelpers { +public: + virtual ~PlatformHelpers () = default; + + // This method shall retrieve DNS server list from the platform and assign it to the core. + virtual void setDnsServers () = 0; + virtual void acquireWifiLock () = 0; + virtual void releaseWifiLock () = 0; + virtual void acquireMcastLock () = 0; + virtual void releaseMcastLock () = 0; + virtual void acquireCpuLock () = 0; + virtual void releaseCpuLock () = 0; + virtual std::string getDataPath () = 0; + virtual std::string getConfigPath () = 0; + +protected: + inline explicit PlatformHelpers (LinphoneCore *lc) : mCore(lc) {} + + LinphoneCore *mCore; +}; + +class StubbedPlatformHelpers : public PlatformHelpers { +public: + explicit StubbedPlatformHelpers (LinphoneCore *lc); + virtual ~StubbedPlatformHelpers () = default; + + void setDnsServers () override; + void acquireWifiLock () override; + void releaseWifiLock () override; + void acquireMcastLock () override; + void releaseMcastLock () override; + void acquireCpuLock () override; + void releaseCpuLock () override; + std::string getDataPath () override; + std::string getConfigPath () override; +}; + +PlatformHelpers *createAndroidPlatformHelpers (LinphoneCore *lc, void *systemContext); +PlatformHelpers *createIosPlatformHelpers (LinphoneCore *lc, void *systemContext); + +LINPHONE_END_NAMESPACE + +#endif // indef _L_PLATFORM_HELPERS_H_ diff --git a/src/cpim/cpim.h b/src/cpim/cpim.h deleted file mode 100644 index a2aa0a824..000000000 --- a/src/cpim/cpim.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * cpim.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CPIM_H_ -#define _CPIM_H_ - -#include "message/cpim-message.h" - -// ============================================================================= - -#endif // ifndef _CPIM_H_ diff --git a/src/cpim/header/cpim-core-headers.cpp b/src/cpim/header/cpim-core-headers.cpp deleted file mode 100644 index 6270b810a..000000000 --- a/src/cpim/header/cpim-core-headers.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * cpim-core-headers.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cpim-header-p.h" -#include "cpim/parser/cpim-parser.h" - -#include "cpim-core-headers.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -Cpim::CoreHeader::CoreHeader () : Header(*new HeaderPrivate) {} - -Cpim::CoreHeader::CoreHeader (HeaderPrivate &p) : Header(p) {} - -Cpim::CoreHeader::~CoreHeader () {} - -bool Cpim::CoreHeader::isValid () const { - return !getValue().empty(); -} - -// ----------------------------------------------------------------------------- - -#define MAKE_CORE_HEADER_IMPL(CLASS_PREFIX) \ - bool Cpim::CLASS_PREFIX ## Header::setValue(const string &value) { \ - return Parser::getInstance()->coreHeaderIsValid(value) && Header::setValue(value); \ - } - -MAKE_CORE_HEADER_IMPL(From); -MAKE_CORE_HEADER_IMPL(To); -MAKE_CORE_HEADER_IMPL(Cc); -MAKE_CORE_HEADER_IMPL(DateTime); - -MAKE_CORE_HEADER_IMPL(Ns); -MAKE_CORE_HEADER_IMPL(Require); - -#undef MAKE_CORE_HEADER_IMPL - -// ----------------------------------------------------------------------------- - -void Cpim::CoreHeader::force (const string &value) { - Header::setValue(value); -} - -// ----------------------------------------------------------------------------- - -class Cpim::SubjectHeaderPrivate : public HeaderPrivate { -public: - string language; -}; - -Cpim::SubjectHeader::SubjectHeader () : CoreHeader(*new SubjectHeaderPrivate) {} - -bool Cpim::SubjectHeader::setValue (const string &value) { - return Parser::getInstance()->coreHeaderIsValid(value) && Header::setValue(value); -} - -string Cpim::SubjectHeader::getLanguage () const { - L_D(const SubjectHeader); - return d->language; -} - -bool Cpim::SubjectHeader::setLanguage (const string &language) { - if (!language.empty() && !Parser::getInstance()->subjectHeaderLanguageIsValid(language)) - return false; - - L_D(SubjectHeader); - d->language = language; - - return true; -} - -string Cpim::SubjectHeader::asString () const { - L_D(const SubjectHeader); - - string languageParam; - if (!d->language.empty()) - languageParam = ";lang=" + d->language; - - return getName() + ":" + languageParam + " " + getValue() + "\r\n"; -} - -void Cpim::SubjectHeader::force (const string &value, const string &language) { - L_D(SubjectHeader); - CoreHeader::force(value); - d->language = language; -} - -LINPHONE_END_NAMESPACE diff --git a/src/cpim/header/cpim-core-headers.h b/src/cpim/header/cpim-core-headers.h deleted file mode 100644 index 15519e5b5..000000000 --- a/src/cpim/header/cpim-core-headers.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * cpim-core-headers.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CPIM_CORE_HEADERS_H_ -#define _CPIM_CORE_HEADERS_H_ - -#include "cpim-header.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -#define MAKE_CORE_HEADER(CLASS_PREFIX, NAME) \ - class LINPHONE_PUBLIC CLASS_PREFIX ## Header : public CoreHeader { \ - public: \ - CLASS_PREFIX ## Header() = default; \ - inline std::string getName() const override { \ - return NAME; \ - } \ - bool setValue(const std::string &value) override; \ - private: \ - L_DISABLE_COPY(CLASS_PREFIX ## Header); \ - }; - -namespace Cpim { - class HeaderNode; - - // ------------------------------------------------------------------------- - // Generic core header. - // ------------------------------------------------------------------------- - - class LINPHONE_PUBLIC CoreHeader : public Header { - friend class HeaderNode; - - public: - CoreHeader (); - - virtual ~CoreHeader () = 0; - - bool isValid () const override; - - protected: - explicit CoreHeader (HeaderPrivate &p); - - void force (const std::string &value); - - private: - L_DISABLE_COPY(CoreHeader); - }; - - // ------------------------------------------------------------------------- - // Core headers. - // ------------------------------------------------------------------------- - - MAKE_CORE_HEADER(From, "From"); - MAKE_CORE_HEADER(To, "To"); - MAKE_CORE_HEADER(Cc, "cc"); - MAKE_CORE_HEADER(DateTime, "DateTime"); - MAKE_CORE_HEADER(Ns, "NS"); - MAKE_CORE_HEADER(Require, "Require"); - - // ------------------------------------------------------------------------- - // Specific Subject declaration. - // ------------------------------------------------------------------------- - - class SubjectHeaderPrivate; - - class LINPHONE_PUBLIC SubjectHeader : public CoreHeader { - friend class HeaderNode; - - public: - SubjectHeader (); - - inline std::string getName () const override { - return "Subject"; - } - - bool setValue (const std::string &value) override; - - std::string getLanguage () const; - bool setLanguage (const std::string &language); - - std::string asString () const override; - - protected: - void force (const std::string &value, const std::string &language); - - private: - L_DECLARE_PRIVATE(SubjectHeader); - L_DISABLE_COPY(SubjectHeader); - }; -} - -#undef MAKE_CORE_HEADER - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CPIM_CORE_HEADERS_H_ diff --git a/src/cpim/header/cpim-generic-header.cpp b/src/cpim/header/cpim-generic-header.cpp deleted file mode 100644 index 040a17e7f..000000000 --- a/src/cpim/header/cpim-generic-header.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - * cpim-generic-header.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "cpim-header-p.h" -#include "cpim/parser/cpim-parser.h" -#include "utils/utils.h" - -#include "cpim-generic-header.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -class Cpim::GenericHeaderPrivate : public HeaderPrivate { -public: - GenericHeaderPrivate () : parameters(make_shared > >()) {} - - string name; - shared_ptr > > parameters; -}; - -Cpim::GenericHeader::GenericHeader () : Header(*new GenericHeaderPrivate) {} - -string Cpim::GenericHeader::getName () const { - L_D(const GenericHeader); - return d->name; -} - -bool Cpim::GenericHeader::setName (const string &name) { - L_D(GenericHeader); - - static const set reserved = { - "From", "To", "cc", "DateTime", "Subject", "NS", "Require" - }; - - if ( - reserved.find(name) != reserved.end() || - !Parser::getInstance()->headerNameIsValid(name) - ) - return false; - - d->name = name; - return true; -} - -bool Cpim::GenericHeader::setValue (const string &value) { - return Parser::getInstance()->headerValueIsValid(value) && Header::setValue(value); -} - -Cpim::GenericHeader::ParameterList Cpim::GenericHeader::getParameters () const { - L_D(const GenericHeader); - return d->parameters; -} - -bool Cpim::GenericHeader::addParameter (const string &key, const string &value) { - L_D(GenericHeader); - - if (!Parser::getInstance()->headerParameterIsValid(key + "=" + value)) - return false; - - d->parameters->push_back(make_pair(key, value)); - return true; -} - -void Cpim::GenericHeader::removeParameter (const string &key, const string &value) { - L_D(GenericHeader); - d->parameters->remove(make_pair(key, value)); -} - -bool Cpim::GenericHeader::isValid () const { - L_D(const GenericHeader); - return !d->name.empty() && !getValue().empty(); -} - -string Cpim::GenericHeader::asString () const { - L_D(const GenericHeader); - - string parameters; - for (const auto ¶meter : *d->parameters) - parameters += ";" + parameter.first + "=" + parameter.second; - - return d->name + ":" + parameters + " " + getValue() + "\r\n"; -} - -// ----------------------------------------------------------------------------- - -void Cpim::GenericHeader::force (const string &name, const string &value, const string ¶meters) { - L_D(GenericHeader); - - // Set name/value. - d->name = name; - Header::setValue(value); - - // Parse and build parameters list. - for (const auto ¶meter : Utils::split(parameters, ';')) { - size_t equalIndex = parameter.find('='); - if (equalIndex != string::npos) - d->parameters->push_back(make_pair(parameter.substr(0, equalIndex), parameter.substr(equalIndex + 1))); - } -} - -LINPHONE_END_NAMESPACE diff --git a/src/cpim/header/cpim-header.cpp b/src/cpim/header/cpim-header.cpp deleted file mode 100644 index 0db1585a6..000000000 --- a/src/cpim/header/cpim-header.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * cpim-header.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cpim-header-p.h" - -#include "cpim-header.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -Cpim::Header::Header (HeaderPrivate &p) : Object(p) {} - -string Cpim::Header::getValue () const { - L_D(const Header); - return d->value; -} - -bool Cpim::Header::setValue (const string &value) { - L_D(Header); - d->value = value; - return true; -} - -string Cpim::Header::asString () const { - L_D(const Header); - return getName() + ": " + d->value + "\r\n"; -} - -LINPHONE_END_NAMESPACE diff --git a/src/cpim/message/cpim-message.cpp b/src/cpim/message/cpim-message.cpp deleted file mode 100644 index d005efc40..000000000 --- a/src/cpim/message/cpim-message.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * cpim-message.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "cpim/parser/cpim-parser.h" -#include "object/object-p.h" -#include "utils/utils.h" - -#include "cpim-message.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -class Cpim::MessagePrivate : public ObjectPrivate { -public: - typedef list > PrivHeaderList; - - shared_ptr cpimHeaders = make_shared(); - shared_ptr messageHeaders = make_shared(); - string content; -}; - -Cpim::Message::Message () : Object(*new MessagePrivate) {} - -// ----------------------------------------------------------------------------- - -Cpim::Message::HeaderList Cpim::Message::getCpimHeaders () const { - L_D(const Message); - return d->cpimHeaders; -} - -bool Cpim::Message::addCpimHeader (const Header &cpimHeader) { - L_D(Message); - - if (!cpimHeader.isValid()) - return false; - - d->cpimHeaders->push_back(Parser::getInstance()->cloneHeader(cpimHeader)); - return true; -} - -void Cpim::Message::removeCpimHeader (const Header &cpimHeader) { - L_D(Message); - d->cpimHeaders->remove_if([&cpimHeader](const shared_ptr &header) { - return cpimHeader.getName() == header->getName() && cpimHeader.getValue() == header->getValue(); - }); -} - -// ----------------------------------------------------------------------------- - -Cpim::Message::HeaderList Cpim::Message::getMessageHeaders () const { - L_D(const Message); - return d->messageHeaders; -} - -bool Cpim::Message::addMessageHeader (const Header &messageHeader) { - L_D(Message); - - if (!messageHeader.isValid()) - return false; - - d->messageHeaders->push_back(Parser::getInstance()->cloneHeader(messageHeader)); - return true; -} - -void Cpim::Message::removeMessageHeader (const Header &messageHeader) { - L_D(Message); - d->messageHeaders->remove_if([&messageHeader](const shared_ptr &header) { - return messageHeader.getName() == header->getName() && messageHeader.getValue() == header->getValue(); - }); -} - -// ----------------------------------------------------------------------------- - -string Cpim::Message::getContent () const { - L_D(const Message); - return d->content; -} - -bool Cpim::Message::setContent (const string &content) { - L_D(Message); - d->content = content; - return true; -} - -// ----------------------------------------------------------------------------- - -bool Cpim::Message::isValid () const { - L_D(const Message); - - return find_if(d->cpimHeaders->cbegin(), d->cpimHeaders->cend(), - [](const shared_ptr &header) { - return Utils::iequals(header->getName(), "content-type") && header->getValue() == "Message/CPIM"; - }) != d->cpimHeaders->cend(); -} - -// ----------------------------------------------------------------------------- - -string Cpim::Message::asString () const { - L_D(const Message); - - string output; - for (const auto &cpimHeader : *d->cpimHeaders) - output += cpimHeader->asString(); - - output += "\r\n"; - - for (const auto &messageHeader : *d->messageHeaders) - output += messageHeader->asString(); - - output += "\r\n"; - output += ""; // TODO: Headers MIME. - output += getContent(); - - return output; -} - -// ----------------------------------------------------------------------------- - -shared_ptr Cpim::Message::createFromString (const string &str) { - return Parser::getInstance()->parseMessage(str); -} - -LINPHONE_END_NAMESPACE diff --git a/src/cpim/message/cpim-message.h b/src/cpim/message/cpim-message.h deleted file mode 100644 index 6905cb364..000000000 --- a/src/cpim/message/cpim-message.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * cpim-message.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CPIM_MESSAGE_H_ -#define _CPIM_MESSAGE_H_ - -#include "cpim/header/cpim-core-headers.h" -#include "cpim/header/cpim-generic-header.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -namespace Cpim { - class MessagePrivate; - - class LINPHONE_PUBLIC Message : public Object { - public: - Message (); - - typedef std::shared_ptr > > HeaderList; - - HeaderList getCpimHeaders () const; - bool addCpimHeader (const Header &cpimHeader); - void removeCpimHeader (const Header &cpimHeader); - - HeaderList getMessageHeaders () const; - bool addMessageHeader (const Header &messageHeader); - void removeMessageHeader (const Header &messageHeader); - - std::string getContent () const; - bool setContent (const std::string &content); - - bool isValid () const; - - std::string asString () const; - - static std::shared_ptr createFromString (const std::string &str); - - private: - L_DECLARE_PRIVATE(Message); - L_DISABLE_COPY(Message); - }; -} - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CPIM_MESSAGE_H_ diff --git a/src/cpim/parser/cpim-grammar.cpp b/src/cpim/parser/cpim-grammar.cpp deleted file mode 100644 index 94bd86d16..000000000 --- a/src/cpim/parser/cpim-grammar.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * cpim-grammar.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cpim-grammar.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -static const char *grammar = -// See: https://tools.ietf.org/html/rfc3862 -R"==GRAMMAR==( -Message = Headers CRLF Headers CRLF - -Headers = *Header -Header = Header-name ":" Header-parameters SP Header-value CRLF - -Header-name = [ Name-prefix "." ] Name -Name-prefix = Name - -Header-parameters = *( ";" Parameter ) - -Parameter = Lang-param / Ext-param -Lang-param = "lang=" Language-tag -Ext-param = Param-name "=" Param-value -Param-name = Name -Param-value = Token / Number / String - -Header-value = *HEADERCHAR - -From-header = %d70.114.111.109 ": " From-header-value -From-header-value = [ Formal-name ] "<" URI ">" - -To-header = %d84.111 ": " To-header-value -To-header-value = [ Formal-name ] "<" URI ">" - -DateTime-header = %d68.97.116.101.84.105.109.101 ": " DateTime-header-value -DateTime-header-value = date-time - -cc-header = %d99.99 ": " cc-header-value -cc-header-value = [ Formal-name ] "<" URI ">" - -Subject-header = %d83.117.98.106.101.99.116 ":" Subject-header-value -Subject-header-value = [ ";" Lang-param ] SP *HEADERCHAR - -NS-header = %d78.83 ": " NS-header-value -NS-header-value = [ Name-prefix SP ] "<" URI ">" - -Require-header = %d82.101.113.117.105.114.101 ": " Require-header-value -Require-header-value = Header-name *( "," Header-name ) - -Name = 1*NAMECHAR -Token = 1*TOKENCHAR -Number = 1*DIGIT -String = DQUOTE *( Str-char / Escape ) DQUOTE -Str-char = %x20-21 / %x23-5B / %x5D-7E / UCS-high -Escape = "\" ( "u" 4(HEXDIG) / "b" / "t" / "n" / "r" / DQUOTE / "'" / "\" ) - -Formal-name = 1*( Token SP ) / String - -HEADERCHAR = UCS-no-CTL / Escape - -NAMECHAR = %x21 / %x23-27 / %x2a-2b / %x2d / %x5e-60 - / %x7c / %x7e / ALPHA / DIGIT - -TOKENCHAR = NAMECHAR / "." / UCS-high - -UCS-no-CTL = UTF8-no-CTL -UCS-high = UTF8-multi -UTF8-no-CTL = %x20-7e / UTF8-multi -UTF8-multi = %xC0-DF %x80-BF - / %xE0-EF %x80-BF %x80-BF - / %xF0-F7 %x80-BF %x80-BF %x80-BF - / %xF8-FB %x80-BF %x80-BF %x80-BF %x80-BF - / %xFC-FD %x80-BF %x80-BF %x80-BF %x80-BF %x80-BF -)==GRAMMAR==" - -// See: https://tools.ietf.org/html/rfc2396 -R"==GRAMMAR==( -URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] - -hier-part = "//" authority path-abempty - / path-absolute - / path-rootless - / path-empty - -URI-reference = URI / relative-ref - -absolute-URI = scheme ":" hier-part [ "?" query ] - -relative-ref = relative-part [ "?" query ] [ "#" fragment ] - -relative-part = "//" authority path-abempty - / path-absolute - / path-noscheme - / path-empty - -scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) - -authority = [ userinfo "@" ] host [ ":" port ] -userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) -host = IP-literal / IPv4address / reg-name -port = *DIGIT - -IP-literal = "[" ( IPv6address / IPvFuture ) "]" - -IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" ) - -IPv6address = 6( h16 ":" ) ls32 - / "::" 5( h16 ":" ) ls32 - / [ h16 ] "::" 4( h16 ":" ) ls32 - / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32 - / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32 - / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32 - / [ *4( h16 ":" ) h16 ] "::" ls32 - / [ *5( h16 ":" ) h16 ] "::" h16 - / [ *6( h16 ":" ) h16 ] "::" - -h16 = 1*4HEXDIG -ls32 = ( h16 ":" h16 ) / IPv4address -IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet -dec-octet = DIGIT - / %x31-39 DIGIT - / "1" 2DIGIT - / "2" %x30-34 DIGIT - / "25" %x30-35 - -reg-name = *( unreserved / pct-encoded / sub-delims ) - -path = path-abempty - / path-absolute - / path-noscheme - / path-rootless - / path-empty - -path-abempty = *( "/" segment ) -path-absolute = "/" [ segment-nz *( "/" segment ) ] -path-noscheme = segment-nz-nc *( "/" segment ) -path-rootless = segment-nz *( "/" segment ) -path-empty = [pchar] - -segment = *pchar -segment-nz = 1*pchar -segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) - -pchar = unreserved / pct-encoded / sub-delims / ":" / "@" / "\," - -query = *( pchar / "/" / "?" ) - -fragment = *( pchar / "/" / "?" ) - -pct-encoded = "%" HEXDIG HEXDIG - -unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" -reserved = gen-delims / sub-delims -gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" -sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - / "*" / "+" / "," / ";" / "=" -)==GRAMMAR==" - -// See: https://tools.ietf.org/html/rfc3066 -R"==GRAMMAR==( -Language-Tag = Primary-subtag *( "-" Subtag ) -Primary-subtag = 1*8ALPHA -Subtag = 1*8(ALPHA / DIGIT) -)==GRAMMAR==" - -// See: https://tools.ietf.org/html/rfc3339 -R"==GRAMMAR==( -date-fullyear = 4DIGIT -date-month = 2DIGIT -date-mday = 2DIGIT - -time-hour = 2DIGIT -time-minute = 2DIGIT -time-second = 2DIGIT - -time-secfrac = "." 1*DIGIT -time-numoffset = ( "+" / "-" ) time-hour ":" time-minute -time-offset = "Z" / time-numoffset - -partial-time = time-hour ":" time-minute ":" time-second [ time-secfrac ] - -full-date = date-fullyear "-" date-month "-" date-mday -full-time = partial-time time-offset - -date-time = full-date "T" full-time -)==GRAMMAR=="; - -const char *Cpim::getGrammar () { - return grammar; -} - -LINPHONE_END_NAMESPACE diff --git a/src/cpim/parser/cpim-grammar.h b/src/cpim/parser/cpim-grammar.h deleted file mode 100644 index d75cbd008..000000000 --- a/src/cpim/parser/cpim-grammar.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * cpim-grammar.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CPIM_GRAMMAR_H_ -#define _CPIM_GRAMMAR_H_ - -#include "utils/general.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -namespace Cpim { - const char *getGrammar (); -} - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CPIM_GRAMMAR_H_ diff --git a/src/cpim/parser/cpim-parser.cpp b/src/cpim/parser/cpim-parser.cpp deleted file mode 100644 index 724f4bf68..000000000 --- a/src/cpim/parser/cpim-parser.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* - * cpim-parser.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include -#include - -#include "cpim-grammar.h" -#include "logger/logger.h" -#include "object/object-p.h" -#include "utils/utils.h" - -#include "cpim-parser.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -namespace Cpim { - class Node { - public: - virtual ~Node () = default; - }; - - class HeaderNode : public Node { - public: - HeaderNode () = default; - - explicit HeaderNode (const Header &header) { - mName = header.getName(); - mValue = header.getValue(); - - // Generic header. - const GenericHeader *genericHeader = dynamic_cast(&header); - if (genericHeader) { - for (const auto ¶meter : *genericHeader->getParameters()) - mParameters += ";" + parameter.first + "=" + parameter.second; - return; - } - - // Subject header. - const SubjectHeader *subjectHeader = dynamic_cast(&header); - if (subjectHeader) { - const string language = subjectHeader->getLanguage(); - if (!language.empty()) - mParameters = ";lang=" + language; - } - } - - string getName () const { - return mName; - } - - void setName (const string &name) { - mName = name; - } - - string getParameters () const { - return mParameters; - } - - void setParameters (const string ¶meters) { - mParameters = parameters; - } - - string getValue () const { - return mValue; - } - - void setValue (const string &value) { - mValue = value; - } - - shared_ptr
createHeader (bool force) const; - - private: - template - shared_ptr
createCoreHeader (bool force) const { - shared_ptr header = make_shared(); - if (force) - header->force(mValue); - else if (!header->setValue(mValue)) { - lWarning() << "Unable to set value on core header: `" << mName << "` => `" << mValue << "`."; - return nullptr; - } - - return header; - } - - string mValue; - string mName; - string mParameters; - }; - - template<> - shared_ptr
HeaderNode::createCoreHeader(bool force) const { - shared_ptr header = make_shared(); - const string language = mParameters.length() >= 6 ? mParameters.substr(6) : ""; - - if (force) - header->force(mValue, language); - else if (!header->setValue(mValue) || (!language.empty() && !header->setLanguage(language))) { - lWarning() << "Unable to set value on subject header: `" << - mName << "` => `" << mValue << "`, `" << language << "`."; - return nullptr; - } - - return header; - } - - shared_ptr
HeaderNode::createHeader (bool force = false) const { - static const unordered_map(HeaderNode::*)(bool)const> reservedHandlers = { - { "From", &HeaderNode::createCoreHeader }, - { "To", &HeaderNode::createCoreHeader }, - { "cc", &HeaderNode::createCoreHeader }, - { "DateTime", &HeaderNode::createCoreHeader }, - { "Subject", &HeaderNode::createCoreHeader }, - { "NS", &HeaderNode::createCoreHeader }, - { "Require", &HeaderNode::createCoreHeader } - }; - - // Core Header. - const auto it = reservedHandlers.find(mName); - if (it != reservedHandlers.cend()) - return (this->*it->second)(force); - - // Generic Header - shared_ptr genericHeader = make_shared(); - genericHeader->force(mName, mValue, mParameters); - return genericHeader; - } - - // ------------------------------------------------------------------------- - - class ListHeaderNode : - public Node, - public list > {}; - - // ------------------------------------------------------------------------- - - class MessageNode : public Node { - public: - void addHeaders (const shared_ptr &headers) { - mHeaders->push_back(headers); - } - - // Warning: Call this function one time! - shared_ptr createMessage () const { - size_t size = mHeaders->size(); - if (size != 2) { - lWarning() << "Bad headers lists size."; - return nullptr; - } - - const shared_ptr message = make_shared(); - const shared_ptr cpimHeaders = mHeaders->front(); - - if (find_if(cpimHeaders->cbegin(), cpimHeaders->cend(), - [](const shared_ptr &headerNode) { - return Utils::iequals(headerNode->getName(), "content-type") && headerNode->getValue() == "Message/CPIM"; - }) == cpimHeaders->cend()) { - lWarning() << "No MIME `Content-Type` found!"; - return nullptr; - } - - // Add MIME headers. - for (const auto &headerNode : *cpimHeaders) { - const shared_ptr header = headerNode->createHeader(); - if (!header || !message->addCpimHeader(*header)) - return nullptr; - } - - // Add message headers. - for (const auto &headerNode : *mHeaders->back()) { - const shared_ptr header = headerNode->createHeader(); - if (!header || !message->addMessageHeader(*header)) - return nullptr; - } - - return message; - } - - private: - shared_ptr > > mHeaders = make_shared > >(); - }; -} - -// ----------------------------------------------------------------------------- - -class Cpim::ParserPrivate : public ObjectPrivate { -public: - shared_ptr grammar; -}; - -Cpim::Parser::Parser () : Singleton(*new ParserPrivate) { - L_D(Parser); - - belr::ABNFGrammarBuilder builder; - - d->grammar = builder.createFromAbnf(getGrammar(), make_shared()); - if (!d->grammar) - lFatal() << "Unable to build CPIM grammar."; -} - -// ----------------------------------------------------------------------------- - -shared_ptr Cpim::Parser::parseMessage (const string &input) { - L_D(Parser); - - typedef void (list >::*pushPtr)(const shared_ptr &value); - - belr::Parser > parser(d->grammar); - parser.setHandler( - "Message", belr::make_fn(make_shared ) - )->setCollector( - "Headers", belr::make_sfn(&MessageNode::addHeaders) - ); - - parser.setHandler( - "Headers", belr::make_fn(make_shared ) - )->setCollector( - "Header", belr::make_sfn(static_cast(&ListHeaderNode::push_back)) - ); - - parser.setHandler( - "Header", belr::make_fn(make_shared ) - )->setCollector( - "Header-name", belr::make_sfn(&HeaderNode::setName) - )->setCollector( - "Header-value", belr::make_sfn(&HeaderNode::setValue) - )->setCollector( - "Header-parameters", belr::make_sfn(&HeaderNode::setParameters) - ); - - size_t parsedSize; - shared_ptr node = parser.parseInput("Message", input, &parsedSize); - if (!node) { - lWarning() << "Unable to parse message."; - return nullptr; - } - - shared_ptr messageNode = dynamic_pointer_cast(node); - if (!messageNode) { - lWarning() << "Unable to cast belr result to message node."; - return nullptr; - } - - shared_ptr message = messageNode->createMessage(); - if (message) - message->setContent(input.substr(parsedSize)); - return message; -} - -// ----------------------------------------------------------------------------- - -shared_ptr Cpim::Parser::cloneHeader (const Header &header) { - return HeaderNode(header).createHeader(true); -} - -// ----------------------------------------------------------------------------- - -class EmptyObject {}; - -static bool headerIsValid (const shared_ptr &grammar, const string &input) { - belr::Parser > parser(grammar); - parser.setHandler( - "Header", belr::make_fn(make_shared ) - ); - - size_t parsedSize; - shared_ptr node = parser.parseInput("Header", input, &parsedSize); - return node && parsedSize == input.length(); -} - -bool Cpim::Parser::headerNameIsValid (const string &headerName) const { - L_D(const Parser); - return headerIsValid(d->grammar, headerName + ": value\r\n"); -} - -bool Cpim::Parser::headerValueIsValid (const string &headerValue) const { - L_D(const Parser); - return headerIsValid(d->grammar, "key: " + headerValue + "\r\n"); -} - -bool Cpim::Parser::headerParameterIsValid (const string &headerParameter) const { - L_D(const Parser); - return headerIsValid(d->grammar, "key:;" + headerParameter + " value\r\n"); -} - -// ----------------------------------------------------------------------------- - -static bool coreHeaderIsValid ( - const shared_ptr &grammar, - const string &headerName, - const string &headerValue, - const string &headerParams = string() -) { - const string mainRule = headerName + "-header"; - - belr::Parser > parser(grammar); - parser.setHandler( - mainRule, belr::make_fn(make_shared ) - ); - - const string input = headerName + ":" + headerParams + " " + headerValue; - - size_t parsedSize; - shared_ptr node = parser.parseInput(mainRule, input, &parsedSize); - return node && parsedSize == input.length(); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid(const string &headerValue) const { - L_D(const Parser); - return LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "From", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid(const string &headerValue) const { - L_D(const Parser); - return LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "To", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid(const string &headerValue) const { - L_D(const Parser); - return LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "cc", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid(const string &headerValue) const { - static const int daysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - - L_D(const Parser); - if (!LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "DateTime", headerValue)) - return false; - - // Check date. - const int year = Utils::stoi(headerValue.substr(0, 4)); - const bool isLeapYear = (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; - - const int month = Utils::stoi(headerValue.substr(5, 2)); - if (month < 1 || month > 12) - return false; - - const int day = Utils::stoi(headerValue.substr(8, 2)); - if (day < 1 || (month == 2 && isLeapYear ? day > 29 : day > daysInMonth[month - 1])) - return false; - - // Check time. - if ( - Utils::stoi(headerValue.substr(11, 2)) > 24 || - Utils::stoi(headerValue.substr(14, 2)) > 59 || - Utils::stoi(headerValue.substr(17, 2)) > 60 - ) - return false; - - // Check num offset. - if (headerValue.back() != 'Z') { - size_t length = headerValue.length(); - if ( - Utils::stoi(headerValue.substr(length - 5, 2)) > 24 || - Utils::stoi(headerValue.substr(length - 2, 2)) > 59 - ) - return false; - } - - return true; -} - -template<> -bool Cpim::Parser::coreHeaderIsValid(const string &headerValue) const { - L_D(const Parser); - return LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "Subject", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid(const string &headerValue) const { - L_D(const Parser); - return LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "NS", headerValue); -} - -template<> -bool Cpim::Parser::coreHeaderIsValid(const string &headerValue) const { - L_D(const Parser); - return LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "Require", headerValue); -} - -// ----------------------------------------------------------------------------- - -bool Cpim::Parser::subjectHeaderLanguageIsValid (const string &language) const { - L_D(const Parser); - return LINPHONE_NAMESPACE::coreHeaderIsValid(d->grammar, "Subject", "SubjectValue", ";lang=" + language); -} - -LINPHONE_END_NAMESPACE diff --git a/src/cpim/parser/cpim-parser.h b/src/cpim/parser/cpim-parser.h deleted file mode 100644 index fc7c42d8d..000000000 --- a/src/cpim/parser/cpim-parser.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * cpim-parser.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CPIM_PARSER_H_ -#define _CPIM_PARSER_H_ - -#include "cpim/message/cpim-message.h" -#include "object/singleton.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -namespace Cpim { - class ParserPrivate; - - class Parser : public Singleton { - friend class Singleton; - - public: - std::shared_ptr parseMessage (const std::string &input); - - std::shared_ptr
cloneHeader (const Header &header); - - bool headerNameIsValid (const std::string &headerName) const; - bool headerValueIsValid (const std::string &headerValue) const; - bool headerParameterIsValid (const std::string &headerParameter) const; - - template - bool coreHeaderIsValid (const std::string &headerValue) const { - return false; - } - - bool subjectHeaderLanguageIsValid (const std::string &language) const; - - private: - Parser (); - - L_DECLARE_PRIVATE(Parser); - L_DISABLE_COPY(Parser); - }; - - // --------------------------------------------------------------------------- - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; - - template<> - bool Parser::coreHeaderIsValid(const std::string &headerValue) const; -} - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CPIM_PARSER_H_ diff --git a/src/db/abstract/abstract-db-p.h b/src/db/abstract/abstract-db-p.h index 51dbd2ffe..4064c5408 100644 --- a/src/db/abstract/abstract-db-p.h +++ b/src/db/abstract/abstract-db-p.h @@ -1,11 +1,11 @@ /* * abstract-db-p.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,14 +13,15 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _ABSTRACT_DB_P_H_ -#define _ABSTRACT_DB_P_H_ +#ifndef _L_ABSTRACT_DB_P_H_ +#define _L_ABSTRACT_DB_P_H_ #include "abstract-db.h" -#include "db/provider/db-session.h" +#include "db/session/db-session.h" #include "object/object-p.h" // ============================================================================= @@ -32,6 +33,8 @@ public: DbSession dbSession; private: + void safeInit (); + AbstractDb::Backend backend; L_DECLARE_PUBLIC(AbstractDb); @@ -39,4 +42,4 @@ private: LINPHONE_END_NAMESPACE -#endif // ifndef _ABSTRACT_DB_P_H_ +#endif // ifndef _L_ABSTRACT_DB_P_H_ diff --git a/src/db/abstract/abstract-db.cpp b/src/db/abstract/abstract-db.cpp index 81df3a33f..18531439a 100644 --- a/src/db/abstract/abstract-db.cpp +++ b/src/db/abstract/abstract-db.cpp @@ -1,11 +1,11 @@ /* * abstract-db.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,13 +13,20 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "abstract-db-p.h" -#include "db/provider/db-session-provider.h" +#ifdef __APPLE__ + #include +#endif // ifdef __APPLE__ -#include "abstract-db.h" +#if (TARGET_OS_IPHONE || defined(__ANDROID__)) + #include +#endif // if (TARGET_OS_IPHONE || defined(__ANDROID__)) + +#include "abstract-db-p.h" +#include "logger/logger.h" // ============================================================================= @@ -27,49 +34,108 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE -AbstractDb::AbstractDb (AbstractDbPrivate &p) : Object(*new AbstractDbPrivate) {} +#if (TARGET_OS_IPHONE || defined(__ANDROID__)) + // Force static sqlite3 linking for IOS and Android. + extern "C" void register_factory_sqlite3(); + + static void sqlite3Log (void *, int iErrCode, const char *zMsg) { + lInfo() << "[sqlite3][" << iErrCode << "]" << zMsg; + } +#endif // if (TARGET_OS_IPHONE || defined(__ANDROID__)) + +void AbstractDbPrivate::safeInit () { + L_Q(); + dbSession.enableForeignKeys(false); + q->init(); + dbSession.enableForeignKeys(true); +} + +AbstractDb::AbstractDb (AbstractDbPrivate &p) : Object(p) {} bool AbstractDb::connect (Backend backend, const string ¶meters) { - L_D(AbstractDb); + L_D(); - d->dbSession = DbSessionProvider::getInstance()->getSession( - (backend == Mysql ? "mysql://" : "sqlite3://") + parameters - ); + #if (TARGET_OS_IPHONE || defined(__ANDROID__)) + if (backend == Sqlite3) { + static bool registered = false; + if (!registered) { + registered = true; + register_factory_sqlite3(); + sqlite3_config(SQLITE_CONFIG_LOG, sqlite3Log, nullptr); + } + } + #endif // if (TARGET_OS_IPHONE || defined(__ANDROID__)) + + d->backend = backend; + d->dbSession = DbSession( + (backend == Mysql ? "mysql://" : "sqlite3://") + parameters + ); + + if (d->dbSession) { + try { + d->safeInit(); + } catch (const exception &e) { + lWarning() << "Unable to init database: " << e.what(); + + // Reset session. + d->dbSession = DbSession(); + } + } - if (d->dbSession) - init(); return d->dbSession; } -bool AbstractDb::isConnected () const { - L_D(const AbstractDb); - return d->dbSession; +void AbstractDb::disconnect () { + L_D(); + d->dbSession = DbSession(); +} + +bool AbstractDb::forceReconnect () { + L_D(); + if (!d->dbSession) { + lWarning() << "Unable to reconnect. Not a valid database session."; + return false; + } + + constexpr int retryCount = 2; + lInfo() << "Trying sql backend reconnect..."; + + try { + for (int i = 0; i < retryCount; ++i) { + try { + lInfo() << "Reconnect... Try: " << i; + d->dbSession.getBackendSession()->reconnect(); // Equivalent to close and connect. + d->safeInit(); + lInfo() << "Database reconnection successful!"; + return true; + } catch (const soci::soci_error &e) { + if (e.get_error_category() != soci::soci_error::connection_error) + throw e; + } + } + } catch (const exception &e) { + lError() << "Unable to reconnect: `" << e.what() << "`."; + return false; + } + + lError() << "Database reconnection failed!"; + + return false; } AbstractDb::Backend AbstractDb::getBackend () const { - L_D(const AbstractDb); + L_D(); return d->backend; } +bool AbstractDb::import (Backend, const string &) { + return false; +} + // ----------------------------------------------------------------------------- void AbstractDb::init () { // Nothing. } -// ----------------------------------------------------------------------------- - -string AbstractDb::primaryKeyAutoIncrementStr (const string &type) const { - L_D(const AbstractDb); - - switch (d->backend) { - case Mysql: - return type + "UNSIGNED PRIMARY KEY AUTO_INCREMENT"; - case Sqlite3: - return " INTEGER PRIMARY KEY AUTOINCREMENT"; - } - - return ""; -} - LINPHONE_END_NAMESPACE diff --git a/src/db/abstract/abstract-db.h b/src/db/abstract/abstract-db.h index 3eac6971f..ff367f764 100644 --- a/src/db/abstract/abstract-db.h +++ b/src/db/abstract/abstract-db.h @@ -1,11 +1,11 @@ /* * abstract-db.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,15 +13,15 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _ABSTRACT_DB_H_ -#define _ABSTRACT_DB_H_ - -#include +#ifndef _L_ABSTRACT_DB_H_ +#define _L_ABSTRACT_DB_H_ #include "object/object.h" +#include "utils/general-internal.h" // ============================================================================= @@ -29,7 +29,7 @@ LINPHONE_BEGIN_NAMESPACE class AbstractDbPrivate; -class LINPHONE_PUBLIC AbstractDb : public Object { +class LINPHONE_INTERNAL_PUBLIC AbstractDb : public Object { public: enum Backend { Mysql, @@ -39,19 +39,19 @@ public: virtual ~AbstractDb () = default; bool connect (Backend backend, const std::string ¶meters); - bool disconnect (); + void disconnect (); - bool isConnected () const; + bool forceReconnect (); Backend getBackend () const; + virtual bool import (Backend backend, const std::string ¶meters); + protected: explicit AbstractDb (AbstractDbPrivate &p); virtual void init (); - std::string primaryKeyAutoIncrementStr (const std::string &type = "INT") const; - private: L_DECLARE_PRIVATE(AbstractDb); L_DISABLE_COPY(AbstractDb); @@ -59,4 +59,4 @@ private: LINPHONE_END_NAMESPACE -#endif // ifndef _ABSTRACT_DB_H_ +#endif // ifndef _L_ABSTRACT_DB_H_ diff --git a/src/db/events-db.cpp b/src/db/events-db.cpp deleted file mode 100644 index 79e140e5c..000000000 --- a/src/db/events-db.cpp +++ /dev/null @@ -1,410 +0,0 @@ -/* - * events-db.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#ifdef SOCI_ENABLED - #include -#endif // ifdef SOCI_ENABLED - -#include "abstract/abstract-db-p.h" -#include "event-log/call-event.h" -#include "event-log/message-event.h" -#include "logger/logger.h" -#include "message/message.h" - -#include "events-db.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -class EventsDbPrivate : public AbstractDbPrivate {}; - -// ----------------------------------------------------------------------------- - -EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {} - -// ----------------------------------------------------------------------------- -// Soci backend. -// ----------------------------------------------------------------------------- - -#ifdef SOCI_ENABLED - - template - struct EnumToSql { - T first; - const char *second; - }; - - template - static constexpr const char *mapEnumToSql (const EnumToSql enumToSql[], size_t n, T key) { - return n == 0 ? "" : ( - enumToSql[n - 1].first == key ? enumToSql[n - 1].second : mapEnumToSql(enumToSql, n - 1, key) - ); - } - -// ----------------------------------------------------------------------------- - - static constexpr EnumToSql eventFilterToSql[] = { - { EventsDb::MessageFilter, "1" }, - { EventsDb::CallFilter, "2" }, - { EventsDb::ConferenceFilter, "3" } - }; - - static constexpr const char *mapEventFilterToSql (EventsDb::Filter filter) { - return mapEnumToSql( - eventFilterToSql, sizeof eventFilterToSql / sizeof eventFilterToSql[0], filter - ); - } - - static constexpr EnumToSql messageStateToSql[] = { - { Message::Idle, "1" }, - { Message::InProgress, "2" }, - { Message::Delivered, "3" }, - { Message::NotDelivered, "4" }, - { Message::FileTransferError, "5" }, - { Message::FileTransferDone, "6" }, - { Message::DeliveredToUser, "7" }, - { Message::Displayed, "8" } - }; - - static constexpr const char *mapMessageStateToSql (Message::State state) { - return mapEnumToSql( - messageStateToSql, sizeof messageStateToSql / sizeof messageStateToSql[0], state - ); - } - - static constexpr const char *mapMessageDirectionToSql (Message::Direction direction) { - return direction == Message::Direction::Incoming ? "1" : "2"; - } - -// ----------------------------------------------------------------------------- - - static string buildSqlEventFilter (const list &filters, EventsDb::FilterMask mask) { - L_ASSERT( - find_if(filters.cbegin(), filters.cend(), [](const EventsDb::Filter &filter) { - return filter == EventsDb::NoFilter; - }) == filters.cend() - ); - - if (mask == EventsDb::NoFilter) - return ""; - - bool isStart = true; - string sql; - for (const auto &filter : filters) { - if (!(mask & filter)) - continue; - - if (isStart) { - isStart = false; - sql += " WHERE "; - } else - sql += " OR "; - sql += " event_type_id = "; - sql += mapEventFilterToSql(filter); - } - - return sql; - } - -// ----------------------------------------------------------------------------- - - void EventsDb::init () { - L_D(EventsDb); - soci::session *session = d->dbSession.getBackendSession(); - - *session << - "CREATE TABLE IF NOT EXISTS sip_address (" - " id" + primaryKeyAutoIncrementStr() + "," - " value VARCHAR(255) NOT NULL" - ")"; - - *session << - "CREATE TABLE IF NOT EXISTS event_type (" - " id" + primaryKeyAutoIncrementStr("TINYINT") + "," - " value VARCHAR(255) NOT NULL" - ")"; - - *session << - "CREATE TABLE IF NOT EXISTS event (" - " id" + primaryKeyAutoIncrementStr() + "," - " event_type_id TINYINT UNSIGNED NOT NULL," - " timestamp TIMESTAMP NOT NULL," - " FOREIGN KEY (event_type_id)" - " REFERENCES event_type(id)" - " ON DELETE CASCADE" - ")"; - - *session << - "CREATE TABLE IF NOT EXISTS message_state (" - " id" + primaryKeyAutoIncrementStr("TINYINT") + "," - " state VARCHAR(255) NOT NULL" - ")"; - - *session << - "CREATE TABLE IF NOT EXISTS message_direction (" - " id" + primaryKeyAutoIncrementStr("TINYINT") + "," - " direction VARCHAR(255) NOT NULL" - ")"; - - *session << - "CREATE TABLE IF NOT EXISTS dialog (" - " id" + primaryKeyAutoIncrementStr() + "," - " local_sip_address_id INT UNSIGNED NOT NULL," // Sip address used to communicate. - " remote_sip_address_id INT UNSIGNED NOT NULL," // Server (for conference) or user sip address. - " creation_timestamp TIMESTAMP NOT NULL," // Dialog creation date. - " last_update_timestamp TIMESTAMP NOT NULL," // Last event timestamp (call, message...). - " FOREIGN KEY (local_sip_address_id)" - " REFERENCES sip_address(id)" - " ON DELETE CASCADE," - " FOREIGN KEY (remote_sip_address_id)" - " REFERENCES sip_address(id)" - " ON DELETE CASCADE" - ")"; - - *session << - "CREATE TABLE IF NOT EXISTS message_event (" - " id" + primaryKeyAutoIncrementStr() + "," - " dialog_id INT UNSIGNED NOT NULL," - " state_id TINYINT UNSIGNED NOT NULL," - " direction_id TINYINT UNSIGNED NOT NULL," - " imdn_message_id VARCHAR(255) NOT NULL," // See: https://tools.ietf.org/html/rfc5438#section-6.3 - " content_type VARCHAR(255) NOT NULL," - " is_secured BOOLEAN NOT NULL," - " app_data VARCHAR(2048)," - " FOREIGN KEY (dialog_id)" - " REFERENCES dialog(id)" - " ON DELETE CASCADE," - " FOREIGN KEY (state_id)" - " REFERENCES message_state(id)" - " ON DELETE CASCADE," - " FOREIGN KEY (direction_id)" - " REFERENCES message_direction(id)" - " ON DELETE CASCADE" - ")"; - - { - string query = getBackend() == Mysql - ? "INSERT INTO event_type (id, value)" - : "INSERT OR IGNORE INTO event_type (id, value)"; - query += "VALUES" - "(1, \"Message\")," - "(2, \"Call\")," - "(3, \"Conference\")"; - if (getBackend() == Mysql) - query += "ON DUPLICATE KEY UPDATE value = VALUES(value)"; - - *session << query; - } - - { - string query = getBackend() == Mysql - ? "INSERT INTO message_direction (id, value)" - : "INSERT OR IGNORE INTO message_direction (id, value)"; - query += "VALUES" - "(1, \"Incoming\")," - "(2, \"Outgoing\")"; - if (getBackend() == Mysql) - query += "ON DUPLICATE KEY UPDATE value = VALUES(value)"; - - *session << query; - } - - { - string query = getBackend() == Mysql - ? "INSERT INTO message_state (id, value)" - : "INSERT OR IGNORE INTO message_state (id, value)"; - query += "VALUES" - "(1, \"Idle\")," - "(2, \"InProgress\")," - "(3, \"Delivered\")," - "(4, \"NotDelivered\")," - "(5, \"FileTransferError\")," - "(6, \"FileTransferDone\")," - "(7, \"DeliveredToUser\")," - "(8, \"Displayed\")"; - if (getBackend() == Mysql) - query += "ON DUPLICATE KEY UPDATE value = VALUES(value)"; - - *session << query; - } - } - - bool EventsDb::addEvent (const EventLog &eventLog) { - // TODO. - switch (eventLog.getType()) { - case EventLog::TypeNone: - return false; - case EventLog::TypeMessage: - case EventLog::TypeCallStart: - case EventLog::TypeCallEnd: - case EventLog::TypeConferenceCreated: - case EventLog::TypeConferenceDestroyed: - case EventLog::TypeConferenceParticipantAdded: - case EventLog::TypeConferenceParticipantRemoved: - case EventLog::TypeConferenceParticipantSetAdmin: - case EventLog::TypeConferenceParticipantUnsetAdmin: - break; - } - - return true; - } - - bool EventsDb::deleteEvent (const EventLog &eventLog) { - // TODO. - (void)eventLog; - return true; - } - - void EventsDb::cleanEvents (FilterMask mask) { - // TODO. - (void)mask; - } - - int EventsDb::getEventsCount (FilterMask mask) const { - L_D(const EventsDb); - - string query = "SELECT COUNT(*) FROM event" + - buildSqlEventFilter({ MessageFilter, CallFilter, ConferenceFilter }, mask); - int count = 0; - - L_BEGIN_LOG_EXCEPTION - - soci::session *session = d->dbSession.getBackendSession(); - *session << query, soci::into(count); - - L_END_LOG_EXCEPTION - - return count; - } - - int EventsDb::getMessagesCount (const string &remoteAddress) const { - L_D(const EventsDb); - - string query = "SELECT COUNT(*) FROM message_event"; - if (!remoteAddress.empty()) - query += " WHERE dialog_id = (" - " SELECT id FROM dialog WHERE remote_sip_address_id =(" - " SELECT id FROM sip_address WHERE value = :remote_address" - " )" - " )"; - int count = 0; - - L_BEGIN_LOG_EXCEPTION - - soci::session *session = d->dbSession.getBackendSession(); - *session << query, soci::use(remoteAddress), soci::into(count); - - L_END_LOG_EXCEPTION - - return count; - } - - int EventsDb::getUnreadMessagesCount (const string &remoteAddress) const { - L_D(const EventsDb); - - string query = "SELECT COUNT(*) FROM message_event"; - if (!remoteAddress.empty()) - query += " WHERE dialog_id = (" - " SELECT id FROM dialog WHERE remote_sip_address_id = (" - " SELECT id FROM sip_address WHERE value = :remote_address" - " )" - " )" - " AND direction_id = " + string(mapMessageDirectionToSql(Message::Incoming)) + - " AND state_id = " + string(mapMessageStateToSql(Message::Displayed)); - int count = 0; - - L_BEGIN_LOG_EXCEPTION - - soci::session *session = d->dbSession.getBackendSession(); - *session << query, soci::use(remoteAddress), soci::into(count); - - L_END_LOG_EXCEPTION - - return count; - } - - list> EventsDb::getHistory (const string &remoteAddress, int nLast, FilterMask mask) const { - // TODO. - (void)remoteAddress; - (void)nLast; - (void)mask; - return list>(); - } - - list> EventsDb::getHistory (const string &remoteAddress, int begin, int end, FilterMask mask) const { - // TODO. - (void)remoteAddress; - (void)begin; - (void)end; - (void)mask; - return list>(); - } - - void EventsDb::cleanHistory (const string &remoteAddress) { - // TODO. - (void)remoteAddress; - } - -// ----------------------------------------------------------------------------- -// No backend. -// ----------------------------------------------------------------------------- - -#else - - void EventsDb::init () {} - - bool EventsDb::addEvent (const EventLog &) { - return false; - } - - bool EventsDb::deleteEvent (const EventLog &) { - return false; - } - - void EventsDb::cleanEvents (FilterMask) {} - - int EventsDb::getEventsCount (FilterMask) const { - return 0; - } - - int EventsDb::getMessagesCount (const string &) const { - return 0; - } - - int EventsDb::getUnreadMessagesCount (const string &) const { - return 0; - } - - list> EventsDb::getHistory (const string &, int, FilterMask) const { - return list>(); - } - - list> EventsDb::getHistory (const string &, int, int, FilterMask) const { - return list>(); - } - - void EventsDb::cleanHistory (const string &) {} - -#endif // ifdef SOCI_ENABLED - -LINPHONE_END_NAMESPACE diff --git a/src/db/events-db.h b/src/db/events-db.h deleted file mode 100644 index 22e187abb..000000000 --- a/src/db/events-db.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * events-db.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _EVENTS_DB_H_ -#define _EVENTS_DB_H_ - -#include -#include - -#include "abstract/abstract-db.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class EventLog; -class EventsDbPrivate; - -class LINPHONE_PUBLIC EventsDb : public AbstractDb { -public: - enum Filter { - NoFilter = 0x0, - MessageFilter = 0x1, - CallFilter = 0x2, - ConferenceFilter = 0x4 - }; - - typedef int FilterMask; - - EventsDb (); - - // Generic. - bool addEvent (const EventLog &eventLog); - bool deleteEvent (const EventLog &eventLog); - void cleanEvents (FilterMask mask = NoFilter); - int getEventsCount (FilterMask mask = NoFilter) const; - - // Messages, calls and conferences. - int getMessagesCount (const std::string &remoteAddress = "") const; - int getUnreadMessagesCount (const std::string &remoteAddress = "") const; - std::list > getHistory (const std::string &remoteAddress, int nLast, FilterMask mask = NoFilter) const; - std::list > getHistory (const std::string &remoteAddress, int begin, int end, FilterMask mask = NoFilter) const; - void cleanHistory (const std::string &remoteAddress = ""); - -protected: - void init () override; - -private: - L_DECLARE_PRIVATE(EventsDb); - L_DISABLE_COPY(EventsDb); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _EVENTS_DB_H_ diff --git a/src/db/internal/db-transaction.h b/src/db/internal/db-transaction.h new file mode 100644 index 000000000..dbb57fa12 --- /dev/null +++ b/src/db/internal/db-transaction.h @@ -0,0 +1,181 @@ +/* + * db-transaction.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_DB_TRANSACTION_H_ +#define _L_DB_TRANSACTION_H_ + +#include "db/main-db-p.h" +#include "logger/logger.h" + +// ============================================================================= + +#define L_DB_TRANSACTION_C(CONTEXT) \ + LinphonePrivate::DbTransactionInfo().set(__func__, CONTEXT) * [&](SmartTransaction &tr) + +#define L_DB_TRANSACTION L_DB_TRANSACTION_C(this) + +LINPHONE_BEGIN_NAMESPACE + +class SmartTransaction { +public: + SmartTransaction (soci::session *session, const char *name) : + mSession(session), mName(name), mIsCommitted(false) { + lInfo() << "Start transaction " << this << " in MainDb::" << mName << "."; + mSession->begin(); + } + + ~SmartTransaction () { + if (!mIsCommitted) { + lInfo() << "Rollback transaction " << this << " in MainDb::" << mName << "."; + mSession->rollback(); + } + } + + void commit () { + if (mIsCommitted) { + lError() << "Transaction " << this << " in MainDb::" << mName << " already committed!!!"; + return; + } + + lInfo() << "Commit transaction " << this << " in MainDb::" << mName << "."; + mIsCommitted = true; + mSession->commit(); + } + +private: + soci::session *mSession; + const char *mName; + bool mIsCommitted; + + L_DISABLE_COPY(SmartTransaction); +}; + +struct DbTransactionInfo { + DbTransactionInfo &set (const char *_name, const MainDb *_mainDb) { + name = _name; + mainDb = const_cast(_mainDb); + return *this; + } + + const char *name = nullptr; + MainDb *mainDb = nullptr; +}; + +template +class DbTransaction { + using InternalReturnType = typename std::remove_reference< + decltype(std::declval()(std::declval())) + >::type; + +public: + using ReturnType = typename std::conditional< + std::is_same::value, + bool, + InternalReturnType + >::type; + + DbTransaction (DbTransactionInfo &info, Function &&function) : mFunction(std::move(function)) { + MainDb *mainDb = info.mainDb; + const char *name = info.name; + soci::session *session = mainDb->getPrivate()->dbSession.getBackendSession(); + + try { + SmartTransaction tr(session, name); + mResult = exec(tr); + } catch (const soci::soci_error &e) { + lWarning() << "Catched exception in MainDb::" << name << "(" << e.what() << ")."; + soci::soci_error::error_category category = e.get_error_category(); + if ( + (category == soci::soci_error::connection_error || category == soci::soci_error::unknown) && + mainDb->forceReconnect() + ) { + try { + SmartTransaction tr(session, name); + mResult = exec(tr); + } catch (const std::exception &e) { + lError() << "Unable to execute query after reconnect in MainDb::" << name << "(" << e.what() << ")."; + } + return; + } + lError() << "Unhandled [" << getErrorCategoryAsString(category) << "] exception in MainDb::" << + name << ": `" << e.what() << "`."; + } catch (const std::exception &e) { + lError() << "Unhandled generic exception in MainDb::" << name << ": `" << e.what() << "`."; + } + } + + DbTransaction (DbTransaction &&DbTransaction) : mFunction(std::move(DbTransaction.mFunction)) {} + + operator ReturnType () const { + return mResult; + } + +private: + // Exec function with no return type. + template + typename std::enable_if::value, bool>::type exec (SmartTransaction &tr) const { + mFunction(tr); + return true; + } + + // Exec function with return type. + template + typename std::enable_if::value, T>::type exec (SmartTransaction &tr) const { + return mFunction(tr); + } + + static const char *getErrorCategoryAsString (soci::soci_error::error_category category) { + switch (category) { + case soci::soci_error::connection_error: + return "CONNECTION ERROR"; + case soci::soci_error::invalid_statement: + return "INVALID STATEMENT"; + case soci::soci_error::no_privilege: + return "NO PRIVILEGE"; + case soci::soci_error::no_data: + return "NO DATA"; + case soci::soci_error::constraint_violation: + return "CONSTRAINT VIOLATION"; + case soci::soci_error::unknown_transaction_state: + return "UNKNOWN TRANSACTION STATE"; + case soci::soci_error::system_error: + return "SYSTEM ERROR"; + case soci::soci_error::unknown: + return "UNKNOWN"; + } + + // Unreachable. + L_ASSERT(false); + return nullptr; + } + + Function mFunction; + ReturnType mResult{}; + + L_DISABLE_COPY(DbTransaction); +}; + +template +typename DbTransaction::ReturnType operator* (DbTransactionInfo &info, Function &&function) { + return DbTransaction(info, std::forward(function)); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_DB_TRANSACTION_H_ diff --git a/src/db/internal/statements.cpp b/src/db/internal/statements.cpp new file mode 100644 index 000000000..01ae12da0 --- /dev/null +++ b/src/db/internal/statements.cpp @@ -0,0 +1,132 @@ +/* + * statements.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "statements.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +namespace Statements { + using Backend = AbstractDb::Backend; + + struct Statement { + template + constexpr Statement (Backend _backend, const char (&_sql)[N]) : backend(_backend), sql(_sql) {} + + Backend backend; + const char *sql; + }; + + struct AbstractStatement { + public: + template + constexpr AbstractStatement (const char (&_sql)[N]) : mSql{ _sql, nullptr } {} + + // TODO: Improve, check backends. + constexpr AbstractStatement (const Statement &a, const Statement &b) : mSql{ a.sql, b.sql } {} + + const char *get (Backend backend) const { + return backend == Backend::Mysql && mSql[1] ? mSql[1] : mSql[0]; + } + + private: + const char *mSql[2]; + }; + + // --------------------------------------------------------------------------- + // Select statements. + // --------------------------------------------------------------------------- + + constexpr const char *select[SelectCount] = { + /* SelectSipAddressId */ R"( + SELECT id + FROM sip_address + WHERE value = :1 + )", + + /* SelectChatRoomId */ R"( + SELECT id + FROM chat_room + WHERE peer_sip_address_id = :1 AND local_sip_address_id = :2 + )", + + /* SelectChatRoomParticipantId */ R"( + SELECT id + FROM chat_room_participant + WHERE chat_room_id = :1 AND participant_sip_address_id = :2 + )", + + /* SelectOneToOneChatRoomId */ R"( + SELECT chat_room_id + FROM one_to_one_chat_room + WHERE participant_a_sip_address_id IN (:1, :2) + AND participant_b_sip_address_id IN (:3, :4) + )", + + /* SelectConferenceEvent */ R"( + SELECT conference_event_view.id AS event_id, type, conference_event_view.creation_time, from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured, notify_id, device_sip_address.value, participant_sip_address.value, conference_event_view.subject, delivery_notification_required, display_notification_required, peer_sip_address.value, local_sip_address.value + FROM conference_event_view + JOIN chat_room ON chat_room.id = chat_room_id + JOIN sip_address AS peer_sip_address ON peer_sip_address.id = peer_sip_address_id + JOIN sip_address AS local_sip_address ON local_sip_address.id = local_sip_address_id + LEFT JOIN sip_address AS from_sip_address ON from_sip_address.id = from_sip_address_id + LEFT JOIN sip_address AS to_sip_address ON to_sip_address.id = to_sip_address_id + LEFT JOIN sip_address AS device_sip_address ON device_sip_address.id = device_sip_address_id + LEFT JOIN sip_address AS participant_sip_address ON participant_sip_address.id = participant_sip_address_id + WHERE event_id = :1 + )", + + /* SelectConferenceEvents */ R"( + SELECT conference_event_view.id AS event_id, type, creation_time, from_sip_address.value, to_sip_address.value, time, imdn_message_id, state, direction, is_secured, notify_id, device_sip_address.value, participant_sip_address.value, subject, delivery_notification_required, display_notification_required + FROM conference_event_view + LEFT JOIN sip_address AS from_sip_address ON from_sip_address.id = from_sip_address_id + LEFT JOIN sip_address AS to_sip_address ON to_sip_address.id = to_sip_address_id + LEFT JOIN sip_address AS device_sip_address ON device_sip_address.id = device_sip_address_id + LEFT JOIN sip_address AS participant_sip_address ON participant_sip_address.id = participant_sip_address_id + WHERE chat_room_id = :1 + )" + }; + + // --------------------------------------------------------------------------- + // Select statements. + // --------------------------------------------------------------------------- + + constexpr AbstractStatement insert[InsertCount] = { + /* InsertOneToOneChatRoom */ R"( + INSERT INTO one_to_one_chat_room ( + chat_room_id, participant_a_sip_address_id, participant_b_sip_address_id + ) VALUES (:1, :2, :3) + )" + }; + + // --------------------------------------------------------------------------- + // Getters. + // --------------------------------------------------------------------------- + + const char *get (Select selectStmt) { + return selectStmt >= Select::SelectCount ? nullptr : select[selectStmt]; + } + + const char *get (Insert insertStmt, AbstractDb::Backend backend) { + return insertStmt >= Insert::InsertCount ? nullptr : insert[insertStmt].get(backend); + } +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/internal/statements.h b/src/db/internal/statements.h new file mode 100644 index 000000000..4f518ccad --- /dev/null +++ b/src/db/internal/statements.h @@ -0,0 +1,51 @@ +/* + * statements.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_STATEMENTS_H_ +#define _L_STATEMENTS_H_ + +#include "db/abstract/abstract-db.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +namespace Statements { + enum Select { + SelectSipAddressId, + SelectChatRoomId, + SelectChatRoomParticipantId, + SelectOneToOneChatRoomId, + SelectConferenceEvent, + SelectConferenceEvents, + SelectCount + }; + + enum Insert { + InsertOneToOneChatRoom, + InsertCount + }; + + const char *get (Select selectStmt); + const char *get (Insert insertStmt, AbstractDb::Backend backend); +} + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_STATEMENTS_H_ diff --git a/src/db/main-db-chat-message-key.cpp b/src/db/main-db-chat-message-key.cpp new file mode 100644 index 000000000..d0628985f --- /dev/null +++ b/src/db/main-db-chat-message-key.cpp @@ -0,0 +1,44 @@ +/* + * main-db-chat-message-key.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "core/core-p.h" +#include "main-db-chat-message-key.h" +#include "main-db-key-p.h" +#include "main-db-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +MainDbChatMessageKey::MainDbChatMessageKey () : MainDbKey() {}; + +MainDbChatMessageKey::MainDbChatMessageKey (const shared_ptr &core, long long storageId) : MainDbKey(core, storageId) {} + +MainDbChatMessageKey::~MainDbChatMessageKey () { + L_D(); + + if (isValid()) + d->core.lock()->getPrivate()->mainDb->getPrivate()->storageIdToChatMessage.erase(d->storageId); +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/main-db-chat-message-key.h b/src/db/main-db-chat-message-key.h new file mode 100644 index 000000000..66b751c6c --- /dev/null +++ b/src/db/main-db-chat-message-key.h @@ -0,0 +1,41 @@ +/* + * main-db-chat-message-key.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAIN_DB_CHAT_MESSAGE_KEY_H_ +#define _L_MAIN_DB_CHAT_MESSAGE_KEY_H_ + +#include "main-db-key.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class MainDbChatMessageKey : public MainDbKey { +public: + MainDbChatMessageKey (); + MainDbChatMessageKey (const std::shared_ptr &core, long long storageId); + ~MainDbChatMessageKey (); + +private: + L_DECLARE_PRIVATE(MainDbKey); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MAIN_DB_CHAT_MESSAGE_KEY_H_ diff --git a/src/db/main-db-event-key.cpp b/src/db/main-db-event-key.cpp new file mode 100644 index 000000000..1df8d9bd2 --- /dev/null +++ b/src/db/main-db-event-key.cpp @@ -0,0 +1,44 @@ +/* + * main-db-event-key.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "core/core-p.h" +#include "main-db-event-key.h" +#include "main-db-key-p.h" +#include "main-db-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +MainDbEventKey::MainDbEventKey () : MainDbKey() {}; + +MainDbEventKey::MainDbEventKey (const shared_ptr &core, long long storageId) : MainDbKey(core, storageId) {} + +MainDbEventKey::~MainDbEventKey () { + L_D(); + + if (isValid()) + d->core.lock()->getPrivate()->mainDb->getPrivate()->storageIdToEvent.erase(d->storageId); +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/main-db-event-key.h b/src/db/main-db-event-key.h new file mode 100644 index 000000000..4e43f798d --- /dev/null +++ b/src/db/main-db-event-key.h @@ -0,0 +1,41 @@ +/* + * main-db-event-key.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAIN_DB_EVENT_KEY_H_ +#define _L_MAIN_DB_EVENT_KEY_H_ + +#include "main-db-key.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class MainDbEventKey : public MainDbKey { +public: + MainDbEventKey (); + MainDbEventKey (const std::shared_ptr &core, long long storageId); + ~MainDbEventKey (); + +private: + L_DECLARE_PRIVATE(MainDbKey); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MAIN_DB_EVENT_KEY_H_ diff --git a/src/db/main-db-key-p.h b/src/db/main-db-key-p.h new file mode 100644 index 000000000..4e37c74e1 --- /dev/null +++ b/src/db/main-db-key-p.h @@ -0,0 +1,38 @@ +/* + * main-db-key-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAIN_DB_KEY_P_H_ +#define _L_MAIN_DB_KEY_P_H_ + +#include "main-db-key.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class MainDbKeyPrivate : public ClonableObjectPrivate { +public: + std::weak_ptr core; + long long storageId = -1; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MAIN_DB_KEY_P_H_ diff --git a/src/db/main-db-key.cpp b/src/db/main-db-key.cpp new file mode 100644 index 000000000..11557b04b --- /dev/null +++ b/src/db/main-db-key.cpp @@ -0,0 +1,67 @@ +/* + * main-db-key.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "core/core-p.h" +#include "main-db-key-p.h" +#include "main-db-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +MainDbKey::MainDbKey () : ClonableObject(*new MainDbKeyPrivate) {} + +MainDbKey::MainDbKey (const shared_ptr &core, long long storageId) : MainDbKey() { + L_D(); + d->core = core; + d->storageId = storageId; +} + +MainDbKey::MainDbKey (const MainDbKey &other) : MainDbKey() { + L_D(); + const MainDbKeyPrivate *dOther = other.getPrivate(); + + d->core = dOther->core; + d->storageId = dOther->storageId; +} + +MainDbKey::~MainDbKey () {} + +MainDbKey &MainDbKey::operator= (const MainDbKey &other) { + L_D(); + + if (this != &other) { + const MainDbKeyPrivate *dOther = other.getPrivate(); + d->core = dOther->core; + d->storageId = dOther->storageId; + } + + return *this; +} + +bool MainDbKey::isValid () const { + L_D(); + return !d->core.expired() && d->storageId >= 0; +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/main-db-key.h b/src/db/main-db-key.h new file mode 100644 index 000000000..bd94582ab --- /dev/null +++ b/src/db/main-db-key.h @@ -0,0 +1,52 @@ +/* + * main-db-key.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAIN_DB_KEY_H_ +#define _L_MAIN_DB_KEY_H_ + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Core; +class MainDbKeyPrivate; + +class MainDbKey : public ClonableObject { + friend class MainDb; + friend class MainDbPrivate; + +public: + MainDbKey (); + MainDbKey (const std::shared_ptr &core, long long storageId); + MainDbKey (const MainDbKey &other); + virtual ~MainDbKey () = 0; + + MainDbKey &operator= (const MainDbKey &other); + + bool isValid () const; + +private: + L_DECLARE_PRIVATE(MainDbKey); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MAIN_DB_KEY_H_ diff --git a/src/db/main-db-p.h b/src/db/main-db-p.h new file mode 100644 index 000000000..41b4e5c6f --- /dev/null +++ b/src/db/main-db-p.h @@ -0,0 +1,192 @@ +/* + * main-db-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAIN_DB_P_H_ +#define _L_MAIN_DB_P_H_ + +#include + +#include "linphone/utils/utils.h" + +#include "abstract/abstract-db-p.h" +#include "event-log/event-log.h" +#include "main-db.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Content; + +class MainDbPrivate : public AbstractDbPrivate { +public: + mutable std::unordered_map> storageIdToEvent; + mutable std::unordered_map> storageIdToChatMessage; + +private: + // --------------------------------------------------------------------------- + // Misc helpers. + // --------------------------------------------------------------------------- + + static time_t getTmAsTimeT (const tm &t); + + std::shared_ptr findChatRoom (const ChatRoomId &chatRoomId) const; + + // --------------------------------------------------------------------------- + // Low level API. + // --------------------------------------------------------------------------- + + long long insertSipAddress (const std::string &sipAddress); + void insertContent (long long chatMessageId, const Content &content); + long long insertContentType (const std::string &contentType); + long long insertOrUpdateImportedBasicChatRoom ( + long long peerSipAddressId, + long long localSipAddressId, + const tm &creationTime + ); + long long insertChatRoom (const std::shared_ptr &chatRoom, unsigned int notifyId = 0); + long long insertChatRoomParticipant (long long chatRoomId, long long participantSipAddressId, bool isAdmin); + void insertChatRoomParticipantDevice (long long participantId, long long participantDeviceSipAddressId); + void insertChatMessageParticipant (long long chatMessageId, long long sipAddressId, int state, time_t stateChangeTime); + + long long selectSipAddressId (const std::string &sipAddress) const; + long long selectChatRoomId (long long peerSipAddressId, long long localSipAddressId) const; + long long selectChatRoomId (const ChatRoomId &chatRoomId) const; + long long selectChatRoomParticipantId (long long chatRoomId, long long participantSipAddressId) const; + long long selectOneToOneChatRoomId (long long sipAddressIdA, long long sipAddressIdB) const; + + void deleteContents (long long chatMessageId); + void deleteChatRoomParticipant (long long chatRoomId, long long participantSipAddressId); + void deleteChatRoomParticipantDevice (long long participantId, long long participantDeviceSipAddressId); + + // --------------------------------------------------------------------------- + // Events API. + // --------------------------------------------------------------------------- + + long long getConferenceEventIdFromRow (const soci::row &row) const { + return dbSession.resolveId(row, -1); + } + + time_t getConferenceEventCreationTimeFromRow (const soci::row &row) const { + return Utils::getTmAsTimeT(row.get(2)); + } + + unsigned int getConferenceEventNotifyIdFromRow (const soci::row &row) const { + L_Q(); + return q->getBackend() == MainDb::Backend::Mysql + ? row.get(10, 0) + : static_cast(row.get(10, 0)); + } + + std::shared_ptr selectGenericConferenceEvent ( + const std::shared_ptr &chatRoom, + const soci::row &row + ) const; + + std::shared_ptr selectGenericConferenceNotifiedEvent ( + const ChatRoomId &chatRoomId, + const soci::row &row + ) const; + + std::shared_ptr selectConferenceEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row + ) const; + + std::shared_ptr selectConferenceCallEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row + ) const; + + std::shared_ptr selectConferenceChatMessageEvent ( + const std::shared_ptr &chatRoom, + EventLog::Type type, + const soci::row &row + ) const; + + std::shared_ptr selectConferenceParticipantEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row + ) const; + + std::shared_ptr selectConferenceParticipantDeviceEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row + ) const; + + std::shared_ptr selectConferenceSubjectEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row + ) const; + + long long insertEvent (const std::shared_ptr &eventLog); + long long insertConferenceEvent (const std::shared_ptr &eventLog, long long *chatRoomId = nullptr); + long long insertConferenceCallEvent (const std::shared_ptr &eventLog); + long long insertConferenceChatMessageEvent (const std::shared_ptr &eventLog); + void updateConferenceChatMessageEvent(const std::shared_ptr &eventLog); + long long insertConferenceNotifiedEvent (const std::shared_ptr &eventLog, long long *chatRoomId = nullptr); + long long insertConferenceParticipantEvent (const std::shared_ptr &eventLog, long long *chatRoomId = nullptr); + long long insertConferenceParticipantDeviceEvent (const std::shared_ptr &eventLog); + long long insertConferenceSubjectEvent (const std::shared_ptr &eventLog); + + void setChatMessageParticipantState ( + const std::shared_ptr &eventLog, + const IdentityAddress &participantAddress, + ChatMessage::State state, + time_t stateChangeTime + ); + + // --------------------------------------------------------------------------- + // Cache API. + // --------------------------------------------------------------------------- + + void cache (const std::shared_ptr &eventLog, long long storageId) const; + void cache (const std::shared_ptr &chatMessage, long long storageId) const; + + std::shared_ptr getEventFromCache (long long storageId) const; + std::shared_ptr getChatMessageFromCache (long long storageId) const; + + void invalidConferenceEventsFromQuery (const std::string &query, long long chatRoomId); + + // --------------------------------------------------------------------------- + // Versions. + // --------------------------------------------------------------------------- + + unsigned int getModuleVersion (const std::string &name); + void updateModuleVersion (const std::string &name, unsigned int version); + void updateSchema (); + + // --------------------------------------------------------------------------- + // Import. + // --------------------------------------------------------------------------- + + void importLegacyFriends (DbSession &inDbSession); + void importLegacyHistory (DbSession &inDbSession); + + L_DECLARE_PUBLIC(MainDb); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MAIN_DB_P_H_ diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp new file mode 100644 index 000000000..6b958df20 --- /dev/null +++ b/src/db/main-db.cpp @@ -0,0 +1,2715 @@ +/* + * main-db.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/algorithm.h" +#include "linphone/utils/static-string.h" + +#include "chat/chat-message/chat-message-p.h" +#include "chat/chat-room/chat-room-p.h" +#include "chat/chat-room/client-group-chat-room.h" +#include "chat/chat-room/server-group-chat-room.h" +#include "conference/participant-device.h" +#include "conference/participant-p.h" +#include "core/core-p.h" +#include "event-log/event-log-p.h" +#include "event-log/events.h" +#include "main-db-key-p.h" + +#include "internal/db-transaction.h" +#include "internal/statements.h" + +// ============================================================================= + +// See: http://soci.sourceforge.net/doc/3.2/exchange.html +// Part: Object lifetime and immutability + +// ----------------------------------------------------------------------------- + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +namespace { + constexpr unsigned int ModuleVersionEvents = makeVersion(1, 0, 4); + constexpr unsigned int ModuleVersionFriends = makeVersion(1, 0, 0); + constexpr unsigned int ModuleVersionLegacyFriendsImport = makeVersion(1, 0, 0); + constexpr unsigned int ModuleVersionLegacyHistoryImport = makeVersion(1, 0, 0); + + constexpr int LegacyFriendListColId = 0; + constexpr int LegacyFriendListColName = 1; + constexpr int LegacyFriendListColRlsUri = 2; + constexpr int LegacyFriendListColSyncUri = 3; + constexpr int LegacyFriendListColRevision = 4; + + constexpr int LegacyFriendColFriendListId = 1; + constexpr int LegacyFriendColSipAddress = 2; + constexpr int LegacyFriendColSubscribePolicy = 3; + constexpr int LegacyFriendColSendSubscribe = 4; + constexpr int LegacyFriendColRefKey = 5; + constexpr int LegacyFriendColVCard = 6; + constexpr int LegacyFriendColVCardEtag = 7; + constexpr int LegacyFriendColVCardSyncUri = 8; + constexpr int LegacyFriendColPresenceReceived = 9; + + constexpr int LegacyMessageColLocalAddress = 1; + constexpr int LegacyMessageColRemoteAddress = 2; + constexpr int LegacyMessageColDirection = 3; + constexpr int LegacyMessageColText = 4; + constexpr int LegacyMessageColState = 7; + constexpr int LegacyMessageColUrl = 8; + constexpr int LegacyMessageColDate = 9; + constexpr int LegacyMessageColAppData = 10; + constexpr int LegacyMessageColContentId = 11; + constexpr int LegacyMessageColContentType = 13; + constexpr int LegacyMessageColIsSecured = 14; +} + +// ----------------------------------------------------------------------------- +// soci helpers. +// ----------------------------------------------------------------------------- + +static inline vector blobToVector (soci::blob &in) { + size_t len = in.get_len(); + if (!len) + return vector(); + vector out(len); + in.read(0, &out[0], len); + return out; +} + +static inline string blobToString (soci::blob &in) { + vector out = blobToVector(in); + return string(out.begin(), out.end()); +} + +static constexpr string &blobToString (string &in) { + return in; +} + +template +static T getValueFromRow (const soci::row &row, int index, bool &isNull) { + isNull = false; + + if (row.get_indicator(size_t(index)) == soci::i_null) { + isNull = true; + return T(); + } + return row.get(size_t(index)); +} + +// ----------------------------------------------------------------------------- +// Event filter tools. +// ----------------------------------------------------------------------------- + +// Some tools to build filters at compile time. +template +struct EnumToSql { + T first; + const char *second; +}; + +template +static constexpr const char *mapEnumToSql (const EnumToSql enumToSql[], size_t n, T key) { + return n == 0 ? "" : ( + enumToSql[n - 1].first == key ? enumToSql[n - 1].second : mapEnumToSql(enumToSql, n - 1, key) + ); +} + +template +struct SqlEventFilterBuilder {}; + +template +struct SqlEventFilterBuilder { + static constexpr auto get () L_AUTO_RETURN( + StaticIntString() + "," + SqlEventFilterBuilder::get() + ); +}; + +template +struct SqlEventFilterBuilder { + static constexpr auto get () L_AUTO_RETURN(StaticIntString()); +}; + +// ----------------------------------------------------------------------------- +// Event filters. +// ----------------------------------------------------------------------------- + +namespace { + #ifdef _WIN32 + // TODO: Find a workaround to deal with StaticString concatenation!!! + constexpr char ConferenceCallFilter[] = "3,4"; + constexpr char ConferenceChatMessageFilter[] = "5"; + constexpr char ConferenceInfoNoDeviceFilter[] = "1,2,6,7,8,9,12"; + constexpr char ConferenceInfoFilter[] = "1,2,6,7,8,9,10,11,12"; + #else + constexpr auto ConferenceCallFilter = SqlEventFilterBuilder< + EventLog::Type::ConferenceCallStart, + EventLog::Type::ConferenceCallEnd + >::get(); + + constexpr auto ConferenceChatMessageFilter = SqlEventFilterBuilder::get(); + + constexpr auto ConferenceInfoNoDeviceFilter = SqlEventFilterBuilder< + EventLog::Type::ConferenceCreated, + EventLog::Type::ConferenceTerminated, + EventLog::Type::ConferenceParticipantAdded, + EventLog::Type::ConferenceParticipantRemoved, + EventLog::Type::ConferenceParticipantSetAdmin, + EventLog::Type::ConferenceParticipantUnsetAdmin, + EventLog::Type::ConferenceSubjectChanged + >::get(); + + constexpr auto ConferenceInfoFilter = ConferenceInfoNoDeviceFilter + "," + SqlEventFilterBuilder< + EventLog::Type::ConferenceParticipantDeviceAdded, + EventLog::Type::ConferenceParticipantDeviceRemoved + >::get(); + #endif // ifdef _WIN32 + + constexpr EnumToSql EventFilterToSql[] = { + { MainDb::ConferenceCallFilter, ConferenceCallFilter }, + { MainDb::ConferenceChatMessageFilter, ConferenceChatMessageFilter }, + { MainDb::ConferenceInfoNoDeviceFilter, ConferenceInfoNoDeviceFilter }, + { MainDb::ConferenceInfoFilter, ConferenceInfoFilter } + }; +} + +static const char *mapEventFilterToSql (MainDb::Filter filter) { + return mapEnumToSql( + EventFilterToSql, sizeof EventFilterToSql / sizeof EventFilterToSql[0], filter + ); +} + +// ----------------------------------------------------------------------------- + +static string buildSqlEventFilter ( + const list &filters, + MainDb::FilterMask mask, + const string &condKeyWord = "WHERE" +) { + L_ASSERT(findIf(filters, [](const MainDb::Filter &filter) { return filter == MainDb::NoFilter; }) == filters.cend()); + + if (mask == MainDb::NoFilter) + return ""; + + bool isStart = true; + string sql; + for (const auto &filter : filters) { + if (!mask.isSet(filter)) + continue; + + if (isStart) { + isStart = false; + sql += " " + condKeyWord + " type IN ("; + } else + sql += ", "; + sql += mapEventFilterToSql(filter); + } + + if (!isStart) + sql += ") "; + + return sql; +} + +// ----------------------------------------------------------------------------- +// Misc helpers. +// ----------------------------------------------------------------------------- + +time_t MainDbPrivate::getTmAsTimeT (const tm &t) { + tm t2 = t; + t2.tm_isdst = 0; + return Utils::getTmAsTimeT(t2); +} + +shared_ptr MainDbPrivate::findChatRoom (const ChatRoomId &chatRoomId) const { + L_Q(); + shared_ptr chatRoom = q->getCore()->findChatRoom(chatRoomId); + if (!chatRoom) + lError() << "Unable to find chat room: " << chatRoomId << "."; + return chatRoom; +} + +// ----------------------------------------------------------------------------- +// Low level API. +// ----------------------------------------------------------------------------- + +long long MainDbPrivate::insertSipAddress (const string &sipAddress) { + long long id = selectSipAddressId(sipAddress); + if (id >= 0) + return id; + + lInfo() << "Insert new sip address in database: `" << sipAddress << "`."; + *dbSession.getBackendSession() << "INSERT INTO sip_address (value) VALUES (:sipAddress)", soci::use(sipAddress); + return dbSession.getLastInsertId(); +} + +void MainDbPrivate::insertContent (long long chatMessageId, const Content &content) { + soci::session *session = dbSession.getBackendSession(); + + const long long &contentTypeId = insertContentType(content.getContentType().asString()); + const string &body = content.getBodyAsString(); + *session << "INSERT INTO chat_message_content (event_id, content_type_id, body) VALUES" + " (:chatMessageId, :contentTypeId, :body)", soci::use(chatMessageId), soci::use(contentTypeId), + soci::use(body); + + const long long &chatMessageContentId = dbSession.getLastInsertId(); + if (content.isFile()) { + const FileContent &fileContent = static_cast(content); + const string &name = fileContent.getFileName(); + const size_t &size = fileContent.getFileSize(); + const string &path = fileContent.getFilePath(); + *session << "INSERT INTO chat_message_file_content (chat_message_content_id, name, size, path) VALUES" + " (:chatMessageContentId, :name, :size, :path)", + soci::use(chatMessageContentId), soci::use(name), soci::use(size), soci::use(path); + } + + for (const auto &appData : content.getAppDataMap()) + *session << "INSERT INTO chat_message_content_app_data (chat_message_content_id, name, data) VALUES" + " (:chatMessageContentId, :name, :data)", + soci::use(chatMessageContentId), soci::use(appData.first), soci::use(appData.second); +} + +long long MainDbPrivate::insertContentType (const string &contentType) { + soci::session *session = dbSession.getBackendSession(); + + long long id; + *session << "SELECT id FROM content_type WHERE value = :contentType", soci::use(contentType), soci::into(id); + if (session->got_data()) + return id; + + lInfo() << "Insert new content type in database: `" << contentType << "`."; + *session << "INSERT INTO content_type (value) VALUES (:contentType)", soci::use(contentType); + return dbSession.getLastInsertId(); +} + +long long MainDbPrivate::insertOrUpdateImportedBasicChatRoom ( + long long peerSipAddressId, + long long localSipAddressId, + const tm &creationTime +) { + soci::session *session = dbSession.getBackendSession(); + + long long id = selectChatRoomId(peerSipAddressId, localSipAddressId); + if (id >= 0) { + *session << "UPDATE chat_room SET last_update_time = :lastUpdateTime WHERE id = :id", + soci::use(creationTime), soci::use(id); + return id; + } + + const int capabilities = ChatRoom::CapabilitiesMask( + { ChatRoom::Capabilities::Basic, ChatRoom::Capabilities::Migratable } + ); + lInfo() << "Insert new chat room in database: (peer=" << peerSipAddressId << + ", local=" << localSipAddressId << ", capabilities=" << capabilities << ")."; + *session << "INSERT INTO chat_room (" + " peer_sip_address_id, local_sip_address_id, creation_time, last_update_time, capabilities" + ") VALUES (:peerSipAddressId, :localSipAddressId, :creationTime, :lastUpdateTime, :capabilities)", + soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(creationTime), soci::use(creationTime), + soci::use(capabilities); + + return dbSession.getLastInsertId(); +} + +long long MainDbPrivate::insertChatRoom (const shared_ptr &chatRoom, unsigned int notifyId) { + const ChatRoomId &chatRoomId = chatRoom->getChatRoomId(); + const long long &peerSipAddressId = insertSipAddress(chatRoomId.getPeerAddress().asString()); + const long long &localSipAddressId = insertSipAddress(chatRoomId.getLocalAddress().asString()); + + long long id = selectChatRoomId(peerSipAddressId, localSipAddressId); + if (id >= 0) { + // The chat room is already stored in DB, but still update the notify id that might have changed + *dbSession.getBackendSession() << "UPDATE chat_room SET last_notify_id = :lastNotifyId WHERE id = :chatRoomId", + soci::use(notifyId), soci::use(id); + return id; + } + + lInfo() << "Insert new chat room in database: " << chatRoomId << "."; + + const tm &creationTime = Utils::getTimeTAsTm(chatRoom->getCreationTime()); + const tm &lastUpdateTime = Utils::getTimeTAsTm(chatRoom->getLastUpdateTime()); + + // Remove capabilities like `Proxy`. + const int &capabilities = chatRoom->getCapabilities() & ~ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Proxy); + + const string &subject = chatRoom->getSubject(); + const int &flags = chatRoom->hasBeenLeft(); + *dbSession.getBackendSession() << "INSERT INTO chat_room (" + " peer_sip_address_id, local_sip_address_id, creation_time," + " last_update_time, capabilities, subject, flags, last_notify_id" + ") VALUES (" + " :peerSipAddressId, :localSipAddressId, :creationTime," + " :lastUpdateTime, :capabilities, :subject, :flags, :lastNotifyId" + ")", + soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(creationTime), + soci::use(lastUpdateTime), soci::use(capabilities), soci::use(subject), soci::use(flags), soci::use(notifyId); + + id = dbSession.getLastInsertId(); + + // Do not add 'me' when creating a server-group-chat-room. + if (chatRoomId.getLocalAddress() != chatRoomId.getPeerAddress()) { + shared_ptr me = chatRoom->getMe(); + long long meId = insertChatRoomParticipant( + id, + insertSipAddress(me->getAddress().asString()), + me->isAdmin() + ); + for (const auto &device : me->getPrivate()->getDevices()) + insertChatRoomParticipantDevice(meId, insertSipAddress(device->getAddress().asString())); + } + + for (const auto &participant : chatRoom->getParticipants()) { + long long participantId = insertChatRoomParticipant( + id, + insertSipAddress(participant->getAddress().asString()), + participant->isAdmin() + ); + for (const auto &device : participant->getPrivate()->getDevices()) + insertChatRoomParticipantDevice(participantId, insertSipAddress(device->getAddress().asString())); + } + + return id; +} + +long long MainDbPrivate::insertChatRoomParticipant ( + long long chatRoomId, + long long participantSipAddressId, + bool isAdmin +) { + soci::session *session = dbSession.getBackendSession(); + long long id = selectChatRoomParticipantId(chatRoomId, participantSipAddressId); + if (id >= 0) { + // See: https://stackoverflow.com/a/15299655 (cast to reference) + *session << "UPDATE chat_room_participant SET is_admin = :isAdmin WHERE id = :id", + soci::use(static_cast(isAdmin)), soci::use(id); + return id; + } + + *session << "INSERT INTO chat_room_participant (chat_room_id, participant_sip_address_id, is_admin)" + " VALUES (:chatRoomId, :participantSipAddressId, :isAdmin)", + soci::use(chatRoomId), soci::use(participantSipAddressId), soci::use(static_cast(isAdmin)); + + return dbSession.getLastInsertId(); +} + +void MainDbPrivate::insertChatRoomParticipantDevice ( + long long participantId, + long long participantDeviceSipAddressId +) { + soci::session *session = dbSession.getBackendSession(); + long long count; + *session << "SELECT COUNT(*) FROM chat_room_participant_device" + " WHERE chat_room_participant_id = :participantId" + " AND participant_device_sip_address_id = :participantDeviceSipAddressId", + soci::into(count), soci::use(participantId), soci::use(participantDeviceSipAddressId); + if (count) + return; + + *session << "INSERT INTO chat_room_participant_device (chat_room_participant_id, participant_device_sip_address_id)" + " VALUES (:participantId, :participantDeviceSipAddressId)", + soci::use(participantId), soci::use(participantDeviceSipAddressId); +} + +void MainDbPrivate::insertChatMessageParticipant (long long chatMessageId, long long sipAddressId, int state, time_t stateChangeTime) { + const tm &stateChangeTm = Utils::getTimeTAsTm(stateChangeTime); + *dbSession.getBackendSession() << + "INSERT INTO chat_message_participant (event_id, participant_sip_address_id, state, state_change_time)" + " VALUES (:chatMessageId, :sipAddressId, :state, :stateChangeTm)", + soci::use(chatMessageId), soci::use(sipAddressId), soci::use(state), soci::use(stateChangeTm); +} + +// ----------------------------------------------------------------------------- + +long long MainDbPrivate::selectSipAddressId (const string &sipAddress) const { + long long id; + + soci::session *session = dbSession.getBackendSession(); + *session << Statements::get(Statements::SelectSipAddressId), + soci::use(sipAddress), soci::into(id); + + return session->got_data() ? id : -1; +} + +long long MainDbPrivate::selectChatRoomId (long long peerSipAddressId, long long localSipAddressId) const { + long long id; + + soci::session *session = dbSession.getBackendSession(); + *session << Statements::get(Statements::SelectChatRoomId), + soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::into(id); + + return session->got_data() ? id : -1; +} + +long long MainDbPrivate::selectChatRoomId (const ChatRoomId &chatRoomId) const { + long long peerSipAddressId = selectSipAddressId(chatRoomId.getPeerAddress().asString()); + if (peerSipAddressId < 0) + return -1; + + long long localSipAddressId = selectSipAddressId(chatRoomId.getLocalAddress().asString()); + if (localSipAddressId < 0) + return -1; + + return selectChatRoomId(peerSipAddressId, localSipAddressId); +} + +long long MainDbPrivate::selectChatRoomParticipantId (long long chatRoomId, long long participantSipAddressId) const { + long long id; + + soci::session *session = dbSession.getBackendSession(); + *session << Statements::get(Statements::SelectChatRoomParticipantId), + soci::use(chatRoomId), soci::use(participantSipAddressId), soci::into(id); + + return session->got_data() ? id : -1; +} + +long long MainDbPrivate::selectOneToOneChatRoomId (long long sipAddressIdA, long long sipAddressIdB) const { + long long id; + + soci::session *session = dbSession.getBackendSession(); + *session << Statements::get(Statements::SelectOneToOneChatRoomId), + soci::use(sipAddressIdA), soci::use(sipAddressIdB), soci::use(sipAddressIdA), soci::use(sipAddressIdB), + soci::into(id); + + return session->got_data() ? id : -1; +} + +// ----------------------------------------------------------------------------- + +void MainDbPrivate::deleteContents (long long chatMessageId) { + *dbSession.getBackendSession() << "DELETE FROM chat_message_content WHERE event_id = :chatMessageId", + soci::use(chatMessageId); +} + +void MainDbPrivate::deleteChatRoomParticipant (long long chatRoomId, long long participantSipAddressId) { + *dbSession.getBackendSession() << "DELETE FROM chat_room_participant" + " WHERE chat_room_id = :chatRoomId AND participant_sip_address_id = :participantSipAddressId", + soci::use(chatRoomId), soci::use(participantSipAddressId); +} + +void MainDbPrivate::deleteChatRoomParticipantDevice ( + long long participantId, + long long participantDeviceSipAddressId +) { + *dbSession.getBackendSession() << "DELETE FROM chat_room_participant_device" + " WHERE chat_room_participant_id = :participantId" + " AND participant_device_sip_address_id = :participantDeviceSipAddressId", + soci::use(participantId), soci::use(participantDeviceSipAddressId); +} + +// ----------------------------------------------------------------------------- +// Events API. +// ----------------------------------------------------------------------------- + +shared_ptr MainDbPrivate::selectGenericConferenceEvent ( + const shared_ptr &chatRoom, + const soci::row &row +) const { + EventLog::Type type = EventLog::Type(row.get(1)); + if (type == EventLog::Type::ConferenceChatMessage) { + long long eventId = getConferenceEventIdFromRow(row); + shared_ptr eventLog = getEventFromCache(eventId); + if (!eventLog) { + eventLog = selectConferenceChatMessageEvent(chatRoom, type, row); + if (eventLog) + cache(eventLog, eventId); + } + return eventLog; + } + + return selectGenericConferenceNotifiedEvent(chatRoom->getChatRoomId(), row); +} + +shared_ptr MainDbPrivate::selectGenericConferenceNotifiedEvent ( + const ChatRoomId &chatRoomId, + const soci::row &row +) const { + long long eventId = getConferenceEventIdFromRow(row); + shared_ptr eventLog = getEventFromCache(eventId); + if (eventLog) + return eventLog; + + EventLog::Type type = EventLog::Type(row.get(1)); + switch (type) { + case EventLog::Type::None: + case EventLog::Type::ConferenceChatMessage: + return nullptr; + + case EventLog::Type::ConferenceCreated: + case EventLog::Type::ConferenceTerminated: + eventLog = selectConferenceEvent(chatRoomId, type, row); + break; + + case EventLog::Type::ConferenceCallStart: + case EventLog::Type::ConferenceCallEnd: + eventLog = selectConferenceCallEvent(chatRoomId, type, row); + break; + + case EventLog::Type::ConferenceParticipantAdded: + case EventLog::Type::ConferenceParticipantRemoved: + case EventLog::Type::ConferenceParticipantSetAdmin: + case EventLog::Type::ConferenceParticipantUnsetAdmin: + eventLog = selectConferenceParticipantEvent(chatRoomId, type, row); + break; + + case EventLog::Type::ConferenceParticipantDeviceAdded: + case EventLog::Type::ConferenceParticipantDeviceRemoved: + eventLog = selectConferenceParticipantDeviceEvent(chatRoomId, type, row); + break; + + case EventLog::Type::ConferenceSubjectChanged: + eventLog = selectConferenceSubjectEvent(chatRoomId, type, row); + break; + } + + if (eventLog) + cache(eventLog, eventId); + + return eventLog; +} + +shared_ptr MainDbPrivate::selectConferenceEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row +) const { + return make_shared( + type, + getConferenceEventCreationTimeFromRow(row), + chatRoomId + ); +} + +shared_ptr MainDbPrivate::selectConferenceCallEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row +) const { + // TODO. + return nullptr; +} + +shared_ptr MainDbPrivate::selectConferenceChatMessageEvent ( + const shared_ptr &chatRoom, + EventLog::Type type, + const soci::row &row +) const { + long long eventId = getConferenceEventIdFromRow(row); + shared_ptr chatMessage = getChatMessageFromCache(eventId); + if (!chatMessage) { + chatMessage = shared_ptr(new ChatMessage( + chatRoom, + ChatMessage::Direction(row.get(8)) + )); + chatMessage->setIsSecured(!!row.get(9)); + + ChatMessagePrivate *dChatMessage = chatMessage->getPrivate(); + ChatMessage::State messageState = ChatMessage::State(row.get(7)); + // This is necessary if linphone has crashed while sending a message. It will set the correct state so the user can resend it. + if (messageState == ChatMessage::State::Idle || messageState == ChatMessage::State::InProgress) + messageState = ChatMessage::State::NotDelivered; + dChatMessage->setState(messageState, true); + + dChatMessage->forceFromAddress(IdentityAddress(row.get(3))); + dChatMessage->forceToAddress(IdentityAddress(row.get(4))); + + dChatMessage->setTime(MainDbPrivate::getTmAsTimeT(row.get(5))); + dChatMessage->setImdnMessageId(row.get(6)); + dChatMessage->setPositiveDeliveryNotificationRequired(!!row.get(14)); + dChatMessage->setDisplayNotificationRequired(!!row.get(15)); + + dChatMessage->markContentsAsNotLoaded(); + dChatMessage->setIsReadOnly(true); + + cache(chatMessage, eventId); + } + + return make_shared( + getConferenceEventCreationTimeFromRow(row), + chatMessage + ); +} + +shared_ptr MainDbPrivate::selectConferenceParticipantEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row +) const { + return make_shared( + type, + getConferenceEventCreationTimeFromRow(row), + chatRoomId, + getConferenceEventNotifyIdFromRow(row), + IdentityAddress(row.get(12)) + ); +} + +shared_ptr MainDbPrivate::selectConferenceParticipantDeviceEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row +) const { + return make_shared( + type, + getConferenceEventCreationTimeFromRow(row), + chatRoomId, + getConferenceEventNotifyIdFromRow(row), + IdentityAddress(row.get(12)), + IdentityAddress(row.get(11)) + ); +} + +shared_ptr MainDbPrivate::selectConferenceSubjectEvent ( + const ChatRoomId &chatRoomId, + EventLog::Type type, + const soci::row &row +) const { + return make_shared( + getConferenceEventCreationTimeFromRow(row), + chatRoomId, + getConferenceEventNotifyIdFromRow(row), + row.get(13) + ); +} + +// ----------------------------------------------------------------------------- + +long long MainDbPrivate::insertEvent (const shared_ptr &eventLog) { + const int &type = int(eventLog->getType()); + const tm &creationTime = Utils::getTimeTAsTm(eventLog->getCreationTime()); + *dbSession.getBackendSession() << "INSERT INTO event (type, creation_time) VALUES (:type, :creationTime)", + soci::use(type), soci::use(creationTime); + + return dbSession.getLastInsertId(); +} + +long long MainDbPrivate::insertConferenceEvent (const shared_ptr &eventLog, long long *chatRoomId) { + shared_ptr conferenceEvent = static_pointer_cast(eventLog); + + long long eventId = -1; + const long long &curChatRoomId = selectChatRoomId(conferenceEvent->getChatRoomId()); + if (curChatRoomId < 0) { + // A conference event can be inserted in database only if chat room exists. + // Otherwise it's an error. + const ChatRoomId &chatRoomId = conferenceEvent->getChatRoomId(); + lError() << "Unable to find chat room storage id of: " << chatRoomId << "."; + } else { + eventId = insertEvent(eventLog); + + soci::session *session = dbSession.getBackendSession(); + *session << "INSERT INTO conference_event (event_id, chat_room_id)" + " VALUES (:eventId, :chatRoomId)", soci::use(eventId), soci::use(curChatRoomId); + + const tm &lastUpdateTime = Utils::getTimeTAsTm(eventLog->getCreationTime()); + *session << "UPDATE chat_room SET last_update_time = :lastUpdateTime" + " WHERE id = :chatRoomId", soci::use(lastUpdateTime), + soci::use(curChatRoomId); + + if (eventLog->getType() == EventLog::Type::ConferenceTerminated) + *session << "UPDATE chat_room SET flags = 1, last_notify_id = 0 WHERE id = :chatRoomId", soci::use(curChatRoomId); + else if (eventLog->getType() == EventLog::Type::ConferenceCreated) + *session << "UPDATE chat_room SET flags = 0 WHERE id = :chatRoomId", soci::use(curChatRoomId); + } + + if (chatRoomId) + *chatRoomId = curChatRoomId; + + return eventId; +} + +long long MainDbPrivate::insertConferenceCallEvent (const shared_ptr &eventLog) { + // TODO. + return 0; +} + +long long MainDbPrivate::insertConferenceChatMessageEvent (const shared_ptr &eventLog) { + const long long &eventId = insertConferenceEvent(eventLog); + if (eventId < 0) + return -1; + + shared_ptr chatMessage = static_pointer_cast(eventLog)->getChatMessage(); + const long long &fromSipAddressId = insertSipAddress(chatMessage->getFromAddress().asString()); + const long long &toSipAddressId = insertSipAddress(chatMessage->getToAddress().asString()); + const tm &messageTime = Utils::getTimeTAsTm(chatMessage->getTime()); + const int &state = int(chatMessage->getState()); + const int &direction = int(chatMessage->getDirection()); + const string &imdnMessageId = chatMessage->getImdnMessageId(); + const int &isSecured = chatMessage->isSecured() ? 1 : 0; + const int &deliveryNotificationRequired = chatMessage->getPrivate()->getPositiveDeliveryNotificationRequired(); + const int &displayNotificationRequired = chatMessage->getPrivate()->getDisplayNotificationRequired(); + + *dbSession.getBackendSession() << "INSERT INTO conference_chat_message_event (" + " event_id, from_sip_address_id, to_sip_address_id," + " time, state, direction, imdn_message_id, is_secured," + " delivery_notification_required, display_notification_required" + ") VALUES (" + " :eventId, :localSipaddressId, :remoteSipaddressId," + " :time, :state, :direction, :imdnMessageId, :isSecured," + " :deliveryNotificationRequired, :displayNotificationRequired" + ")", soci::use(eventId), soci::use(fromSipAddressId), soci::use(toSipAddressId), + soci::use(messageTime), soci::use(state), soci::use(direction), + soci::use(imdnMessageId), soci::use(isSecured), + soci::use(deliveryNotificationRequired), soci::use(displayNotificationRequired); + + for (const Content *content : chatMessage->getContents()) + insertContent(eventId, *content); + + for (const auto &participant : chatMessage->getChatRoom()->getParticipants()) { + const long long &participantSipAddressId = selectSipAddressId(participant->getAddress().asString()); + insertChatMessageParticipant(eventId, participantSipAddressId, state, chatMessage->getTime()); + } + + return eventId; +} + +void MainDbPrivate::updateConferenceChatMessageEvent (const shared_ptr &eventLog) { + shared_ptr chatMessage = static_pointer_cast(eventLog)->getChatMessage(); + + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + + const int &state = int(chatMessage->getState()); + const string &imdnMessageId = chatMessage->getImdnMessageId(); + *dbSession.getBackendSession() << "UPDATE conference_chat_message_event SET state = :state, imdn_message_id = :imdnMessageId" + " WHERE event_id = :eventId", + soci::use(state), soci::use(imdnMessageId), soci::use(eventId); + + deleteContents(eventId); + for (const auto &content : chatMessage->getContents()) + insertContent(eventId, *content); + + if ((chatMessage->getDirection() == ChatMessage::Direction::Outgoing) + && ((chatMessage->getState() == ChatMessage::State::Delivered) || (chatMessage->getState() == ChatMessage::State::NotDelivered)) + ) { + for (const auto &participant : chatMessage->getChatRoom()->getParticipants()) + setChatMessageParticipantState(eventLog, participant->getAddress(), chatMessage->getState(), std::time(nullptr)); + } +} + +long long MainDbPrivate::insertConferenceNotifiedEvent (const shared_ptr &eventLog, long long *chatRoomId) { + long long curChatRoomId; + const long long &eventId = insertConferenceEvent(eventLog, &curChatRoomId); + if (eventId < 0) + return -1; + + const unsigned int &lastNotifyId = static_pointer_cast(eventLog)->getNotifyId(); + + soci::session *session = dbSession.getBackendSession(); + *session << "INSERT INTO conference_notified_event (event_id, notify_id)" + " VALUES (:eventId, :notifyId)", soci::use(eventId), soci::use(lastNotifyId); + *session << "UPDATE chat_room SET last_notify_id = :lastNotifyId WHERE id = :chatRoomId", + soci::use(lastNotifyId), soci::use(curChatRoomId); + + if (chatRoomId) + *chatRoomId = curChatRoomId; + + return eventId; +} + +long long MainDbPrivate::insertConferenceParticipantEvent ( + const shared_ptr &eventLog, + long long *chatRoomId +) { + long long curChatRoomId; + const long long &eventId = insertConferenceNotifiedEvent(eventLog, &curChatRoomId); + if (eventId < 0) + return -1; + + shared_ptr participantEvent = + static_pointer_cast(eventLog); + + const long long &participantAddressId = insertSipAddress( + participantEvent->getParticipantAddress().asString() + ); + + *dbSession.getBackendSession() << "INSERT INTO conference_participant_event (event_id, participant_sip_address_id)" + " VALUES (:eventId, :participantAddressId)", soci::use(eventId), soci::use(participantAddressId); + + bool isAdmin = eventLog->getType() == EventLog::Type::ConferenceParticipantSetAdmin; + switch (eventLog->getType()) { + case EventLog::Type::ConferenceParticipantAdded: + case EventLog::Type::ConferenceParticipantSetAdmin: + case EventLog::Type::ConferenceParticipantUnsetAdmin: + insertChatRoomParticipant(curChatRoomId, participantAddressId, isAdmin); + break; + + case EventLog::Type::ConferenceParticipantRemoved: + deleteChatRoomParticipant(curChatRoomId, participantAddressId); + break; + + default: + break; + } + + if (chatRoomId) + *chatRoomId = curChatRoomId; + + return eventId; +} + +long long MainDbPrivate::insertConferenceParticipantDeviceEvent (const shared_ptr &eventLog) { + long long chatRoomId; + const long long &eventId = insertConferenceParticipantEvent(eventLog, &chatRoomId); + if (eventId < 0) + return -1; + + shared_ptr participantDeviceEvent = + static_pointer_cast(eventLog); + + const string participantAddress = participantDeviceEvent->getParticipantAddress().asString(); + const long long &participantAddressId = selectSipAddressId(participantAddress); + if (participantAddressId < 0) { + lError() << "Unable to find sip address id of: `" << participantAddress << "`."; + return -1; + } + const long long &participantId = selectChatRoomParticipantId(chatRoomId, participantAddressId); + if (participantId < 0) { + lError() << "Unable to find valid participant id in database with chat room id = " << chatRoomId << + " and participant address id = " << participantAddressId; + return -1; + } + const long long &deviceAddressId = insertSipAddress( + participantDeviceEvent->getDeviceAddress().asString() + ); + + *dbSession.getBackendSession() << "INSERT INTO conference_participant_device_event (event_id, device_sip_address_id)" + " VALUES (:eventId, :deviceAddressId)", soci::use(eventId), soci::use(deviceAddressId); + + switch (eventLog->getType()) { + case EventLog::Type::ConferenceParticipantDeviceAdded: + insertChatRoomParticipantDevice(participantId, deviceAddressId); + break; + + case EventLog::Type::ConferenceParticipantDeviceRemoved: + deleteChatRoomParticipantDevice(participantId, deviceAddressId); + break; + + default: + break; + } + + return eventId; +} + +long long MainDbPrivate::insertConferenceSubjectEvent (const shared_ptr &eventLog) { + long long chatRoomId; + const long long &eventId = insertConferenceNotifiedEvent(eventLog, &chatRoomId); + if (eventId < 0) + return -1; + + const string &subject = static_pointer_cast(eventLog)->getSubject(); + + soci::session *session = dbSession.getBackendSession(); + *session << "INSERT INTO conference_subject_event (event_id, subject)" + " VALUES (:eventId, :subject)", soci::use(eventId), soci::use(subject); + + *session << "UPDATE chat_room SET subject = :subject" + " WHERE id = :chatRoomId", soci::use(subject), soci::use(chatRoomId); + + return eventId; +} + +void MainDbPrivate::setChatMessageParticipantState ( + const shared_ptr &eventLog, + const IdentityAddress &participantAddress, + ChatMessage::State state, + time_t stateChangeTime +) { + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + const long long &participantSipAddressId = selectSipAddressId(participantAddress.asString()); + int stateInt = static_cast(state); + const tm &stateChangeTm = Utils::getTimeTAsTm(stateChangeTime); + + *dbSession.getBackendSession() << "UPDATE chat_message_participant SET state = :state," + " state_change_time = :stateChangeTm" + " WHERE event_id = :eventId AND participant_sip_address_id = :participantSipAddressId", + soci::use(stateInt), soci::use(stateChangeTm), soci::use(eventId), soci::use(participantSipAddressId); +} + + +// ----------------------------------------------------------------------------- +// Cache API. +// ----------------------------------------------------------------------------- + +shared_ptr MainDbPrivate::getEventFromCache (long long storageId) const { + auto it = storageIdToEvent.find(storageId); + if (it == storageIdToEvent.cend()) + return nullptr; + + shared_ptr eventLog = it->second.lock(); + L_ASSERT(eventLog); + return eventLog; +} + +shared_ptr MainDbPrivate::getChatMessageFromCache (long long storageId) const { + auto it = storageIdToChatMessage.find(storageId); + if (it == storageIdToChatMessage.cend()) + return nullptr; + + shared_ptr chatMessage = it->second.lock(); + L_ASSERT(chatMessage); + return chatMessage; +} + +void MainDbPrivate::cache (const shared_ptr &eventLog, long long storageId) const { + L_Q(); + + EventLogPrivate *dEventLog = eventLog->getPrivate(); + L_ASSERT(!dEventLog->dbKey.isValid()); + dEventLog->dbKey = MainDbEventKey(q->getCore(), storageId); + storageIdToEvent[storageId] = eventLog; + L_ASSERT(dEventLog->dbKey.isValid()); +} + +void MainDbPrivate::cache (const shared_ptr &chatMessage, long long storageId) const { + L_Q(); + + ChatMessagePrivate *dChatMessage = chatMessage->getPrivate(); + L_ASSERT(!dChatMessage->dbKey.isValid()); + dChatMessage->dbKey = MainDbChatMessageKey(q->getCore(), storageId); + storageIdToChatMessage[storageId] = chatMessage; + L_ASSERT(dChatMessage->dbKey.isValid()); +} + +void MainDbPrivate::invalidConferenceEventsFromQuery (const string &query, long long chatRoomId) { + soci::rowset rows = (dbSession.getBackendSession()->prepare << query, soci::use(chatRoomId)); + for (const auto &row : rows) { + long long eventId = dbSession.resolveId(row, 0); + shared_ptr eventLog = getEventFromCache(eventId); + if (eventLog) { + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + L_ASSERT(dEventLog->dbKey.isValid()); + dEventLog->dbKey = MainDbEventKey(); + } + shared_ptr chatMessage = getChatMessageFromCache(eventId); + if (chatMessage) { + const ChatMessagePrivate *dChatMessage = chatMessage->getPrivate(); + L_ASSERT(dChatMessage->dbKey.isValid()); + dChatMessage->dbKey = MainDbChatMessageKey(); + } + } +} + +// ----------------------------------------------------------------------------- +// Versions. +// ----------------------------------------------------------------------------- + +unsigned int MainDbPrivate::getModuleVersion (const string &name) { + soci::session *session = dbSession.getBackendSession(); + + unsigned int version; + *session << "SELECT version FROM db_module_version WHERE name = :name", soci::into(version), soci::use(name); + return session->got_data() ? version : 0; +} + +void MainDbPrivate::updateModuleVersion (const string &name, unsigned int version) { + unsigned int oldVersion = getModuleVersion(name); + if (version <= oldVersion) + return; + + soci::session *session = dbSession.getBackendSession(); + *session << "REPLACE INTO db_module_version (name, version) VALUES (:name, :version)", + soci::use(name), soci::use(version); +} + +void MainDbPrivate::updateSchema () { + L_Q(); + + soci::session *session = dbSession.getBackendSession(); + unsigned int version = getModuleVersion("events"); + + if (version < makeVersion(1, 0, 1)) + *session << "ALTER TABLE chat_room_participant_device ADD COLUMN state TINYINT UNSIGNED DEFAULT 0"; + if (version < makeVersion(1, 0, 2)) { + *session << "DROP TRIGGER IF EXISTS chat_message_participant_deleter"; + *session << "ALTER TABLE chat_message_participant ADD COLUMN state_change_time" + + dbSession.timestampType() + " NOT NULL DEFAULT " + dbSession.currentTimestamp(); + } + if (version < makeVersion(1, 0, 3)) { + // Remove client group one-to-one chat rooms for the moment as there are still some issues + // with them and we prefer to keep using basic chat rooms instead + const int &capabilities = ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Conference) + | ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::OneToOne); + *session << "DELETE FROM chat_room WHERE (capabilities & :capabilities1) = :capabilities2", + soci::use(capabilities), soci::use(capabilities); + linphone_config_set_bool(linphone_core_get_config(q->getCore()->getCCore()), "misc", "prefer_basic_chat_room", TRUE); + } + if (version < makeVersion(1, 0, 4)) { + *session << "ALTER TABLE conference_chat_message_event ADD COLUMN delivery_notification_required BOOLEAN NOT NULL DEFAULT 0"; + *session << "ALTER TABLE conference_chat_message_event ADD COLUMN display_notification_required BOOLEAN NOT NULL DEFAULT 0"; + + *session << "DROP VIEW IF EXISTS conference_event_view"; + + string query; + if (q->getBackend() == AbstractDb::Backend::Mysql) + query = "CREATE OR REPLACE VIEW conference_event_view AS"; + else + query = "CREATE VIEW IF NOT EXISTS conference_event_view AS"; + *session << query + + " SELECT id, type, creation_time, chat_room_id, from_sip_address_id, to_sip_address_id, time, imdn_message_id, state, direction, is_secured, notify_id, device_sip_address_id, participant_sip_address_id, subject, delivery_notification_required, display_notification_required" + " FROM event" + " LEFT JOIN conference_event ON conference_event.event_id = event.id" + " LEFT JOIN conference_chat_message_event ON conference_chat_message_event.event_id = event.id" + " LEFT JOIN conference_notified_event ON conference_notified_event.event_id = event.id" + " LEFT JOIN conference_participant_device_event ON conference_participant_device_event.event_id = event.id" + " LEFT JOIN conference_participant_event ON conference_participant_event.event_id = event.id" + " LEFT JOIN conference_subject_event ON conference_subject_event.event_id = event.id"; + } +} + +// ----------------------------------------------------------------------------- +// Import. +// ----------------------------------------------------------------------------- + +static inline bool checkLegacyTableExists (soci::session &session, const string &name) { + session << "SELECT name FROM sqlite_master WHERE type='table' AND name = :name", soci::use(name); + return session.got_data(); +} + +static inline bool checkLegacyFriendsTableExists (soci::session &session) { + return checkLegacyTableExists(session, "friends"); +} + +static inline bool checkLegacyHistoryTableExists (soci::session &session) { + return checkLegacyTableExists(session, "history"); +} + +void MainDbPrivate::importLegacyFriends (DbSession &inDbSession) { + L_Q(); + L_DB_TRANSACTION_C(q) { + if (getModuleVersion("legacy-friends-import") >= makeVersion(1, 0, 0)) + return; + updateModuleVersion("legacy-friends-import", ModuleVersionLegacyFriendsImport); + + soci::session *inSession = inDbSession.getBackendSession(); + if (!checkLegacyFriendsTableExists(*inSession)) + return; + + unordered_map resolvedListsIds; + soci::session *session = dbSession.getBackendSession(); + + soci::rowset friendsLists = (inSession->prepare << "SELECT * FROM friends_lists"); + + set names; + for (const auto &friendList : friendsLists) { + const string &name = friendList.get(LegacyFriendListColName, ""); + const string &rlsUri = friendList.get(LegacyFriendListColRlsUri, ""); + const string &syncUri = friendList.get(LegacyFriendListColSyncUri, ""); + const int &revision = friendList.get(LegacyFriendListColRevision, 0); + + string uniqueName = name; + for (int id = 0; names.find(uniqueName) != names.end(); uniqueName = name + "-" + Utils::toString(id++)); + names.insert(uniqueName); + + *session << "INSERT INTO friends_list (name, rls_uri, sync_uri, revision) VALUES (" + " :name, :rlsUri, :syncUri, :revision" + ")", soci::use(uniqueName), soci::use(rlsUri), soci::use(syncUri), soci::use(revision); + resolvedListsIds[friendList.get(LegacyFriendListColId)] = dbSession.getLastInsertId(); + } + + soci::rowset friends = (inSession->prepare << "SELECT * FROM friends"); + for (const auto &friendInfo : friends) { + long long friendsListId; + { + auto it = resolvedListsIds.find(friendInfo.get(LegacyFriendColFriendListId, -1)); + if (it == resolvedListsIds.end()) + continue; + friendsListId = it->second; + } + + const long long &sipAddressId = insertSipAddress(friendInfo.get(LegacyFriendColSipAddress, "")); + const int &subscribePolicy = friendInfo.get(LegacyFriendColSubscribePolicy, LinphoneSPAccept); + const int &sendSubscribe = friendInfo.get(LegacyFriendColSendSubscribe, 1); + const string &vCard = friendInfo.get(LegacyFriendColVCard, ""); + const string &vCardEtag = friendInfo.get(LegacyFriendColVCardEtag, ""); + const string &vCardSyncUri = friendInfo.get(LegacyFriendColVCardSyncUri, ""); + const int &presenceReveived = friendInfo.get(LegacyFriendColPresenceReceived, 0); + + *session << "INSERT INTO friend (" + " sip_address_id, friends_list_id, subscribe_policy, send_subscribe," + " presence_received, v_card, v_card_etag, v_card_sync_uri" + ") VALUES (" + " :sipAddressId, :friendsListId, :subscribePolicy, :sendSubscribe," + " :presenceReceived, :vCard, :vCardEtag, :vCardSyncUri" + ")", soci::use(sipAddressId), soci::use(friendsListId), soci::use(subscribePolicy), soci::use(sendSubscribe), + soci::use(presenceReveived), soci::use(vCard), soci::use(vCardEtag), soci::use(vCardSyncUri); + + bool isNull; + const string &data = getValueFromRow(friendInfo, LegacyFriendColRefKey, isNull); + if (!isNull) + *session << "INSERT INTO friend_app_data (friend_id, name, data) VALUES" + " (:friendId, 'legacy', :data)", + soci::use(dbSession.getLastInsertId()), soci::use(data); + } + tr.commit(); + lInfo() << "Successful import of legacy friends."; + }; +} + +// TODO: Move in a helper file? With others xml. +struct XmlCharObjectDeleter { + void operator() (void *ptr) const { + xmlFree(ptr); + } +}; +using XmlCharObject = unique_ptr; + +struct XmlDocObjectDeleter { + void operator() (xmlDocPtr ptr) const { + xmlFreeDoc(ptr); + } +}; +using XmlDocObject = unique_ptr::type, XmlDocObjectDeleter>; + +typedef const xmlChar* XmlCharPtr; + +static string extractLegacyFileContentType (const string &xml) { + XmlDocObject xmlMessageBody(xmlParseDoc(XmlCharPtr(xml.c_str()))); + xmlNodePtr xmlElement = xmlDocGetRootElement(xmlMessageBody.get()); + if (!xmlElement) + return ""; + + for (xmlElement = xmlElement->xmlChildrenNode; xmlElement; xmlElement = xmlElement->next) { + if (xmlStrcmp(xmlElement->name, XmlCharPtr("file-info"))) + continue; + + XmlCharObject typeAttribute(xmlGetProp(xmlElement, XmlCharPtr("type"))); + if (xmlStrcmp(typeAttribute.get(), XmlCharPtr("file"))) + continue; + + for (xmlElement = xmlElement->xmlChildrenNode; xmlElement; xmlElement = xmlElement->next) + if (!xmlStrcmp(xmlElement->name, XmlCharPtr("content-type"))) { + XmlCharObject xmlContentType(xmlNodeListGetString(xmlMessageBody.get(), xmlElement->xmlChildrenNode, 1)); + return ContentType(reinterpret_cast(xmlContentType.get())).asString(); + } + } + + return ""; +} + +void MainDbPrivate::importLegacyHistory (DbSession &inDbSession) { + L_Q(); + L_DB_TRANSACTION_C(q) { + if (getModuleVersion("legacy-history-import") >= makeVersion(1, 0, 0)) + return; + updateModuleVersion("legacy-history-import", ModuleVersionLegacyHistoryImport); + + soci::session *inSession = inDbSession.getBackendSession(); + if (!checkLegacyHistoryTableExists(*inSession)) + return; + + soci::rowset messages = (inSession->prepare << "SELECT * FROM history"); + for (const auto &message : messages) { + const int direction = message.get(LegacyMessageColDirection); + if (direction != 0 && direction != 1) { + lWarning() << "Unable to import legacy message with invalid direction."; + continue; + } + + const int &state = message.get( + LegacyMessageColState, int(ChatMessage::State::Displayed) + ); + if (state < 0 || state > int(ChatMessage::State::Displayed)) { + lWarning() << "Unable to import legacy message with invalid state."; + continue; + } + + const tm &creationTime = Utils::getTimeTAsTm(message.get(LegacyMessageColDate, 0)); + + bool isNull; + getValueFromRow(message, LegacyMessageColUrl, isNull); + + const int &contentId = message.get(LegacyMessageColContentId, -1); + ContentType contentType(message.get(LegacyMessageColContentType, "")); + if (!contentType.isValid()) + contentType = contentId != -1 + ? ContentType::FileTransfer + : (isNull ? ContentType::PlainText : ContentType::ExternalBody); + if (contentType == ContentType::ExternalBody) { + lInfo() << "Import of external body content is skipped."; + continue; + } + + const string &text = getValueFromRow(message, LegacyMessageColText, isNull); + + unique_ptr content; + if (contentType == ContentType::FileTransfer) { + const string appData = getValueFromRow(message, LegacyMessageColAppData, isNull); + if (isNull) { + lWarning() << "Unable to import legacy file message without app data."; + continue; + } + + string contentTypeString = extractLegacyFileContentType(text); + if (contentTypeString.empty()) { + lWarning() << "Unable to extract file content type form legacy transfer message"; + continue; + } + ContentType fileContentType(contentTypeString); + content.reset(new FileContent()); + content->setContentType(fileContentType); + content->setAppData("legacy", appData); + content->setBody(text); + } else { + content.reset(new Content()); + content->setContentType(contentType); + if (contentType == ContentType::PlainText) { + if (isNull) { + lWarning() << "Unable to import legacy message with no text."; + continue; + } + content->setBody(text); + } else { + lWarning() << "Unable to import unsupported legacy content."; + continue; + } + } + + soci::session *session = dbSession.getBackendSession(); + const int &eventType = int(EventLog::Type::ConferenceChatMessage); + *session << "INSERT INTO event (type, creation_time) VALUES (:type, :creationTime)", + soci::use(eventType), soci::use(creationTime); + + const long long &eventId = dbSession.getLastInsertId(); + const long long &localSipAddressId = insertSipAddress( + IdentityAddress(message.get(LegacyMessageColLocalAddress)).asString() + ); + const long long &remoteSipAddressId = insertSipAddress( + IdentityAddress(message.get(LegacyMessageColRemoteAddress)).asString() + ); + const long long &chatRoomId = insertOrUpdateImportedBasicChatRoom( + remoteSipAddressId, + localSipAddressId, + creationTime + ); + const int &isSecured = message.get(LegacyMessageColIsSecured, 0); + const int deliveryNotificationRequired = 0; + const int displayNotificationRequired = 0; + + *session << "INSERT INTO conference_event (event_id, chat_room_id)" + " VALUES (:eventId, :chatRoomId)", soci::use(eventId), soci::use(chatRoomId); + + *session << "INSERT INTO conference_chat_message_event (" + " event_id, from_sip_address_id, to_sip_address_id," + " time, state, direction, imdn_message_id, is_secured," + " delivery_notification_required, display_notification_required" + ") VALUES (" + " :eventId, :localSipAddressId, :remoteSipAddressId," + " :creationTime, :state, :direction, '', :isSecured," + " :deliveryNotificationRequired, :displayNotificationRequired" + ")", soci::use(eventId), soci::use(localSipAddressId), soci::use(remoteSipAddressId), + soci::use(creationTime), soci::use(state), soci::use(direction), soci::use(isSecured), + soci::use(deliveryNotificationRequired), soci::use(displayNotificationRequired); + + if (content) + insertContent(eventId, *content); + insertChatRoomParticipant(chatRoomId, remoteSipAddressId, false); + insertChatMessageParticipant(eventId, remoteSipAddressId, state, std::time(nullptr)); + } + tr.commit(); + lInfo() << "Successful import of legacy messages."; + }; +} + +// ============================================================================= + +MainDb::MainDb (const shared_ptr &core) : AbstractDb(*new MainDbPrivate), CoreAccessor(core) {} + +void MainDb::init () { + L_D(); + + Backend backend = getBackend(); + + const string charset = backend == Mysql ? "DEFAULT CHARSET=utf8" : ""; + soci::session *session = d->dbSession.getBackendSession(); + + using namespace placeholders; + auto primaryKeyRefStr = bind(&DbSession::primaryKeyRefStr, &d->dbSession, _1); + auto primaryKeyStr = bind(&DbSession::primaryKeyStr, &d->dbSession, _1); + auto timestampType = bind(&DbSession::timestampType, &d->dbSession); + auto varcharPrimaryKeyStr = bind(&DbSession::varcharPrimaryKeyStr, &d->dbSession, _1); + + *session << + "CREATE TABLE IF NOT EXISTS sip_address (" + " id" + primaryKeyStr("BIGINT UNSIGNED") + "," + " value VARCHAR(255) UNIQUE NOT NULL" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS content_type (" + " id" + primaryKeyStr("SMALLINT UNSIGNED") + "," + " value VARCHAR(255) UNIQUE NOT NULL" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS event (" + " id" + primaryKeyStr("BIGINT UNSIGNED") + "," + " type TINYINT UNSIGNED NOT NULL," + " creation_time" + timestampType() + " NOT NULL" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS chat_room (" + " id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + // Server (for conference) or user sip address. + " peer_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + + " local_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + + // Dialog creation time. + " creation_time" + timestampType() + " NOT NULL," + + // Last event time (call, message...). + " last_update_time" + timestampType() + " NOT NULL," + + // ConferenceChatRoom, BasicChatRoom, RTT... + " capabilities TINYINT UNSIGNED NOT NULL," + + // Chatroom subject. + " subject VARCHAR(255)," + + " last_notify_id INT UNSIGNED DEFAULT 0," + + " flags INT UNSIGNED DEFAULT 0," + + " UNIQUE (peer_sip_address_id, local_sip_address_id)," + + " FOREIGN KEY (peer_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (local_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS one_to_one_chat_room (" + " chat_room_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " participant_a_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + " participant_b_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + + " FOREIGN KEY (chat_room_id)" + " REFERENCES chat_room(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (participant_a_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (participant_b_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS chat_room_participant (" + " id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " chat_room_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + " participant_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + + " is_admin BOOLEAN NOT NULL," + + " UNIQUE (chat_room_id, participant_sip_address_id)," + + " FOREIGN KEY (chat_room_id)" + " REFERENCES chat_room(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (participant_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS chat_room_participant_device (" + " chat_room_participant_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + " participant_device_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + + " PRIMARY KEY (chat_room_participant_id, participant_device_sip_address_id)," + + " FOREIGN KEY (chat_room_participant_id)" + " REFERENCES chat_room_participant(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (participant_device_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS conference_event (" + " event_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " chat_room_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + + " FOREIGN KEY (event_id)" + " REFERENCES event(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (chat_room_id)" + " REFERENCES chat_room(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS conference_notified_event (" + " event_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " notify_id INT UNSIGNED NOT NULL," + + " FOREIGN KEY (event_id)" + " REFERENCES conference_event(event_id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS conference_participant_event (" + " event_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " participant_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + + " FOREIGN KEY (event_id)" + " REFERENCES conference_notified_event(event_id)" + " ON DELETE CASCADE," + " FOREIGN KEY (participant_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS conference_participant_device_event (" + " event_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " device_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + + " FOREIGN KEY (event_id)" + " REFERENCES conference_participant_event(event_id)" + " ON DELETE CASCADE," + " FOREIGN KEY (device_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS conference_subject_event (" + " event_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " subject VARCHAR(255) NOT NULL," + + " FOREIGN KEY (event_id)" + " REFERENCES conference_notified_event(event_id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS conference_chat_message_event (" + " event_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " from_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + " to_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + + " time" + timestampType() + " ," + + // See: https://tools.ietf.org/html/rfc5438#section-6.3 + " imdn_message_id VARCHAR(255) NOT NULL," + + " state TINYINT UNSIGNED NOT NULL," + " direction TINYINT UNSIGNED NOT NULL," + " is_secured BOOLEAN NOT NULL," + + " FOREIGN KEY (event_id)" + " REFERENCES conference_event(event_id)" + " ON DELETE CASCADE," + " FOREIGN KEY (from_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (to_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS chat_message_participant (" + " event_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + " participant_sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + " state TINYINT UNSIGNED NOT NULL," + + " PRIMARY KEY (event_id, participant_sip_address_id)," + + " FOREIGN KEY (event_id)" + " REFERENCES conference_chat_message_event(event_id)" + " ON DELETE CASCADE," + " FOREIGN KEY (participant_sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS chat_message_content (" + " id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " event_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + " content_type_id" + primaryKeyRefStr("SMALLINT UNSIGNED") + " NOT NULL," + " body TEXT NOT NULL," + + " UNIQUE (id, event_id)," + + " FOREIGN KEY (event_id)" + " REFERENCES conference_chat_message_event(event_id)" + " ON DELETE CASCADE," + " FOREIGN KEY (content_type_id)" + " REFERENCES content_type(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS chat_message_file_content (" + " chat_message_content_id" + primaryKeyStr("BIGINT UNSIGNED") + "," + + " name VARCHAR(256) NOT NULL," + " size INT UNSIGNED NOT NULL," + " path VARCHAR(512) NOT NULL," + + " FOREIGN KEY (chat_message_content_id)" + " REFERENCES chat_message_content(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS chat_message_content_app_data (" + " chat_message_content_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + + " name VARCHAR(255)," + " data BLOB NOT NULL," + + " PRIMARY KEY (chat_message_content_id, name)," + " FOREIGN KEY (chat_message_content_id)" + " REFERENCES chat_message_content(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS conference_message_crypto_data (" + " event_id" + primaryKeyRefStr("BIGINT UNSIGNED") + "," + + " name VARCHAR(255)," + " data BLOB NOT NULL," + + " PRIMARY KEY (event_id, name)," + " FOREIGN KEY (event_id)" + " REFERENCES conference_chat_message_event(event_id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS friends_list (" + " id" + primaryKeyStr("INT UNSIGNED") + "," + + " name VARCHAR(255) UNIQUE," + " rls_uri VARCHAR(2047)," + " sync_uri VARCHAR(2047)," + " revision INT UNSIGNED NOT NULL" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS friend (" + " id" + primaryKeyStr("INT UNSIGNED") + "," + + " sip_address_id" + primaryKeyRefStr("BIGINT UNSIGNED") + " NOT NULL," + " friends_list_id" + primaryKeyRefStr("INT UNSIGNED") + " NOT NULL," + + " subscribe_policy TINYINT UNSIGNED NOT NULL," + " send_subscribe BOOLEAN NOT NULL," + " presence_received BOOLEAN NOT NULL," + + " v_card MEDIUMTEXT," + " v_card_etag VARCHAR(255)," + " v_card_sync_uri VARCHAR(2047)," + + " FOREIGN KEY (sip_address_id)" + " REFERENCES sip_address(id)" + " ON DELETE CASCADE," + " FOREIGN KEY (friends_list_id)" + " REFERENCES friends_list(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS friend_app_data (" + " friend_id" + primaryKeyRefStr("INT UNSIGNED") + "," + + " name VARCHAR(255)," + " data BLOB NOT NULL," + + " PRIMARY KEY (friend_id, name)," + " FOREIGN KEY (friend_id)" + " REFERENCES friend(id)" + " ON DELETE CASCADE" + ") " + charset; + + *session << + "CREATE TABLE IF NOT EXISTS db_module_version (" + " name" + varcharPrimaryKeyStr(255) + "," + " version INT UNSIGNED NOT NULL" + ") " + charset; + + d->updateSchema(); + + d->updateModuleVersion("events", ModuleVersionEvents); + d->updateModuleVersion("friends", ModuleVersionFriends); +} + +bool MainDb::addEvent (const shared_ptr &eventLog) { + if (eventLog->getPrivate()->dbKey.isValid()) { + lWarning() << "Unable to add an event twice!!!"; + return false; + } + + return L_DB_TRANSACTION { + L_D(); + + long long eventId = -1; + + EventLog::Type type = eventLog->getType(); + switch (type) { + case EventLog::Type::None: + return false; + + case EventLog::Type::ConferenceCreated: + case EventLog::Type::ConferenceTerminated: + eventId = d->insertConferenceEvent(eventLog); + break; + + case EventLog::Type::ConferenceCallStart: + case EventLog::Type::ConferenceCallEnd: + eventId = d->insertConferenceCallEvent(eventLog); + break; + + case EventLog::Type::ConferenceChatMessage: + eventId = d->insertConferenceChatMessageEvent(eventLog); + break; + + case EventLog::Type::ConferenceParticipantAdded: + case EventLog::Type::ConferenceParticipantRemoved: + case EventLog::Type::ConferenceParticipantSetAdmin: + case EventLog::Type::ConferenceParticipantUnsetAdmin: + eventId = d->insertConferenceParticipantEvent(eventLog); + break; + + case EventLog::Type::ConferenceParticipantDeviceAdded: + case EventLog::Type::ConferenceParticipantDeviceRemoved: + eventId = d->insertConferenceParticipantDeviceEvent(eventLog); + break; + + case EventLog::Type::ConferenceSubjectChanged: + eventId = d->insertConferenceSubjectEvent(eventLog); + break; + } + + if (eventId >= 0) { + tr.commit(); + d->cache(eventLog, eventId); + + if (type == EventLog::Type::ConferenceChatMessage) + d->cache(static_pointer_cast(eventLog)->getChatMessage(), eventId); + + return true; + } + + return false; + }; +} + +bool MainDb::updateEvent (const shared_ptr &eventLog) { + if (!eventLog->getPrivate()->dbKey.isValid()) { + lWarning() << "Unable to update an event that wasn't inserted yet!!!"; + return false; + } + + return L_DB_TRANSACTION { + L_D(); + + switch (eventLog->getType()) { + case EventLog::Type::None: + return false; + + case EventLog::Type::ConferenceChatMessage: + d->updateConferenceChatMessageEvent(eventLog); + break; + + case EventLog::Type::ConferenceCreated: + case EventLog::Type::ConferenceTerminated: + case EventLog::Type::ConferenceCallStart: + case EventLog::Type::ConferenceCallEnd: + case EventLog::Type::ConferenceParticipantAdded: + case EventLog::Type::ConferenceParticipantRemoved: + case EventLog::Type::ConferenceParticipantSetAdmin: + case EventLog::Type::ConferenceParticipantUnsetAdmin: + case EventLog::Type::ConferenceParticipantDeviceAdded: + case EventLog::Type::ConferenceParticipantDeviceRemoved: + case EventLog::Type::ConferenceSubjectChanged: + return false; + } + + tr.commit(); + + return true; + }; +} + +bool MainDb::deleteEvent (const shared_ptr &eventLog) { + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + if (!dEventLog->dbKey.isValid()) { + lWarning() << "Unable to delete invalid event."; + return false; + } + + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + shared_ptr core = dEventKey->core.lock(); + L_ASSERT(core); + + MainDb &mainDb = *core->getPrivate()->mainDb.get(); + + return L_DB_TRANSACTION_C(&mainDb) { + soci::session *session = mainDb.getPrivate()->dbSession.getBackendSession(); + *session << "DELETE FROM event WHERE id = :id", soci::use(dEventKey->storageId); + tr.commit(); + + dEventLog->dbKey = MainDbEventKey(); + + if (eventLog->getType() == EventLog::Type::ConferenceChatMessage) + static_pointer_cast( + eventLog + )->getChatMessage()->getPrivate()->dbKey = MainDbChatMessageKey(); + + return true; + }; +} + +int MainDb::getEventCount (FilterMask mask) const { + const string query = "SELECT COUNT(*) FROM event" + + buildSqlEventFilter( + { ConferenceCallFilter, ConferenceChatMessageFilter, ConferenceInfoFilter, ConferenceInfoNoDeviceFilter }, + mask + ); + + DurationLogger durationLogger("Get event count with mask=" + Utils::toString(mask) + "."); + + return L_DB_TRANSACTION { + L_D(); + + int count; + *d->dbSession.getBackendSession() << query, soci::into(count); + return count; + }; +} + +shared_ptr MainDb::getEventFromKey (const MainDbKey &dbKey) { + if (!dbKey.isValid()) { + lWarning() << "Unable to get event from invalid key."; + return nullptr; + } + + unique_ptr &q = dbKey.getPrivate()->core.lock()->getPrivate()->mainDb; + MainDbPrivate *d = q->getPrivate(); + + const long long &eventId = dbKey.getPrivate()->storageId; + shared_ptr event = d->getEventFromCache(eventId); + if (event) + return event; + + return L_DB_TRANSACTION_C(q.get()) { + // TODO: Improve. Deal with all events in the future. + soci::row row; + *d->dbSession.getBackendSession() << Statements::get(Statements::SelectConferenceEvent), + soci::into(row), soci::use(eventId); + + ChatRoomId chatRoomId(IdentityAddress(row.get(16)), IdentityAddress(row.get(17))); + shared_ptr chatRoom = d->findChatRoom(chatRoomId); + if (!chatRoom) + return shared_ptr(); + + return d->selectGenericConferenceEvent(chatRoom, row); + }; +} + +list> MainDb::getConferenceNotifiedEvents ( + const ChatRoomId &chatRoomId, + unsigned int lastNotifyId +) const { + // TODO: Optimize. + const string query = Statements::get(Statements::SelectConferenceEvents) + + string(" AND notify_id > :lastNotifyId"); + + DurationLogger durationLogger( + "Get conference notified events of: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + + ", lastNotifyId=" + Utils::toString(lastNotifyId) + ")." + ); + + return L_DB_TRANSACTION { + L_D(); + + soci::session *session = d->dbSession.getBackendSession(); + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + + list> events; + soci::rowset rows = (session->prepare << query, soci::use(dbChatRoomId), soci::use(lastNotifyId)); + for (const auto &row : rows) + events.push_back(d->selectGenericConferenceNotifiedEvent(chatRoomId, row)); + return events; + }; +} + +int MainDb::getChatMessageCount (const ChatRoomId &chatRoomId) const { + DurationLogger durationLogger( + "Get chat messages count of: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + ")." + ); + + return L_DB_TRANSACTION { + L_D(); + + int count; + + soci::session *session = d->dbSession.getBackendSession(); + + string query = "SELECT COUNT(*) FROM conference_chat_message_event"; + if (!chatRoomId.isValid()) + *session << query, soci::into(count); + else { + query += " WHERE event_id IN (" + " SELECT event_id FROM conference_event WHERE chat_room_id = :chatRoomId" + ")"; + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + *session << query, soci::use(dbChatRoomId), soci::into(count); + } + + return count; + }; +} + +int MainDb::getUnreadChatMessageCount (const ChatRoomId &chatRoomId) const { + string query = "SELECT COUNT(*) FROM conference_chat_message_event WHERE"; + if (chatRoomId.isValid()) + query += " event_id IN (" + " SELECT event_id FROM conference_event WHERE chat_room_id = :chatRoomId" + ") AND"; + + query += " direction = " + Utils::toString(int(ChatMessage::Direction::Incoming)) + + + " AND state <> " + Utils::toString(int(ChatMessage::State::Displayed)); + + DurationLogger durationLogger( + "Get unread chat messages count of: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + ")." + ); + + return L_DB_TRANSACTION { + L_D(); + + int count = 0; + + soci::session *session = d->dbSession.getBackendSession(); + + if (!chatRoomId.isValid()) + *session << query, soci::into(count); + else { + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + *session << query, soci::use(dbChatRoomId), soci::into(count); + } + + return count; + }; +} + +void MainDb::markChatMessagesAsRead (const ChatRoomId &chatRoomId) const { + if (getUnreadChatMessageCount(chatRoomId) == 0) + return; + + static const string query = "UPDATE conference_chat_message_event" + " SET state = " + Utils::toString(int(ChatMessage::State::Displayed)) + + " WHERE event_id IN (" + " SELECT event_id FROM conference_event WHERE chat_room_id = :chatRoomId" + ") AND direction = " + Utils::toString(int(ChatMessage::Direction::Incoming)); + + DurationLogger durationLogger( + "Mark chat messages as read of: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + ")." + ); + + L_DB_TRANSACTION { + L_D(); + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + *d->dbSession.getBackendSession() << query, soci::use(dbChatRoomId); + + tr.commit(); + }; +} + +list> MainDb::getUnreadChatMessages (const ChatRoomId &chatRoomId) const { + // TODO: Optimize. + static const string query = Statements::get(Statements::SelectConferenceEvents) + + string(" AND direction = ") + Utils::toString(int(ChatMessage::Direction::Incoming)) + + " AND state <> " + Utils::toString(int(ChatMessage::State::Displayed)); + + DurationLogger durationLogger( + "Get unread chat messages: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + ")." + ); + + return L_DB_TRANSACTION { + L_D(); + + soci::session *session = d->dbSession.getBackendSession(); + + long long dbChatRoomId = d->selectChatRoomId(chatRoomId); + shared_ptr chatRoom = d->findChatRoom(chatRoomId); + list> chatMessages; + if (!chatRoom) + return chatMessages; + + soci::rowset rows = (session->prepare << query, soci::use(dbChatRoomId)); + for (const auto &row : rows) { + shared_ptr event = d->selectGenericConferenceEvent( + chatRoom, + row + ); + + if (event) + chatMessages.push_back(static_pointer_cast(event)->getChatMessage()); + } + + return chatMessages; + }; +} + +list MainDb::getChatMessageParticipantsByImdnState ( + const shared_ptr &eventLog, + ChatMessage::State state +) const { + return L_DB_TRANSACTION { + L_D(); + + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + int stateInt = static_cast(state); + + static const string query = "SELECT sip_address.value, chat_message_participant.state_change_time" + " FROM sip_address, chat_message_participant" + " WHERE event_id = :eventId AND state = :state" + " AND sip_address.id = chat_message_participant.participant_sip_address_id"; + soci::rowset rows = (d->dbSession.getBackendSession()->prepare << query, + soci::use(eventId), soci::use(stateInt) + ); + + list result; + for (const auto &row : rows) + result.emplace_back(IdentityAddress(row.get(0)), state, MainDbPrivate::getTmAsTimeT(row.get(1))); + return result; + }; +} + +list MainDb::getChatMessageParticipantStates (const shared_ptr &eventLog) const { + return L_DB_TRANSACTION { + L_D(); + + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + + unsigned int state; + soci::statement statement = ( + d->dbSession.getBackendSession()->prepare << "SELECT state FROM chat_message_participant WHERE event_id = :eventId", + soci::into(state), soci::use(eventId) + ); + statement.execute(); + + list states; + while (statement.fetch()) + states.push_back(ChatMessage::State(state)); + + return states; + }; +} + +ChatMessage::State MainDb::getChatMessageParticipantState ( + const shared_ptr &eventLog, + const IdentityAddress &participantAddress +) const { + return L_DB_TRANSACTION { + L_D(); + + const EventLogPrivate *dEventLog = eventLog->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dEventLog->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + const long long &participantSipAddressId = d->selectSipAddressId(participantAddress.asString()); + + unsigned int state; + *d->dbSession.getBackendSession() << "SELECT state FROM chat_message_participant" + " WHERE event_id = :eventId AND participant_sip_address_id = :participantSipAddressId", + soci::into(state), soci::use(eventId), soci::use(participantSipAddressId); + + return ChatMessage::State(state); + }; +} + +void MainDb::setChatMessageParticipantState ( + const shared_ptr &eventLog, + const IdentityAddress &participantAddress, + ChatMessage::State state, + time_t stateChangeTime +) { + L_DB_TRANSACTION { + L_D(); + d->setChatMessageParticipantState(eventLog, participantAddress, state, stateChangeTime); + tr.commit(); + }; +} + +shared_ptr MainDb::getLastChatMessage (const ChatRoomId &chatRoomId) const { + list> chatList = getHistory(chatRoomId, 1, Filter::ConferenceChatMessageFilter); + if (chatList.empty()) + return nullptr; + + return static_pointer_cast(chatList.front())->getChatMessage(); +} + +list> MainDb::findChatMessages ( + const ChatRoomId &chatRoomId, + const string &imdnMessageId +) const { + // TODO: Optimize. + static const string query = Statements::get(Statements::SelectConferenceEvents) + + string(" AND imdn_message_id = :imdnMessageId"); + + DurationLogger durationLogger( + "Find chat messages: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + ")." + ); + + return L_DB_TRANSACTION { + L_D(); + + shared_ptr chatRoom = d->findChatRoom(chatRoomId); + list> chatMessages; + if (!chatRoom) + return chatMessages; + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + soci::rowset rows = ( + d->dbSession.getBackendSession()->prepare << query, soci::use(dbChatRoomId), soci::use(imdnMessageId) + ); + for (const auto &row : rows) { + shared_ptr event = d->selectGenericConferenceEvent(chatRoom, row); + if (event) { + L_ASSERT(event->getType() == EventLog::Type::ConferenceChatMessage); + chatMessages.push_back(static_pointer_cast(event)->getChatMessage()); + } + } + + return chatMessages; + }; +} + +list> MainDb::findChatMessagesToBeNotifiedAsDelivered ( + const ChatRoomId &chatRoomId +) const { + static const string query = Statements::get(Statements::SelectConferenceEvents) + + string(" AND direction = :direction AND state = :state AND delivery_notification_required <> 0"); + + DurationLogger durationLogger( + "Find chat messages to be notified as delivered: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + ")." + ); + + return L_DB_TRANSACTION { + L_D(); + + shared_ptr chatRoom = d->findChatRoom(chatRoomId); + list> chatMessages; + if (!chatRoom) + return chatMessages; + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + const int &state = int(ChatMessage::State::Delivered); + const int &direction = int(ChatMessage::Direction::Incoming); + soci::rowset rows = ( + d->dbSession.getBackendSession()->prepare << query, soci::use(dbChatRoomId), soci::use(direction), soci::use(state) + ); + for (const auto &row : rows) { + shared_ptr event = d->selectGenericConferenceEvent(chatRoom, row); + if (event) { + L_ASSERT(event->getType() == EventLog::Type::ConferenceChatMessage); + chatMessages.push_back(static_pointer_cast(event)->getChatMessage()); + } + } + + return chatMessages; + }; +} + +list> MainDb::getHistory (const ChatRoomId &chatRoomId, int nLast, FilterMask mask) const { + return getHistoryRange(chatRoomId, 0, nLast, mask); +} + +list> MainDb::getHistoryRange ( + const ChatRoomId &chatRoomId, + int begin, + int end, + FilterMask mask +) const { + L_D(); + + if (begin < 0) + begin = 0; + + list> events; + if (end > 0 && begin > end) { + lWarning() << "Unable to get history. Invalid range."; + return events; + } + + string query = Statements::get(Statements::SelectConferenceEvents) + buildSqlEventFilter({ + ConferenceCallFilter, ConferenceChatMessageFilter, ConferenceInfoFilter, ConferenceInfoNoDeviceFilter + }, mask, "AND"); + query += " ORDER BY event_id DESC"; + + if (end > 0) + query += " LIMIT " + Utils::toString(end - begin); + else + query += " LIMIT " + d->dbSession.noLimitValue(); + + if (begin > 0) + query += " OFFSET " + Utils::toString(begin); + + DurationLogger durationLogger( + "Get history range of: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + + ", begin=" + Utils::toString(begin) + ", end=" + Utils::toString(end) + ")." + ); + + return L_DB_TRANSACTION { + L_D(); + + shared_ptr chatRoom = d->findChatRoom(chatRoomId); + if (!chatRoom) + return events; + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + soci::rowset rows = (d->dbSession.getBackendSession()->prepare << query, soci::use(dbChatRoomId)); + for (const auto &row : rows) { + shared_ptr event = d->selectGenericConferenceEvent(chatRoom, row); + if (event) + events.push_front(event); + } + + return events; + }; +} + +int MainDb::getHistorySize (const ChatRoomId &chatRoomId, FilterMask mask) const { + const string query = "SELECT COUNT(*) FROM event, conference_event" + " WHERE chat_room_id = :chatRoomId" + " AND event_id = event.id" + buildSqlEventFilter({ + ConferenceCallFilter, ConferenceChatMessageFilter, ConferenceInfoFilter, ConferenceInfoNoDeviceFilter + }, mask, "AND"); + + return L_DB_TRANSACTION { + L_D(); + + int count; + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + *d->dbSession.getBackendSession() << query, soci::into(count), soci::use(dbChatRoomId); + + return count; + }; +} + +template +static void fetchContentAppData (soci::session *session, Content &content, long long contentId, T &data) { + static const string query = "SELECT name, data FROM chat_message_content_app_data" + " WHERE chat_message_content_id = :contentId"; + + string name; + soci::statement statement = (session->prepare << query, soci::use(contentId), soci::into(name), soci::into(data)); + statement.execute(); + while (statement.fetch()) + content.setAppData(name, blobToString(data)); +} + +void MainDb::loadChatMessageContents (const shared_ptr &chatMessage) { + L_DB_TRANSACTION { + L_D(); + + soci::session *session = d->dbSession.getBackendSession(); + + bool hasFileTransferContent = false; + + ChatMessagePrivate *dChatMessage = chatMessage->getPrivate(); + MainDbKeyPrivate *dEventKey = static_cast(dChatMessage->dbKey).getPrivate(); + const long long &eventId = dEventKey->storageId; + + static const string query = "SELECT chat_message_content.id, content_type.id, content_type.value, body" + " FROM chat_message_content, content_type" + " WHERE event_id = :eventId AND content_type_id = content_type.id"; + soci::rowset rows = (session->prepare << query, soci::use(eventId)); + for (const auto &row : rows) { + ContentType contentType(row.get(2)); + const long long &contentId = d->dbSession.resolveId(row, 0); + Content *content; + + if (contentType == ContentType::FileTransfer) { + hasFileTransferContent = true; + content = new FileTransferContent(); + } else if (contentType.isFile()) { + // 1.1 - Fetch contents' file informations. + string name; + int size; + string path; + + *session << "SELECT name, size, path FROM chat_message_file_content" + " WHERE chat_message_content_id = :contentId", + soci::into(name), soci::into(size), soci::into(path), soci::use(contentId); + + FileContent *fileContent = new FileContent(); + fileContent->setFileName(name); + fileContent->setFileSize(size_t(size)); + fileContent->setFilePath(path); + + content = fileContent; + } else + content = new Content(); + + content->setContentType(contentType); + content->setBody(row.get(3)); + + // 1.2 - Fetch contents' app data. + // TODO: Do not test backend, encapsulate!!! + if (getBackend() == MainDb::Backend::Sqlite3) { + soci::blob data(*session); + fetchContentAppData(session, *content, contentId, data); + } else { + string data; + fetchContentAppData(session, *content, contentId, data); + } + chatMessage->addContent(content); + } + + // 2 - Load external body url from body into FileTransferContent if needed. + if (hasFileTransferContent) + dChatMessage->loadFileTransferUrlFromBodyToContent(); + }; +} + +void MainDb::cleanHistory (const ChatRoomId &chatRoomId, FilterMask mask) { + const string query = "SELECT event_id FROM conference_event WHERE chat_room_id = :chatRoomId" + + buildSqlEventFilter({ + ConferenceCallFilter, ConferenceChatMessageFilter, ConferenceInfoFilter, ConferenceInfoNoDeviceFilter + }, mask); + + DurationLogger durationLogger( + "Clean history of: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + + ", mask=" + Utils::toString(mask) + ")." + ); + + L_DB_TRANSACTION { + L_D(); + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + + d->invalidConferenceEventsFromQuery(query, dbChatRoomId); + *d->dbSession.getBackendSession() << "DELETE FROM event WHERE id IN (" + query + ")", soci::use(dbChatRoomId); + + tr.commit(); + }; +} + +// ----------------------------------------------------------------------------- + +list> MainDb::getChatRooms () const { + static const string query = "SELECT chat_room.id, peer_sip_address.value, local_sip_address.value," + " creation_time, last_update_time, capabilities, subject, last_notify_id, flags" + " FROM chat_room, sip_address AS peer_sip_address, sip_address AS local_sip_address" + " WHERE chat_room.peer_sip_address_id = peer_sip_address.id AND chat_room.local_sip_address_id = local_sip_address.id" + " ORDER BY last_update_time DESC"; + + DurationLogger durationLogger("Get chat rooms."); + + return L_DB_TRANSACTION { + L_D(); + + list> chatRooms; + shared_ptr core = getCore(); + + soci::session *session = d->dbSession.getBackendSession(); + + soci::rowset rows = (session->prepare << query); + for (const auto &row : rows) { + ChatRoomId chatRoomId = ChatRoomId( + IdentityAddress(row.get(1)), + IdentityAddress(row.get(2)) + ); + shared_ptr chatRoom = core->findChatRoom(chatRoomId); + if (chatRoom) { + chatRooms.push_back(chatRoom); + continue; + } + + tm creationTime = row.get(3); + tm lastUpdateTime = row.get(4); + int capabilities = row.get(5); + string subject = row.get(6, ""); + unsigned int lastNotifyId = getBackend() == Backend::Mysql + ? row.get(7, 0) + : static_cast(row.get(7, 0)); + + if (capabilities & ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Basic)) { + chatRoom = core->getPrivate()->createBasicChatRoom(chatRoomId, capabilities); + chatRoom->setSubject(subject); + } else if (capabilities & ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Conference)) { + list> participants; + + const long long &dbChatRoomId = d->dbSession.resolveId(row, 0); + static const string query = "SELECT chat_room_participant.id, sip_address.value, is_admin" + " FROM sip_address, chat_room, chat_room_participant" + " WHERE chat_room.id = :chatRoomId" + " AND sip_address.id = chat_room_participant.participant_sip_address_id" + " AND chat_room_participant.chat_room_id = chat_room.id"; + + // Fetch participants. + soci::rowset rows = (session->prepare << query, soci::use(dbChatRoomId)); + shared_ptr me; + for (const auto &row : rows) { + shared_ptr participant = make_shared(nullptr, IdentityAddress(row.get(1))); + ParticipantPrivate *dParticipant = participant->getPrivate(); + dParticipant->setAdmin(!!row.get(2)); + + // Fetch devices. + { + const long long &participantId = d->dbSession.resolveId(row, 0); + static const string query = "SELECT sip_address.value, state FROM chat_room_participant_device, sip_address" + " WHERE chat_room_participant_id = :participantId" + " AND participant_device_sip_address_id = sip_address.id"; + + soci::rowset rows = (session->prepare << query, soci::use(participantId)); + for (const auto &row : rows) { + shared_ptr device = dParticipant->addDevice(IdentityAddress(row.get(0))); + device->setState(ParticipantDevice::State(static_cast(row.get(1, 0)))); + } + } + + if (participant->getAddress() == chatRoomId.getLocalAddress().getAddressWithoutGruu()) + me = participant; + else + participants.push_back(participant); + } + + Conference *conference = nullptr; + if (!linphone_core_conference_server_enabled(core->getCCore())) { + bool hasBeenLeft = !!row.get(8, 0); + if (!me) { + lError() << "Unable to find me in: (peer=" + chatRoomId.getPeerAddress().asString() + + ", local=" + chatRoomId.getLocalAddress().asString() + ")."; + continue; + } + auto clientGroupChatRoom = make_shared( + core, + chatRoomId, + me, + capabilities, + subject, + move(participants), + lastNotifyId, + hasBeenLeft + ); + chatRoom = clientGroupChatRoom; + conference = clientGroupChatRoom.get(); + AbstractChatRoomPrivate *dChatRoom = chatRoom->getPrivate(); + dChatRoom->setState(ChatRoom::State::Instantiated); + dChatRoom->setState(hasBeenLeft + ? ChatRoom::State::Terminated + : ChatRoom::State::Created + ); + } else { + auto serverGroupChatRoom = make_shared( + core, + chatRoomId.getPeerAddress(), + capabilities, + subject, + move(participants), + lastNotifyId + ); + chatRoom = serverGroupChatRoom; + conference = serverGroupChatRoom.get(); + AbstractChatRoomPrivate *dChatRoom = chatRoom->getPrivate(); + dChatRoom->setState(ChatRoom::State::Instantiated); + dChatRoom->setState(ChatRoom::State::Created); + } + for (auto participant : chatRoom->getParticipants()) + participant->getPrivate()->setConference(conference); + } + + if (!chatRoom) + continue; // Not fetched. + + AbstractChatRoomPrivate *dChatRoom = chatRoom->getPrivate(); + dChatRoom->setCreationTime(MainDbPrivate::getTmAsTimeT(creationTime)); + dChatRoom->setLastUpdateTime(MainDbPrivate::getTmAsTimeT(lastUpdateTime)); + + lInfo() << "Found chat room in DB: (peer=" << + chatRoomId.getPeerAddress().asString() << ", local=" << chatRoomId.getLocalAddress().asString() << ")."; + + chatRooms.push_back(chatRoom); + } + + tr.commit(); + + return chatRooms; + }; +} + +void MainDb::insertChatRoom (const shared_ptr &chatRoom, unsigned int notifyId) { + L_DB_TRANSACTION { + L_D(); + + d->insertChatRoom(chatRoom, notifyId); + tr.commit(); + }; +} + +void MainDb::deleteChatRoom (const ChatRoomId &chatRoomId) { + L_DB_TRANSACTION { + L_D(); + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + + d->invalidConferenceEventsFromQuery( + "SELECT event_id FROM conference_event WHERE chat_room_id = :chatRoomId", + dbChatRoomId + ); + + *d->dbSession.getBackendSession() << "DELETE FROM chat_room WHERE id = :chatRoomId", soci::use(dbChatRoomId); + + tr.commit(); + }; +} + +void MainDb::migrateBasicToClientGroupChatRoom ( + const shared_ptr &basicChatRoom, + const shared_ptr &clientGroupChatRoom +) { + L_ASSERT(basicChatRoom->getCapabilities().isSet(ChatRoom::Capabilities::Basic)); + L_ASSERT(clientGroupChatRoom->getCapabilities().isSet(ChatRoom::Capabilities::Conference)); + + L_DB_TRANSACTION { + L_D(); + + // TODO: Update events and chat messages. (Or wait signals.) + const long long &dbChatRoomId = d->selectChatRoomId(basicChatRoom->getChatRoomId()); + + const ChatRoomId &newChatRoomId = clientGroupChatRoom->getChatRoomId(); + const long long &peerSipAddressId = d->insertSipAddress(newChatRoomId.getPeerAddress().asString()); + const long long &localSipAddressId = d->insertSipAddress(newChatRoomId.getLocalAddress().asString()); + const int &capabilities = clientGroupChatRoom->getCapabilities(); + + *d->dbSession.getBackendSession() << "UPDATE chat_room" + " SET capabilities = :capabilities," + " peer_sip_address_id = :peerSipAddressId," + " local_sip_address_id = :localSipAddressId" + " WHERE id = :chatRoomId", soci::use(capabilities), soci::use(peerSipAddressId), + soci::use(localSipAddressId), soci::use(dbChatRoomId); + + shared_ptr me = clientGroupChatRoom->getMe(); + long long meId = d->insertChatRoomParticipant( + dbChatRoomId, + d->insertSipAddress(me->getAddress().asString()), + true + ); + for (const auto &device : me->getPrivate()->getDevices()) + d->insertChatRoomParticipantDevice(meId, d->insertSipAddress(device->getAddress().asString())); + + for (const auto &participant : clientGroupChatRoom->getParticipants()) { + long long participantId = d->insertChatRoomParticipant( + dbChatRoomId, + d->insertSipAddress(participant->getAddress().asString()), + true + ); + for (const auto &device : participant->getPrivate()->getDevices()) + d->insertChatRoomParticipantDevice(participantId, d->insertSipAddress(device->getAddress().asString())); + } + + tr.commit(); + }; +} + +IdentityAddress MainDb::findMissingOneToOneConferenceChatRoomParticipantAddress ( + const shared_ptr &chatRoom, + const IdentityAddress &presentParticipantAddr +) { + L_ASSERT(linphone_core_conference_server_enabled(chatRoom->getCore()->getCCore())); + L_ASSERT(chatRoom->getCapabilities() & ChatRoom::Capabilities::OneToOne); + L_ASSERT(chatRoom->getParticipantCount() == 1); + + return L_DB_TRANSACTION { + L_D(); + + string missingParticipantAddress; + string participantASipAddress; + string participantBSipAddress; + + const long long &chatRoomId = d->selectChatRoomId(chatRoom->getChatRoomId()); + L_ASSERT(chatRoomId != -1); + + *d->dbSession.getBackendSession() << "SELECT participant_a_sip_address.value, participant_b_sip_address.value" + " FROM one_to_one_chat_room, sip_address AS participant_a_sip_address, sip_address AS participant_b_sip_address" + " WHERE chat_room_id = :chatRoomId" + " AND participant_a_sip_address_id = participant_a_sip_address.id" + " AND participant_b_sip_address_id = participant_b_sip_address.id", + soci::into(participantASipAddress), soci::into(participantBSipAddress), soci::use(chatRoomId); + + string presentParticipantAddress(presentParticipantAddr.asString()); + if (presentParticipantAddress == participantASipAddress) + missingParticipantAddress = participantBSipAddress; + else if (presentParticipantAddress == participantBSipAddress) + missingParticipantAddress = participantASipAddress; + + return IdentityAddress(missingParticipantAddress); + }; +} + +IdentityAddress MainDb::findOneToOneConferenceChatRoomAddress ( + const IdentityAddress &participantA, + const IdentityAddress &participantB +) const { + return L_DB_TRANSACTION { + L_D(); + + const long long &participantASipAddressId = d->selectSipAddressId(participantA.asString()); + const long long &participantBSipAddressId = d->selectSipAddressId(participantB.asString()); + if (participantASipAddressId == -1 || participantBSipAddressId == -1) + return IdentityAddress(); + + const long long &chatRoomId = d->selectOneToOneChatRoomId(participantASipAddressId, participantBSipAddressId); + + string chatRoomAddress; + *d->dbSession.getBackendSession() << "SELECT sip_address.value" + " FROM chat_room, sip_address" + " WHERE chat_room.id = :chatRoomId AND peer_sip_address_id = sip_address.id", + soci::use(chatRoomId), soci::into(chatRoomAddress); + + return IdentityAddress(chatRoomAddress); + }; +} + +void MainDb::insertOneToOneConferenceChatRoom (const shared_ptr &chatRoom) { + L_ASSERT(linphone_core_conference_server_enabled(chatRoom->getCore()->getCCore())); + L_ASSERT(chatRoom->getCapabilities() & ChatRoom::Capabilities::OneToOne); + + L_DB_TRANSACTION { + L_D(); + + const list> &participants = chatRoom->getParticipants(); + const long long &participantASipAddressId = d->selectSipAddressId(participants.front()->getAddress().asString()); + const long long &participantBSipAddressId = d->selectSipAddressId(participants.back()->getAddress().asString()); + L_ASSERT(participantASipAddressId != -1); + L_ASSERT(participantBSipAddressId != -1); + + long long chatRoomId = d->selectOneToOneChatRoomId(participantASipAddressId, participantBSipAddressId); + if (chatRoomId == -1) { + chatRoomId = d->selectChatRoomId(chatRoom->getChatRoomId()); + *d->dbSession.getBackendSession() << Statements::get(Statements::InsertOneToOneChatRoom, getBackend()), + soci::use(chatRoomId), soci::use(participantASipAddressId), soci::use(participantBSipAddressId); + } + + tr.commit(); + }; +} + +void MainDb::enableChatRoomMigration (const ChatRoomId &chatRoomId, bool enable) { + L_DB_TRANSACTION { + L_D(); + + soci::session *session = d->dbSession.getBackendSession(); + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoomId); + + int capabilities = 0; + *session << "SELECT capabilities FROM chat_room WHERE id = :chatRoomId", + soci::use(dbChatRoomId), soci::into(capabilities); + if (enable) + capabilities |= int(ChatRoom::Capabilities::Migratable); + else + capabilities &= ~int(ChatRoom::Capabilities::Migratable); + *session << "UPDATE chat_room SET capabilities = :capabilities WHERE id = :chatRoomId", + soci::use(capabilities), soci::use(dbChatRoomId); + + tr.commit(); + }; +} + +void MainDb::updateChatRoomParticipantDevice ( + const shared_ptr &chatRoom, + const shared_ptr &device +) { + L_DB_TRANSACTION { + L_D(); + + const long long &dbChatRoomId = d->selectChatRoomId(chatRoom->getChatRoomId()); + const long long &participantSipAddressId = d->selectSipAddressId(device->getParticipant()->getAddress().asString()); + const long long &participantId = d->selectChatRoomParticipantId(dbChatRoomId, participantSipAddressId); + const long long &participantSipDeviceAddressId = d->selectSipAddressId(device->getAddress().asString()); + unsigned int state = static_cast(device->getState()); + *d->dbSession.getBackendSession() << "UPDATE chat_room_participant_device SET state = :state" + " WHERE chat_room_participant_id = :participantId AND participant_device_sip_address_id = :participantSipDeviceAddressId", + soci::use(state), soci::use(participantId), soci::use(participantSipDeviceAddressId); + + tr.commit(); + }; +} + +// ----------------------------------------------------------------------------- + +bool MainDb::import (Backend, const string ¶meters) { + L_D(); + + // Backend is useless, it's sqlite3. (Only available legacy backend.) + const string uri = "sqlite3://" + parameters; + DbSession inDbSession(uri); + + if (!inDbSession) { + lWarning() << "Unable to connect to: `" << uri << "`."; + return false; + } + + // TODO: Remove condition after cpp migration in friends/friends list. + if (false) + d->importLegacyFriends(inDbSession); + + d->importLegacyHistory(inDbSession); + + return true; +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/main-db.h b/src/db/main-db.h new file mode 100644 index 000000000..b43f4a7ae --- /dev/null +++ b/src/db/main-db.h @@ -0,0 +1,204 @@ +/* + * main-db.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAIN_DB_H_ +#define _L_MAIN_DB_H_ + +#include +#include + +#include "linphone/utils/enum-mask.h" + +#include "abstract/abstract-db.h" +#include "chat/chat-message/chat-message.h" +#include "chat/chat-room/chat-room-id.h" +#include "core/core-accessor.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class AbstractChatRoom; +class ChatMessage; +class Core; +class EventLog; +class MainDbKey; +class MainDbPrivate; +class ParticipantDevice; + +class LINPHONE_INTERNAL_PUBLIC MainDb : public AbstractDb, public CoreAccessor { + template + friend class DbTransaction; + + friend class MainDbChatMessageKey; + friend class MainDbEventKey; + +public: + enum Filter { + NoFilter = 0x0, + ConferenceCallFilter = 0x1, + ConferenceChatMessageFilter = 0x2, + ConferenceInfoFilter = 0x4, + ConferenceInfoNoDeviceFilter = 0x8 + }; + + typedef EnumMask FilterMask; + + struct ParticipantState { + ParticipantState (const IdentityAddress &address, ChatMessage::State state, time_t timestamp) + : address(address), state(state), timestamp(timestamp) {} + + IdentityAddress address; + ChatMessage::State state = ChatMessage::State::Idle; + time_t timestamp = 0; + }; + + MainDb (const std::shared_ptr &core); + + // --------------------------------------------------------------------------- + // Generic. + // --------------------------------------------------------------------------- + + bool addEvent (const std::shared_ptr &eventLog); + bool updateEvent (const std::shared_ptr &eventLog); + static bool deleteEvent (const std::shared_ptr &eventLog); + int getEventCount (FilterMask mask = NoFilter) const; + + static std::shared_ptr getEventFromKey (const MainDbKey &dbKey); + + // --------------------------------------------------------------------------- + // Conference notified events. + // --------------------------------------------------------------------------- + + std::list> getConferenceNotifiedEvents ( + const ChatRoomId &chatRoomId, + unsigned int lastNotifyId + ) const; + + // --------------------------------------------------------------------------- + // Conference chat message events. + // --------------------------------------------------------------------------- + + using ParticipantStateRetrievalFunc = std::function(const std::shared_ptr &eventLog)>; + + int getChatMessageCount (const ChatRoomId &chatRoomId = ChatRoomId()) const; + int getUnreadChatMessageCount (const ChatRoomId &chatRoomId = ChatRoomId()) const; + void markChatMessagesAsRead (const ChatRoomId &chatRoomId) const; + std::list> getUnreadChatMessages (const ChatRoomId &chatRoomId) const; + + std::list getChatMessageParticipantsByImdnState ( + const std::shared_ptr &eventLog, + ChatMessage::State state + ) const; + std::list getChatMessageParticipantStates (const std::shared_ptr &eventLog) const; + ChatMessage::State getChatMessageParticipantState ( + const std::shared_ptr &eventLog, + const IdentityAddress &participantAddress + ) const; + void setChatMessageParticipantState ( + const std::shared_ptr &eventLog, + const IdentityAddress &participantAddress, + ChatMessage::State state, + time_t stateChangeTime + ); + + std::shared_ptr getLastChatMessage (const ChatRoomId &chatRoomId) const; + + std::list> findChatMessages ( + const ChatRoomId &chatRoomId, + const std::string &imdnMessageId + ) const; + + std::list> findChatMessagesToBeNotifiedAsDelivered ( + const ChatRoomId &chatRoomId + ) const; + + // --------------------------------------------------------------------------- + // Conference events. + // --------------------------------------------------------------------------- + + std::list> getHistory ( + const ChatRoomId &chatRoomId, + int nLast, + FilterMask mask = NoFilter + ) const; + std::list> getHistoryRange ( + const ChatRoomId &chatRoomId, + int begin, + int end, + FilterMask mask = NoFilter + ) const; + + int getHistorySize (const ChatRoomId &chatRoomId, FilterMask mask = NoFilter) const; + + void cleanHistory (const ChatRoomId &chatRoomId, FilterMask mask = NoFilter); + + // --------------------------------------------------------------------------- + // Chat messages. + // --------------------------------------------------------------------------- + + void loadChatMessageContents (const std::shared_ptr &chatMessage); + + // --------------------------------------------------------------------------- + // Chat rooms. + // --------------------------------------------------------------------------- + + std::list> getChatRooms () const; + void insertChatRoom (const std::shared_ptr &chatRoom, unsigned int notifyId = 0); + void deleteChatRoom (const ChatRoomId &chatRoomId); + void enableChatRoomMigration (const ChatRoomId &chatRoomId, bool enable); + + void migrateBasicToClientGroupChatRoom ( + const std::shared_ptr &basicChatRoom, + const std::shared_ptr &clientGroupChatRoom + ); + + IdentityAddress findMissingOneToOneConferenceChatRoomParticipantAddress ( + const std::shared_ptr &chatRoom, + const IdentityAddress &presentParticipantAddr + ); + IdentityAddress findOneToOneConferenceChatRoomAddress ( + const IdentityAddress &participantA, + const IdentityAddress &participantB + ) const; + void insertOneToOneConferenceChatRoom (const std::shared_ptr &chatRoom); + + void updateChatRoomParticipantDevice ( + const std::shared_ptr &chatRoom, + const std::shared_ptr &device + ); + + // --------------------------------------------------------------------------- + // Other. + // --------------------------------------------------------------------------- + + // Import legacy calls/messages from old db. + bool import (Backend backend, const std::string ¶meters) override; + +protected: + void init () override; + +private: + L_DECLARE_PRIVATE(MainDb); + L_DISABLE_COPY(MainDb); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_MAIN_DB_H_ diff --git a/src/db/provider/db-session-p.h b/src/db/provider/db-session-p.h deleted file mode 100644 index de9e9b5da..000000000 --- a/src/db/provider/db-session-p.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * db-session-p.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _DB_SESSION_P_H_ -#define _DB_SESSION_P_H_ - -#include - -#include "db-session.h" -#include "object/clonable-object-p.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -// ----------------------------------------------------------------------------- - -class DbSessionPrivate : public ClonableObjectPrivate { - friend class DbSessionProvider; - -private: - bool isValid = false; - - DbSession::Type type = DbSession::None; - std::shared_ptr backendSession; - - L_DECLARE_PUBLIC(DbSession); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _DB_SESSION_P_H_ diff --git a/src/db/provider/db-session-provider.cpp b/src/db/provider/db-session-provider.cpp deleted file mode 100644 index 35dc9c82c..000000000 --- a/src/db/provider/db-session-provider.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * db-session-provider.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#ifdef SOCI_ENABLED - #include -#endif // ifdef SOCI_ENABLED - -#include "db-session-p.h" -#include "object/object-p.h" - -#include "db-session-provider.h" - -#define CLEAN_COUNTER_MAX 1000 - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -class DbSessionProviderPrivate : public ObjectPrivate { -public: - typedef pair, DbSessionPrivate *> InternalSession; - unordered_map sessions; - int cleanCounter = 0; -}; - -DbSessionProvider::DbSessionProvider () : Singleton(*new DbSessionProviderPrivate) {} - -DbSession DbSessionProvider::getSession (const string &uri) { - L_D(DbSessionProvider); - - #ifdef SOCI_ENABLED - DbSession session(DbSession::Soci); - try { - shared_ptr backendSession = d->sessions[uri].first.lock(); - ++d->cleanCounter; - if (!backendSession) { // Create new session. - backendSession = make_shared(uri); - DbSessionPrivate *p = session.getPrivate(); - p->backendSession = backendSession; - p->isValid = true; - d->sessions[uri] = make_pair(backendSession, p); - } else // Share session. - session.setRef(*d->sessions[uri].second); - } catch (const exception &) {} - #else - DbSession session(DbSession::None); - #endif // ifdef SOCI_ENABLED - - // Remove invalid weak ptrs. - if (d->cleanCounter >= CLEAN_COUNTER_MAX) { - d->cleanCounter = 0; - - for (auto it = d->sessions.begin(), itEnd = d->sessions.end(); it != itEnd;) { - if (it->second.first.expired()) - it = d->sessions.erase(it); - else - ++it; - } - } - - return session; -} - -LINPHONE_END_NAMESPACE diff --git a/src/db/provider/db-session-provider.h b/src/db/provider/db-session-provider.h deleted file mode 100644 index 50542d5eb..000000000 --- a/src/db/provider/db-session-provider.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * db-session-provider.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _DB_SESSION_PROVIDER_H_ -#define _DB_SESSION_PROVIDER_H_ - -#include - -#include "db-session.h" -#include "object/singleton.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class DbSessionProviderPrivate; - -class DbSessionProvider : public Singleton { - friend class Singleton; - -public: - DbSession getSession (const std::string &uri); - -private: - DbSessionProvider (); - - L_DECLARE_PRIVATE(DbSessionProvider); - L_DISABLE_COPY(DbSessionProvider); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _DB_SESSION_PROVIDER_H_ diff --git a/src/db/provider/db-session.cpp b/src/db/provider/db-session.cpp deleted file mode 100644 index f074804b3..000000000 --- a/src/db/provider/db-session.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * db-session.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "db-session-p.h" - -#include "db-session.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -DbSession::DbSession (Type type) : ClonableObject(*new DbSessionPrivate) { - L_D(DbSession); - d->type = type; -} - -L_USE_DEFAULT_SHARE_IMPL(DbSession, ClonableObject); - -DbSession::operator bool () const { - L_D(const DbSession); - return d->isValid; -} - -DbSession::Type DbSession::getBackendType () const { - L_D(const DbSession); - return d->type; -} - -void *DbSession::getBackendSession () const { - L_D(const DbSession); - return d->backendSession.get(); -} - -LINPHONE_END_NAMESPACE diff --git a/src/db/provider/db-session.h b/src/db/provider/db-session.h deleted file mode 100644 index ac8a0582e..000000000 --- a/src/db/provider/db-session.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * db-session.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _DB_SESSION_H_ -#define _DB_SESSION_H_ - -#include - -#include "object/clonable-object.h" - -// ============================================================================= - -#ifdef SOCI_ENABLED - namespace soci { - class session; - } -#endif // ifdef SOCI_ENABLED - -LINPHONE_BEGIN_NAMESPACE - -class DbSessionPrivate; - -class DbSession : public ClonableObject { - friend class DbSessionProvider; - -public: - enum Type { - None, - Soci - }; - - DbSession (Type type = None); - DbSession (const DbSession &src); - - DbSession &operator= (const DbSession &src); - - operator bool () const; - - Type getBackendType () const; - - template - T *getBackendSession () const; - -private: - void *getBackendSession () const; - - L_DECLARE_PRIVATE(DbSession); -}; - -// ----------------------------------------------------------------------------- - -template -struct TypeOfDbSession { - static const DbSession::Type type = DbSession::None; -}; - -#ifdef SOCI_ENABLED - - template<> - struct TypeOfDbSession<::soci::session> { - static const DbSession::Type type = DbSession::Soci; - }; - -#endif // ifdef SOCI_ENABLED - -template -T *DbSession::getBackendSession () const { - typedef TypeOfDbSession Type; - static_assert(Type::type != DbSession::None, "Unable to get backend session, invalid type."); - if (getBackendType() != Type::type) - return nullptr; - return static_cast(getBackendSession()); -} - -LINPHONE_END_NAMESPACE - -#endif // ifndef _DB_SESSION_H_ diff --git a/src/db/session/db-session.cpp b/src/db/session/db-session.cpp new file mode 100644 index 000000000..d96031f7a --- /dev/null +++ b/src/db/session/db-session.cpp @@ -0,0 +1,256 @@ +/* + * db-session.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "db-session.h" +#include "logger/logger.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionPrivate { +public: + enum class Backend { + None, + Mysql, + Sqlite3 + } backend = Backend::None; + + std::unique_ptr backendSession; +}; + +DbSession::DbSession () : mPrivate(new DbSessionPrivate) {} + +DbSession::DbSession (const string &uri) : DbSession() { + try { + L_D(); + d->backendSession = makeUnique(uri); + d->backend = !uri.find("mysql") ? DbSessionPrivate::Backend::Mysql : DbSessionPrivate::Backend::Sqlite3; + } catch (const exception &e) { + lWarning() << "Unable to build db session with uri: " << e.what(); + } +} + +DbSession::DbSession (DbSession &&other) : mPrivate(other.mPrivate) { + other.mPrivate = nullptr; +} + +DbSession::~DbSession () { + delete mPrivate; +} + +DbSession &DbSession::operator= (DbSession &&other) { + std::swap(mPrivate, other.mPrivate); + return *this; +} + +DbSession::operator bool () const { + L_D(); + return d->backend != DbSessionPrivate::Backend::None; +} + +soci::session *DbSession::getBackendSession () const { + L_D(); + return d->backendSession.get(); +} + +string DbSession::primaryKeyStr (const string &type) const { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + return " " + type + " AUTO_INCREMENT PRIMARY KEY"; + case DbSessionPrivate::Backend::Sqlite3: + // See: ROWIDs and the INTEGER PRIMARY KEY + // https://www.sqlite.org/lang_createtable.html + return " INTEGER PRIMARY KEY ASC"; + case DbSessionPrivate::Backend::None: + return ""; + } + + L_ASSERT(false); + return ""; +} + +string DbSession::primaryKeyRefStr (const string &type) const { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + return " " + type; + case DbSessionPrivate::Backend::Sqlite3: + return " INTEGER"; + case DbSessionPrivate::Backend::None: + return ""; + } + + L_ASSERT(false); + return ""; +} + +string DbSession::varcharPrimaryKeyStr (int length) const { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + return " VARCHAR(" + Utils::toString(length) + ") PRIMARY KEY"; + case DbSessionPrivate::Backend::Sqlite3: + return " VARCHAR(" + Utils::toString(length) + ") PRIMARY KEY"; + case DbSessionPrivate::Backend::None: + return ""; + } + + L_ASSERT(false); + return ""; +} + +string DbSession::currentTimestamp () const { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + return " CURRENT_TIMESTAMP"; + case DbSessionPrivate::Backend::Sqlite3: + // Ugly hack but Sqlite3 does not allow table alteration where we add a date column using a default value + // of CURRENT_TIMESTAMP + { + const tm &now = Utils::getTimeTAsTm(std::time(nullptr)); + const size_t bufSize = 22; + char buffer[bufSize]; + snprintf(buffer, bufSize, "'%d-%02d-%02d %02d:%02d:%02d'", + now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec); + return buffer; + } + case DbSessionPrivate::Backend::None: + return ""; + } + + L_ASSERT(false); + return ""; +} + +string DbSession::timestampType () const { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + return " TIMESTAMP"; + case DbSessionPrivate::Backend::Sqlite3: + return " DATE"; + case DbSessionPrivate::Backend::None: + return ""; + } + + L_ASSERT(false); + return ""; +} + +string DbSession::noLimitValue () const { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + return "9999999999999999999"; + case DbSessionPrivate::Backend::Sqlite3: + return "-1"; + case DbSessionPrivate::Backend::None: + return ""; + } + + L_ASSERT(false); + return ""; +} + +long long DbSession::getLastInsertId () const { + long long id = 0; + + L_D(); + + string sql; + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + sql = "SELECT LAST_INSERT_ID()"; + break; + case DbSessionPrivate::Backend::Sqlite3: + sql = "SELECT last_insert_rowid()"; + break; + case DbSessionPrivate::Backend::None: + break; + } + + *d->backendSession << sql, soci::into(id); + + return id; +} + +void DbSession::enableForeignKeys (bool status) { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + *d->backendSession << string("SET FOREIGN_KEY_CHECKS = ") + (status ? "1" : "0"); + break; + case DbSessionPrivate::Backend::Sqlite3: + *d->backendSession << string("PRAGMA foreign_keys = ") + (status ? "ON" : "OFF"); + break; + case DbSessionPrivate::Backend::None: + break; + } +} + +bool DbSession::checkTableExists (const string &table) const { + L_D(); + + soci::session *session = d->backendSession.get(); + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + *session << "SHOW TABLES LIKE :table", soci::use(table); + return session->got_data(); + case DbSessionPrivate::Backend::Sqlite3: + *session << "SELECT name FROM sqlite_master WHERE type='table' AND name=:table", soci::use(table); + return session->got_data(); + case DbSessionPrivate::Backend::None: + return false; + } + + L_ASSERT(false); + return false; +} + +long long DbSession::resolveId (const soci::row &row, int col) const { + L_D(); + + switch (d->backend) { + case DbSessionPrivate::Backend::Mysql: + return static_cast(row.get(0)); + case DbSessionPrivate::Backend::Sqlite3: + return static_cast(row.get(0)); + case DbSessionPrivate::Backend::None: + return 0; + } + + L_ASSERT(false); + return 0; +} + +LINPHONE_END_NAMESPACE diff --git a/src/db/session/db-session.h b/src/db/session/db-session.h new file mode 100644 index 000000000..d05c47e18 --- /dev/null +++ b/src/db/session/db-session.h @@ -0,0 +1,71 @@ +/* + * db-session.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_DB_SESSION_H_ +#define _L_DB_SESSION_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class DbSessionPrivate; + +class DbSession { +public: + DbSession (); + explicit DbSession (const std::string &uri); + DbSession (DbSession &&other); + ~DbSession (); + + DbSession &operator= (DbSession &&other); + + operator bool () const; + + soci::session *getBackendSession () const; + + std::string primaryKeyStr (const std::string &type = "INT") const; + std::string primaryKeyRefStr (const std::string &type = "INT") const; + std::string varcharPrimaryKeyStr (int length) const; + + std::string currentTimestamp () const; + std::string timestampType () const; + + std::string noLimitValue () const; + + long long getLastInsertId () const; + + void enableForeignKeys (bool status); + + bool checkTableExists (const std::string &table) const; + + long long resolveId (const soci::row &row, int col) const; + +private: + DbSessionPrivate *mPrivate; + + L_DECLARE_PRIVATE(DbSession); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_DB_SESSION_H_ diff --git a/src/dial-plan/dial-plan-p.h b/src/dial-plan/dial-plan-p.h new file mode 100644 index 000000000..ccab4f885 --- /dev/null +++ b/src/dial-plan/dial-plan-p.h @@ -0,0 +1,45 @@ +/* + * dial-plan-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_DIAL_PLAN_P_H_ +#define _L_DIAL_PLAN_P_H_ + +#include "dial-plan.h" +#include "object/clonable-object-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class DialPlanPrivate : public ClonableObjectPrivate { +private: + std::string country; + std::string isoCountryCode; // ISO 3166-1 alpha-2 code, ex: FR for France. + std::string countryCallingCode; // Country calling code. + int nationalNumberLength = 0; // Maximum national number length. + std::string internationalCallPrefix; // International call prefix, ex: 00 in europe. + + static const std::list DialPlans; + + L_DECLARE_PUBLIC(DialPlan); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_DIAL_PLAN_P_H_ diff --git a/src/dial-plan/dial-plan.cpp b/src/dial-plan/dial-plan.cpp new file mode 100644 index 000000000..9d8b64be6 --- /dev/null +++ b/src/dial-plan/dial-plan.cpp @@ -0,0 +1,403 @@ +/* + * dial-plan.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/utils.h" + +#include "dial-plan-p.h" +#include "logger/logger.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +/* + * http://en.wikipedia.org/wiki/Telephone_numbering_plan + * http://en.wikipedia.org/wiki/Telephone_numbers_in_Europe + * imported from https://en.wikipedia.org/wiki/List_of_mobile_phone_number_series_by_country + */ +const list DialPlanPrivate::DialPlans = { + // Country, iso country code, e164 country calling code, number length, international usual prefix + { "Afghanistan", "AF", "93", 9, "00" }, + { "Albania", "AL", "355", 9, "00" }, + { "Algeria", "DZ", "213", 9, "00" }, + { "American Samoa", "AS", "1", 10, "011" }, + { "Andorra", "AD", "376", 6, "00" }, + { "Angola", "AO", "244", 9, "00" }, + { "Anguilla", "AI", "1", 10, "011" }, + { "Antigua and Barbuda", "AG", "1", 10, "011" }, + { "Argentina", "AR", "54", 10, "00" }, + { "Armenia", "AM", "374", 8, "00" }, + { "Aruba", "AW", "297", 7, "011" }, + { "Australia", "AU", "61", 9, "0011" }, + { "Austria", "AT", "43", 10, "00" }, + { "Azerbaijan", "AZ", "994", 9, "00" }, + { "Bahamas", "BS", "1", 10, "011" }, + { "Bahrain", "BH", "973", 8, "00" }, + { "Bangladesh", "BD", "880", 10, "00" }, + { "Barbados", "BB", "1", 10, "011" }, + { "Belarus", "BY", "375", 9, "00" }, + { "Belgium", "BE", "32", 9, "00" }, + { "Belize", "BZ", "501", 7, "00" }, + { "Benin", "BJ", "229", 8, "00" }, + { "Bermuda", "BM", "1", 10, "011" }, + { "Bhutan", "BT", "975", 8, "00" }, + { "Bolivia", "BO", "591", 8, "00" }, + { "Bosnia and Herzegovina", "BA", "387", 8, "00" }, + { "Botswana", "BW", "267", 8, "00" }, + { "Brazil", "BR", "55", 11, "00" }, + { "Brunei Darussalam", "BN", "673", 7, "00" }, + { "Bulgaria", "BG", "359", 9, "00" }, + { "Burkina Faso", "BF", "226", 8, "00" }, + { "Burundi", "BI", "257", 8, "011" }, + { "Cambodia", "KH", "855", 9, "00" }, + { "Cameroon", "CM", "237", 9, "00" }, + { "Canada", "CA", "1", 10, "011" }, + { "Cape Verde", "CV", "238", 7, "00" }, + { "Cayman Islands", "KY", "1", 10, "011" }, + { "Central African Republic", "CF", "236", 8, "00" }, + { "Chad", "TD", "235", 8, "00" }, + { "Chile", "CL", "56", 9, "00" }, + { "China", "CN", "86", 11, "00" }, + { "Colombia", "CO", "57", 10, "00" }, + { "Comoros", "KM", "269", 7, "00" }, + { "Congo", "CG", "242", 9, "00" }, + { "Congo Democratic Republic", "CD", "243", 9, "00" }, + { "Cook Islands", "CK", "682", 5, "00" }, + { "Costa Rica", "CR", "506", 8, "00" }, + { "Cote d'Ivoire", "AD", "225", 8, "00" }, + { "Croatia", "HR", "385", 9, "00" }, + { "Cuba", "CU", "53", 8, "119" }, + { "Cyprus", "CY", "357", 8, "00" }, + { "Czech Republic", "CZ", "420", 9, "00" }, + { "Denmark", "DK", "45", 8, "00" }, + { "Djibouti", "DJ", "253", 8, "00" }, + { "Dominica", "DM", "1", 10, "011" }, + { "Dominican Republic", "DO", "1", 10, "011" }, + { "Ecuador", "EC", "593", 9, "00" }, + { "Egypt", "EG", "20", 10, "00" }, + { "El Salvador", "SV", "503", 8, "00" }, + { "Equatorial Guinea", "GQ", "240", 9, "00" }, + { "Eritrea", "ER", "291", 7, "00" }, + { "Estonia", "EE", "372", 8, "00" }, + { "Ethiopia", "ET", "251", 9, "00" }, + { "Falkland Islands", "FK", "500", 5, "00" }, + { "Faroe Islands", "FO", "298", 6, "00" }, + { "Fiji", "FJ", "679", 7, "00" }, + { "Finland", "FI", "358", 9, "00" }, + { "France", "FR", "33", 9, "00" }, + { "French Guiana", "GF", "594", 9, "00" }, + { "French Polynesia", "PF", "689", 6, "00" }, + { "Gabon", "GA", "241", 8, "00" }, + { "Gambia", "GM", "220", 7, "00" }, + { "Georgia", "GE", "995", 9, "00" }, + { "Germany", "DE", "49", 11, "00" }, + { "Ghana", "GH", "233", 9, "00" }, + { "Gibraltar", "GI", "350", 8, "00" }, + { "Greece", "GR", "30", 10, "00" }, + { "Greenland", "GL", "299", 6, "00" }, + { "Grenada", "GD", "1", 10, "011" }, + { "Guadeloupe", "GP", "590", 9, "00" }, + { "Guam", "GU", "1", 10, "011" }, + { "Guatemala", "GT", "502", 8, "00" }, + { "Guinea", "GN", "224", 8, "00" }, + { "Guinea-Bissau", "GW", "245", 7, "00" }, + { "Guyana", "GY", "592", 7, "001" }, + { "Haiti", "HT", "509", 8, "00" }, + { "Honduras", "HN", "504", 8, "00" }, + { "Hong Kong", "HK", "852", 8, "001" }, + { "Hungary", "HU", "36", 9, "00" }, + { "Iceland", "IS", "354", 9, "00" }, + { "India", "IN", "91", 10, "00" }, + { "Indonesia", "ID", "62", 12, "001" }, + { "Iran", "IR", "98", 10, "00" }, + { "Iraq", "IQ", "964", 10, "00" }, + { "Ireland", "IE", "353", 9, "00" }, + { "Israel", "IL", "972", 9, "00" }, + { "Italy", "IT", "39", 10, "00" }, + /* {"Jersey" ,"JE" , "44" , 10 , "00" },*/ + { "Jamaica", "JM", "1", 10, "011" }, + { "Japan", "JP", "81", 10, "010" }, + { "Jordan", "JO", "962", 9, "00" }, + { "Kazakhstan", "KZ", "7", 10, "00" }, + { "Kenya", "KE", "254", 9, "000" }, + { "Kiribati", "KI", "686", 5, "00" }, + { "Korea, North", "KP", "850", 12, "99" }, + { "Korea, South", "KR", "82", 12, "001" }, + { "Kuwait", "KW", "965", 8, "00" }, + { "Kyrgyzstan", "KG", "996", 9, "00" }, + { "Laos", "LA", "856", 10, "00" }, + { "Latvia", "LV", "371", 8, "00" }, + { "Lebanon", "LB", "961", 7, "00" }, + { "Lesotho", "LS", "266", 8, "00" }, + { "Liberia", "LR", "231", 8, "00" }, + { "Libya", "LY", "218", 8, "00" }, + { "Liechtenstein", "LI", "423", 7, "00" }, + { "Lithuania", "LT", "370", 8, "00" }, + { "Luxembourg", "LU", "352", 9, "00" }, + { "Macau", "MO", "853", 8, "00" }, + { "Macedonia", "MK", "389", 8, "00" }, + { "Madagascar", "MG", "261", 9, "00" }, + { "Malawi", "MW", "265", 9, "00" }, + { "Malaysia", "MY", "60", 9, "00" }, + { "Maldives", "MV", "960", 7, "00" }, + { "Mali", "ML", "223", 8, "00" }, + { "Malta", "MT", "356", 8, "00" }, + { "Marshall Islands", "MH", "692", 7, "011" }, + { "Martinique", "MQ", "596", 9, "00" }, + { "Mauritania", "MR", "222", 8, "00" }, + { "Mauritius", "MU", "230", 7, "00" }, + { "Mayotte Island", "YT", "262", 9, "00" }, + { "Mexico", "MX", "52", 10, "00" }, + /*The following is a pseudo dial plan for Mexican mobile phones. See https://en.wikipedia.org/wiki/Telephone_numbers_in_Mexico*/ + { "Mexico", "MX", "521", 10, "00" }, + { "Micronesia", "FM", "691", 7, "011" }, + { "Moldova", "MD", "373", 8, "00" }, + { "Monaco", "MC", "377", 8, "00" }, + { "Mongolia", "MN", "976", 8, "001" }, + { "Montenegro", "ME", "382", 8, "00" }, + { "Montserrat", "MS", "664", 10, "011" }, + { "Morocco", "MA", "212", 9, "00" }, + { "Mozambique", "MZ", "258", 9, "00" }, + { "Myanmar", "MM", "95", 10, "00" }, + { "Namibia", "NA", "264", 9, "00" }, + { "Nauru", "NR", "674", 7, "00" }, + { "Nepal", "NP", "43", 10, "00" }, + { "Netherlands", "NL", "31", 9, "00" }, + { "New Caledonia", "NC", "687", 6, "00" }, + { "New Zealand", "NZ", "64", 8, "00" }, + { "Nicaragua", "NI", "505", 8, "00" }, + { "Niger", "NE", "227", 8, "00" }, + { "Nigeria", "NG", "234", 10, "009" }, + { "Niue", "NU", "683", 4, "00" }, + { "Norfolk Island", "NF", "672", 5, "00" }, + { "Northern Mariana Islands", "MP", "1", 10, "011" }, + { "Norway", "NO", "47", 8, "00" }, + { "Oman", "OM", "968", 8, "00" }, + { "Pakistan", "PK", "92", 10, "00" }, + { "Palau", "PW", "680", 7, "011" }, + { "Palestine", "PS", "970", 9, "00" }, + { "Panama", "PA", "507", 8, "00" }, + { "Papua New Guinea", "PG", "675", 8, "00" }, + { "Paraguay", "PY", "595", 9, "00" }, + { "Peru", "PE", "51", 9, "00" }, + { "Philippines", "PH", "63", 10, "00" }, + { "Poland", "PL", "48", 9, "00" }, + { "Portugal", "PT", "351", 9, "00" }, + { "Puerto Rico", "PR", "1", 10, "011" }, + { "Qatar", "QA", "974", 8, "00" }, + { "R�union Island", "RE", "262", 9, "011" }, + { "Romania", "RO", "40", 9, "00" }, + { "Russian Federation", "RU", "7", 10, "8" }, + { "Rwanda", "RW", "250", 9, "00" }, + { "Saint Helena", "SH", "290", 4, "00" }, + { "Saint Kitts and Nevis", "KN", "1", 10, "011" }, + { "Saint Lucia", "LC", "1", 10, "011" }, + { "Saint Pierre and Miquelon", "PM", "508", 6, "00" }, + { "Saint Vincent and the Grenadines", "VC", "1", 10, "011" }, + { "Samoa", "WS", "685", 7, "0" }, + { "San Marino", "SM", "378", 10, "00" }, + { "Sao Tome and Principe", "ST", "239", 7, "00" }, + { "Saudi Arabia", "SA", "966", 9, "00" }, + { "Senegal", "SN", "221", 9, "00" }, + { "Serbia", "RS", "381", 9, "00" }, + { "Seychelles", "SC", "248", 7, "00" }, + { "Sierra Leone", "SL", "232", 8, "00" }, + { "Singapore", "SG", "65", 8, "001" }, + { "Slovakia", "SK", "421", 9, "00" }, + { "Slovenia", "SI", "386", 8, "00" }, + { "Solomon Islands", "SB", "677", 7, "00" }, + { "Somalia", "SO", "252", 8, "00" }, + { "South Africa", "ZA", "27", 9, "00" }, + { "Spain", "ES", "34", 9, "00" }, + { "Sri Lanka", "LK", "94", 9, "00" }, + { "Sudan", "SD", "249", 9, "00" }, + { "Suriname", "SR", "597", 7, "00" }, + { "Swaziland", "SZ", "268", 8, "00" }, + { "Sweden", "SE", "46", 9, "00" }, + { "Switzerland", "XK", "41", 9, "00" }, + { "Syria", "SY", "963", 9, "00" }, + { "Taiwan", "TW", "886", 9, "810" }, + { "Tajikistan", "TJ", "992", 9, "002" }, + { "Tanzania", "TZ", "255", 9, "000" }, + { "Thailand", "TH", "66", 9, "001" }, + { "Togo", "TG", "228", 8, "00" }, + { "Tokelau", "TK", "690", 4, "00" }, + { "Tonga", "TO", "676", 5, "00" }, + { "Trinidad and Tobago", "TT", "1", 10, "011" }, + { "Tunisia", "TN", "216", 8, "00" }, + { "Turkey", "TR", "90", 10, "00" }, + { "Turkmenistan", "TM", "993", 8, "00" }, + { "Turks and Caicos Islands", "TC", "1", 7, "0" }, + { "Tuvalu", "TV", "688", 5, "00" }, + { "Uganda", "UG", "256", 9, "000" }, + { "Ukraine", "UA", "380", 9, "00" }, + { "United Arab Emirates", "AE", "971", 9, "00" }, + { "United Kingdom", "GB", "44", 10, "00" }, + /* {"United Kingdom" ,"UK" , "44" , 10 , "00" },*/ + { "United States", "US", "1", 10, "011" }, + { "Uruguay", "UY", "598", 8, "00" }, + { "Uzbekistan", "UZ", "998", 9, "8" }, + { "Vanuatu", "VU", "678", 7, "00" }, + { "Venezuela", "VE", "58", 10, "00" }, + { "Vietnam", "VN", "84", 9, "00" }, + { "Wallis and Futuna", "WF", "681", 5, "00" }, + { "Yemen", "YE", "967", 9, "00" }, + { "Zambia", "ZM", "260", 9, "00" }, + { "Zimbabwe", "ZW", "263", 9, "00" } +}; + +const DialPlan DialPlan::MostCommon("generic", "", "", 10, "00"); + +DialPlan::DialPlan ( + const string &country, + const string &isoCountryCode, + const string &ccc, + int nnl, + const string &icp +) : ClonableObject(*new DialPlanPrivate) { + L_D(); + d->country = country; + d->isoCountryCode = isoCountryCode; + d->countryCallingCode = ccc; + d->nationalNumberLength = nnl; + d->internationalCallPrefix = icp; +} + +DialPlan::DialPlan (const DialPlan &other) : ClonableObject(*new DialPlanPrivate) { + L_D(); + d->country = other.getCountry(); + d->isoCountryCode = other.getIsoCountryCode(); + d->countryCallingCode = other.getCountryCallingCode(); + d->nationalNumberLength = other.getNationalNumberLength(); + d->internationalCallPrefix = other.getInternationalCallPrefix(); +} + +DialPlan &DialPlan::operator= (const DialPlan &other) { + L_D(); + + if (this != &other) { + d->country = other.getCountry(); + d->isoCountryCode = other.getIsoCountryCode(); + d->countryCallingCode = other.getCountryCallingCode(); + d->nationalNumberLength = other.getNationalNumberLength(); + d->internationalCallPrefix = other.getInternationalCallPrefix(); + } + + return *this; +} + +const string &DialPlan::getCountry () const { + L_D(); + return d->country; +} + +const string &DialPlan::getIsoCountryCode () const { + L_D(); + return d->isoCountryCode; +} + +const string &DialPlan::getCountryCallingCode () const { + L_D(); + return d->countryCallingCode; +} + +void DialPlan::setCountryCallingCode(const std::string &ccc) { + L_D(); + d->countryCallingCode = ccc; +} + +int DialPlan::getNationalNumberLength () const { + L_D(); + return d->nationalNumberLength; +} + +const string &DialPlan::getInternationalCallPrefix () const { + L_D(); + return d->internationalCallPrefix; +} + +bool DialPlan::isGeneric () const { + L_D(); + return d->country == MostCommon.getCountry(); +} + +int DialPlan::lookupCccFromE164 (const string &e164) { + if (e164[0] != '+') + return -1; // Not an e164 number. + + // USA case. + if (e164[1] == '1') + return 1; + + DialPlan electedDialPlan; + unsigned int found; + unsigned int i = 0; + + do { + found = 0; + i++; + for (const auto &dp : DialPlanPrivate::DialPlans) { + if (strncmp(dp.getCountryCallingCode().c_str(), &e164[1], i) == 0) { + electedDialPlan = dp; + found++; + } + } + } while ((found > 1 || found == 0) && i < e164.length() - 1); + + if (found == 1) + return Utils::stoi(electedDialPlan.getCountryCallingCode()); + + return -1; +} + +int DialPlan::lookupCccFromIso (const string &iso) { + for (const auto &dp : DialPlanPrivate::DialPlans) { + if (dp.getIsoCountryCode() == iso) + return Utils::stoi(dp.getCountryCallingCode()); + } + + return -1; +} + +const DialPlan &DialPlan::findByCcc (int ccc) { + return DialPlan::findByCcc(Utils::toString(ccc)); +} + +const DialPlan &DialPlan::findByCcc (const string &ccc) { + if (ccc.empty()) + return MostCommon; + + for (const auto &dp : DialPlanPrivate::DialPlans) { + if (dp.getCountryCallingCode() == ccc) + return dp; + } + + // Return a generic "most common" dial plan. + return MostCommon; +} + +const list &DialPlan::getAllDialPlans () { + return DialPlanPrivate::DialPlans; +} + +LINPHONE_END_NAMESPACE diff --git a/src/dial-plan/dial-plan.h b/src/dial-plan/dial-plan.h new file mode 100644 index 000000000..d944f2e98 --- /dev/null +++ b/src/dial-plan/dial-plan.h @@ -0,0 +1,68 @@ +/* + * dial-plan.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_DIAL_PLAN_H_ +#define _L_DIAL_PLAN_H_ + +#include + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class DialPlanPrivate; + +class LINPHONE_PUBLIC DialPlan : public ClonableObject { +public: + DialPlan ( + const std::string &country = "", + const std::string &isoCountryCode = "", + const std::string &ccc = "", + int nnl = 0, + const std::string &icp = "" + ); + DialPlan (const DialPlan &other); + + DialPlan &operator= (const DialPlan &other); + + const std::string &getCountry () const; + const std::string &getIsoCountryCode () const; + const std::string &getCountryCallingCode () const; + void setCountryCallingCode(const std::string &ccc); + int getNationalNumberLength () const; + const std::string &getInternationalCallPrefix () const; + bool isGeneric () const; + + static const DialPlan MostCommon; + + static int lookupCccFromE164 (const std::string &e164); + static int lookupCccFromIso (const std::string &iso); + static const DialPlan &findByCcc (int ccc); + static const DialPlan &findByCcc (const std::string &ccc); + static const std::list &getAllDialPlans (); + +private: + L_DECLARE_PRIVATE(DialPlan); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_DIAL_PLAN_H_ diff --git a/src/enums.h b/src/enums.h new file mode 100644 index 000000000..dc8753d39 --- /dev/null +++ b/src/enums.h @@ -0,0 +1,38 @@ +/* + * enums.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ENUMS_H_ +#define _L_ENUMS_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +enum class Transport { + Udp, + Tcp, + Tls, + Dtls +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ENUMS_H_ diff --git a/src/event-log/call-event.cpp b/src/event-log/call-event.cpp deleted file mode 100644 index 1078606ec..000000000 --- a/src/event-log/call-event.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * call-event.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "event-log-p.h" - -#include "call-event.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -class CallEventPrivate : public EventLogPrivate { -public: - shared_ptr call; -}; - -// ----------------------------------------------------------------------------- - -CallEvent::CallEvent (Type type, const shared_ptr &call) : EventLog(*new CallEventPrivate, type) { - L_D(CallEvent); - L_ASSERT(call); - L_ASSERT(type == TypeCallStart || type == TypeCallEnd); - d->call = call; -} - -CallEvent::CallEvent (const CallEvent &src) : CallEvent(src.getType(), src.getCall()) {} - -CallEvent &CallEvent::operator= (const CallEvent &src) { - L_D(CallEvent); - if (this != &src) { - EventLog::operator=(src); - d->call = src.getPrivate()->call; - } - - return *this; -} - -shared_ptr CallEvent::getCall () const { - L_D(const CallEvent); - return d->call; -} - -LINPHONE_END_NAMESPACE diff --git a/src/event-log/call-event.h b/src/event-log/call-event.h deleted file mode 100644 index 423f71449..000000000 --- a/src/event-log/call-event.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * call-event.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CALL_EVENT_H_ -#define _CALL_EVENT_H_ - -#include - -#include "event-log.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class Call; -class CallEventPrivate; - -class LINPHONE_PUBLIC CallEvent : public EventLog { -public: - CallEvent (Type type, const std::shared_ptr &message); - CallEvent (const CallEvent &src); - - CallEvent &operator= (const CallEvent &src); - - std::shared_ptr getCall () const; - -private: - L_DECLARE_PRIVATE(CallEvent); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CALL_EVENT_H_ diff --git a/src/event-log/conference-event-p.h b/src/event-log/conference-event-p.h deleted file mode 100644 index 1a44b76b8..000000000 --- a/src/event-log/conference-event-p.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * conference-event-p.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CONFERENCE_EVENT_P_H_ -#define _CONFERENCE_EVENT_P_H_ - -#include "conference-event.h" - -#include "event-log-p.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class ConferenceEventPrivate : public EventLogPrivate { -private: - std::shared_ptr address; - - L_DECLARE_PUBLIC(ConferenceEvent); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CONFERENCE_EVENT_P_H_ diff --git a/src/event-log/conference-event.cpp b/src/event-log/conference-event.cpp deleted file mode 100644 index cfb4ca69c..000000000 --- a/src/event-log/conference-event.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * conference-event.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "conference-event-p.h" - -#include "conference-event.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -ConferenceEvent::ConferenceEvent (Type type, const shared_ptr &address) : - EventLog(*new ConferenceEventPrivate, type) { - L_D(ConferenceEvent); - L_ASSERT(type == TypeConferenceCreated || type == TypeConferenceDestroyed); - L_ASSERT(address); - // TODO: Duplicate address. - d->address = address; -} - -ConferenceEvent::ConferenceEvent (const ConferenceEvent &src) : ConferenceEvent(src.getType(), src.getAddress()) {} - -ConferenceEvent::ConferenceEvent (ConferenceEventPrivate &p, Type type, const shared_ptr &address) : - EventLog(p, type) { - L_D(ConferenceEvent); - L_ASSERT(address); - // TODO: Duplicate address. - d->address = address; -} - -ConferenceEvent &ConferenceEvent::operator= (const ConferenceEvent &src) { - L_D(ConferenceEvent); - if (this != &src) { - EventLog::operator=(src); - // TODO: Duplicate address. - d->address = src.getPrivate()->address; - } - - return *this; -} - -shared_ptr ConferenceEvent::getAddress () const { - // TODO. - return nullptr; -} - -LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference-event.h b/src/event-log/conference-event.h deleted file mode 100644 index 966af2b2d..000000000 --- a/src/event-log/conference-event.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * conference-event.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CONFERENCE_EVENT_H_ -#define _CONFERENCE_EVENT_H_ - -#include - -#include "event-log.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class Address; -class ConferenceEventPrivate; - -class LINPHONE_PUBLIC ConferenceEvent : public EventLog { -public: - ConferenceEvent (Type type, const std::shared_ptr &address); - ConferenceEvent (const ConferenceEvent &src); - virtual ~ConferenceEvent () = default; - - ConferenceEvent &operator= (const ConferenceEvent &src); - - std::shared_ptr getAddress () const; - -protected: - ConferenceEvent (ConferenceEventPrivate &p, Type type, const std::shared_ptr &address); - -private: - L_DECLARE_PRIVATE(ConferenceEvent); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CONFERENCE_EVENT_H_ diff --git a/src/event-log/conference-participant-event.cpp b/src/event-log/conference-participant-event.cpp deleted file mode 100644 index 0095da63a..000000000 --- a/src/event-log/conference-participant-event.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - * conference-participant-event.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "conference-event-p.h" - -#include "conference-participant-event.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -class ConferenceParticipantEventPrivate : public ConferenceEventPrivate { -public: - shared_ptr participantAddress; -}; - -// ----------------------------------------------------------------------------- - -ConferenceParticipantEvent::ConferenceParticipantEvent ( - Type type, - const shared_ptr &conferenceAddress, - const shared_ptr &participantAddress -) : ConferenceEvent(*new ConferenceParticipantEventPrivate, type, conferenceAddress) { - L_D(ConferenceParticipantEvent); - L_ASSERT( - type == TypeConferenceParticipantAdded || - type == TypeConferenceParticipantRemoved || - type == TypeConferenceParticipantSetAdmin || - type == TypeConferenceParticipantUnsetAdmin - ); - L_ASSERT(participantAddress); - // TODO: Duplicate address. - d->participantAddress = participantAddress; -} - -ConferenceParticipantEvent::ConferenceParticipantEvent (const ConferenceParticipantEvent &src) : - ConferenceParticipantEvent(src.getType(), src.getAddress(), src.getParticipantAddress()) {} - -ConferenceParticipantEvent &ConferenceParticipantEvent::operator= (const ConferenceParticipantEvent &src) { - L_D(ConferenceParticipantEvent); - if (this != &src) { - ConferenceEvent::operator=(src); - // TODO: Duplicate address. - d->participantAddress = src.getPrivate()->participantAddress; - } - - return *this; -} - -shared_ptr ConferenceParticipantEvent::getParticipantAddress () const { - // TODO. - return nullptr; -} - -LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference-participant-event.h b/src/event-log/conference-participant-event.h deleted file mode 100644 index fbb6514d7..000000000 --- a/src/event-log/conference-participant-event.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * conference-participant-event.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _CONFERENCE_PARTICIPANT_EVENT_H_ -#define _CONFERENCE_PARTICIPANT_EVENT_H_ - -#include "conference-event.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class ConferenceParticipantEventPrivate; - -class LINPHONE_PUBLIC ConferenceParticipantEvent : public ConferenceEvent { -public: - ConferenceParticipantEvent ( - Type type, - const std::shared_ptr &conferenceAddress, - const std::shared_ptr &participantAddress - ); - ConferenceParticipantEvent (const ConferenceParticipantEvent &src); - - ConferenceParticipantEvent &operator= (const ConferenceParticipantEvent &src); - - std::shared_ptr getParticipantAddress () const; - -private: - L_DECLARE_PRIVATE(ConferenceParticipantEvent); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _CONFERENCE_PARTICIPANT_EVENT_H_ diff --git a/src/event-log/conference/conference-call-event.cpp b/src/event-log/conference/conference-call-event.cpp new file mode 100644 index 000000000..9df1a92a9 --- /dev/null +++ b/src/event-log/conference/conference-call-event.cpp @@ -0,0 +1,51 @@ +/* + * conference-call-event.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference-call-event.h" +#include "event-log/event-log-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class ConferenceCallEventPrivate : public EventLogPrivate { +public: + shared_ptr call; +}; + +// ----------------------------------------------------------------------------- + +ConferenceCallEvent::ConferenceCallEvent (Type type, time_t creationTime, const shared_ptr &call) : + EventLog(*new ConferenceCallEventPrivate, type, creationTime) { + L_D(); + L_ASSERT(call); + L_ASSERT(type == Type::ConferenceCallStart || type == Type::ConferenceCallEnd); + d->call = call; +} + +shared_ptr ConferenceCallEvent::getCall () const { + L_D(); + return d->call; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference/conference-call-event.h b/src/event-log/conference/conference-call-event.h new file mode 100644 index 000000000..682d476ae --- /dev/null +++ b/src/event-log/conference/conference-call-event.h @@ -0,0 +1,45 @@ +/* + * conference-call-event.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_CALL_EVENT_H_ +#define _L_CONFERENCE_CALL_EVENT_H_ + +#include "event-log/event-log.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Call; +class ConferenceCallEventPrivate; + +class LINPHONE_PUBLIC ConferenceCallEvent : public EventLog { +public: + ConferenceCallEvent (Type type, time_t creationTime, const std::shared_ptr &call); + + std::shared_ptr getCall () const; + +private: + L_DECLARE_PRIVATE(ConferenceCallEvent); + L_DISABLE_COPY(ConferenceCallEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_CALL_EVENT_H_ diff --git a/src/event-log/conference/conference-chat-message-event.cpp b/src/event-log/conference/conference-chat-message-event.cpp new file mode 100644 index 000000000..5c1fbf6ea --- /dev/null +++ b/src/event-log/conference/conference-chat-message-event.cpp @@ -0,0 +1,59 @@ +/* + * conference-chat-message-event.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "chat/chat-message/chat-message.h" +#include "chat/chat-room/chat-room.h" +#include "conference-chat-message-event.h" +#include "conference-event-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class ConferenceChatMessageEventPrivate : public ConferenceEventPrivate { +public: + shared_ptr chatMessage; +}; + +// ----------------------------------------------------------------------------- + +ConferenceChatMessageEvent::ConferenceChatMessageEvent ( + time_t creationTime, + const shared_ptr &chatMessage +) : ConferenceEvent( + *new ConferenceChatMessageEventPrivate, + EventLog::Type::ConferenceChatMessage, + creationTime, + chatMessage->getChatRoom()->getChatRoomId() +) { + L_D(); + L_ASSERT(chatMessage); + d->chatMessage = chatMessage; +} + +shared_ptr ConferenceChatMessageEvent::getChatMessage () const { + L_D(); + return d->chatMessage; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference/conference-chat-message-event.h b/src/event-log/conference/conference-chat-message-event.h new file mode 100644 index 000000000..495989c13 --- /dev/null +++ b/src/event-log/conference/conference-chat-message-event.h @@ -0,0 +1,45 @@ +/* + * chat-message-event.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CHAT_MESSAGE_EVENT_H_ +#define _L_CHAT_MESSAGE_EVENT_H_ + +#include "conference-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ChatMessage; +class ConferenceChatMessageEventPrivate; + +class LINPHONE_PUBLIC ConferenceChatMessageEvent : public ConferenceEvent { +public: + ConferenceChatMessageEvent (time_t creationTime, const std::shared_ptr &chatMessage); + + std::shared_ptr getChatMessage () const; + +private: + L_DECLARE_PRIVATE(ConferenceChatMessageEvent); + L_DISABLE_COPY(ConferenceChatMessageEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CHAT_MESSAGE_EVENT_H_ diff --git a/src/event-log/conference/conference-event-p.h b/src/event-log/conference/conference-event-p.h new file mode 100644 index 000000000..603bdb47f --- /dev/null +++ b/src/event-log/conference/conference-event-p.h @@ -0,0 +1,40 @@ +/* + * conference-event-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_EVENT_P_H_ +#define _L_CONFERENCE_EVENT_P_H_ + +#include "chat/chat-room/chat-room-id.h" +#include "conference-event.h" +#include "event-log/event-log-p.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceEventPrivate : public EventLogPrivate { +private: + ChatRoomId chatRoomId; + + L_DECLARE_PUBLIC(ConferenceEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_EVENT_P_H_ diff --git a/src/event-log/conference/conference-event.cpp b/src/event-log/conference/conference-event.cpp new file mode 100644 index 000000000..b0faa33aa --- /dev/null +++ b/src/event-log/conference/conference-event.cpp @@ -0,0 +1,52 @@ +/* + * conference-event.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference-event-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +ConferenceEvent::ConferenceEvent (Type type, time_t creationTime, const ChatRoomId &chatRoomId) : + EventLog(*new ConferenceEventPrivate, type, creationTime) { + L_D(); + L_ASSERT(type == Type::ConferenceCreated || type == Type::ConferenceTerminated); + d->chatRoomId = chatRoomId; +} + +ConferenceEvent::ConferenceEvent ( + ConferenceEventPrivate &p, + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId +) : EventLog(p, type, creationTime) { + L_D(); + d->chatRoomId = chatRoomId; +} + +const ChatRoomId &ConferenceEvent::getChatRoomId () const { + L_D(); + return d->chatRoomId; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference/conference-event.h b/src/event-log/conference/conference-event.h new file mode 100644 index 000000000..23638b69e --- /dev/null +++ b/src/event-log/conference/conference-event.h @@ -0,0 +1,48 @@ +/* + * conference-event.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_EVENT_H_ +#define _L_CONFERENCE_EVENT_H_ + +#include "event-log/event-log.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceEventPrivate; +class ChatRoomId; + +class LINPHONE_PUBLIC ConferenceEvent : public EventLog { +public: + ConferenceEvent (Type type, time_t creationTime, const ChatRoomId &chatRoomId); + + const ChatRoomId &getChatRoomId () const; + +protected: + ConferenceEvent (ConferenceEventPrivate &p, Type type, time_t creationTime, const ChatRoomId &chatRoomId); + +private: + L_DECLARE_PRIVATE(ConferenceEvent); + L_DISABLE_COPY(ConferenceEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_EVENT_H_ diff --git a/src/event-log/conference/conference-notified-event-p.h b/src/event-log/conference/conference-notified-event-p.h new file mode 100644 index 000000000..371c575ad --- /dev/null +++ b/src/event-log/conference/conference-notified-event-p.h @@ -0,0 +1,39 @@ +/* + * conference-notified-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_NOTIFIED_EVENT_P_H_ +#define _L_CONFERENCE_NOTIFIED_EVENT_P_H_ + +#include "conference-event-p.h" +#include "conference-notified-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceNotifiedEventPrivate : public ConferenceEventPrivate { +private: + unsigned int notifyId = 0; + + L_DECLARE_PUBLIC(ConferenceNotifiedEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_NOTIFIED_EVENT_P_H_ diff --git a/src/event-log/conference/conference-notified-event.cpp b/src/event-log/conference/conference-notified-event.cpp new file mode 100644 index 000000000..00fd599c1 --- /dev/null +++ b/src/event-log/conference/conference-notified-event.cpp @@ -0,0 +1,56 @@ +/* + * conference-notified-event.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference-notified-event-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +ConferenceNotifiedEvent::ConferenceNotifiedEvent ( + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId +) : ConferenceEvent(*new ConferenceNotifiedEventPrivate, type, creationTime, chatRoomId) { + L_D(); + d->notifyId = notifyId; +} + +ConferenceNotifiedEvent::ConferenceNotifiedEvent ( + ConferenceNotifiedEventPrivate &p, + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId +) : ConferenceEvent(p, type, creationTime, chatRoomId) { + L_D(); + d->notifyId = notifyId; +} + +unsigned int ConferenceNotifiedEvent::getNotifyId () const { + L_D(); + return d->notifyId; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference/conference-notified-event.h b/src/event-log/conference/conference-notified-event.h new file mode 100644 index 000000000..00a519f2a --- /dev/null +++ b/src/event-log/conference/conference-notified-event.h @@ -0,0 +1,57 @@ +/* + * conference-notified-event.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_NOTIFIED_EVENT_H_ +#define _L_CONFERENCE_NOTIFIED_EVENT_H_ + +#include "conference-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceNotifiedEventPrivate; + +class LINPHONE_PUBLIC ConferenceNotifiedEvent : public ConferenceEvent { +public: + ConferenceNotifiedEvent ( + Type type, time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifiyId + ); + + unsigned int getNotifyId () const; + +protected: + ConferenceNotifiedEvent ( + ConferenceNotifiedEventPrivate &p, + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId + ); + +private: + L_DECLARE_PRIVATE(ConferenceNotifiedEvent); + L_DISABLE_COPY(ConferenceNotifiedEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_NOTIFIED_EVENT_H_ diff --git a/src/event-log/conference/conference-participant-device-event.cpp b/src/event-log/conference/conference-participant-device-event.cpp new file mode 100644 index 000000000..8e27853e4 --- /dev/null +++ b/src/event-log/conference/conference-participant-device-event.cpp @@ -0,0 +1,66 @@ +/* + * conference-participant-device-event.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference-participant-device-event.h" +#include "conference-participant-event-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class ConferenceParticipantDeviceEventPrivate : public ConferenceParticipantEventPrivate { +public: + IdentityAddress deviceAddress; +}; + +// ----------------------------------------------------------------------------- + +ConferenceParticipantDeviceEvent::ConferenceParticipantDeviceEvent ( + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId, + const IdentityAddress &participantAddress, + const IdentityAddress &deviceAddress +) : ConferenceParticipantEvent( + *new ConferenceParticipantDeviceEventPrivate, + type, + creationTime, + chatRoomId, + notifyId, + participantAddress +) { + L_D(); + L_ASSERT( + type == Type::ConferenceParticipantDeviceAdded || + type == Type::ConferenceParticipantDeviceRemoved + ); + d->deviceAddress = deviceAddress; +} + +const IdentityAddress &ConferenceParticipantDeviceEvent::getDeviceAddress () const { + L_D(); + return d->deviceAddress; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference/conference-participant-device-event.h b/src/event-log/conference/conference-participant-device-event.h new file mode 100644 index 000000000..fdb25fc66 --- /dev/null +++ b/src/event-log/conference/conference-participant-device-event.h @@ -0,0 +1,51 @@ +/* + * conference-participant-device-event.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_PARTICIPANT_DEVICE_EVENT_H_ +#define _L_CONFERENCE_PARTICIPANT_DEVICE_EVENT_H_ + +#include "conference-participant-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceParticipantDeviceEventPrivate; + +class LINPHONE_PUBLIC ConferenceParticipantDeviceEvent : public ConferenceParticipantEvent { +public: + ConferenceParticipantDeviceEvent ( + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId, + const IdentityAddress &participantAddress, + const IdentityAddress &deviceAddress + ); + + const IdentityAddress &getDeviceAddress () const; + +private: + L_DECLARE_PRIVATE(ConferenceParticipantDeviceEvent); + L_DISABLE_COPY(ConferenceParticipantDeviceEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_PARTICIPANT_DEVICE_EVENT_H_ diff --git a/src/event-log/conference/conference-participant-event-p.h b/src/event-log/conference/conference-participant-event-p.h new file mode 100644 index 000000000..103d27808 --- /dev/null +++ b/src/event-log/conference/conference-participant-event-p.h @@ -0,0 +1,39 @@ +/* + * conference-participant-event-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_PARTICIPANT_EVENT_P_H_ +#define _L_CONFERENCE_PARTICIPANT_EVENT_P_H_ + +#include "conference-notified-event-p.h" +#include "conference-participant-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceParticipantEventPrivate : public ConferenceNotifiedEventPrivate { +private: + IdentityAddress participantAddress; + + L_DECLARE_PUBLIC(ConferenceParticipantEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_PARTICIPANT_EVENT_P_H_ diff --git a/src/event-log/conference/conference-participant-event.cpp b/src/event-log/conference/conference-participant-event.cpp new file mode 100644 index 000000000..5203fd59a --- /dev/null +++ b/src/event-log/conference/conference-participant-event.cpp @@ -0,0 +1,76 @@ +/* + * conference-participant-event.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference-participant-event-p.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +ConferenceParticipantEvent::ConferenceParticipantEvent ( + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId, + const IdentityAddress &participantAddress +) : ConferenceNotifiedEvent( + *new ConferenceParticipantEventPrivate, + type, + creationTime, + chatRoomId, + notifyId +) { + L_D(); + L_ASSERT( + type == Type::ConferenceParticipantAdded || + type == Type::ConferenceParticipantRemoved || + type == Type::ConferenceParticipantSetAdmin || + type == Type::ConferenceParticipantUnsetAdmin + ); + d->participantAddress = participantAddress; +} + +ConferenceParticipantEvent::ConferenceParticipantEvent ( + ConferenceParticipantEventPrivate &p, + Type type, + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId, + const IdentityAddress &participantAddress +) : ConferenceNotifiedEvent( + p, + type, + creationTime, + chatRoomId, + notifyId +) { + L_D(); + d->participantAddress = participantAddress; +} + +const IdentityAddress &ConferenceParticipantEvent::getParticipantAddress () const { + L_D(); + return d->participantAddress; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference/conference-participant-event.h b/src/event-log/conference/conference-participant-event.h new file mode 100644 index 000000000..15b9d6d2c --- /dev/null +++ b/src/event-log/conference/conference-participant-event.h @@ -0,0 +1,61 @@ +/* + * conference-participant-event.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_PARTICIPANT_EVENT_H_ +#define _L_CONFERENCE_PARTICIPANT_EVENT_H_ + +#include "conference-notified-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceParticipantEventPrivate; +class IdentityAddress; + +class LINPHONE_PUBLIC ConferenceParticipantEvent : public ConferenceNotifiedEvent { +public: + ConferenceParticipantEvent ( + Type type, + time_t creationTime, + const ChatRoomId &ChatRoomId, + unsigned int notifyId, + const IdentityAddress &participantAddress + ); + + const IdentityAddress &getParticipantAddress () const; + +protected: + ConferenceParticipantEvent ( + ConferenceParticipantEventPrivate &p, + Type type, + time_t creationTime, + const ChatRoomId &ChatRoomId, + unsigned int notifyId, + const IdentityAddress &participantAddress + ); + +private: + L_DECLARE_PRIVATE(ConferenceParticipantEvent); + L_DISABLE_COPY(ConferenceParticipantEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_PARTICIPANT_EVENT_H_ diff --git a/src/event-log/conference/conference-subject-event.cpp b/src/event-log/conference/conference-subject-event.cpp new file mode 100644 index 000000000..04f36d18c --- /dev/null +++ b/src/event-log/conference/conference-subject-event.cpp @@ -0,0 +1,59 @@ +/* + * conference-subject-event.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "conference-notified-event-p.h" +#include "conference-subject-event.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class ConferenceSubjectEventPrivate : public ConferenceNotifiedEventPrivate { +public: + string subject; +}; + +// ----------------------------------------------------------------------------- + +ConferenceSubjectEvent::ConferenceSubjectEvent ( + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId, + const string &subject +) : ConferenceNotifiedEvent( + *new ConferenceSubjectEventPrivate, + Type::ConferenceSubjectChanged, + creationTime, + chatRoomId, + notifyId +) { + L_D(); + d->subject = subject; +} + +const string &ConferenceSubjectEvent::getSubject () const { + L_D(); + return d->subject; +} + +LINPHONE_END_NAMESPACE diff --git a/src/event-log/conference/conference-subject-event.h b/src/event-log/conference/conference-subject-event.h new file mode 100644 index 000000000..866a8d017 --- /dev/null +++ b/src/event-log/conference/conference-subject-event.h @@ -0,0 +1,51 @@ +/* + * conference-subject-event.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CONFERENCE_SUBJECT_EVENT_H_ +#define _L_CONFERENCE_SUBJECT_EVENT_H_ + +#include + +#include "conference-notified-event.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class ConferenceSubjectEventPrivate; + +class LINPHONE_PUBLIC ConferenceSubjectEvent : public ConferenceNotifiedEvent { +public: + ConferenceSubjectEvent ( + time_t creationTime, + const ChatRoomId &chatRoomId, + unsigned int notifyId, + const std::string &subject + ); + + const std::string &getSubject () const; + +private: + L_DECLARE_PRIVATE(ConferenceSubjectEvent); + L_DISABLE_COPY(ConferenceSubjectEvent); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_CONFERENCE_SUBJECT_EVENT_H_ diff --git a/src/event-log/event-log-enums.h b/src/event-log/event-log-enums.h deleted file mode 100644 index 878d1644b..000000000 --- a/src/event-log/event-log-enums.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * event-log-enums.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _EVENT_LOG_ENUMS_H_ -#define _EVENT_LOG_ENUMS_H_ - -#include "utils/enum-generator.h" - -// ============================================================================= - -#define L_ENUM_VALUES_EVENT_LOG_TYPE \ - L_DECLARE_ENUM_VALUES(EventLog, Type, \ - None, \ - Message, \ - CallStart, \ - CallEnd, \ - ConferenceCreated, \ - ConferenceDestroyed, \ - ConferenceParticipantAdded, \ - ConferenceParticipantRemoved, \ - ConferenceParticipantSetAdmin, \ - ConferenceParticipantUnsetAdmin \ - ) - -#endif // ifndef _EVENT_LOG_ENUMS_H_ diff --git a/src/event-log/event-log-p.h b/src/event-log/event-log-p.h index 6a71e025f..bea828588 100644 --- a/src/event-log/event-log-p.h +++ b/src/event-log/event-log-p.h @@ -1,11 +1,11 @@ /* * event-log-p.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,26 +13,33 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _EVENT_LOG_P_H_ -#define _EVENT_LOG_P_H_ +#ifndef _L_EVENT_LOG_P_H_ +#define _L_EVENT_LOG_P_H_ + +#include "db/main-db-event-key.h" +#include "object/base-object-p.h" #include "event-log.h" -#include "object/clonable-object-p.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE -class EventLogPrivate : public ClonableObjectPrivate { +class EventLogPrivate : public BaseObjectPrivate { +public: + mutable MainDbEventKey dbKey; + private: - EventLog::Type type = EventLog::TypeNone; + EventLog::Type type = EventLog::Type::None; + time_t creationTime = -1; L_DECLARE_PUBLIC(EventLog); }; LINPHONE_END_NAMESPACE -#endif // ifndef _EVENT_LOG_P_H_ +#endif // ifndef _L_EVENT_LOG_P_H_ diff --git a/src/event-log/event-log.cpp b/src/event-log/event-log.cpp index cacec4d0d..807401603 100644 --- a/src/event-log/event-log.cpp +++ b/src/event-log/event-log.cpp @@ -1,11 +1,11 @@ /* * event-log.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,38 +13,39 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "db/main-db.h" #include "event-log-p.h" -#include "event-log.h" - // ============================================================================= +using namespace std; + LINPHONE_BEGIN_NAMESPACE -// ----------------------------------------------------------------------------- +EventLog::EventLog () : BaseObject(*new EventLogPrivate) {} -EventLog::EventLog () : ClonableObject(*new EventLogPrivate) {} - -EventLog::EventLog (const EventLog &) : ClonableObject(*new EventLogPrivate) {} - -EventLog::EventLog (EventLogPrivate &p, Type type) : ClonableObject(*new EventLogPrivate) { - L_D(EventLog); +EventLog::EventLog (EventLogPrivate &p, Type type, time_t creationTime) : BaseObject(p) { + L_D(); d->type = type; -} - -EventLog &EventLog::operator= (const EventLog &src) { - L_D(EventLog); - if (this != &src) - d->type = src.getPrivate()->type; - return *this; + d->creationTime = creationTime; } EventLog::Type EventLog::getType () const { - L_D(const EventLog); + L_D(); return d->type; } +time_t EventLog::getCreationTime () const { + L_D(); + return d->creationTime; +} + +void EventLog::deleteFromDatabase (const shared_ptr &eventLog) { + MainDb::deleteEvent(eventLog); +} + LINPHONE_END_NAMESPACE diff --git a/src/event-log/event-log.h b/src/event-log/event-log.h index 831fca24f..48109ecd9 100644 --- a/src/event-log/event-log.h +++ b/src/event-log/event-log.h @@ -1,11 +1,11 @@ /* * event-log.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,14 +13,19 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _EVENT_LOG_H_ -#define _EVENT_LOG_H_ +#ifndef _L_EVENT_LOG_H_ +#define _L_EVENT_LOG_H_ -#include "object/clonable-object.h" -#include "event-log-enums.h" +#include + +#include "linphone/enums/event-log-enums.h" +#include "linphone/utils/enum-generator.h" + +#include "object/base-object.h" // ============================================================================= @@ -28,27 +33,28 @@ LINPHONE_BEGIN_NAMESPACE class EventLogPrivate; -class LINPHONE_PUBLIC EventLog : public ClonableObject { +class LINPHONE_PUBLIC EventLog : public BaseObject { + friend class MainDb; + friend class MainDbPrivate; + public: - enum Type { - L_ENUM_VALUES_EVENT_LOG_TYPE - }; + L_DECLARE_ENUM(Type, L_ENUM_VALUES_EVENT_LOG_TYPE); EventLog (); - EventLog (const EventLog &src); - virtual ~EventLog () = default; - - EventLog &operator= (const EventLog &src); Type getType () const; + time_t getCreationTime () const; + + static void deleteFromDatabase (const std::shared_ptr &eventLog); protected: - EventLog (EventLogPrivate &p, Type type); + EventLog (EventLogPrivate &p, Type type, time_t creationTime); private: L_DECLARE_PRIVATE(EventLog); + L_DISABLE_COPY(EventLog); }; LINPHONE_END_NAMESPACE -#endif // ifndef _EVENT_LOG_H_ +#endif // ifndef _L_EVENT_LOG_H_ diff --git a/src/event-log/events.h b/src/event-log/events.h new file mode 100644 index 000000000..831ef9415 --- /dev/null +++ b/src/event-log/events.h @@ -0,0 +1,28 @@ +/* + * events.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_EVENTS_H_ +#define _L_EVENTS_H_ + +#include "conference/conference-call-event.h" +#include "conference/conference-chat-message-event.h" +#include "conference/conference-participant-device-event.h" +#include "conference/conference-subject-event.h" + +#endif // ifndef _L_EVENTS_H_ diff --git a/src/event-log/message-event.cpp b/src/event-log/message-event.cpp deleted file mode 100644 index cda82eb68..000000000 --- a/src/event-log/message-event.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * message-event.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "event-log-p.h" - -#include "message-event.h" - -// ============================================================================= - -using namespace std; - -LINPHONE_BEGIN_NAMESPACE - -class MessageEventPrivate : public EventLogPrivate { -public: - shared_ptr message; -}; - -// ----------------------------------------------------------------------------- - -MessageEvent::MessageEvent (const shared_ptr &message) : - EventLog(*new MessageEventPrivate, EventLog::TypeMessage) { - L_D(MessageEvent); - L_ASSERT(message); - d->message = message; -} - -MessageEvent::MessageEvent (const MessageEvent &src) : MessageEvent(src.getMessage()) {} - -MessageEvent &MessageEvent::operator= (const MessageEvent &src) { - L_D(MessageEvent); - if (this != &src) { - EventLog::operator=(src); - d->message = src.getPrivate()->message; - } - - return *this; -} - -shared_ptr MessageEvent::getMessage () const { - L_D(const MessageEvent); - return d->message; -} - -LINPHONE_END_NAMESPACE diff --git a/src/event-log/message-event.h b/src/event-log/message-event.h deleted file mode 100644 index b1c12a5fb..000000000 --- a/src/event-log/message-event.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * message-event.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _MESSAGE_EVENT_H_ -#define _MESSAGE_EVENT_H_ - -#include - -#include "event-log.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class Message; -class MessageEventPrivate; - -class LINPHONE_PUBLIC MessageEvent : public EventLog { -public: - MessageEvent (const std::shared_ptr &message); - MessageEvent (const MessageEvent &src); - - MessageEvent &operator= (const MessageEvent &src); - - std::shared_ptr getMessage () const; - -private: - L_DECLARE_PRIVATE(MessageEvent); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _MESSAGE_EVENT_H_ diff --git a/src/hacks/hacks.cpp b/src/hacks/hacks.cpp new file mode 100644 index 000000000..3e7e48caf --- /dev/null +++ b/src/hacks/hacks.cpp @@ -0,0 +1,30 @@ +/* + * hacks.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "hacks.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// Place your hacks here. + +LINPHONE_END_NAMESPACE diff --git a/src/hacks/hacks.h b/src/hacks/hacks.h new file mode 100644 index 000000000..2508b297c --- /dev/null +++ b/src/hacks/hacks.h @@ -0,0 +1,43 @@ +/* + * hacks.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_HACKS_H_ +#define _L_HACKS_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +/* + * This class has the purpose to centralize the TEMPORARY (!!!) hacks so that they + * can be located more easily. Useful for dev cpp refactoring. + */ +class Hacks { +public: + Hacks () = delete; + +private: + L_DISABLE_COPY(Hacks); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_HACKS_H_ diff --git a/src/logger/logger.cpp b/src/logger/logger.cpp index 7ca01589d..e1dcc63c1 100644 --- a/src/logger/logger.cpp +++ b/src/logger/logger.cpp @@ -1,11 +1,11 @@ /* * logger.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,12 +13,15 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "linphone/core.h" +#include -#include "object/object-p.h" +#include + +#include "object/base-object-p.h" #include "logger.h" @@ -28,7 +31,9 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE -class LoggerPrivate : public ObjectPrivate { +// ----------------------------------------------------------------------------- + +class LoggerPrivate : public BaseObjectPrivate { public: Logger::Level level; ostringstream os; @@ -36,41 +41,68 @@ public: // ----------------------------------------------------------------------------- -Logger::Logger (Level level) : Object(*new LoggerPrivate) { - L_D(Logger); +Logger::Logger (Level level) : BaseObject(*new LoggerPrivate) { + L_D(); d->level = level; } Logger::~Logger () { - L_D(Logger); + L_D(); - d->os << endl; const string str = d->os.str(); switch (d->level) { case Debug: #if DEBUG_LOGS - ms_debug("%s", str.c_str()); + bctbx_debug("%s", str.c_str()); #endif // if DEBUG_LOGS break; case Info: - ms_message("%s", str.c_str()); + bctbx_message("%s", str.c_str()); break; case Warning: - ms_warning("%s", str.c_str()); + bctbx_warning("%s", str.c_str()); break; case Error: - ms_error("%s", str.c_str()); + bctbx_error("%s", str.c_str()); break; case Fatal: - ms_fatal("%s", str.c_str()); + bctbx_fatal("%s", str.c_str()); break; } } ostringstream &Logger::getOutput () { - L_D(Logger); + L_D(); return d->os; } +// ----------------------------------------------------------------------------- + +class DurationLoggerPrivate : public BaseObjectPrivate { +public: + unique_ptr logger; + + chrono::high_resolution_clock::time_point start; +}; + +// ----------------------------------------------------------------------------- + +DurationLogger::DurationLogger (const string &label, Logger::Level level) : BaseObject(*new DurationLoggerPrivate) { + L_D(); + + d->logger.reset(new Logger(level)); + d->logger->getOutput() << "Duration of [" + label + "]: "; + d->start = chrono::high_resolution_clock::now(); + + Logger(level).getOutput() << "Start measurement of [" + label + "]."; +} + +DurationLogger::~DurationLogger () { + L_D(); + + chrono::high_resolution_clock::time_point end = chrono::high_resolution_clock::now(); + d->logger->getOutput() << chrono::duration_cast(end - d->start).count() << "ms."; +} + LINPHONE_END_NAMESPACE diff --git a/src/logger/logger.h b/src/logger/logger.h index 2314a9ea9..d3729b582 100644 --- a/src/logger/logger.h +++ b/src/logger/logger.h @@ -1,11 +1,11 @@ /* * logger.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,15 +13,16 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _LOGGER_H_ -#define _LOGGER_H_ +#ifndef _L_LOGGER_H_ +#define _L_LOGGER_H_ #include -#include "object/object.h" +#include "object/base-object.h" // ============================================================================= @@ -29,7 +30,7 @@ LINPHONE_BEGIN_NAMESPACE class LoggerPrivate; -class LINPHONE_PUBLIC Logger : public Object { +class LINPHONE_PUBLIC Logger : public BaseObject { public: enum Level { Debug, @@ -39,7 +40,7 @@ public: Fatal }; - Logger (Level level); + explicit Logger (Level level); ~Logger (); std::ostringstream &getOutput (); @@ -49,18 +50,31 @@ private: L_DISABLE_COPY(Logger); }; +class DurationLoggerPrivate; + +class DurationLogger : public BaseObject { +public: + DurationLogger (const std::string &label, Logger::Level level = Logger::Info); + ~DurationLogger (); + +private: + L_DECLARE_PRIVATE(DurationLogger); + L_DISABLE_COPY(DurationLogger); +}; + LINPHONE_END_NAMESPACE -#define lDebug() LINPHONE_NAMESPACE::Logger(Logger::Debug).getOutput() -#define lInfo() LINPHONE_NAMESPACE::Logger(Logger::Info).getOutput() -#define lWarning() LINPHONE_NAMESPACE::Logger(Logger::Warning).getOutput() -#define lError() LINPHONE_NAMESPACE::Logger(Logger::Error).getOutput() -#define lFatal() LINPHONE_NAMESPACE::Logger(Logger::Fatal).getOutput() +#define lDebug() LinphonePrivate::Logger(LinphonePrivate::Logger::Debug).getOutput() +#define lInfo() LinphonePrivate::Logger(LinphonePrivate::Logger::Info).getOutput() +#define lWarning() LinphonePrivate::Logger(LinphonePrivate::Logger::Warning).getOutput() +#define lError() LinphonePrivate::Logger(LinphonePrivate::Logger::Error).getOutput() +#define lFatal() LinphonePrivate::Logger(LinphonePrivate::Logger::Fatal).getOutput() #define L_BEGIN_LOG_EXCEPTION try { - #define L_END_LOG_EXCEPTION \ -} catch (const exception &e) { \ - lWarning() << "Error: " << e.what(); \ -} -#endif // ifndef _LOGGER_H_ +#define L_END_LOG_EXCEPTION \ + } catch (const exception &e) { \ + lWarning() << "Error: " << e.what(); \ + } + +#endif // ifndef _L_LOGGER_H_ diff --git a/src/message/message.cpp b/src/message/message.cpp deleted file mode 100644 index a4e907426..000000000 --- a/src/message/message.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - * message.cpp - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include - -#include "db/events-db.h" -#include "object/object-p.h" - -#include "message.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -using namespace std; - -class MessagePrivate : public ObjectPrivate { -private: - weak_ptr chatRoom; - Message::Direction direction = Message::Incoming; - // LinphoneAddress *from; - // LinphoneAddress *to; - shared_ptr errorInfo; - string contentType; - string text; - bool isSecured = false; - time_t time = 0; - string id; - string appData; - list > contents; - unordered_map customHeaders; - Message::State state = Message::Idle; - shared_ptr eventsDb; - - L_DECLARE_PUBLIC(Message); -}; - -// ----------------------------------------------------------------------------- - -Message::Message (MessagePrivate &p) : Object(p) {} - -shared_ptr Message::getChatRoom () const { - L_D(const Message); - shared_ptr chatRoom = d->chatRoom.lock(); - if (!chatRoom) { - // TODO. - } - return chatRoom; -} - -Message::Direction Message::getDirection () const { - L_D(const Message); - return d->direction; -} - -shared_ptr Message::getFromAddress () const { - // TODO. - return nullptr; -} - -shared_ptr Message::getToAddress () const { - // TODO. - return nullptr; -} - -shared_ptr Message::getLocalAddress () const { - // TODO. - return nullptr; -} - -shared_ptr Message::getRemoteAddress () const { - // TODO. - return nullptr; -} - -Message::State Message::getState () const { - L_D(const Message); - return d->state; -} - -shared_ptr Message::getErrorInfo () const { - L_D(const Message); - return d->errorInfo; -} - -string Message::getContentType () const { - L_D(const Message); - return d->contentType; -} - -string Message::getText () const { - L_D(const Message); - return d->text; -} - -void Message::setText (const string &text) { - L_D(Message); - d->text = text; -} - -void Message::send () const { - // TODO. -} - -bool Message::containsReadableText () const { - // TODO: Check content type. - return true; -} - -bool Message::isSecured () const { - L_D(const Message); - return d->isSecured; -} - -time_t Message::getTime () const { - L_D(const Message); - return d->time; -} - -string Message::getId () const { - L_D(const Message); - return d->id; -} - -string Message::getAppdata () const { - L_D(const Message); - return d->appData; -} - -void Message::setAppdata (const string &appData) { - L_D(Message); - d->appData = appData; -} - -list > Message::getContents () const { - L_D(const Message); - list > contents; - for (const auto &content : d->contents) - contents.push_back(content); - return contents; -} - -void Message::addContent (const shared_ptr &content) { - L_D(Message); - d->contents.push_back(content); -} - -void Message::removeContent (const shared_ptr &content) { - L_D(Message); - d->contents.remove(const_pointer_cast(content)); -} - -string Message::getCustomHeaderValue (const string &headerName) const { - L_D(const Message); - try { - return d->customHeaders.at(headerName); - } catch (const exception &) { - // Key doesn't exist. - } - return ""; -} - -void Message::addCustomHeader (const string &headerName, const string &headerValue) { - L_D(Message); - d->customHeaders[headerName] = headerValue; -} - -void Message::removeCustomHeader (const string &headerName) { - L_D(Message); - d->customHeaders.erase(headerName); -} - -LINPHONE_END_NAMESPACE diff --git a/src/message/message.h b/src/message/message.h deleted file mode 100644 index 3bb643315..000000000 --- a/src/message/message.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * message.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _MESSAGE_H_ -#define _MESSAGE_H_ - -#include -#include -#include - -#include "object/object.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -class Address; -class ChatRoom; -class Content; -class ErrorInfo; -class MessagePrivate; - -class LINPHONE_PUBLIC Message : public Object { - friend class ChatRoom; - -public: - enum Direction { - Incoming, - Outgoing - }; - - enum State { - Idle, - InProgress, - Delivered, - NotDelivered, - FileTransferError, - FileTransferDone, - DeliveredToUser, - Displayed - }; - - std::shared_ptr getChatRoom () const; - - Direction getDirection () const; - - std::shared_ptr getFromAddress () const; - std::shared_ptr getToAddress () const; - std::shared_ptr getLocalAddress () const; - std::shared_ptr getRemoteAddress () const; - - State getState () const; - - std::shared_ptr getErrorInfo () const; - - std::string getContentType () const; - - std::string getText () const; - void setText (const std::string &text); - - void send () const; - - bool containsReadableText () const; - - bool isSecured () const; - - time_t getTime () const; - - std::string getId () const; - - std::string getAppdata () const; - void setAppdata (const std::string &appData); - - std::list > getContents () const; - void addContent (const std::shared_ptr &content); - void removeContent (const std::shared_ptr &content); - - std::string getCustomHeaderValue (const std::string &headerName) const; - void addCustomHeader (const std::string &headerName, const std::string &headerValue); - void removeCustomHeader (const std::string &headerName); - -private: - Message (MessagePrivate &p); - - L_DECLARE_PRIVATE(Message); - L_DISABLE_COPY(Message); -}; - -LINPHONE_END_NAMESPACE - -#endif // ifndef _MESSAGE_H_ diff --git a/src/nat/ice-agent.cpp b/src/nat/ice-agent.cpp new file mode 100644 index 000000000..b296f066a --- /dev/null +++ b/src/nat/ice-agent.cpp @@ -0,0 +1,767 @@ +/* + * ice-agent.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/core.h" + +#include "private.h" + +#include "conference/session/media-session-p.h" +#include "core/core.h" +#include "logger/logger.h" + +#include "ice-agent.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +bool IceAgent::candidatesGathered () const { + if (!iceSession) + return false; + return !!ice_session_candidates_gathered(iceSession); +} + +void IceAgent::checkSession (IceRole role, bool isReinvite) { + // Already created. + if (iceSession) + return; + + LinphoneConfig *config = linphone_core_get_config(mediaSession.getCore()->getCCore()); + + if (lp_config_get_int(config, "net", "force_ice_disablement", 0)){ + lWarning()<<"ICE is disabled in this version"; + return; + } + + if (isReinvite && (lp_config_get_int(config, "net", "allow_late_ice", 0) == 0)) + return; + + iceSession = ice_session_new(); + + // For backward compatibility purposes, shall be enabled by default in the future. + ice_session_enable_message_integrity_check( + iceSession, + !!lp_config_get_int(config, "net", "ice_session_enable_message_integrity_check", 1) + ); + if (lp_config_get_int(config, "net", "dont_default_to_stun_candidates", 0)) { + IceCandidateType types[ICT_CandidateTypeMax]; + types[0] = ICT_HostCandidate; + types[1] = ICT_RelayedCandidate; + types[2] = ICT_CandidateInvalid; + ice_session_set_default_candidates_types(iceSession, types); + } + ice_session_set_role(iceSession, role); +} + +void IceAgent::deleteSession () { + if (!iceSession) + return; + + ice_session_destroy(iceSession); + iceSession = nullptr; + mediaSession.getPrivate()->deactivateIce(); +} + +void IceAgent::gatheringFinished () { + const SalMediaDescription *rmd = mediaSession.getPrivate()->getOp()->getRemoteMediaDescription(); + if (rmd) + clearUnusedIceCandidates(mediaSession.getPrivate()->getLocalDesc(), rmd); + if (!iceSession) + return; + + ice_session_compute_candidates_foundations(iceSession); + ice_session_eliminate_redundant_candidates(iceSession); + ice_session_choose_default_candidates(iceSession); + + int pingTime = ice_session_average_gathering_round_trip_time(iceSession); + if (pingTime >= 0) { + mediaSession.getPrivate()->setPingTime(pingTime); + } +} + +int IceAgent::getNbLosingPairs () const { + if (!iceSession) + return 0; + return ice_session_nb_losing_pairs(iceSession); +} + +bool IceAgent::hasCompleted () const { + if (!iceSession) + return true; + return ice_session_state(iceSession) == IS_Completed; +} + +bool IceAgent::hasCompletedCheckList () const { + if (!iceSession) + return false; + switch (ice_session_state(iceSession)) { + case IS_Completed: + case IS_Failed: + return !!ice_session_has_completed_check_list(iceSession); + default: + return false; + } +} + +bool IceAgent::isControlling () const { + if (!iceSession) + return false; + return ice_session_role(iceSession) == IR_Controlling; +} + +bool IceAgent::prepare (const SalMediaDescription *localDesc, bool incomingOffer, bool allowGathering) { + if (!iceSession) + return false; + + SalMediaDescription *remoteDesc = nullptr; + bool hasVideo = false; + if (incomingOffer) { + remoteDesc = mediaSession.getPrivate()->getOp()->getRemoteMediaDescription(); + hasVideo = linphone_core_video_enabled(mediaSession.getCore()->getCCore()) && + linphone_core_media_description_contains_video_stream(remoteDesc); + } else + hasVideo = mediaSession.getMediaParams()->videoEnabled(); + + prepareIceForStream(mediaSession.getPrivate()->getMediaStream(LinphoneStreamTypeAudio), true); + if (hasVideo) + prepareIceForStream(mediaSession.getPrivate()->getMediaStream(LinphoneStreamTypeVideo), true); + if (mediaSession.getMediaParams()->realtimeTextEnabled()) + prepareIceForStream(mediaSession.getPrivate()->getMediaStream(LinphoneStreamTypeText), true); + + // Start ICE gathering. + if (incomingOffer){ + // This may delete the ice session. + updateFromRemoteMediaDescription(localDesc, remoteDesc, true); + } + if (iceSession && allowGathering && !ice_session_candidates_gathered(iceSession)) { + mediaSession.getPrivate()->prepareStreamsForIceGathering(hasVideo); + int err = gatherIceCandidates(); + if (err == 0) { + // Ice candidates gathering wasn't started, but we can proceed with the call anyway. + mediaSession.getPrivate()->stopStreamsForIceGathering(); + return false; + } else if (err == -1) { + mediaSession.getPrivate()->stopStreamsForIceGathering(); + deleteSession(); + return false; + } + return true; + } + return false; +} + +void IceAgent::prepareIceForStream (MediaStream *ms, bool createChecklist) { + if (!iceSession) + return; + + int streamIndex = mediaSession.getPrivate()->getStreamIndex(ms); + rtp_session_set_pktinfo(ms->sessions.rtp_session, true); + IceCheckList *cl = ice_session_check_list(iceSession, streamIndex); + if (!cl && createChecklist) { + cl = ice_check_list_new(); + ice_session_add_check_list(iceSession, cl, static_cast(streamIndex)); + lInfo() << "Created new ICE check list for stream [" << streamIndex << "]"; + } + if (cl) + media_stream_set_ice_check_list(ms, cl); +} + +void IceAgent::resetSession (IceRole role) { + if (!iceSession) + return; + ice_session_reset(iceSession, role); +} + +void IceAgent::restartSession (IceRole role) { + if (!iceSession) + return; + ice_session_restart(iceSession, role); +} + +void IceAgent::startConnectivityChecks () { + if (!iceSession) + return; + ice_session_start_connectivity_checks(iceSession); +} + +void IceAgent::stopIceForInactiveStreams (SalMediaDescription *desc) { + if (!iceSession) + return; + if (ice_session_state(iceSession) == IS_Completed) + return; + for (int i = 0; i < desc->nb_streams; i++) { + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (!sal_stream_description_active(&desc->streams[i]) && cl) { + ice_session_remove_check_list(iceSession, cl); + mediaSession.getPrivate()->clearIceCheckList(cl); + } + } + updateIceStateInCallStats(); +} + +void IceAgent::updateFromRemoteMediaDescription ( + const SalMediaDescription *localDesc, + const SalMediaDescription *remoteDesc, + bool isOffer +) { + if (!iceSession) + return; + + if (!iceParamsFoundInRemoteMediaDescription(remoteDesc)) { + // Response from remote does not contain mandatory ICE attributes, delete the session. + deleteSession(); + mediaSession.getPrivate()->enableSymmetricRtp(!!linphone_core_symmetric_rtp_enabled(mediaSession.getCore()->getCCore())); + return; + } + + // Check for ICE restart and set remote credentials. + bool iceRestarted = checkForIceRestartAndSetRemoteCredentials(remoteDesc, isOffer); + + // Create ICE check lists if needed and parse ICE attributes. + createIceCheckListsAndParseIceAttributes(remoteDesc, iceRestarted); + for (int i = 0; i < remoteDesc->nb_streams; i++) { + const SalStreamDescription *stream = &remoteDesc->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (!cl) continue; + if (!sal_stream_description_active(stream)) { + ice_session_remove_check_list_from_idx(iceSession, static_cast(i)); + mediaSession.getPrivate()->clearIceCheckList(cl); + } + } + clearUnusedIceCandidates(localDesc, remoteDesc); + ice_session_check_mismatch(iceSession); + + if (ice_session_nb_check_lists(iceSession) == 0) { + deleteSession(); + mediaSession.getPrivate()->enableSymmetricRtp(!!linphone_core_symmetric_rtp_enabled(mediaSession.getCore()->getCCore())); + } +} + +void IceAgent::updateIceStateInCallStats () { + if (!iceSession) + return; + IceCheckList *audioCheckList = ice_session_check_list(iceSession, mediaSession.getPrivate()->getStreamIndex(LinphoneStreamTypeAudio)); + IceCheckList *videoCheckList = ice_session_check_list(iceSession, mediaSession.getPrivate()->getStreamIndex(LinphoneStreamTypeVideo)); + IceCheckList *textCheckList = ice_session_check_list(iceSession, mediaSession.getPrivate()->getStreamIndex(LinphoneStreamTypeText)); + if (!audioCheckList && !videoCheckList && !textCheckList) + return; + + LinphoneCallStats *audioStats = mediaSession.getPrivate()->getStats(LinphoneStreamTypeAudio); + LinphoneCallStats *videoStats = mediaSession.getPrivate()->getStats(LinphoneStreamTypeVideo); + LinphoneCallStats *textStats = mediaSession.getPrivate()->getStats(LinphoneStreamTypeText); + IceSessionState sessionState = ice_session_state(iceSession); + if ((sessionState == IS_Completed) || ((sessionState == IS_Failed) && ice_session_has_completed_check_list(iceSession))) { + _linphone_call_stats_set_ice_state(audioStats, LinphoneIceStateNotActivated); + if (audioCheckList && mediaSession.getMediaParams()->audioEnabled()) + updateIceStateInCallStatsForStream(audioStats, audioCheckList); + + _linphone_call_stats_set_ice_state(videoStats, LinphoneIceStateNotActivated); + if (videoCheckList && mediaSession.getMediaParams()->videoEnabled()) + updateIceStateInCallStatsForStream(videoStats, videoCheckList); + + _linphone_call_stats_set_ice_state(textStats, LinphoneIceStateNotActivated); + if (textCheckList && mediaSession.getMediaParams()->realtimeTextEnabled()) + updateIceStateInCallStatsForStream(textStats, textCheckList); + } else if (sessionState == IS_Running) { + if (audioCheckList && mediaSession.getMediaParams()->audioEnabled()) + _linphone_call_stats_set_ice_state(audioStats, LinphoneIceStateInProgress); + if (videoCheckList && mediaSession.getMediaParams()->videoEnabled()) + _linphone_call_stats_set_ice_state(videoStats, LinphoneIceStateInProgress); + if (textCheckList && mediaSession.getMediaParams()->realtimeTextEnabled()) + _linphone_call_stats_set_ice_state(textStats, LinphoneIceStateInProgress); + } else { + if (audioCheckList && mediaSession.getMediaParams()->audioEnabled()) + _linphone_call_stats_set_ice_state(audioStats, LinphoneIceStateFailed); + if (videoCheckList && mediaSession.getMediaParams()->videoEnabled()) + _linphone_call_stats_set_ice_state(videoStats, LinphoneIceStateFailed); + if (textCheckList && mediaSession.getMediaParams()->realtimeTextEnabled()) + _linphone_call_stats_set_ice_state(textStats, LinphoneIceStateFailed); + } + lInfo() << "CallSession [" << &mediaSession << "] New ICE state: audio: [" << linphone_ice_state_to_string(linphone_call_stats_get_ice_state(audioStats)) << + "] video: [" << linphone_ice_state_to_string(linphone_call_stats_get_ice_state(videoStats)) << + "] text: [" << linphone_ice_state_to_string(linphone_call_stats_get_ice_state(textStats)) << "]"; +} + +void IceAgent::updateLocalMediaDescriptionFromIce (SalMediaDescription *desc) { + if (!iceSession) + return; + IceCandidate *rtpCandidate = nullptr; + IceCandidate *rtcpCandidate = nullptr; + bool result = false; + IceSessionState sessionState = ice_session_state(iceSession); + if (sessionState == IS_Completed) { + IceCheckList *firstCl = nullptr; + for (int i = 0; i < desc->nb_streams; i++) { + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (cl) { + firstCl = cl; + break; + } + } + if (firstCl) + result = !!ice_check_list_selected_valid_local_candidate(firstCl, &rtpCandidate, nullptr); + if (result) { + strncpy(desc->addr, rtpCandidate->taddr.ip, sizeof(desc->addr)); + } else { + lWarning() << "If ICE has completed successfully, rtp_candidate should be set!"; + ice_dump_valid_list(firstCl); + } + } + + strncpy(desc->ice_pwd, ice_session_local_pwd(iceSession), sizeof(desc->ice_pwd)); + strncpy(desc->ice_ufrag, ice_session_local_ufrag(iceSession), sizeof(desc->ice_ufrag)); + for (int i = 0; i < desc->nb_streams; i++) { + SalStreamDescription *stream = &desc->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + rtpCandidate = rtcpCandidate = nullptr; + if (!sal_stream_description_active(stream) || !cl) + continue; + if (ice_check_list_state(cl) == ICL_Completed) { + LinphoneConfig *config = linphone_core_get_config(mediaSession.getCore()->getCCore()); + // TODO: Remove `ice_uses_nortpproxy` option, let's say in December 2018. + bool useNoRtpProxy = !!lp_config_get_int(config, "sip", "ice_uses_nortpproxy", false); + if (useNoRtpProxy) + stream->set_nortpproxy = true; + result = !!ice_check_list_selected_valid_local_candidate(ice_session_check_list(iceSession, i), &rtpCandidate, &rtcpCandidate); + } else { + stream->set_nortpproxy = false; + result = !!ice_check_list_default_local_candidate(ice_session_check_list(iceSession, i), &rtpCandidate, &rtcpCandidate); + } + if (result) { + strncpy(stream->rtp_addr, rtpCandidate->taddr.ip, sizeof(stream->rtp_addr)); + strncpy(stream->rtcp_addr, rtcpCandidate->taddr.ip, sizeof(stream->rtcp_addr)); + stream->rtp_port = rtpCandidate->taddr.port; + stream->rtcp_port = rtcpCandidate->taddr.port; + } else { + memset(stream->rtp_addr, 0, sizeof(stream->rtp_addr)); + memset(stream->rtcp_addr, 0, sizeof(stream->rtcp_addr)); + } + if ((strlen(ice_check_list_local_pwd(cl)) != strlen(desc->ice_pwd)) || (strcmp(ice_check_list_local_pwd(cl), desc->ice_pwd))) + strncpy(stream->ice_pwd, ice_check_list_local_pwd(cl), sizeof(stream->ice_pwd)); + else + memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd)); + if ((strlen(ice_check_list_local_ufrag(cl)) != strlen(desc->ice_ufrag)) || (strcmp(ice_check_list_local_ufrag(cl), desc->ice_ufrag))) + strncpy(stream->ice_ufrag, ice_check_list_local_ufrag(cl), sizeof(stream->ice_ufrag)); + else + memset(stream->ice_pwd, 0, sizeof(stream->ice_pwd)); + stream->ice_mismatch = ice_check_list_is_mismatch(cl); + if ((ice_check_list_state(cl) == ICL_Running) || (ice_check_list_state(cl) == ICL_Completed)) { + memset(stream->ice_candidates, 0, sizeof(stream->ice_candidates)); + int nbCandidates = 0; + for (int j = 0; j < MIN((int)bctbx_list_size(cl->local_candidates), SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES); j++) { + SalIceCandidate *salCandidate = &stream->ice_candidates[nbCandidates]; + IceCandidate *iceCandidate = reinterpret_cast(bctbx_list_nth_data(cl->local_candidates, j)); + const char *defaultAddr = nullptr; + int defaultPort = 0; + if (iceCandidate->componentID == 1) { + defaultAddr = stream->rtp_addr; + defaultPort = stream->rtp_port; + } else if (iceCandidate->componentID == 2) { + defaultAddr = stream->rtcp_addr; + defaultPort = stream->rtcp_port; + } else + continue; + if (defaultAddr[0] == '\0') + defaultAddr = desc->addr; + // Only include the candidates matching the default destination for each component of the stream if the state is Completed as specified in RFC5245 section 9.1.2.2. + if ( + ice_check_list_state(cl) == ICL_Completed && + !((iceCandidate->taddr.port == defaultPort) && (strlen(iceCandidate->taddr.ip) == strlen(defaultAddr)) && (strcmp(iceCandidate->taddr.ip, defaultAddr) == 0)) + ) + continue; + strncpy(salCandidate->foundation, iceCandidate->foundation, sizeof(salCandidate->foundation)); + salCandidate->componentID = iceCandidate->componentID; + salCandidate->priority = iceCandidate->priority; + strncpy(salCandidate->type, ice_candidate_type(iceCandidate), sizeof(salCandidate->type)); + strncpy(salCandidate->addr, iceCandidate->taddr.ip, sizeof(salCandidate->addr)); + salCandidate->port = iceCandidate->taddr.port; + if (iceCandidate->base && (iceCandidate->base != iceCandidate)) { + strncpy(salCandidate->raddr, iceCandidate->base->taddr.ip, sizeof(salCandidate->raddr)); + salCandidate->rport = iceCandidate->base->taddr.port; + } + nbCandidates++; + } + } + if ((ice_check_list_state(cl) == ICL_Completed) && (ice_session_role(iceSession) == IR_Controlling)) { + memset(stream->ice_remote_candidates, 0, sizeof(stream->ice_remote_candidates)); + if (ice_check_list_selected_valid_remote_candidate(cl, &rtpCandidate, &rtcpCandidate)) { + strncpy(stream->ice_remote_candidates[0].addr, rtpCandidate->taddr.ip, sizeof(stream->ice_remote_candidates[0].addr)); + stream->ice_remote_candidates[0].port = rtpCandidate->taddr.port; + strncpy(stream->ice_remote_candidates[1].addr, rtcpCandidate->taddr.ip, sizeof(stream->ice_remote_candidates[1].addr)); + stream->ice_remote_candidates[1].port = rtcpCandidate->taddr.port; + } else + lError() << "ice: Selected valid remote candidates should be present if the check list is in the Completed state"; + } else { + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) { + stream->ice_remote_candidates[j].addr[0] = '\0'; + stream->ice_remote_candidates[j].port = 0; + } + } + } +} + +// ----------------------------------------------------------------------------- + +void IceAgent::addLocalIceCandidates (int family, const char *addr, IceCheckList *audioCl, IceCheckList *videoCl, IceCheckList *textCl) { + if ((ice_check_list_state(audioCl) != ICL_Completed) && !ice_check_list_candidates_gathered(audioCl)) { + int rtpPort = mediaSession.getPrivate()->getRtpPort(LinphoneStreamTypeAudio); + int rtcpPort = mediaSession.getPrivate()->getRtcpPort(LinphoneStreamTypeAudio); + ice_add_local_candidate(audioCl, "host", family, addr, rtpPort, 1, nullptr); + ice_add_local_candidate(audioCl, "host", family, addr, rtcpPort, 2, nullptr); + LinphoneCallStats *audioStats = mediaSession.getPrivate()->getStats(LinphoneStreamTypeAudio); + _linphone_call_stats_set_ice_state(audioStats, LinphoneIceStateInProgress); + } + LinphoneCore *core = mediaSession.getCore()->getCCore(); + if (linphone_core_video_enabled(core) && videoCl && (ice_check_list_state(videoCl) != ICL_Completed) && !ice_check_list_candidates_gathered(videoCl)) { + int rtpPort = mediaSession.getPrivate()->getRtpPort(LinphoneStreamTypeVideo); + int rtcpPort = mediaSession.getPrivate()->getRtcpPort(LinphoneStreamTypeVideo); + ice_add_local_candidate(videoCl, "host", family, addr, rtpPort, 1, nullptr); + ice_add_local_candidate(videoCl, "host", family, addr, rtcpPort, 2, nullptr); + LinphoneCallStats *videoStats = mediaSession.getPrivate()->getStats(LinphoneStreamTypeVideo); + _linphone_call_stats_set_ice_state(videoStats, LinphoneIceStateInProgress); + } + if (mediaSession.getMediaParams()->realtimeTextEnabled() && textCl && (ice_check_list_state(textCl) != ICL_Completed) && !ice_check_list_candidates_gathered(textCl)) { + int rtpPort = mediaSession.getPrivate()->getRtpPort(LinphoneStreamTypeText); + int rtcpPort = mediaSession.getPrivate()->getRtcpPort(LinphoneStreamTypeText); + ice_add_local_candidate(textCl, "host", family, addr, rtpPort, 1, nullptr); + ice_add_local_candidate(textCl, "host", family, addr, rtcpPort, 2, nullptr); + LinphoneCallStats *textStats = mediaSession.getPrivate()->getStats(LinphoneStreamTypeText); + _linphone_call_stats_set_ice_state(textStats, LinphoneIceStateInProgress); + } +} + +bool IceAgent::checkForIceRestartAndSetRemoteCredentials (const SalMediaDescription *md, bool isOffer) { + bool iceRestarted = false; + string addr = md->addr; + if ((addr == "0.0.0.0") || (addr == "::0")) { + ice_session_restart(iceSession, isOffer ? IR_Controlled : IR_Controlling); + iceRestarted = true; + } else { + for (int i = 0; i < md->nb_streams; i++) { + const SalStreamDescription *stream = &md->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + string rtpAddr = stream->rtp_addr; + if (cl && (rtpAddr == "0.0.0.0")) { + ice_session_restart(iceSession, isOffer ? IR_Controlled : IR_Controlling); + iceRestarted = true; + break; + } + } + } + if (!ice_session_remote_ufrag(iceSession) && !ice_session_remote_pwd(iceSession)) { + ice_session_set_remote_credentials(iceSession, md->ice_ufrag, md->ice_pwd); + } else if (ice_session_remote_credentials_changed(iceSession, md->ice_ufrag, md->ice_pwd)) { + if (!iceRestarted) { + ice_session_restart(iceSession, isOffer ? IR_Controlled : IR_Controlling); + iceRestarted = true; + } + ice_session_set_remote_credentials(iceSession, md->ice_ufrag, md->ice_pwd); + } + for (int i = 0; i < md->nb_streams; i++) { + const SalStreamDescription *stream = &md->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (cl && (stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) { + if (ice_check_list_remote_credentials_changed(cl, stream->ice_ufrag, stream->ice_pwd)) { + if (!iceRestarted && ice_check_list_get_remote_ufrag(cl) && ice_check_list_get_remote_pwd(cl)) { + // Restart only if remote ufrag/paswd was already set. + ice_session_restart(iceSession, isOffer ? IR_Controlled : IR_Controlling); + iceRestarted = true; + } + ice_check_list_set_remote_credentials(cl, stream->ice_ufrag, stream->ice_pwd); + break; + } + } + } + return iceRestarted; +} + +void IceAgent::clearUnusedIceCandidates (const SalMediaDescription *localDesc, const SalMediaDescription *remoteDesc) { + if (!localDesc) + return; + for (int i = 0; i < remoteDesc->nb_streams; i++) { + const SalStreamDescription *localStream = &localDesc->streams[i]; + const SalStreamDescription *stream = &remoteDesc->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (!cl || !localStream) + continue; + if (stream->rtcp_mux && localStream->rtcp_mux) { + ice_check_list_remove_rtcp_candidates(cl); + } + } +} + +void IceAgent::createIceCheckListsAndParseIceAttributes (const SalMediaDescription *md, bool iceRestarted) { + for (int i = 0; i < md->nb_streams; i++) { + const SalStreamDescription *stream = &md->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (!cl) + continue; + if (stream->ice_mismatch) { + ice_check_list_set_state(cl, ICL_Failed); + continue; + } + if (stream->rtp_port == 0) { + ice_session_remove_check_list(iceSession, cl); + mediaSession.getPrivate()->clearIceCheckList(cl); + continue; + } + if ((stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) + ice_check_list_set_remote_credentials(cl, stream->ice_ufrag, stream->ice_pwd); + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_CANDIDATES; j++) { + bool defaultCandidate = false; + const SalIceCandidate *candidate = &stream->ice_candidates[j]; + if (candidate->addr[0] == '\0') + break; + if ((candidate->componentID == 0) || (candidate->componentID > 2)) + continue; + const char *addr = nullptr; + int port = 0; + getIceDefaultAddrAndPort(static_cast(candidate->componentID), md, stream, &addr, &port); + if (addr && (candidate->port == port) && (strlen(candidate->addr) == strlen(addr)) && (strcmp(candidate->addr, addr) == 0)) + defaultCandidate = true; + int family = AF_INET; + if (strchr(candidate->addr, ':')) + family = AF_INET6; + ice_add_remote_candidate( + cl, candidate->type, family, candidate->addr, candidate->port, + static_cast(candidate->componentID), + candidate->priority, candidate->foundation, defaultCandidate + ); + } + if (!iceRestarted) { + bool losingPairsAdded = false; + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) { + const SalIceRemoteCandidate *remoteCandidate = &stream->ice_remote_candidates[j]; + const char *addr = nullptr; + int port = 0; + int componentID = j + 1; + if (remoteCandidate->addr[0] == '\0') break; + getIceDefaultAddrAndPort(static_cast(componentID), md, stream, &addr, &port); + + // If we receive a re-invite and we finished ICE processing on our side, use the candidates given by the remote. + if (j == 0) + ice_check_list_unselect_valid_pairs(cl); + + int remoteFamily = AF_INET; + if (strchr(remoteCandidate->addr, ':')) + remoteFamily = AF_INET6; + int family = AF_INET; + if (strchr(addr, ':')) + family = AF_INET6; + ice_add_losing_pair(cl, static_cast(j + 1), remoteFamily, remoteCandidate->addr, remoteCandidate->port, family, addr, port); + losingPairsAdded = true; + } + if (losingPairsAdded) + ice_check_list_check_completed(cl); + } + } +} + +/** Return values: + * 1: STUN gathering is started + * 0: no STUN gathering is started, but it's ok to proceed with ICE anyway (with local candidates only or because STUN gathering was already done before) + * -1: no gathering started and something went wrong with local candidates. There is no way to start the ICE session. + */ +int IceAgent::gatherIceCandidates () { + if (!iceSession) + return -1; + IceCheckList *audioCl = ice_session_check_list(iceSession, mediaSession.getPrivate()->getStreamIndex(LinphoneStreamTypeAudio)); + IceCheckList *videoCl = ice_session_check_list(iceSession, mediaSession.getPrivate()->getStreamIndex(LinphoneStreamTypeVideo)); + IceCheckList *textCl = ice_session_check_list(iceSession, mediaSession.getPrivate()->getStreamIndex(LinphoneStreamTypeText)); + if (!audioCl && !videoCl && !textCl) + return -1; + + const struct addrinfo *ai = nullptr; + LinphoneNatPolicy *natPolicy = mediaSession.getPrivate()->getNatPolicy(); + if (natPolicy && linphone_nat_policy_stun_server_activated(natPolicy)) { + ai = linphone_nat_policy_get_stun_server_addrinfo(natPolicy); + if (ai) + ai = getIcePreferredStunServerAddrinfo(ai); + else + lWarning() << "Failed to resolve STUN server for ICE gathering, continuing without STUN"; + } else + lWarning() << "ICE is used without STUN server"; + LinphoneCore *core = mediaSession.getCore()->getCCore(); + ice_session_enable_forced_relay(iceSession, core->forced_ice_relay); + ice_session_enable_short_turn_refresh(iceSession, core->short_turn_refresh); + + // Gather local host candidates. + char localAddr[64]; + if (mediaSession.getPrivate()->getAf() == AF_INET6) { + if (linphone_core_get_local_ip_for(AF_INET6, nullptr, localAddr) < 0) { + lError() << "Fail to get local IPv6"; + } else + addLocalIceCandidates(AF_INET6, localAddr, audioCl, videoCl, textCl); + } + if (linphone_core_get_local_ip_for(AF_INET, nullptr, localAddr) < 0) { + if (mediaSession.getPrivate()->getAf() != AF_INET6) { + lError() << "Fail to get local IPv4"; + return -1; + } + } else + addLocalIceCandidates(AF_INET, localAddr, audioCl, videoCl, textCl); + if (ai && natPolicy && linphone_nat_policy_stun_server_activated(natPolicy)) { + string server = linphone_nat_policy_get_stun_server(natPolicy); + lInfo() << "ICE: gathering candidates from [" << server << "] using " << (linphone_nat_policy_turn_enabled(natPolicy) ? "TURN" : "STUN"); + // Gather local srflx candidates. + ice_session_enable_turn(iceSession, linphone_nat_policy_turn_enabled(natPolicy)); + ice_session_set_stun_auth_requested_cb(iceSession, MediaSessionPrivate::stunAuthRequestedCb, mediaSession.getPrivate()); + return ice_session_gather_candidates(iceSession, ai->ai_addr, (socklen_t)ai->ai_addrlen) ? 1 : 0; + } else { + lInfo() << "ICE: bypass candidates gathering"; + ice_session_compute_candidates_foundations(iceSession); + ice_session_eliminate_redundant_candidates(iceSession); + ice_session_choose_default_candidates(iceSession); + } + return 0; +} + +void IceAgent::getIceDefaultAddrAndPort ( + uint16_t componentID, + const SalMediaDescription *md, + const SalStreamDescription *stream, + const char **addr, + int *port +) { + if (componentID == 1) { + *addr = stream->rtp_addr; + *port = stream->rtp_port; + } else if (componentID == 2) { + *addr = stream->rtcp_addr; + *port = stream->rtcp_port; + } else + return; + if ((*addr)[0] == '\0') *addr = md->addr; +} + +/** + * Choose the preferred IP address to use to contact the STUN server from the list of IP addresses + * the DNS resolution returned. If a NAT64 address is present, use it, otherwise if an IPv4 address + * is present, use it, otherwise use an IPv6 address if it is present. + */ +const struct addrinfo *IceAgent::getIcePreferredStunServerAddrinfo (const struct addrinfo *ai) { + // Search for NAT64 addrinfo. + const struct addrinfo *it = ai; + while (it) { + if (it->ai_family == AF_INET6) { + struct sockaddr_storage ss; + socklen_t sslen = sizeof(ss); + memset(&ss, 0, sizeof(ss)); + bctbx_sockaddr_remove_nat64_mapping(it->ai_addr, (struct sockaddr *)&ss, &sslen); + if (ss.ss_family == AF_INET) break; + } + it = it->ai_next; + } + const struct addrinfo *preferredAi = it; + if (!preferredAi) { + // Search for IPv4 addrinfo. + it = ai; + while (it) { + if (it->ai_family == AF_INET) + break; + if ((it->ai_family == AF_INET6) && (it->ai_flags & AI_V4MAPPED)) + break; + it = it->ai_next; + } + preferredAi = it; + } + if (!preferredAi) { + // Search for IPv6 addrinfo. + it = ai; + while (it) { + if (it->ai_family == AF_INET6) + break; + it = it->ai_next; + } + preferredAi = it; + } + return preferredAi; +} + +bool IceAgent::iceParamsFoundInRemoteMediaDescription (const SalMediaDescription *md) { + if ((md->ice_pwd[0] != '\0') && (md->ice_ufrag[0] != '\0')) + return true; + bool found = false; + for (int i = 0; i < md->nb_streams; i++) { + const SalStreamDescription *stream = &md->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (cl) { + if ((stream->ice_pwd[0] != '\0') && (stream->ice_ufrag[0] != '\0')) + found = true; + else { + found = false; + break; + } + } + } + return found; +} + +void IceAgent::updateIceStateInCallStatsForStream (LinphoneCallStats *stats, IceCheckList *cl) { + if (ice_check_list_state(cl) != ICL_Completed) { + _linphone_call_stats_set_ice_state(stats, LinphoneIceStateFailed); + return; + } + + switch (ice_check_list_selected_valid_candidate_type(cl)) { + case ICT_HostCandidate: + _linphone_call_stats_set_ice_state(stats, LinphoneIceStateHostConnection); + break; + case ICT_ServerReflexiveCandidate: + case ICT_PeerReflexiveCandidate: + _linphone_call_stats_set_ice_state(stats, LinphoneIceStateReflexiveConnection); + break; + case ICT_RelayedCandidate: + _linphone_call_stats_set_ice_state(stats, LinphoneIceStateRelayConnection); + break; + case ICT_CandidateInvalid: + case ICT_CandidateTypeMax: + // Shall not happen. + L_ASSERT(false); + break; + } +} + +bool IceAgent::checkIceReinviteNeedsDeferedResponse(SalMediaDescription *md) { + if (!iceSession || (ice_session_state(iceSession) != IS_Running)) + return false; + + for (int i = 0; i < md->nb_streams; i++) { + SalStreamDescription *stream = &md->streams[i]; + IceCheckList *cl = ice_session_check_list(iceSession, i); + if (!cl) + continue; + + if (stream->ice_mismatch) + return false; + if ((stream->rtp_port == 0) || (ice_check_list_state(cl) != ICL_Running)) + continue; + + for (int j = 0; j < SAL_MEDIA_DESCRIPTION_MAX_ICE_REMOTE_CANDIDATES; j++) { + const SalIceRemoteCandidate *remote_candidate = &stream->ice_remote_candidates[j]; + if (remote_candidate->addr[0] != '\0') + return true; + } + } + return false; +} + +LINPHONE_END_NAMESPACE diff --git a/src/nat/ice-agent.h b/src/nat/ice-agent.h new file mode 100644 index 000000000..f98f2a02e --- /dev/null +++ b/src/nat/ice-agent.h @@ -0,0 +1,93 @@ +/* + * ice-agent.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_ICE_AGENT_H_ +#define _L_ICE_AGENT_H_ + +#include +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +L_DECL_C_STRUCT_PREFIX_LESS(SalMediaDescription); +L_DECL_C_STRUCT_PREFIX_LESS(SalStreamDescription); +L_DECL_C_STRUCT(LinphoneCallStats); +L_DECL_C_STRUCT(LinphoneCore); +L_DECL_C_STRUCT(MediaStream); + +class MediaSession; + +LINPHONE_BEGIN_NAMESPACE + +class IceAgent { +public: + explicit IceAgent (MediaSession &mediaSession) : mediaSession(mediaSession) {} + + bool candidatesGathered () const; + void checkSession (IceRole role, bool isReinvite); + void deleteSession (); + void gatheringFinished (); + int getNbLosingPairs () const; + IceSession *getIceSession () const { + return iceSession; + } + + bool hasCompleted () const; + bool hasCompletedCheckList () const; + bool hasSession () const { + return !!iceSession; + } + + bool isControlling () const; + bool prepare (const SalMediaDescription *localDesc, bool incomingOffer, bool allowGathering = true); + void prepareIceForStream (MediaStream *ms, bool createChecklist); + void resetSession (IceRole role); + void restartSession (IceRole role); + void startConnectivityChecks (); + void stopIceForInactiveStreams (SalMediaDescription *desc); + void updateFromRemoteMediaDescription (const SalMediaDescription *localDesc, const SalMediaDescription *remoteDesc, bool isOffer); + void updateIceStateInCallStats (); + void updateLocalMediaDescriptionFromIce (SalMediaDescription *desc); + /* + * Checks if an incoming offer with ICE needs a delayed answer, because the ice session hasn't completed yet with + * connecvity checks. + */ + bool checkIceReinviteNeedsDeferedResponse (SalMediaDescription *md); + +private: + void addLocalIceCandidates (int family, const char *addr, IceCheckList *audioCl, IceCheckList *videoCl, IceCheckList *textCl); + bool checkForIceRestartAndSetRemoteCredentials (const SalMediaDescription *md, bool isOffer); + void clearUnusedIceCandidates (const SalMediaDescription *localDesc, const SalMediaDescription *remoteDesc); + void createIceCheckListsAndParseIceAttributes (const SalMediaDescription *md, bool iceRestarted); + int gatherIceCandidates (); + void getIceDefaultAddrAndPort (uint16_t componentID, const SalMediaDescription *md, const SalStreamDescription *stream, const char **addr, int *port); + const struct addrinfo *getIcePreferredStunServerAddrinfo (const struct addrinfo *ai); + bool iceParamsFoundInRemoteMediaDescription (const SalMediaDescription *md); + void updateIceStateInCallStatsForStream (LinphoneCallStats *stats, IceCheckList *cl); + +private: + MediaSession &mediaSession; + IceSession *iceSession = nullptr; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_ICE_AGENT_H_ diff --git a/src/nat/stun-client.cpp b/src/nat/stun-client.cpp new file mode 100644 index 000000000..590abfd1d --- /dev/null +++ b/src/nat/stun-client.cpp @@ -0,0 +1,263 @@ +/* + * stun-client.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "private.h" + +#include "logger/logger.h" + +#include "stun-client.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +int StunClient::run (int audioPort, int videoPort, int textPort) { + stunDiscoveryDone = false; + if (linphone_core_ipv6_enabled(getCore()->getCCore())) { + lWarning() << "STUN support is not implemented for ipv6"; + return -1; + } + if (!linphone_core_get_stun_server(getCore()->getCCore())) + return -1; + const struct addrinfo *ai = linphone_core_get_stun_server_addrinfo(getCore()->getCCore()); + if (!ai) { + lError() << "Could not obtain STUN server addrinfo"; + return -1; + } + + /* Create the RTP sockets and send STUN messages to the STUN server */ + ortp_socket_t sockAudio = createStunSocket(audioPort); + if (sockAudio == -1) + return -1; + ortp_socket_t sockVideo = -1; + if (linphone_core_video_enabled(getCore()->getCCore())) { + sockVideo = createStunSocket(videoPort); + if (sockVideo == -1) + return -1; + } + ortp_socket_t sockText = -1; + if (linphone_core_realtime_text_enabled(getCore()->getCCore())) { + sockText = createStunSocket(textPort); + if (sockText == -1) + return -1; + } + + int ret = 0; + int loops = 0; + bool gotAudio = false; + bool gotVideo = false; + bool gotText = false; + bool coneAudio = false; + bool coneVideo = false; + bool coneText = false; + double elapsed; + struct timeval init; + ortp_gettimeofday(&init, nullptr); + + do { + int id; + if ((loops % 20) == 0) { + lInfo() << "Sending STUN requests..."; + sendStunRequest(sockAudio, ai->ai_addr, (socklen_t)ai->ai_addrlen, 11, true); + sendStunRequest(sockAudio, ai->ai_addr, (socklen_t)ai->ai_addrlen, 1, false); + if (sockVideo != -1) { + sendStunRequest(sockVideo, ai->ai_addr, (socklen_t)ai->ai_addrlen, 22, true); + sendStunRequest(sockVideo, ai->ai_addr, (socklen_t)ai->ai_addrlen, 2, false); + } + if (sockText != -1) { + sendStunRequest(sockText, ai->ai_addr, (socklen_t)ai->ai_addrlen, 33, true); + sendStunRequest(sockText, ai->ai_addr, (socklen_t)ai->ai_addrlen, 3, false); + } + } + ms_usleep(10000); + + if (recvStunResponse(sockAudio, audioCandidate, id) > 0) { + lInfo() << "STUN test result: local audio port maps to " << audioCandidate.address << ":" << audioCandidate.port; + if (id == 11) coneAudio = true; + gotAudio = true; + } + if (recvStunResponse(sockVideo, videoCandidate, id) > 0) { + lInfo() << "STUN test result: local video port maps to " << videoCandidate.address << ":" << videoCandidate.port; + if (id == 22) coneVideo = true; + gotVideo = true; + } + if (recvStunResponse(sockText, textCandidate, id) > 0) { + lInfo() << "STUN test result: local text port maps to " << textCandidate.address << ":" << textCandidate.port; + if (id == 33) coneText = true; + gotText = true; + } + struct timeval cur; + ortp_gettimeofday(&cur, nullptr); + elapsed = static_cast(cur.tv_sec - init.tv_sec) * 1000 + static_cast(cur.tv_usec - init.tv_usec) / 1000; + if (elapsed > 2000.) { + lInfo() << "STUN responses timeout, going ahead"; + ret = -1; + break; + } + loops++; + } while (!(gotAudio && (gotVideo || sockVideo == -1) && (gotText || sockText == -1))); + + if (ret == 0) + ret = (int)elapsed; + + if (!gotAudio) + lError() << "No STUN server response for audio port"; + else if (!coneAudio) + lInfo() << "NAT is symmetric for audio port"; + + if (sockVideo != -1) { + if (!gotVideo) + lError() << "No STUN server response for video port"; + else if (!coneVideo) + lInfo() << "NAT is symmetric for video port"; + } + + if (sockText != -1) { + if (!gotText) + lError() << "No STUN server response for text port"; + else if (!coneText) + lInfo() << "NAT is symmetric for text port"; + } + + close_socket(sockAudio); + if (sockVideo != -1) close_socket(sockVideo); + if (sockText != -1) close_socket(sockText); + stunDiscoveryDone = true; + return ret; +} + +void StunClient::updateMediaDescription (SalMediaDescription *md) const { + if (!stunDiscoveryDone) return; + for (int i = 0; i < SAL_MEDIA_DESCRIPTION_MAX_STREAMS; i++) { + if (!sal_stream_description_active(&md->streams[i])) + continue; + if (md->streams[i].type == SalAudio && audioCandidate.port != 0) { + strncpy(md->streams[i].rtp_addr, audioCandidate.address.c_str(), sizeof(md->streams[i].rtp_addr)); + md->streams[i].rtp_port = audioCandidate.port; + if ( + ( + !audioCandidate.address.empty() && + !videoCandidate.address.empty() && + audioCandidate.address == videoCandidate.address + ) || + sal_media_description_get_nb_active_streams(md) == 1 + ) + strncpy(md->addr, audioCandidate.address.c_str(), sizeof(md->addr)); + } else if (md->streams[i].type == SalVideo && videoCandidate.port != 0) { + strncpy(md->streams[i].rtp_addr, videoCandidate.address.c_str(), sizeof(md->streams[i].rtp_addr)); + md->streams[i].rtp_port = videoCandidate.port; + } else if (md->streams[i].type == SalText && textCandidate.port != 0) { + strncpy(md->streams[i].rtp_addr, textCandidate.address.c_str(), sizeof(md->streams[i].rtp_addr)); + md->streams[i].rtp_port = textCandidate.port; + } + } +} + +// ----------------------------------------------------------------------------- + +ortp_socket_t StunClient::createStunSocket (int localPort) { + if (localPort < 0) + return -1; + ortp_socket_t sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) { + lError() << "Fail to create socket"; + return -1; + } + struct sockaddr_in laddr; + memset(&laddr, 0, sizeof(laddr)); + laddr.sin_family = AF_INET; + laddr.sin_addr.s_addr = INADDR_ANY; + laddr.sin_port = htons(static_cast(localPort)); + if (::bind(sock, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) { + lError() << "Bind socket to 0.0.0.0:" << localPort << " failed: " << getSocketError(); + close_socket(sock); + return -1; + } + int optval = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (SOCKET_OPTION_VALUE)&optval, sizeof(optval)) < 0) + lWarning() << "Fail to set SO_REUSEADDR"; + set_non_blocking_socket(sock); + return sock; +} + +int StunClient::recvStunResponse (ortp_socket_t sock, Candidate &candidate, int &id) { + char buf[MS_STUN_MAX_MESSAGE_SIZE]; + int len = MS_STUN_MAX_MESSAGE_SIZE; + + len = static_cast(recv(sock, buf, static_cast(len), 0)); + if (len > 0) { + struct in_addr ia; + MSStunMessage *resp = ms_stun_message_create_from_buffer_parsing((uint8_t *)buf, (ssize_t)len); + if (resp) { + UInt96 trId = ms_stun_message_get_tr_id(resp); + id = trId.octet[0]; + const MSStunAddress *stunAddr = ms_stun_message_get_xor_mapped_address(resp); + if (stunAddr) { + candidate.port = stunAddr->ip.v4.port; + ia.s_addr = htonl(stunAddr->ip.v4.addr); + } else { + stunAddr = ms_stun_message_get_mapped_address(resp); + if (stunAddr) { + candidate.port = stunAddr->ip.v4.port; + ia.s_addr = htonl(stunAddr->ip.v4.addr); + } else + len = -1; + } + if (len > 0) + candidate.address = inet_ntoa(ia); + } + } + return len; +} + +int StunClient::sendStunRequest ( + ortp_socket_t sock, + const struct sockaddr *server, + socklen_t addrlen, + int id, + bool changeAddr +) { + MSStunMessage *req = ms_stun_binding_request_create(); + UInt96 trId = ms_stun_message_get_tr_id(req); + trId.octet[0] = static_cast(id); + ms_stun_message_set_tr_id(req, trId); + ms_stun_message_enable_change_ip(req, changeAddr); + ms_stun_message_enable_change_port(req, changeAddr); + int err = 0; + char *buf = nullptr; + size_t len = ms_stun_message_encode(req, &buf); + if (len <= 0) { + lError() << "Failed to encode STUN message"; + err = -1; + } else { + err = static_cast(bctbx_sendto(sock, buf, len, 0, server, addrlen)); + if (err < 0) { + lError() << "sendto failed: " << strerror(errno); + err = -1; + } + } + if (buf) + ms_free(buf); + ms_free(req); + return err; +} + +LINPHONE_END_NAMESPACE diff --git a/src/nat/stun-client.h b/src/nat/stun-client.h new file mode 100644 index 000000000..d686ea9cb --- /dev/null +++ b/src/nat/stun-client.h @@ -0,0 +1,75 @@ +/* + * stun-client.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_STUN_CLIENT_H_ +#define _L_STUN_CLIENT_H_ + +#include + +#include + +#include "core/core.h" +#include "core/core-accessor.h" + +#include "linphone/utils/general.h" + +// ============================================================================= + +L_DECL_C_STRUCT_PREFIX_LESS(SalMediaDescription); + +LINPHONE_BEGIN_NAMESPACE + +class StunClient : public CoreAccessor { + struct Candidate { + std::string address; + int port = 0; + }; + +public: + StunClient (const std::shared_ptr &core) : CoreAccessor(core) {} + + int run (int audioPort, int videoPort, int textPort); + void updateMediaDescription (SalMediaDescription *md) const; + + const Candidate &getAudioCandidate () const { + return audioCandidate; + } + + const Candidate &getVideoCandidate () const { + return videoCandidate; + } + + const Candidate &getTextCandidate () const { + return textCandidate; + } + + ortp_socket_t createStunSocket (int localPort); + int recvStunResponse (ortp_socket_t sock, Candidate &candidate, int &id); + int sendStunRequest (ortp_socket_t sock, const struct sockaddr *server, socklen_t addrlen, int id, bool changeAddr); + +private: + Candidate audioCandidate; + Candidate videoCandidate; + Candidate textCandidate; + bool stunDiscoveryDone = false; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_STUN_CLIENT_H_ diff --git a/src/object/app-data-container.cpp b/src/object/app-data-container.cpp new file mode 100644 index 000000000..b55a5e180 --- /dev/null +++ b/src/object/app-data-container.cpp @@ -0,0 +1,81 @@ +/* + * app-data-container.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "app-data-container.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class AppDataContainerPrivate { +public: + shared_ptr> appData; +}; + +// ----------------------------------------------------------------------------- + +AppDataContainer::AppDataContainer () : mPrivate(new AppDataContainerPrivate) { + L_D(); + d->appData = make_shared>(); +} + +AppDataContainer::AppDataContainer (const AppDataContainer &other) : mPrivate(new AppDataContainerPrivate) { + L_D(); + d->appData = other.getPrivate()->appData; +} + +AppDataContainer::~AppDataContainer () { + delete mPrivate; +} + +AppDataContainer &AppDataContainer::operator= (const AppDataContainer &other) { + L_D(); + if (this != &other) + d->appData = other.getPrivate()->appData; + return *this; +} + +const unordered_map &AppDataContainer::getAppDataMap () const { + L_D(); + return *d->appData.get(); +} + +const string &AppDataContainer::getAppData (const string &name) const { + L_D(); + auto it = d->appData->find(name); + return it == d->appData->cend() ? Utils::getEmptyConstRefObject() : it->second; +} + +void AppDataContainer::setAppData (const string &name, const string &appData) { + L_D(); + (*d->appData)[name] = appData; +} + +void AppDataContainer::setAppData (const string &name, string &&appData) { + L_D(); + (*d->appData)[name] = move(appData); +} + +LINPHONE_END_NAMESPACE diff --git a/src/object/app-data-container.h b/src/object/app-data-container.h new file mode 100644 index 000000000..05641a004 --- /dev/null +++ b/src/object/app-data-container.h @@ -0,0 +1,56 @@ +/* + * app-data-container.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_APP_DATA_CONTAINER_H_ +#define _L_APP_DATA_CONTAINER_H_ + +#include +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class AppDataContainerPrivate; + +class LINPHONE_PUBLIC AppDataContainer { +public: + AppDataContainer (); + AppDataContainer (const AppDataContainer &other); + virtual ~AppDataContainer (); + + AppDataContainer &operator= (const AppDataContainer &other); + + const std::unordered_map &getAppDataMap () const; + + const std::string &getAppData (const std::string &name) const; + void setAppData (const std::string &name, const std::string &appData); + void setAppData (const std::string &name, std::string &&appData); + +private: + AppDataContainerPrivate *mPrivate = nullptr; + + L_DECLARE_PRIVATE(AppDataContainer); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_APP_DATA_CONTAINER_H_ diff --git a/src/object/base-object-p.h b/src/object/base-object-p.h new file mode 100644 index 000000000..ee1099e3a --- /dev/null +++ b/src/object/base-object-p.h @@ -0,0 +1,48 @@ +/* + * base-object-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_BASE_OBJECT_P_H_ +#define _L_BASE_OBJECT_P_H_ + +#include "linphone/utils/general.h" + +#include "object-head-p.h" +#include "utils/general-internal.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class LINPHONE_INTERNAL_PUBLIC BaseObjectPrivate { + L_OBJECT_PRIVATE; + +public: + BaseObjectPrivate () = default; + virtual ~BaseObjectPrivate () = default; + +protected: + BaseObject *mPublic = nullptr; + +private: + L_DECLARE_PUBLIC(BaseObject); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_BASE_OBJECT_P_H_ diff --git a/src/object/base-object.cpp b/src/object/base-object.cpp new file mode 100644 index 000000000..7ef6e2b22 --- /dev/null +++ b/src/object/base-object.cpp @@ -0,0 +1,39 @@ +/* + * base-object.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "base-object-p.h" +#include "base-object.h" +#include "c-wrapper/internal/c-tools.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +L_OBJECT_IMPL(BaseObject); + +BaseObject::BaseObject (BaseObjectPrivate &p) : mPrivate(&p) { + mPrivate->mPublic = this; +} + +BaseObject::~BaseObject () { + Wrapper::handleObjectDestruction(this); + delete mPrivate; +} + +LINPHONE_END_NAMESPACE diff --git a/src/object/base-object.h b/src/object/base-object.h new file mode 100644 index 000000000..cca4188ab --- /dev/null +++ b/src/object/base-object.h @@ -0,0 +1,56 @@ +/* + * base-object.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_BASE_OBJECT_H_ +#define _L_BASE_OBJECT_H_ + +#include "linphone/utils/general.h" + +#include "object-head.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class BaseObjectPrivate; + +/* + * Base Object of Linphone. Cannot be cloned. Can be Shared. + * It's the base class of Object. It's useful for lightweight entities + * like Events. + */ +class LINPHONE_PUBLIC BaseObject { + L_OBJECT; + +public: + virtual ~BaseObject (); + +protected: + explicit BaseObject (BaseObjectPrivate &p); + + BaseObjectPrivate *mPrivate = nullptr; + +private: + L_DECLARE_PRIVATE(BaseObject); + L_DISABLE_COPY(BaseObject); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_BASE_OBJECT_H_ diff --git a/src/object/clonable-object-p.h b/src/object/clonable-object-p.h index 8c099be7b..82869a328 100644 --- a/src/object/clonable-object-p.h +++ b/src/object/clonable-object-p.h @@ -1,11 +1,11 @@ /* * clonable-object-p.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,36 +13,41 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CLONABLE_OBJECT_P_H_ -#define _CLONABLE_OBJECT_P_H_ +#ifndef _L_CLONABLE_OBJECT_P_H_ +#define _L_CLONABLE_OBJECT_P_H_ -#include +#include -#include "utils/general.h" +#include "linphone/utils/general.h" + +#include "object-head-p.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE class ClonableObjectPrivate { + L_OBJECT_PRIVATE; + public: + ClonableObjectPrivate () = default; virtual ~ClonableObjectPrivate () = default; protected: - std::unordered_map *mPublic = nullptr; + std::set mPublic; private: - void ref (); - void unref (); - - int nRefs = 0; - L_DECLARE_PUBLIC(ClonableObject); + + // It's forbidden to copy directly one Clonable object private. + // To allow copy, you must define copy constructor in inherited object. + L_DISABLE_COPY(ClonableObjectPrivate); }; LINPHONE_END_NAMESPACE -#endif // ifndef _CLONABLE_OBJECT_P_H_ +#endif // ifndef _L_CLONABLE_OBJECT_P_H_ diff --git a/src/object/clonable-object.cpp b/src/object/clonable-object.cpp index 1eb46a512..5c6ce7f4a 100644 --- a/src/object/clonable-object.cpp +++ b/src/object/clonable-object.cpp @@ -1,11 +1,11 @@ /* * clonable-object.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "c-wrapper/internal/c-tools.h" #include "clonable-object-p.h" - #include "clonable-object.h" // ============================================================================= @@ -26,60 +27,42 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE -// TODO: Use atomic counter? - -void ClonableObjectPrivate::ref () { - ++nRefs; -} - -void ClonableObjectPrivate::unref () { - if (--nRefs == 0) { - delete mPublic; - delete this; - } -} - // ----------------------------------------------------------------------------- -ClonableObject::ClonableObject (ClonableObjectPrivate &p) : mPrivate(&p) { - // Q-pointer must be empty. It's a constructor that takes a new private data. - L_ASSERT(!mPrivate->mPublic); - - mPrivate->mPublic = new remove_pointermPublic)>::type; - (*mPrivate->mPublic)[mPrivate] = this; - mPrivate->ref(); -} - -ClonableObject::ClonableObject (const ClonableObjectPrivate &p) { - // Cannot access to Q-pointer. It's a copy constructor from private data. - L_ASSERT(!mPrivate); +L_OBJECT_IMPL(ClonableObject); +ClonableObject::ClonableObject (ClonableObjectPrivate &p) { setRef(p); } +#define UNREF() \ + do { \ + auto &h = mPrivate->mPublic; \ + h.erase(this); \ + if (h.empty()) \ + delete mPrivate; \ + } while (false); + ClonableObject::~ClonableObject () { - mPrivate->mPublic->erase(mPrivate); - mPrivate->unref(); + Wrapper::handleClonableObjectDestruction(this); + UNREF(); } void ClonableObject::setRef (const ClonableObjectPrivate &p) { // Q-pointer must exist if private data is defined. - L_ASSERT(!mPrivate || mPrivate->mPublic); + L_ASSERT(!mPrivate || !mPrivate->mPublic.empty()); // Nothing, same reference. if (&p == mPrivate) return; // Unref previous private data. - if (mPrivate) { - mPrivate->mPublic->erase(mPrivate); - mPrivate->unref(); - } + if (mPrivate) + UNREF(); // Add and reference new private data. mPrivate = const_cast(&p); - (*mPrivate->mPublic)[mPrivate] = this; - mPrivate->ref(); + mPrivate->mPublic.insert(this); } LINPHONE_END_NAMESPACE diff --git a/src/object/clonable-object.h b/src/object/clonable-object.h index 490c5bc71..0352ce3dd 100644 --- a/src/object/clonable-object.h +++ b/src/object/clonable-object.h @@ -1,11 +1,11 @@ /* * clonable-object.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,30 +13,44 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _CLONABLE_OBJECT_H_ -#define _CLONABLE_OBJECT_H_ +#ifndef _L_CLONABLE_OBJECT_H_ +#define _L_CLONABLE_OBJECT_H_ -#include "utils/general.h" +#include "object-head.h" +#include "property-container.h" // ============================================================================= +#define L_USE_DEFAULT_CLONABLE_OBJECT_SHARED_IMPL(CLASS) \ + CLASS::CLASS (const CLASS &other) : ClonableObject( \ + const_cast::type &>(*other.getPrivate()) \ + ) {} \ + CLASS &CLASS::operator= (const CLASS &other) { \ + if (this != &other) \ + setRef(*other.getPrivate()); \ + return *this; \ + } + LINPHONE_BEGIN_NAMESPACE -class LINPHONE_PUBLIC ClonableObject { +/* + * Clonable Object of Linphone. Generally it's just a data object with no + * intelligence. + */ +class LINPHONE_PUBLIC ClonableObject : public PropertyContainer { + L_OBJECT; + public: virtual ~ClonableObject (); protected: - // Use a new ClonableObjectPrivate without owner. explicit ClonableObject (ClonableObjectPrivate &p); - // If you want share an existing ClonableObjectPrivate, call this function. - explicit ClonableObject (const ClonableObjectPrivate &p); - - // Change the ClonableObjectPrivate, it can be shared. + // Change the ClonableObjectPrivate. Unref previous. void setRef (const ClonableObjectPrivate &p); ClonableObjectPrivate *mPrivate = nullptr; @@ -51,4 +65,4 @@ private: LINPHONE_END_NAMESPACE -#endif // ifndef _CLONABLE_OBJECT_H_ +#endif // ifndef _L_CLONABLE_OBJECT_H_ diff --git a/src/object/clonable-shared-pointer.h b/src/object/clonable-shared-pointer.h new file mode 100644 index 000000000..52c640d5c --- /dev/null +++ b/src/object/clonable-shared-pointer.h @@ -0,0 +1,156 @@ +/* + * clonable-shared-pointer.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_CLONABLE_SHARED_POINTER_H_ +#define _L_CLONABLE_SHARED_POINTER_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class SharedObject { +template +friend class ClonableSharedPointer; + +public: + int getRefCount () { + return mRefCounter; + } + +protected: + SharedObject () : mRefCounter(1) {} + + // Do not use virtual here. Avoid extra storage (little bonus). + ~SharedObject () = default; + +private: + int mRefCounter; + + L_DISABLE_COPY(SharedObject); +}; + +// ----------------------------------------------------------------------------- + +template +class ClonableSharedPointer { + static_assert(std::is_base_of::value, "T must be a inherited class of SharedObject."); + +public: + explicit ClonableSharedPointer (T *pointer = nullptr) : mPointer(pointer) {} + + ClonableSharedPointer (const ClonableSharedPointer &other) : mPointer(other.mPointer) { + ref(); + } + + ClonableSharedPointer (ClonableSharedPointer &&other) : mPointer(other.mPointer) { + other.mPointer = nullptr; + } + + ~ClonableSharedPointer () { + unref(); + } + + ClonableSharedPointer &operator= (const ClonableSharedPointer &other) { + if (mPointer != other.mPointer) { + unref(); + mPointer = other.mPointer; + ref(); + } + return *this; + } + + ClonableSharedPointer &operator= (ClonableSharedPointer &&other) { + std::swap(mPointer, other.mPointer); + return *this; + } + + bool operator== (const ClonableSharedPointer &other) const { + return mPointer == other.mPointer; + } + + bool operator!= (const ClonableSharedPointer &other) const { + return mPointer != other.mPointer; + } + + T &operator* () { + N_ASSERT(mPointer); + tryClone(); + return *mPointer; + } + + const T &operator* () const { + N_ASSERT(mPointer); + return *mPointer; + } + + T *operator-> () { + tryClone(); + return mPointer; + } + + const T *operator-> () const { + return mPointer; + } + + explicit operator bool () const { + return mPointer; + } + + bool operator! () const { + return !mPointer; + } + + T *get () { + return mPointer; + } + + const T *get () const { + return mPointer; + } + +private: + void ref () { + if (mPointer) + ++mPointer->mRefCounter; + } + + void unref () { + if (mPointer && --mPointer->mRefCounter == 0) { + delete mPointer; + mPointer = nullptr; + } + } + + void tryClone () { + if (mPointer && mPointer->mRefCounter > 1) { + T *newPointer = new T(*mPointer); + if (--mPointer->mRefCounter == 0) + delete mPointer; + mPointer = newPointer; + } + } + + T *mPointer; +}; + +LINPHONE_END_NAMESPACE + +#endif // _L_CLONABLE_SHARED_POINTER_H_ diff --git a/src/object/object-head-p.h b/src/object/object-head-p.h new file mode 100644 index 000000000..23e21cffe --- /dev/null +++ b/src/object/object-head-p.h @@ -0,0 +1,38 @@ +/* + * object-head-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_OBJECT_HEAD_P_H_ +#define _L_OBJECT_HEAD_P_H_ + +// ============================================================================= + +#define L_OBJECT_IMPL(CLASS) \ + void *CLASS::getCBackPtr () const { \ + L_D(); \ + return d->cBackPtr; \ + } \ + void CLASS::setCBackPtr (void *cBackPtr) { \ + L_D(); \ + d->cBackPtr = cBackPtr; \ + } + +#define L_OBJECT_PRIVATE \ + void *cBackPtr = nullptr; + +#endif // ifndef _L_OBJECT_HEAD_P_H_ diff --git a/src/object/object-head.h b/src/object/object-head.h new file mode 100644 index 000000000..e297bcf0a --- /dev/null +++ b/src/object/object-head.h @@ -0,0 +1,29 @@ +/* + * object-head.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_OBJECT_HEAD_H_ +#define _L_OBJECT_HEAD_H_ + +// ============================================================================= + +#define L_OBJECT \ + void *getCBackPtr () const; \ + void setCBackPtr (void *cBackPtr); + +#endif // ifndef _L_OBJECT_HEAD_H_ diff --git a/src/object/object-p.h b/src/object/object-p.h index ca9111eac..2b2d0d351 100644 --- a/src/object/object-p.h +++ b/src/object/object-p.h @@ -1,11 +1,11 @@ /* * object-p.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,29 +13,43 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _OBJECT_P_H_ -#define _OBJECT_P_H_ +#ifndef _L_OBJECT_P_H_ +#define _L_OBJECT_P_H_ -#include "utils/general.h" +#include "base-object-p.h" +#include "object.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE -class ObjectPrivate { -public: - virtual ~ObjectPrivate () = default; +#ifdef _WIN32 + // TODO: Avoid this error. + // Disable C4251 triggered by std::recursive_mutex. + #pragma warning(push) + #pragma warning(disable: 4251) +#endif // ifdef _WIN32 +class LINPHONE_INTERNAL_PUBLIC ObjectPrivate : public BaseObjectPrivate { protected: - Object *mPublic = nullptr; + inline const Object::Lock &getLock () const { + return lock; + } private: + Object::Lock lock; + L_DECLARE_PUBLIC(Object); }; +#ifdef _WIN32 + #pragma warning(pop) +#endif // ifdef _WIN32 + LINPHONE_END_NAMESPACE -#endif // ifndef _OBJECT_P_H_ +#endif // ifndef _L_OBJECT_P_H_ diff --git a/src/object/object.cpp b/src/object/object.cpp index 191337235..6c7e55fd5 100644 --- a/src/object/object.cpp +++ b/src/object/object.cpp @@ -1,11 +1,11 @@ /* * object.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,23 +13,42 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "logger/logger.h" #include "object-p.h" -#include "object.h" - // ============================================================================= +using namespace std; + LINPHONE_BEGIN_NAMESPACE -Object::~Object () { - delete mPrivate; +// ----------------------------------------------------------------------------- + +Object::Object (ObjectPrivate &p) : BaseObject(p) {} + +shared_ptr Object::getSharedFromThis () { + return const_pointer_cast(static_cast(this)->getSharedFromThis()); } -Object::Object (ObjectPrivate &p) : mPrivate(&p) { - mPrivate->mPublic = this; +shared_ptr Object::getSharedFromThis () const { + try { + return shared_from_this(); + } catch (const exception &) { + lFatal() << "Object " << this << " was not created with make_shared."; + } + + // Unable to reach this point. + L_ASSERT(false); + return nullptr; +} + +inline const Object::Lock &Object::getLock () const { + L_D(); + return d->getLock(); } LINPHONE_END_NAMESPACE diff --git a/src/object/object.h b/src/object/object.h index d3cc22808..8a313ff17 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -1,11 +1,11 @@ /* * object.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,32 +13,66 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _OBJECT_H_ -#define _OBJECT_H_ +#ifndef _L_OBJECT_H_ +#define _L_OBJECT_H_ -#include "utils/general.h" +#include + +#include "base-object.h" +#include "property-container.h" // ============================================================================= +// Must be used in Object or ObjectPrivate. +#define L_SYNC() \ + static_assert( \ + !std::is_base_of::value && !std::is_base_of::value, \ + "Unable to lock. Instance is not an Object or ObjectPrivate." \ + ); \ + const std::lock_guard synchronized(const_cast(getLock())); + LINPHONE_BEGIN_NAMESPACE -class LINPHONE_PUBLIC Object { +#ifdef _WIN32 + // TODO: Avoid this error. Maybe with a custom enabled_shared_from_this. + // Disable C4251 triggered by std::enabled_shared_from_this. + #pragma warning(push) + #pragma warning(disable: 4251) +#endif // ifdef _WIN32 + +/* + * Main Object of Linphone. Can be shared but is not Clonable. + * Supports properties and shared from this. + * Must be built with ObjectFactory. + */ +class LINPHONE_PUBLIC Object : + public std::enable_shared_from_this, + public BaseObject, + public PropertyContainer { public: - virtual ~Object (); + typedef std::recursive_mutex Lock; + + std::shared_ptr getSharedFromThis (); + std::shared_ptr getSharedFromThis () const; protected: explicit Object (ObjectPrivate &p); - ObjectPrivate *mPrivate = nullptr; + const Lock &getLock () const; private: L_DECLARE_PRIVATE(Object); L_DISABLE_COPY(Object); }; +#ifdef _WIN32 + #pragma warning(pop) +#endif // ifdef _WIN32 + LINPHONE_END_NAMESPACE -#endif // ifndef _OBJECT_H_ +#endif // ifndef _L_OBJECT_H_ diff --git a/src/object/property-container.cpp b/src/object/property-container.cpp new file mode 100644 index 000000000..dbd216ace --- /dev/null +++ b/src/object/property-container.cpp @@ -0,0 +1,76 @@ +/* + * property-container.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "property-container.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class PropertyContainerPrivate { +public: + unordered_map properties; +}; + +// ----------------------------------------------------------------------------- + +PropertyContainer::PropertyContainer () : mPrivate(nullptr) {} + +/* + * Empty copy constructor. Don't change this pattern. + * PropertyContainer is an Entity component, not a simple structure. + * An Entity is UNIQUE. + */ +PropertyContainer::PropertyContainer (const PropertyContainer &) : mPrivate(nullptr) {} + +PropertyContainer::~PropertyContainer () { + delete mPrivate; +} + +PropertyContainer &PropertyContainer::operator= (const PropertyContainer &) { + return *this; +} + +Variant PropertyContainer::getProperty (const string &name) const { + if (!mPrivate) + return Variant(); + auto &properties = mPrivate->properties; + auto it = properties.find(name); + return it == properties.cend() ? Variant() : it->second; +} + +void PropertyContainer::setProperty (const string &name, const Variant &value) { + if (!mPrivate) + mPrivate = new PropertyContainerPrivate(); + mPrivate->properties[name] = value; +} + +void PropertyContainer::setProperty (const string &name, Variant &&value) { + if (!mPrivate) + mPrivate = new PropertyContainerPrivate(); + mPrivate->properties[name] = move(value); +} + +LINPHONE_END_NAMESPACE diff --git a/src/object/property-container.h b/src/object/property-container.h new file mode 100644 index 000000000..8f9db93bb --- /dev/null +++ b/src/object/property-container.h @@ -0,0 +1,49 @@ +/* + * property-container.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PROPERTY_CONTAINER_H_ +#define _L_PROPERTY_CONTAINER_H_ + +#include "variant/variant.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class PropertyContainerPrivate; + +class LINPHONE_PUBLIC PropertyContainer { +public: + PropertyContainer (); + PropertyContainer (const PropertyContainer &other); + virtual ~PropertyContainer (); + + PropertyContainer &operator= (const PropertyContainer &other); + + Variant getProperty (const std::string &name) const; + void setProperty (const std::string &name, const Variant &value); + void setProperty (const std::string &name, Variant &&value); + +private: + PropertyContainerPrivate *mPrivate; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PROPERTY_CONTAINER_H_ diff --git a/src/object/singleton.h b/src/object/singleton.h index 667f71f9b..e2c84cd71 100644 --- a/src/object/singleton.h +++ b/src/object/singleton.h @@ -1,11 +1,11 @@ /* * singleton.h - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,11 +13,12 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef _SINGLETON_H_ -#define _SINGLETON_H_ +#ifndef _L_SINGLETON_H_ +#define _L_SINGLETON_H_ #include "object.h" @@ -26,7 +27,7 @@ LINPHONE_BEGIN_NAMESPACE template -class Singleton : public Object { +class LINPHONE_PUBLIC Singleton : public Object { public: virtual ~Singleton () = default; @@ -44,4 +45,4 @@ private: LINPHONE_END_NAMESPACE -#endif // ifndef _SINGLETON_H_ +#endif // ifndef _L_SINGLETON_H_ diff --git a/src/sal/call-op.cpp b/src/sal/call-op.cpp new file mode 100644 index 000000000..d92e4b9ec --- /dev/null +++ b/src/sal/call-op.cpp @@ -0,0 +1,1569 @@ +/* + * call-op.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "bellesip_sal/sal_impl.h" +#include "offeranswer.h" +#include "sal/call-op.h" + +#include +#include + +#include "content/content-disposition.h" +#include "content/content-type.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +SalCallOp::~SalCallOp() { + if (mLocalMedia) sal_media_description_unref(mLocalMedia); + if (mRemoteMedia) sal_media_description_unref(mRemoteMedia); +} + +int SalCallOp::setLocalMediaDescription(SalMediaDescription *desc) { + if (desc) { + sal_media_description_ref(desc); + belle_sip_error_code error; + belle_sdp_session_description_t *sdp = media_description_to_sdp(desc); + vector buffer = marshalMediaDescription(sdp, error); + if (error != BELLE_SIP_OK) return -1; + + mLocalBody.setContentType(ContentType::Sdp); + mLocalBody.setBody(move(buffer)); + } else { + mLocalBody = Content(); + } + + if (mLocalMedia) + sal_media_description_unref(mLocalMedia); + mLocalMedia=desc; + + if (mRemoteMedia){ + /*case of an incoming call where we modify the local capabilities between the time + * the call is ringing and it is accepted (for example if you want to accept without video*/ + /*reset the sdp answer so that it is computed again*/ + if (mSdpAnswer){ + belle_sip_object_unref(mSdpAnswer); + mSdpAnswer=NULL; + } + } + return 0; +} + +int SalCallOp::setLocalBody(const Content &body) { + Content bodyCopy = body; + return setLocalBody(move(bodyCopy)); +} + +int SalCallOp::setLocalBody(const Content &&body) { + if (!body.isValid()) return -1; + + if (body.getContentType() == ContentType::Sdp) { + SalMediaDescription *desc = NULL; + if (body.getSize() > 0) { + belle_sdp_session_description_t *sdp = belle_sdp_session_description_parse(body.getBodyAsString().c_str()); + if (sdp == NULL) return -1; + desc = sal_media_description_new(); + if (sdp_to_media_description(sdp, desc) != 0) { + sal_media_description_unref(desc); + return -1; + } + } + if (mLocalMedia) sal_media_description_unref(mLocalMedia); + mLocalMedia = desc; + } + + mLocalBody = body; + return 0; +} + +belle_sip_header_allow_t *SalCallOp::createAllow(bool enable_update) { + belle_sip_header_allow_t* header_allow; + char allow [256]; + snprintf(allow,sizeof(allow),"INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO%s",(enable_update?", UPDATE":"")); + header_allow = belle_sip_header_allow_create(allow); + return header_allow; +} + +int SalCallOp::setCustomBody(belle_sip_message_t *msg, const Content &body) { + ContentType contentType = body.getContentType(); + auto contentDisposition = body.getContentDisposition(); + string contentEncoding = body.getContentEncoding(); + size_t bodySize = body.getBody().size(); + + if (bodySize > SIP_MESSAGE_BODY_LIMIT) { + bctbx_error("trying to add a body greater than %lukB to message [%p]", (unsigned long)SIP_MESSAGE_BODY_LIMIT/1024, msg); + return -1; + } + + if (contentType.isValid()) { + belle_sip_header_content_type_t *content_type = belle_sip_header_content_type_create(contentType.getType().c_str(), contentType.getSubType().c_str()); + belle_sip_message_add_header(msg, BELLE_SIP_HEADER(content_type)); + } + if (contentDisposition.isValid()) { + belle_sip_header_content_disposition_t *contentDispositionHeader = belle_sip_header_content_disposition_create( + contentDisposition.asString().c_str() + ); + belle_sip_message_add_header(msg, BELLE_SIP_HEADER(contentDispositionHeader)); + } + if (!contentEncoding.empty()) + belle_sip_message_add_header(msg, belle_sip_header_create("Content-Encoding", contentEncoding.c_str())); + belle_sip_header_content_length_t *content_length = belle_sip_header_content_length_create(bodySize); + belle_sip_message_add_header(msg, BELLE_SIP_HEADER(content_length)); + + if (bodySize > 0) { + char *buffer = bctbx_new(char, bodySize + 1); + memcpy(buffer, body.getBody().data(), bodySize); + buffer[bodySize] = '\0'; + belle_sip_message_assign_body(msg, buffer, bodySize); + } + + return 0; +} + +std::vector SalCallOp::marshalMediaDescription(belle_sdp_session_description_t *session_desc, belle_sip_error_code &error) { + size_t length = 0; + size_t bufLen = 2048; + vector buff(bufLen); + error = BELLE_SIP_BUFFER_OVERFLOW; + + /* try to marshal the description. This could go higher than 2k so we iterate */ + while( error != BELLE_SIP_OK && bufLen <= SIP_MESSAGE_BODY_LIMIT) { + error = belle_sip_object_marshal(BELLE_SIP_OBJECT(session_desc),buff.data(),bufLen,&length); + if( error != BELLE_SIP_OK ){ + bufLen *= 2; + length = 0; + buff.resize(bufLen); + } + } + + /* give up if hard limit reached */ + if (error != BELLE_SIP_OK) { + ms_error("Buffer too small (%d) or not enough memory, giving up SDP", (int)bufLen); + return std::vector(); // return a new vector in order to free the buffer held by 'buff' vector + } + + buff.resize(length); + return buff; +} + +int SalCallOp::setSdp(belle_sip_message_t *msg,belle_sdp_session_description_t* session_desc) { + belle_sip_error_code error; + + if (session_desc == NULL) return -1; + + vector buff = marshalMediaDescription(session_desc, error); + if (error != BELLE_SIP_OK) return -1; + + Content body; + body.setContentType(ContentType::Sdp); + body.setBody(move(buff)); + setCustomBody(msg, body); + + return 0; +} + +int SalCallOp::setSdpFromDesc(belle_sip_message_t *msg, const SalMediaDescription *desc) { + int err; + belle_sdp_session_description_t *sdp=media_description_to_sdp(desc); + err=setSdp(msg,sdp); + belle_sip_object_unref(sdp); + return err; + +} + +void SalCallOp::fillInvite(belle_sip_request_t* invite) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(createAllow(mRoot->mEnableSipUpdate))); + if (mRoot->mSessionExpires!=0){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Session-expires", "600;refresher=uas")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),belle_sip_header_create( "Supported", "timer")); + } + mSdpOffering = (mLocalBody.getContentType() == ContentType::Sdp); + setCustomBody(BELLE_SIP_MESSAGE(invite), mLocalBody); +} + +void SalCallOp::setReleased() { + if (!mCallReleased){ + mState=State::Terminated; + mRoot->mCallbacks.call_released(this); + mCallReleased=TRUE; + /*be aware that the following line may destroy the op*/ + setOrUpdateDialog(NULL); + } +} + +void SalCallOp::processIoErrorCb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalCallOp *op = (SalCallOp *)user_ctx; + + if (op->mState == State::Terminated) return; + + if (op->mPendingClientTransaction && (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->mPendingClientTransaction)) == BELLE_SIP_TRANSACTION_INIT)) { + + sal_error_info_set(&op->mErrorInfo, SalReasonIOError, "SIP", 503, "IO error", NULL); + op->mRoot->mCallbacks.call_failure(op); + + if (!op->mDialog || belle_sip_dialog_get_state(op->mDialog) != BELLE_SIP_DIALOG_CONFIRMED){ + /* Call terminated very very early, before INVITE is even sent, probably DNS resolution timeout. */ + op->mState = State::Terminating; + op->setReleased(); + } + } else { + /* Nothing to be done. If the error comes from a connectivity loss, + * the call will be marked as broken, and an attempt to repair it will be done. */ + } +} + +void SalCallOp::cancellingInvite(const SalErrorInfo *info) { + cancelInvite(info); + mState=State::Terminating; +} + +Content SalCallOp::extractBody(belle_sip_message_t *message) { + Content body; + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(message, belle_sip_header_content_type_t); + belle_sip_header_content_disposition_t *contentDispositionHeader = belle_sip_message_get_header_by_type(message, belle_sip_header_content_disposition_t); + belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(message, belle_sip_header_content_length_t); + const char *type_str = content_type ? belle_sip_header_content_type_get_type(content_type) : NULL; + const char *subtype_str = content_type ? belle_sip_header_content_type_get_subtype(content_type) : NULL; + size_t length = content_length ? belle_sip_header_content_length_get_content_length(content_length) : 0; + const char *body_str = belle_sip_message_get_body(message); + + if (type_str && subtype_str) body.setContentType(ContentType(type_str, subtype_str)); + if (contentDispositionHeader) { + auto contentDisposition = ContentDisposition(belle_sip_header_content_disposition_get_content_disposition(contentDispositionHeader)); + if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contentDispositionHeader), "handling")) { + contentDisposition.setParameter("handling=" + string(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(contentDispositionHeader), "handling"))); + } + body.setContentDisposition(contentDisposition); + } + if (length > 0 && body_str) body.setBody(body_str, length); + return body; +} + +int SalCallOp::parseSdpBody(const Content &body,belle_sdp_session_description_t** session_desc, SalReason *error) { + *session_desc = NULL; + *error = SalReasonNone; + + if (mSdpHandling == SalOpSDPSimulateError) { + ms_error("Simulating SDP parsing error for op %p", this); + *error = SalReasonNotAcceptable; + return -1; + } + + if (mSdpHandling == SalOpSDPSimulateRemove) { + ms_error("Simulating no SDP for op %p", this); + return 0; + } + + string strBody = body.getBodyAsString(); + if (strBody.empty()) + return 0; + *session_desc = belle_sdp_session_description_parse(strBody.c_str()); + if (*session_desc == NULL) { + ms_error("Failed to parse SDP message."); + *error = SalReasonNotAcceptable; + return -1; + } + + return 0; +} + +void SalCallOp::setAddrTo0000(char value[], size_t sz) { + if (ms_is_ipv6(value)) { + strncpy(value,"::0", sz); + } else { + strncpy(value,"0.0.0.0", sz); + } + return; +} + +void SalCallOp::sdpProcess(){ + ms_message("Doing SDP offer/answer process of type %s", mSdpOffering ? "outgoing" : "incoming"); + if (mResult){ + sal_media_description_unref(mResult); + mResult = NULL; + } + + /* if SDP was invalid */ + if (mRemoteMedia == NULL) return; + + mResult=sal_media_description_new(); + if (mSdpOffering){ + offer_answer_initiate_outgoing(mRoot->mFactory, mLocalMedia,mRemoteMedia,mResult); + }else{ + int i; + if (mSdpAnswer){ + belle_sip_object_unref(mSdpAnswer); + } + offer_answer_initiate_incoming(mRoot->mFactory, mLocalMedia,mRemoteMedia,mResult,mRoot->mOneMatchingCodec); + /*for backward compatibility purpose*/ + if(mCnxIpTo0000IfSendOnlyEnabled && sal_media_description_has_dir(mResult,SalStreamSendOnly)) { + setAddrTo0000(mResult->addr, sizeof(mResult->addr)); + for(i=0;istreams[i].dir == SalStreamSendOnly) { + setAddrTo0000(mResult->streams[i].rtp_addr, sizeof(mResult->streams[i].rtp_addr)); + setAddrTo0000(mResult->streams[i].rtcp_addr, sizeof(mResult->streams[i].rtcp_addr)); + } + } + } + + mSdpAnswer=(belle_sdp_session_description_t *)belle_sip_object_ref(media_description_to_sdp(mResult)); + /*once we have generated the SDP answer, we modify the result description for processing by the upper layer. + It should contains media parameters constraint from the remote offer, not our response*/ + strcpy(mResult->addr,mRemoteMedia->addr); + mResult->bandwidth=mRemoteMedia->bandwidth; + + for(i=0;istreams[i].rtp_port!=0){ /*if stream was accepted*/ + strcpy(mResult->streams[i].rtp_addr,mRemoteMedia->streams[i].rtp_addr); + mResult->streams[i].ptime=mRemoteMedia->streams[i].ptime; + mResult->streams[i].bandwidth=mRemoteMedia->streams[i].bandwidth; + mResult->streams[i].rtp_port=mRemoteMedia->streams[i].rtp_port; + strcpy(mResult->streams[i].rtcp_addr,mRemoteMedia->streams[i].rtcp_addr); + mResult->streams[i].rtcp_port=mRemoteMedia->streams[i].rtcp_port; + + if (sal_stream_description_has_srtp(&mResult->streams[i])) { + mResult->streams[i].crypto[0] = mRemoteMedia->streams[i].crypto[0]; + } + } + } + } +} + +void SalCallOp::handleBodyFromResponse(belle_sip_response_t* response) { + SalReason reason; + belle_sdp_session_description_t* sdp = nullptr; + Content body = extractBody(BELLE_SIP_MESSAGE(response)); + if (mRemoteMedia){ + sal_media_description_unref(mRemoteMedia); + mRemoteMedia=NULL; + } + if (body.getContentType() == ContentType::Sdp) { + if (parseSdpBody(body, &sdp, &reason) == 0) { + if (sdp) { + mRemoteMedia = sal_media_description_new(); + sdp_to_media_description(sdp, mRemoteMedia); + mRemoteBody = move(body); + }/*if no sdp in response, what can we do ?*/ + } + /* process sdp in any case to reset result media description*/ + if (mLocalMedia) sdpProcess(); + } else { + mRemoteBody = move(body); + } +} + +void SalCallOp::setError(belle_sip_response_t* response, bool fatal){ + setErrorInfoFromResponse(response); + if (fatal) mState = State::Terminating; + mRoot->mCallbacks.call_failure(this); +} + +int SalCallOp::vfuRetryCb (void *user_data, unsigned int events) { + SalCallOp *op=(SalCallOp *)user_data; + op->sendVfuRequest(); + op->unref(); + return BELLE_SIP_STOP; +} + +void SalCallOp::processResponseCb(void *op_base, const belle_sip_response_event_t *event) { + SalCallOp * op = (SalCallOp *)op_base; + belle_sip_request_t* ack; + belle_sip_dialog_state_t dialog_state; + belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); + belle_sip_request_t* req; + belle_sip_response_t* response=belle_sip_response_event_get_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); + return; + } + req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + op->setOrUpdateDialog(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)); + /*to make sure no cb will destroy op*/ + op->ref(); + switch(dialog_state) { + case BELLE_SIP_DIALOG_NULL: + case BELLE_SIP_DIALOG_EARLY: { + if (strcmp("INVITE",method)==0 ) { + if (op->mState == State::Terminating) { + /*check if CANCEL was sent before*/ + if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->mPendingClientTransaction))))!=0) { + /*it wasn't sent */ + if (code<200) { + op->cancellingInvite(NULL); + }else{ + /* no need to send the INVITE because the UAS rejected the INVITE*/ + if (op->mDialog==NULL) op->setReleased(); + } + } else { + /*it was sent already, so just expect the 487 or any error response to send the call_released() notification*/ + if (code>=300){ + if (op->mDialog==NULL) op->setReleased(); + } + } + } else if (code >= 180 && code<200) { + belle_sip_response_t *prev_response=reinterpret_cast(belle_sip_object_data_get(BELLE_SIP_OBJECT(dialog),"early_response")); + if (!prev_response || code>belle_sip_response_get_status_code(prev_response)){ + op->handleBodyFromResponse(response); + op->mRoot->mCallbacks.call_ringing(op); + } + belle_sip_object_data_set(BELLE_SIP_OBJECT(dialog),"early_response",belle_sip_object_ref(response),belle_sip_object_unref); + } else if (code>=300){ + op->setError(response, TRUE); + if (op->mDialog==NULL) op->setReleased(); + } + } else if (code >=200 && code<300) { + if (strcmp("UPDATE",method)==0) { + op->handleBodyFromResponse(response); + op->mRoot->mCallbacks.call_accepted(op); + } else if (strcmp("CANCEL", method) == 0) { + op->mRoot->mCallbacks.call_cancel_done(op); + } + } + } + break; + case BELLE_SIP_DIALOG_CONFIRMED: { + switch (op->mState) { + case State::Early:/*invite case*/ + case State::Active: /*re-invite, INFO, UPDATE case*/ + if (strcmp("INVITE",method)==0){ + if (code >=200 && code<300) { + op->handleBodyFromResponse(response); + ack=belle_sip_dialog_create_ack(op->mDialog,belle_sip_dialog_get_local_seq_number(op->mDialog)); + if (ack == NULL) { + ms_error("This call has been already terminated."); + return ; + } + if (op->mSdpAnswer){ + setSdp(BELLE_SIP_MESSAGE(ack),op->mSdpAnswer); + belle_sip_object_unref(op->mSdpAnswer); + op->mSdpAnswer=NULL; + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(ack),BELLE_SIP_HEADER(op->mRoot->mUserAgentHeader)); + op->mRoot->mCallbacks.call_accepted(op); /*INVITE*/ + op->mRoot->mCallbacks.call_ack_being_sent(op, (SalCustomHeader*)ack); + belle_sip_dialog_send_ack(op->mDialog,ack); + op->mState=State::Active; + }else if (code >= 300){ + op->setError(response, FALSE); + } + }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) { + unsigned int retry_in = rand() % 1001; // [0;1000] + belle_sip_source_t *s=op->mRoot->createTimer(vfuRetryCb,op->ref(), retry_in, "vfu request retry"); + ms_message("Rejected vfu request on op [%p], just retry in [%u] ms",op,retry_in); + belle_sip_object_unref(s); + }else { + /*ignoring*/ + } + }else if (strcmp("UPDATE",method)==0){ + op->mRoot->mCallbacks.call_accepted(op); /*INVITE*/ + }else if (strcmp("CANCEL",method)==0){ + op->mRoot->mCallbacks.call_cancel_done(op); + } + break; + case State::Terminating: + op->sendRequest(belle_sip_dialog_create_request(op->mDialog,"BYE")); + break; + case State::Terminated: + default: + lError() << "Call op [" << op << "] receives unexpected answer [" << code << "] while in state [" << toString(op->mState) << "]"; + } + } + break; + case BELLE_SIP_DIALOG_TERMINATED: { + if ((code >= 300) + && ((strcmp("INVITE", method) == 0) || (strcmp("BYE", method) == 0)) + ) { + op->setError(response, TRUE); + } + } + break; + default: { + ms_error("call op [%p] receive answer [%i] not implemented",op,code); + } + break; + } + op->unref(); +} + +void SalCallOp::processTimeoutCb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalCallOp * op=(SalCallOp *)user_ctx; + + if (op->mState==State::Terminated) return; + + if (!op->mDialog) { + /*call terminated very early*/ + sal_error_info_set(&op->mErrorInfo, SalReasonRequestTimeout, "SIP", 408, "Request timeout", NULL); + op->mRoot->mCallbacks.call_failure(op); + op->mState = State::Terminating; + op->setReleased(); + } else { + /*dialog will terminated shortly, nothing to do*/ + } +} + +void SalCallOp::processTransactionTerminatedCb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { + SalCallOp * op = (SalCallOp *)user_ctx; + belle_sip_client_transaction_t *client_transaction=belle_sip_transaction_terminated_event_get_client_transaction(event); + belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event); + belle_sip_request_t* req; + belle_sip_response_t* resp; + int code = 0; + bool release_call = false; + + if (client_transaction) { + req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction)); + } else { + req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); + resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(server_transaction)); + } + if (resp) code = belle_sip_response_get_status_code(resp); + + if (op->mState == State::Terminating + && strcmp("BYE",belle_sip_request_get_method(req))==0 + && (!resp || (belle_sip_response_get_status_code(resp) != 401 + && belle_sip_response_get_status_code(resp) != 407)) + && op->mDialog==NULL) { + release_call=true; + }else if (op->mState == State::Early && code < 200){ + /*call terminated early*/ + sal_error_info_set(&op->mErrorInfo, SalReasonIOError, "SIP", 503, "I/O error", NULL); + op->mState = State::Terminating; + op->mRoot->mCallbacks.call_failure(op); + release_call=true; + } + if (server_transaction){ + if (op->mPendingServerTransaction==server_transaction){ + belle_sip_object_unref(op->mPendingServerTransaction); + op->mPendingServerTransaction=NULL; + } + if (op->mPendingUpdateServerTransaction==server_transaction){ + belle_sip_object_unref(op->mPendingUpdateServerTransaction); + op->mPendingUpdateServerTransaction=NULL; + } + } + if (release_call) op->setReleased(); +} + +int SalCallOp::isMediaDescriptionAcceptable(SalMediaDescription *md) { + if (md->nb_streams==0){ + ms_warning("Media description does not define any stream."); + return FALSE; + } + return TRUE; +} + +SalReason SalCallOp::processBodyForInvite(belle_sip_request_t* invite) { + SalReason reason = SalReasonNone; + + Content body = extractBody(BELLE_SIP_MESSAGE(invite)); + if (!body.isValid()) return SalReasonUnsupportedContent; + + if ((body.getContentType() == ContentType::Sdp) || (body.getContentType().isEmpty() && body.isEmpty())) { + belle_sdp_session_description_t* sdp; + if (parseSdpBody(body, &sdp, &reason) == 0) { + if (sdp) { + mSdpOffering = FALSE; + if (mRemoteMedia) sal_media_description_unref(mRemoteMedia); + mRemoteMedia = sal_media_description_new(); + sdp_to_media_description(sdp, mRemoteMedia); + /*make some sanity check about the SDP received*/ + if (!isMediaDescriptionAcceptable(mRemoteMedia)) { + reason = SalReasonNotAcceptable; + } + belle_sip_object_unref(sdp); + } else mSdpOffering = TRUE; /*INVITE without SDP*/ + } + if (reason != SalReasonNone) { + SalErrorInfo sei; + memset(&sei, 0, sizeof(sei)); + sal_error_info_set(&sei, reason, "SIP", 0, NULL, NULL); + declineWithErrorInfo(&sei, NULL); + sal_error_info_reset(&sei); + } + } + mRemoteBody = move(body); + return reason; +} + +SalReason SalCallOp::processBodyForAck(belle_sip_request_t *ack) { + SalReason reason = SalReasonNone; + Content body = extractBody(BELLE_SIP_MESSAGE(ack)); + if (!body.isValid()) return SalReasonUnsupportedContent; + if (body.getContentType() == ContentType::Sdp) { + belle_sdp_session_description_t *sdp; + if (parseSdpBody(body, &sdp, &reason) == 0) { + if (sdp) { + if (mRemoteMedia) sal_media_description_unref(mRemoteMedia); + mRemoteMedia = sal_media_description_new(); + sdp_to_media_description(sdp, mRemoteMedia); + sdpProcess(); + belle_sip_object_unref(sdp); + } else { + ms_warning("SDP expected in ACK but not found."); + } + } + } + mRemoteBody = move(body); + return reason; +} + +void SalCallOp::callTerminated(belle_sip_server_transaction_t* server_transaction, int status_code, belle_sip_request_t* cancel_request) { + belle_sip_response_t* resp; + belle_sip_request_t* server_req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)); + mState = State::Terminating; + setReasonErrorInfo(BELLE_SIP_MESSAGE(cancel_request ? cancel_request : server_req)); + resp=createResponseFromRequest(server_req,status_code); + belle_sip_server_transaction_send_response(server_transaction,resp); + mRoot->mCallbacks.call_terminated(this,mDir==Dir::Incoming?getFrom().c_str():getTo().c_str()); +} + +void SalCallOp::resetDescriptions() { + if (mRemoteMedia){ + sal_media_description_unref(mRemoteMedia); + mRemoteMedia=NULL; + } + if (mResult){ + sal_media_description_unref(mResult); + mResult=NULL; + } +} + +void SalCallOp::unsupportedMethod(belle_sip_server_transaction_t* server_transaction,belle_sip_request_t* request) { + belle_sip_response_t* resp; + resp=belle_sip_response_create_from_request(request,501); + belle_sip_server_transaction_send_response(server_transaction,resp); +} + +bool SalCallOp::isAPendingIncomingInviteTransaction(belle_sip_transaction_t *tr){ + return BELLE_SIP_OBJECT_IS_INSTANCE_OF(tr, belle_sip_ist_t) && belle_sip_transaction_state_is_transient( + belle_sip_transaction_get_state(tr)); +} + +void SalCallOp::processRequestEventCb(void *op_base, const belle_sip_request_event_t *event) { + SalCallOp * op = (SalCallOp *)op_base; + SalReason reason; + belle_sip_server_transaction_t* server_transaction=NULL; + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_state_t dialog_state; + belle_sip_response_t* resp; + belle_sip_header_t* call_info; + const char *method=belle_sip_request_get_method(req); + bool is_update = false; + bool drop_op = false; + + if (strcmp("ACK",method)!=0){ /*ACK doesn't create a server transaction*/ + server_transaction = belle_sip_provider_create_server_transaction(op->mRoot->mProvider,belle_sip_request_event_get_request(event)); + belle_sip_object_ref(server_transaction); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),op->ref()); + } + + if (strcmp("INVITE",method)==0) { + if (op->mPendingServerTransaction) belle_sip_object_unref(op->mPendingServerTransaction); + /*updating pending invite transaction*/ + op->mPendingServerTransaction=server_transaction; + belle_sip_object_ref(op->mPendingServerTransaction); + } + + if (strcmp("UPDATE",method)==0) { + if (op->mPendingUpdateServerTransaction) belle_sip_object_unref(op->mPendingUpdateServerTransaction); + /*updating pending update transaction*/ + op->mPendingUpdateServerTransaction=server_transaction; + belle_sip_object_ref(op->mPendingUpdateServerTransaction); + } + + if (!op->mDialog) { + op->setOrUpdateDialog(belle_sip_provider_create_dialog(op->mRoot->mProvider, BELLE_SIP_TRANSACTION(op->mPendingServerTransaction))); + ms_message("new incoming call from [%s] to [%s]",op->getFrom().c_str(),op->getTo().c_str()); + } + dialog_state=belle_sip_dialog_get_state(op->mDialog); + switch(dialog_state) { + case BELLE_SIP_DIALOG_NULL: { + if (strcmp("INVITE",method)==0) { + if (!op->mReplaces && (op->mReplaces=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_replaces_t))) { + belle_sip_object_ref(op->mReplaces); + } else if(op->mReplaces) { + ms_warning("replace header already set"); + } + + if ( (reason = op->processBodyForInvite(req)) == SalReasonNone) { + if ((call_info=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Call-Info"))) { + if( strstr(belle_sip_header_get_unparsed_value(call_info),"answer-after=") != NULL) { + op->mAutoAnswerAsked=TRUE; + ms_message("The caller asked to automatically answer the call(Emergency?)\n"); + } + } + op->mRoot->mCallbacks.call_received(op); + }else{ + sal_error_info_set(&op->mErrorInfo, reason, "SIP", 0, NULL, NULL); + op->mRoot->mCallbacks.call_rejected(op); + /*the INVITE was declined by process_sdp_for_invite(). As we are not inside an established dialog, we can drop the op immediately*/ + drop_op = true; + } + break; + }BCTBX_NO_BREAK; /* else same behavior as for EARLY state, thus NO BREAK*/ + } + case BELLE_SIP_DIALOG_EARLY: { + if (strcmp("CANCEL",method)==0) { + if(belle_sip_request_event_get_server_transaction(event)) { + /*first answer 200 ok to cancel*/ + belle_sip_server_transaction_send_response(server_transaction + ,op->createResponseFromRequest(req,200)); + /*terminate invite transaction*/ + op->callTerminated(op->mPendingServerTransaction,487,req); + } else { + /*call leg does not exist*/ + belle_sip_server_transaction_send_response(server_transaction + ,op->createResponseFromRequest(req,481)); + } + } else if (strcmp("PRACK",method)==0) { + resp=op->createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else if (strcmp("UPDATE",method)==0) { + op->resetDescriptions(); + if (op->processBodyForInvite(req)==SalReasonNone) + op->mRoot->mCallbacks.call_updating(op,TRUE); + } else { + belle_sip_error("Unexpected method [%s] for dialog state BELLE_SIP_DIALOG_EARLY",belle_sip_request_get_method(req)); + unsupportedMethod(server_transaction,req); + } + break; + } + case BELLE_SIP_DIALOG_CONFIRMED: + /*great ACK received*/ + if (strcmp("ACK",method)==0) { + if (!op->mPendingClientTransaction || + !belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state((belle_sip_transaction_t*)op->mPendingClientTransaction))){ + if (op->mSdpOffering){ + op->processBodyForAck(req); + } + op->mRoot->mCallbacks.call_ack_received(op, (SalCustomHeader*)req); + }else{ + ms_message("Ignored received ack since a new client transaction has been started since."); + } + } else if(strcmp("BYE",method)==0) { + op->callTerminated(server_transaction,200,req); + /*call end not notified by dialog deletion because transaction can end before dialog*/ + } 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=op->createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + belle_sip_object_unref(op->mPendingUpdateServerTransaction); + op->mPendingUpdateServerTransaction=NULL; + } else { + /*re-invite*/ + op->resetDescriptions(); + if (op->processBodyForInvite(req)==SalReasonNone) + op->mRoot->mCallbacks.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")) { + /*vfu request*/ + ms_message("Receiving VFU request on op [%p]",op); + if (op->mRoot->mCallbacks.vfu_request){ + op->mRoot->mCallbacks.vfu_request(op); + + } + }else{ + belle_sip_message_t *msg = BELLE_SIP_MESSAGE(req); + belle_sip_body_handler_t *body_handler = BELLE_SIP_BODY_HANDLER(op->getBodyHandler(msg)); + if (body_handler) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + if (content_type + && (strcmp(belle_sip_header_content_type_get_type(content_type), "application") == 0) + && (strcmp(belle_sip_header_content_type_get_subtype(content_type), "dtmf-relay") == 0)) { + char tmp[10]; + if (sal_lines_get_value(belle_sip_message_get_body(msg), "Signal",tmp, sizeof(tmp))){ + op->mRoot->mCallbacks.dtmf_received(op,tmp[0]); + } + }else + op->mRoot->mCallbacks.info_received(op, (SalBodyHandler *)body_handler); + } else { + op->mRoot->mCallbacks.info_received(op,NULL); + } + } + resp=op->createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + }else if (strcmp("REFER",method)==0) { + op->processRefer(event,server_transaction); + } else if (strcmp("NOTIFY",method)==0) { + op->processNotify(event,server_transaction); + } else if (strcmp("OPTIONS",method)==0) { + resp=op->createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else if (strcmp("CANCEL",method)==0) { + belle_sip_transaction_t *last_transaction = belle_sip_dialog_get_last_transaction(op->mDialog); + if (last_transaction == NULL || !isAPendingIncomingInviteTransaction(last_transaction) ) { + /*call leg does not exist because 200ok already sent*/ + belle_sip_server_transaction_send_response(server_transaction,op->createResponseFromRequest(req,481)); + } else { + /* CANCEL on re-INVITE for which a 200ok has not been sent yet */ + belle_sip_server_transaction_send_response(server_transaction, op->createResponseFromRequest(req, 200)); + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(last_transaction), + op->createResponseFromRequest(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_transaction)), 487)); + } + } else if (strcmp("MESSAGE",method)==0){ + op->processIncomingMessage(event); + }else{ + ms_error("unexpected method [%s] for dialog [%p]",belle_sip_request_get_method(req),op->mDialog); + unsupportedMethod(server_transaction,req); + } + break; + default: + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + break; + } + + if (server_transaction) belle_sip_object_unref(server_transaction); + if (drop_op) op->release(); +} + +void SalCallOp::setCallAsReleased(SalCallOp *op) { + op->setReleased(); +} + +void SalCallOp::processDialogTerminatedCb(void *ctx, const belle_sip_dialog_terminated_event_t *event) { + SalCallOp * op=(SalCallOp *)ctx; + + if (op->mDialog && op->mDialog==belle_sip_dialog_terminated_event_get_dialog(event)) { + /*belle_sip_transaction_t* trans=belle_sip_dialog_get_last_transaction(op->dialog);*/ + ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op); + + switch(belle_sip_dialog_get_previous_state(op->mDialog)) { + case BELLE_SIP_DIALOG_EARLY: + case BELLE_SIP_DIALOG_NULL: + if (op->mState!=State::Terminated && op->mState!=State::Terminating) { + /*this is an early termination due to incorrect response received*/ + op->mRoot->mCallbacks.call_failure(op); + op->mState=State::Terminating; + } + break; + case BELLE_SIP_DIALOG_CONFIRMED: + if (op->mState!=State::Terminated && op->mState!=State::Terminating) { + /*this is probably a normal termination from a BYE*/ + op->mRoot->mCallbacks.call_terminated(op,op->mDir==Dir::Incoming?op->getFrom().c_str():op->getTo().c_str()); + op->mState=State::Terminating; + } + break; + default: + break; + } + belle_sip_main_loop_do_later(belle_sip_stack_get_main_loop(op->mRoot->mStack) + ,(belle_sip_callback_t) setCallAsReleased + , op); + } else { + ms_error("dialog unknown for op "); + } +} + +void SalCallOp::fillCallbacks() { + static belle_sip_listener_callbacks_t call_op_callbacks = {0}; + if (call_op_callbacks.process_response_event==NULL){ + call_op_callbacks.process_io_error=processIoErrorCb; + call_op_callbacks.process_response_event=processResponseCb; + call_op_callbacks.process_timeout=processTimeoutCb; + call_op_callbacks.process_transaction_terminated=processTransactionTerminatedCb; + call_op_callbacks.process_request_event=processRequestEventCb; + call_op_callbacks.process_dialog_terminated=processDialogTerminatedCb; + } + mCallbacks=&call_op_callbacks; + mType=Type::Call; +} + +int SalCallOp::call(const char *from, const char *to, const char *subject) { + belle_sip_request_t* invite; + mDir=Dir::Outgoing; + + setFrom(from); + setTo(to); + + ms_message("[%s] calling [%s] on op [%p]", from, to, this); + invite=buildRequest("INVITE"); + + if( invite == NULL ){ + /* can happen if the op has an invalid address */ + return -1; + } + + fillInvite(invite); + if (subject) belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite), belle_sip_header_create("Subject", subject)); + + fillCallbacks(); + if (mReplaces){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(mReplaces)); + } + if (mReferredBy) + belle_sip_message_add_header(BELLE_SIP_MESSAGE(invite),BELLE_SIP_HEADER(mReferredBy)); + + return sendRequest(invite); +} + +int SalCallOp::notifyRinging(bool early_media){ + int status_code =early_media?183:180; + belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(mPendingServerTransaction)); + belle_sip_response_t* ringing_response = createResponseFromRequest(req,status_code); + belle_sip_header_t *require; + const char *tags=NULL; + + if (early_media) + handleOfferAnswerResponse(ringing_response); + require=belle_sip_message_get_header((belle_sip_message_t*)req,"Require"); + if (require) tags=belle_sip_header_get_unparsed_value(require); + /* if client requires 100rel, then add necessary stuff*/ + if (tags && strstr(tags,"100rel")!=0) { + belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("Require","100rel")); + belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("RSeq","1")); + } + +#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING + if (tags && strstr(tags,"100rel")!=0) +#endif + { + belle_sip_header_address_t* contact= (belle_sip_header_address_t*)getContactAddress(); + belle_sip_header_contact_t* contact_header; + if (contact && (contact_header=belle_sip_header_contact_create(contact))) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header)); + } + } + belle_sip_server_transaction_send_response(mPendingServerTransaction,ringing_response); + return 0; +} + +int SalCallOp::accept() { + belle_sip_response_t *response; + belle_sip_header_contact_t* contact_header; + belle_sip_server_transaction_t* transaction; + + /*first check if an UPDATE transaction need to be accepted*/ + if (mPendingUpdateServerTransaction) { + transaction= mPendingUpdateServerTransaction; + } else if (mPendingServerTransaction) { + /*so it must be an invite/re-invite*/ + transaction= mPendingServerTransaction; + } else { + ms_error("No transaction to accept for op [%p]", this); + return -1; + } + ms_message("Accepting server transaction [%p] on op [%p]", transaction, this); + + /* sends a 200 OK */ + response = createResponseFromRequest(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(transaction)),200); + if (response==NULL){ + ms_error("Fail to build answer for call"); + return -1; + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(createAllow(mRoot->mEnableSipUpdate))); + if (mRoot->mSessionExpires!=0){ +/* if (h->supports_session_timers) {*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Session-expires", "600;refresher=uac")); + /*}*/ + } + + if ((contact_header=createContact())) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header)); + } + + addCustomHeaders(BELLE_SIP_MESSAGE(response)); + + handleOfferAnswerResponse(response); + + belle_sip_server_transaction_send_response(transaction,response); + if (mPendingUpdateServerTransaction) { + belle_sip_object_unref(mPendingUpdateServerTransaction); + mPendingUpdateServerTransaction=NULL; + } + if (mState == State::Early){ + mState = State::Active; + } + return 0; +} + +int SalCallOp::decline(SalReason reason, const char *redirection){ + belle_sip_response_t* response; + belle_sip_header_contact_t* contact=NULL; + int status=to_sip_code(reason); + belle_sip_transaction_t *trans; + + if (reason==SalReasonRedirect){ + if (redirection!=NULL) { + if (strstr(redirection,"sip:")!=0) status=302; + else status=380; + contact= belle_sip_header_contact_new(); + belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); + } else { + ms_error("Cannot redirect to null"); + } + } + trans=(belle_sip_transaction_t*)mPendingServerTransaction; + if (!trans) trans=(belle_sip_transaction_t*)mPendingUpdateServerTransaction; + if (!trans){ + ms_error("sal_call_decline(): no pending transaction to decline."); + return -1; + } + response = createResponseFromRequest(belle_sip_transaction_get_request(trans),status); + if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); + return 0; +} + +belle_sip_header_reason_t *SalCallOp::makeReasonHeader( const SalErrorInfo *info){ + if (info && info->reason != SalReasonNone) { + belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); + belle_sip_header_reason_set_text(reason, info->status_string); + belle_sip_header_reason_set_protocol(reason,info->protocol); + belle_sip_header_reason_set_cause(reason,info->protocol_code); + return reason; + } + return NULL; +} + +int SalCallOp::declineWithErrorInfo(const SalErrorInfo *info, const SalAddress *redirectionAddr){ + belle_sip_response_t* response; + belle_sip_header_contact_t* contact=NULL; + int status = info->protocol_code; + belle_sip_transaction_t *trans; + + if (info->reason==SalReasonRedirect){ + if (redirectionAddr) { + status = 302; + contact = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(redirectionAddr)); + } else { + ms_error("Cannot redirect to null"); + } + } + trans=(belle_sip_transaction_t*)mPendingServerTransaction; + if (!trans) trans=(belle_sip_transaction_t*)mPendingUpdateServerTransaction; + if (!trans){ + ms_error("sal_call_decline_with_error_info(): no pending transaction to decline."); + return -1; + } + response = createResponseFromRequest(belle_sip_transaction_get_request(trans),status); + belle_sip_header_reason_t* reason_header = makeReasonHeader(info->sub_sei); + if (reason_header) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(reason_header)); + } + + if (contact) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); + } + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); + return 0; +} + +int SalCallOp::update(const char *subject, bool no_user_consent) { + belle_sip_request_t *update; + belle_sip_dialog_state_t state; + + if (mDialog == NULL) { + /* If the dialog does not exist, this is that we are trying to recover from a connection loss + during a very early state of outgoing call initiation (the dialog has not been created yet). */ + return call(mFrom.c_str(), mTo.c_str(), subject); + } + + state = belle_sip_dialog_get_state(mDialog); + belle_sip_dialog_enable_pending_trans_checking(mDialog,mRoot->mPendingTransactionChecking); + + /*check for dialog state*/ + if ( state == BELLE_SIP_DIALOG_CONFIRMED) { + if (no_user_consent) + update=belle_sip_dialog_create_request(mDialog,"UPDATE"); + else + update=belle_sip_dialog_create_request(mDialog,"INVITE"); + } else if (state == BELLE_SIP_DIALOG_EARLY) { + update=belle_sip_dialog_create_request(mDialog,"UPDATE"); + } else { + ms_error("Cannot update op [%p] with dialog [%p] in state [%s]", this, mDialog,belle_sip_dialog_state_to_string(state)); + return -1; + } + if (update){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(update),belle_sip_header_create( "Subject", subject)); + fillInvite(update); + return sendRequest(update); + } + /*it failed why ?*/ + if (belle_sip_dialog_request_pending(mDialog)) + sal_error_info_set(&mErrorInfo,SalReasonRequestPending, "SIP", 491,NULL,NULL); + else + sal_error_info_set(&mErrorInfo,SalReasonUnknown, "SIP", 500,NULL,NULL); + return -1; +} + +int SalCallOp::cancelInvite(const SalErrorInfo *info) { + belle_sip_request_t* cancel; + ms_message("Cancelling INVITE request from [%s] to [%s] ",getFrom().c_str(), getTo().c_str()); + + if (mPendingClientTransaction == NULL) { + ms_warning("There is no transaction to cancel."); + return -1; + } + + cancel = belle_sip_client_transaction_create_cancel(mPendingClientTransaction); + if (cancel) { + if (info && info->reason != SalReasonNone) { + belle_sip_header_reason_t* reason = makeReasonHeader(info); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(cancel),BELLE_SIP_HEADER(reason)); + } + sendRequest(cancel); + return 0; + } else if (mDialog) { + belle_sip_dialog_state_t state = belle_sip_dialog_get_state(mDialog);; + /*case where the response received is invalid (could not establish a dialog), but the transaction is not cancellable + * because already terminated*/ + switch(state) { + case BELLE_SIP_DIALOG_EARLY: + case BELLE_SIP_DIALOG_NULL: + /*force kill the dialog*/ + ms_warning("op [%p]: force kill of dialog [%p]", this, mDialog); + belle_sip_dialog_delete(mDialog); + break; + default: + break; + } + } + return -1; +} + +SalMediaDescription *SalCallOp::getFinalMediaDescription() { + if (mLocalMedia && mRemoteMedia && !mResult){ + sdpProcess(); + } + return mResult; +} + +int SalCallOp::referTo(belle_sip_header_refer_to_t* refer_to, belle_sip_header_referred_by_t* referred_by) { + char* tmp; + belle_sip_request_t* req=mDialog?belle_sip_dialog_create_request(mDialog,"REFER"):buildRequest("REFER"); + if (!req) { + tmp=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to))); + ms_error("Cannot refer to [%s] for op [%p]",tmp, this); + belle_sip_free(tmp); + return -1; + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(refer_to)); + if (referred_by) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(referred_by)); + return sendRequest(req); +} + +int SalCallOp::refer(const char *refer_to_){ + belle_sip_header_address_t *referred_by; + belle_sip_header_refer_to_t* refer_to_header; + if (mDialog) { + referred_by=(belle_sip_header_address_t*)belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_dialog_get_local_party(mDialog))); + }else{ + referred_by=BELLE_SIP_HEADER_ADDRESS(getFromAddress()); + } + refer_to_header=belle_sip_header_refer_to_create(belle_sip_header_address_parse(refer_to_)); + + return referTo(refer_to_header,belle_sip_header_referred_by_create(referred_by)); +} + +int SalCallOp::referWithReplaces(SalCallOp *other_call_op) { + belle_sip_dialog_state_t other_call_dialog_state=other_call_op->mDialog?belle_sip_dialog_get_state(other_call_op->mDialog):BELLE_SIP_DIALOG_NULL; + belle_sip_dialog_state_t op_dialog_state= mDialog?belle_sip_dialog_get_state(mDialog):BELLE_SIP_DIALOG_NULL; + belle_sip_header_replaces_t* replaces; + belle_sip_header_refer_to_t* refer_to_; + belle_sip_header_referred_by_t* referred_by; + const char* from_tag; + const char* to_tag; + char* escaped_replaces; + /*first, build refer to*/ + if ((other_call_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) && (other_call_dialog_state!=BELLE_SIP_DIALOG_EARLY)) { + ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED or BELE_SIP_DIALOG_EARLY", + belle_sip_dialog_state_to_string(other_call_dialog_state), + other_call_op); + return -1; + } + if (op_dialog_state!=BELLE_SIP_DIALOG_CONFIRMED) { + ms_error("wrong dialog state [%s] for op [%p], should be BELLE_SIP_DIALOG_CONFIRMED", + belle_sip_dialog_state_to_string(op_dialog_state), + this); + return -1; + } + + refer_to_ =belle_sip_header_refer_to_create(belle_sip_dialog_get_remote_party(other_call_op->mDialog)); + belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(refer_to_)); + /*rfc3891 + ... + 4. User Agent Client Behavior: Sending a Replaces Header + + A User Agent that wishes to replace a single existing early or + confirmed dialog with a new dialog of its own, MAY send the target + User Agent an INVITE request containing a Replaces header field. The + User Agent Client (UAC) places the Call-ID, to-tag, and from-tag + information for the target dialog in a single Replaces header field + and sends the new INVITE to the target.*/ + from_tag=belle_sip_dialog_get_local_tag(other_call_op->mDialog); + to_tag=belle_sip_dialog_get_remote_tag(other_call_op->mDialog); + + replaces=belle_sip_header_replaces_create(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(other_call_op->mDialog)) + ,from_tag,to_tag); + escaped_replaces=belle_sip_header_replaces_value_to_escaped_string(replaces); + belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to_)),"Replaces",escaped_replaces); + belle_sip_free(escaped_replaces); + referred_by=belle_sip_header_referred_by_create(belle_sip_dialog_get_local_party(mDialog)); + belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(referred_by)); + return referTo(refer_to_,referred_by); +} + +int SalCallOp::setReferrer(SalCallOp *refered_call){ + if (refered_call->mReplaces) + SalOp::setReplaces(refered_call->mReplaces); + if (refered_call->mReferredBy) + setReferredBy(refered_call->mReferredBy); + return 0; +} + +SalCallOp *SalCallOp::getReplaces() const { + if (mReplaces){ + /*rfc3891 + 3. User Agent Server Behavior: Receiving a Replaces Header + + The Replaces header contains information used to match an existing + SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE + with a Replaces header, the User Agent (UA) attempts to match this + information with a confirmed or early dialog. The User Agent Server + (UAS) matches the to-tag and from-tag parameters as if they were tags + present in an incoming request. In other words, the to-tag parameter + is compared to the local tag, and the from-tag parameter is compared + to the remote tag. + */ + belle_sip_dialog_t* dialog=belle_sip_provider_find_dialog(mRoot->mProvider + ,belle_sip_header_replaces_get_call_id(mReplaces) + ,belle_sip_header_replaces_get_to_tag(mReplaces) + ,belle_sip_header_replaces_get_from_tag(mReplaces)); + + if (!dialog) { + /*for backward compatibility with liblinphone <= 3.10.2-243 */ + dialog=belle_sip_provider_find_dialog(mRoot->mProvider + ,belle_sip_header_replaces_get_call_id(mReplaces) + ,belle_sip_header_replaces_get_from_tag(mReplaces) + ,belle_sip_header_replaces_get_to_tag(mReplaces)); + } + if (dialog) { + return (SalCallOp*)belle_sip_dialog_get_application_data(dialog); + } + } + return NULL; +} + +int SalCallOp::sendDtmf(char dtmf){ + if (mDialog && (belle_sip_dialog_get_state(mDialog) == BELLE_SIP_DIALOG_CONFIRMED || belle_sip_dialog_get_state(mDialog) == BELLE_SIP_DIALOG_EARLY)){ + belle_sip_request_t *req=belle_sip_dialog_create_queued_request(mDialog,"INFO"); + if (req){ + size_t bodylen; + char dtmf_body[128]={0}; + + snprintf(dtmf_body, sizeof(dtmf_body)-1, "Signal=%c\r\nDuration=250\r\n", dtmf); + bodylen=strlen(dtmf_body); + belle_sip_message_set_body((belle_sip_message_t*)req,dtmf_body,bodylen); + belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_length_create(bodylen)); + belle_sip_message_add_header((belle_sip_message_t*)req,(belle_sip_header_t*)belle_sip_header_content_type_create("application", "dtmf-relay")); + sendRequest(req); + }else ms_error("sal_call_send_dtmf(): could not build request"); + }else ms_error("sal_call_send_dtmf(): no dialog"); + return 0; +} + +int SalCallOp::terminate(const SalErrorInfo *info) { + SalErrorInfo sei; + const SalErrorInfo *p_sei; + belle_sip_dialog_state_t dialog_state = mDialog ? belle_sip_dialog_get_state(mDialog) : BELLE_SIP_DIALOG_NULL; + int ret = 0; + + memset(&sei, 0, sizeof(sei)); + if (info == NULL && dialog_state != BELLE_SIP_DIALOG_CONFIRMED && mDir == Dir::Incoming) { + /*the purpose of this line is to set a default SalErrorInfo for declining an incoming call (not yet established of course) */ + sal_error_info_set(&sei,SalReasonDeclined, "SIP", 0, NULL, NULL); + p_sei = &sei; + } else{ + p_sei = info; + } + if (mState==State::Terminating || mState==State::Terminated) { + lError() << "Cannot terminate op [" << this << "] in state [" << toString(mState) << "]"; + ret = -1; + goto end; + } + switch(dialog_state) { + case BELLE_SIP_DIALOG_CONFIRMED: { + belle_sip_request_t * req = belle_sip_dialog_create_request(mDialog,"BYE"); + if (info && info->reason != SalReasonNone) { + belle_sip_header_reason_t* reason = makeReasonHeader(info); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(reason)); + } + sendRequest(req); + mState=State::Terminating; + break; + } + + case BELLE_SIP_DIALOG_NULL: { + if (mDir == Dir::Incoming) { + declineWithErrorInfo(p_sei, NULL); + mState=State::Terminated; + } else if (mPendingClientTransaction){ + if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(mPendingClientTransaction)) == BELLE_SIP_TRANSACTION_PROCEEDING){ + cancellingInvite(p_sei); + } else { + /* Case where the CANCEL cannot be sent because no provisional response was received so far. + * The Op must be kept for the time of the transaction in case a response is received later. + * The state is passed to Terminating to remember to terminate later. + */ + mState=State::Terminating; + /* However, even if the transaction is kept alive, we can stop sending retransmissions to avoid flowing the network with no longer + * necessary messages and avoid confusion in logs.*/ + belle_sip_client_transaction_stop_retransmissions(mPendingClientTransaction); + } + } + break; + } + case BELLE_SIP_DIALOG_EARLY: { + if (mDir == Dir::Incoming) { + declineWithErrorInfo(p_sei,NULL); + mState=State::Terminated; + } else { + cancellingInvite(p_sei); + } + break; + } + default: { + ms_error("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + ret = -1; + goto end; + } + } +end: + sal_error_info_reset(&sei); + return ret; +} + +void SalCallOp::sendVfuRequest() { + char info_body[] = + "" + "" + " " + " " + " " + " " + " " + ""; + size_t content_lenth = sizeof(info_body) - 1; + belle_sip_dialog_state_t dialog_state= mDialog?belle_sip_dialog_get_state(mDialog):BELLE_SIP_DIALOG_NULL; /*no dialog = dialog in NULL state*/ + if (dialog_state == BELLE_SIP_DIALOG_CONFIRMED) { + belle_sip_request_t* info = belle_sip_dialog_create_queued_request(mDialog,"INFO"); + int error=TRUE; + if (info) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_type_create("application","media_control+xml"))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(info),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_lenth))); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(info),info_body,content_lenth); + error=sendRequest(info); + } + if (error) + ms_warning("Cannot send vfu request to [%s] ", getTo().c_str()); + + } else { + ms_warning("Cannot send vfu request to [%s] because dialog [%p] in wrong state [%s]",getTo().c_str() + ,mDialog + ,belle_sip_dialog_state_to_string(dialog_state)); + } + + return ; +} + +int SalCallOp::sendNotifyForRefer(int code, const char *reason) { + belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(mDialog,"NOTIFY"); + char *sipfrag=belle_sip_strdup_printf("SIP/2.0 %i %s\r\n",code,reason); + size_t content_length=strlen(sipfrag); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,-1))); + + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),belle_sip_header_create("Event","refer")); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_type_create("message","sipfrag"))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length))); + belle_sip_message_assign_body(BELLE_SIP_MESSAGE(notify),sipfrag,content_length); + return sendRequest(notify); +} + +void SalCallOp::notifyLastResponse(SalCallOp *newcall) { + belle_sip_client_transaction_t *tr=newcall->mPendingClientTransaction; + belle_sip_response_t *resp=NULL; + if (tr){ + resp=belle_sip_transaction_get_response((belle_sip_transaction_t*)tr); + } + if (resp==NULL){ + sendNotifyForRefer(100, "Trying"); + }else{ + sendNotifyForRefer(belle_sip_response_get_status_code(resp), belle_sip_response_get_reason_phrase(resp)); + } +} + +int SalCallOp::notifyReferState(SalCallOp *newcall) { + belle_sip_dialog_state_t state; + if(belle_sip_dialog_get_state(mDialog) == BELLE_SIP_DIALOG_TERMINATED){ + return 0; + } + state = newcall->mDialog?belle_sip_dialog_get_state(newcall->mDialog):BELLE_SIP_DIALOG_NULL; + switch(state) { + case BELLE_SIP_DIALOG_EARLY: + sendNotifyForRefer(100, "Trying"); + break; + case BELLE_SIP_DIALOG_CONFIRMED: + sendNotifyForRefer(200, "Ok"); + break; + case BELLE_SIP_DIALOG_TERMINATED: + case BELLE_SIP_DIALOG_NULL: + notifyLastResponse(newcall); + break; + } + return 0; +} + +void SalCallOp::setReplaces(const char *call_id, const char *from_tag, const char *to_tag) { + belle_sip_header_replaces_t *replaces = belle_sip_header_replaces_create(call_id, from_tag, to_tag); + SalOp::setReplaces(replaces); +} + +void SalCallOp::setSdpHandling(SalOpSDPHandling handling) { + if (handling != SalOpSDPNormal) ms_message("Enabling special SDP handling for SalOp[%p]!", this); + mSdpHandling = handling; +} + +void SalCallOp::processRefer(const belle_sip_request_event_t *event, belle_sip_server_transaction_t *server_transaction) { + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t); + belle_sip_header_referred_by_t *referred_by= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_referred_by_t); + belle_sip_response_t* resp; + belle_sip_uri_t* refer_to_uri; + + ms_message("Receiving REFER request on op [%p]", this); + if (refer_to) { + refer_to_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(refer_to)); + + if (refer_to_uri && belle_sip_uri_get_header(refer_to_uri,"Replaces")) { + SalOp::setReplaces(belle_sip_header_replaces_create2(belle_sip_uri_get_header(refer_to_uri,"Replaces"))); + belle_sip_uri_remove_header(refer_to_uri,"Replaces"); + } + if (referred_by){ + setReferredBy(referred_by); + } + resp = createResponseFromRequest(req,202); + belle_sip_server_transaction_send_response(server_transaction,resp); + mRoot->mCallbacks.call_refer_received(this,(SalAddress*)BELLE_SIP_HEADER_ADDRESS(refer_to)); + } else { + ms_warning("cannot do anything with the refer without destination"); + resp = createResponseFromRequest(req,400); + belle_sip_server_transaction_send_response(server_transaction,resp); + } + +} + +void SalCallOp::processNotify(const belle_sip_request_event_t *event, belle_sip_server_transaction_t* server_transaction) { + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + const char* body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); + belle_sip_header_t* header_event=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"); + belle_sip_header_content_type_t* content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t); + belle_sip_response_t* resp; + + ms_message("Receiving NOTIFY request on op [%p]", this); + if (header_event + && strncasecmp(belle_sip_header_get_unparsed_value(header_event),"refer",strlen("refer"))==0 + && content_type + && strcmp(belle_sip_header_content_type_get_type(content_type),"message")==0 + && strcmp(belle_sip_header_content_type_get_subtype(content_type),"sipfrag")==0 + && body){ + belle_sip_response_t* sipfrag=BELLE_SIP_RESPONSE(belle_sip_message_parse(body)); + + if (sipfrag){ + int code=belle_sip_response_get_status_code(sipfrag); + SalReferStatus status=SalReferFailed; + if (code<200){ + status=SalReferTrying; + }else if (code<300){ + status=SalReferSuccess; + }else if (code>=400){ + status=SalReferFailed; + } + belle_sip_object_unref(sipfrag); + resp = createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + mRoot->mCallbacks.notify_refer(this,status); + } + }else{ + ms_error("Notify without sipfrag or not for 'refer' event package, rejecting"); + resp = createResponseFromRequest(req, 489); + belle_sip_server_transaction_send_response(server_transaction,resp); + } +} + +int SalCallOp::sendMessage (const Content &content) { + if (!mDialog) + return -1; + belle_sip_request_t *req = belle_sip_dialog_create_queued_request(mDialog, "MESSAGE"); + prepareMessageRequest(req, content); + return sendRequest(req); +} + +bool SalCallOp::compareOp(const SalCallOp *op2) const { + return mCallId == op2->mCallId; +} + +void SalCallOp::handleOfferAnswerResponse(belle_sip_response_t* response) { + if (mLocalMedia){ + /*this is the case where we received an invite without SDP*/ + if (mSdpOffering) { + setSdpFromDesc(BELLE_SIP_MESSAGE(response),mLocalMedia); + }else{ + + if ( mSdpAnswer==NULL ) + { + if( mSdpHandling == SalOpSDPSimulateRemove ){ + ms_warning("Simulating SDP removal in answer for op %p", this); + } else { + sdpProcess(); + } + } + + if (mSdpAnswer){ + setSdp(BELLE_SIP_MESSAGE(response),mSdpAnswer); + belle_sip_object_unref(mSdpAnswer); + mSdpAnswer=NULL; + } + } + }else{ + ms_error("You are accepting a call but not defined any media capabilities !"); + } +} + +LINPHONE_END_NAMESPACE diff --git a/src/sal/call-op.h b/src/sal/call-op.h new file mode 100644 index 000000000..dfb4ead5e --- /dev/null +++ b/src/sal/call-op.h @@ -0,0 +1,129 @@ +/* + * call-op.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_CALL_OP_H_ +#define _L_SAL_CALL_OP_H_ + +#include "sal/op.h" +#include "sal/message-op-interface.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalCallOp : public SalOp, public SalMessageOpInterface { +public: + SalCallOp (Sal *sal) : SalOp(sal) {} + ~SalCallOp () override; + + SalMediaDescription *getLocalMediaDescription () const { return mLocalMedia; } + int setLocalMediaDescription (SalMediaDescription *desc); + int setLocalBody (const Content &body); + int setLocalBody (const Content &&body); + + SalMediaDescription *getRemoteMediaDescription () { return mRemoteMedia; } + const Content &getRemoteBody () const { return mRemoteBody; } + SalMediaDescription *getFinalMediaDescription (); + + int call (const char *from, const char *to, const char *subject); + int notifyRinging (bool earlyMedia); + int accept (); + int decline (SalReason reason, const char *redirection = nullptr); + int declineWithErrorInfo (const SalErrorInfo *info, const SalAddress *redirectionAddr = nullptr); + int update (const char *subject, bool noUserConsent); + int cancelInvite (const SalErrorInfo *info = nullptr); + int refer (const char *referTo); + int referWithReplaces (SalCallOp *otherCallOp); + int setReferrer (SalCallOp *referredCall); + SalCallOp *getReplaces () const; + int sendDtmf (char dtmf); + int terminate (const SalErrorInfo *info = nullptr); + bool autoAnswerAsked () const { return mAutoAnswerAsked; } + void sendVfuRequest (); + int isOfferer () const { return mSdpOffering; } + int notifyReferState (SalCallOp *newCallOp); + bool compareOp (const SalCallOp *otherCallOp) const; + bool dialogRequestPending () const { return (belle_sip_dialog_request_pending(mDialog) != 0); } + const char *getLocalTag () { return belle_sip_dialog_get_local_tag(mDialog); } + const char *getRemoteTag () { return belle_sip_dialog_get_remote_tag(mDialog); } + void setReplaces (const char *callId, const char *fromTag, const char *toTag); + void setSdpHandling (SalOpSDPHandling handling); + + // Implementation of SalMessageOpInterface + int sendMessage (const Content &content) override; + int reply (SalReason reason) override { return SalOp::replyMessage(reason); } + +private: + virtual void fillCallbacks () override; + void setReleased (); + + void setError (belle_sip_response_t *response, bool fatal); + void callTerminated (belle_sip_server_transaction_t *serverTransaction, int statusCode, belle_sip_request_t *cancelRequest); + void resetDescriptions (); + + int parseSdpBody (const Content &body, belle_sdp_session_description_t **sessionDesc, SalReason *error); + void sdpProcess (); + void handleBodyFromResponse (belle_sip_response_t *response); + SalReason processBodyForInvite (belle_sip_request_t *invite); + SalReason processBodyForAck (belle_sip_request_t *ack); + void handleOfferAnswerResponse (belle_sip_response_t *response); + + void fillInvite (belle_sip_request_t *invite); + void cancellingInvite (const SalErrorInfo *info); + int referTo (belle_sip_header_refer_to_t *referToHeader, belle_sip_header_referred_by_t *referredByHeader); + int sendNotifyForRefer (int code, const char *reason); + void notifyLastResponse (SalCallOp *newCallOp); + void processRefer (const belle_sip_request_event_t *event, belle_sip_server_transaction_t *serverTransaction); + void processNotify (const belle_sip_request_event_t *event, belle_sip_server_transaction_t *serverTransaction); + + static void setAddrTo0000 (char value[], size_t sz); + static int isMediaDescriptionAcceptable (SalMediaDescription *md); + static bool isAPendingIncomingInviteTransaction (belle_sip_transaction_t *tr); + static void setCallAsReleased (SalCallOp *op); + static void unsupportedMethod (belle_sip_server_transaction_t *serverTransaction, belle_sip_request_t *request); + static belle_sip_header_reason_t *makeReasonHeader (const SalErrorInfo *info); + static belle_sip_header_allow_t *createAllow (bool enableUpdate); + static std::vector marshalMediaDescription (belle_sdp_session_description_t *sessionDesc, belle_sip_error_code &error); + + // belle_sip_message handlers + static int setCustomBody (belle_sip_message_t *message, const Content &body); + static int setSdp (belle_sip_message_t *message, belle_sdp_session_description_t *sessionDesc); + static int setSdpFromDesc (belle_sip_message_t *message, const SalMediaDescription *desc); + static void processIoErrorCb (void *userCtx, const belle_sip_io_error_event_t *event); + static Content extractBody (belle_sip_message_t *message); + + // Callbacks + static int vfuRetryCb (void *userCtx, unsigned int events); + static void processResponseCb (void *userCtx, const belle_sip_response_event_t *event); + static void processTimeoutCb (void *userCtx, const belle_sip_timeout_event_t *event); + static void processTransactionTerminatedCb (void *userCtx, const belle_sip_transaction_terminated_event_t *event); + static void processRequestEventCb (void *userCtx, const belle_sip_request_event_t *event); + static void processDialogTerminatedCb (void *userCtx, const belle_sip_dialog_terminated_event_t *event); + + // Private constants + static const size_t SIP_MESSAGE_BODY_LIMIT = 16 * 1024; // 16kB + + // Attributes + SalMediaDescription *mLocalMedia = nullptr; + SalMediaDescription *mRemoteMedia = nullptr; + Content mLocalBody; + Content mRemoteBody; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_CALL_OP_H_ diff --git a/src/sal/event-op.cpp b/src/sal/event-op.cpp new file mode 100644 index 000000000..b7c316264 --- /dev/null +++ b/src/sal/event-op.cpp @@ -0,0 +1,435 @@ +/* + * event-op.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "sal/event-op.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void SalSubscribeOp::subscribeProcessIoErrorCb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalSubscribeOp *op = (SalSubscribeOp *)user_ctx; + belle_sip_object_t *src = belle_sip_io_error_event_get_source(event); + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(src, belle_sip_client_transaction_t)){ + belle_sip_client_transaction_t *tr = BELLE_SIP_CLIENT_TRANSACTION(src); + belle_sip_request_t* req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); + const char *method=belle_sip_request_get_method(req); + + if (strcmp(method,"NOTIFY")==0){ + SalErrorInfo *ei=&op->mErrorInfo; + sal_error_info_set(ei,SalReasonIOError, "SIP", 0,NULL,NULL); + op->mRoot->mCallbacks.on_notify_response(op); + } + } +} + +void SalSubscribeOp::subscribeResponseEventCb(void *op_base, const belle_sip_response_event_t *event){ + SalSubscribeOp *op = (SalSubscribeOp *)op_base; + belle_sip_request_t * req; + const char *method; + belle_sip_client_transaction_t *tr = belle_sip_response_event_get_client_transaction(event); + + if (!tr) return; + req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); + method = belle_sip_request_get_method(req); + + if (strcmp(method,"NOTIFY")==0){ + op->setErrorInfoFromResponse(belle_sip_response_event_get_response(event)); + op->mRoot->mCallbacks.on_notify_response(op); + } +} + +void SalSubscribeOp::subscribeProcessTimeoutCb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalSubscribeOp *op = (SalSubscribeOp *)user_ctx; + belle_sip_request_t * req; + const char *method; + belle_sip_client_transaction_t *tr = belle_sip_timeout_event_get_client_transaction(event); + + if (!tr) return; + req = belle_sip_transaction_get_request((belle_sip_transaction_t*)tr); + method = belle_sip_request_get_method(req); + + if (strcmp(method,"NOTIFY")==0){ + SalErrorInfo *ei=&op->mErrorInfo; + sal_error_info_set(ei,SalReasonRequestTimeout, "SIP", 0,NULL,NULL); + op->mRoot->mCallbacks.on_notify_response(op); + } +} + +void SalSubscribeOp::handleNotify(belle_sip_request_t *req, const char *eventname, SalBodyHandler* body_handler){ + SalSubscribeStatus sub_state; + belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(req,belle_sip_header_subscription_state_t); + belle_sip_response_t* resp; + belle_sip_server_transaction_t* server_transaction = mPendingServerTransaction; + + if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { + sub_state=SalSubscribeTerminated; + ms_message("Outgoing subscription terminated by remote [%s]",getTo().c_str()); + } else + sub_state=SalSubscribeActive; + ref(); + mRoot->mCallbacks.notify(this,sub_state,eventname,body_handler); + resp=createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + unref(); +} + +void SalSubscribeOp::subscribeProcessRequestEventCb(void *op_base, const belle_sip_request_event_t *event) { + SalSubscribeOp * op = (SalSubscribeOp *)op_base; + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->mRoot->mProvider,belle_sip_request_event_get_request(event)); + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_state_t dialog_state; + belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); + belle_sip_header_event_t *event_header; + belle_sip_body_handler_t *body_handler; + belle_sip_response_t* resp; + const char *eventname=NULL; + const char *method=belle_sip_request_get_method(req); + belle_sip_dialog_t *dialog = NULL; + + belle_sip_object_ref(server_transaction); + if (op->mPendingServerTransaction) belle_sip_object_unref(op->mPendingServerTransaction); + op->mPendingServerTransaction=server_transaction; + + event_header=belle_sip_message_get_header_by_type(req,belle_sip_header_event_t); + body_handler = BELLE_SIP_BODY_HANDLER(op->getBodyHandler(BELLE_SIP_MESSAGE(req))); + + if (event_header==NULL){ + ms_warning("No event header in incoming SUBSCRIBE."); + resp=op->createResponseFromRequest(req,400); + belle_sip_server_transaction_send_response(server_transaction,resp); + if (!op->mDialog) op->release(); + return; + } + if (op->mEvent==NULL) { + op->mEvent=event_header; + belle_sip_object_ref(op->mEvent); + } + eventname=belle_sip_header_event_get_package_name(event_header); + + if (!op->mDialog) { + if (strcmp(method,"SUBSCRIBE")==0){ + dialog = belle_sip_provider_create_dialog(op->mRoot->mProvider,BELLE_SIP_TRANSACTION(server_transaction)); + if (!dialog){ + resp=op->createResponseFromRequest(req,481); + belle_sip_server_transaction_send_response(server_transaction,resp); + op->release(); + return; + } + op->setOrUpdateDialog(dialog); + ms_message("new incoming subscription from [%s] to [%s]",op->getFrom().c_str(),op->getTo().c_str()); + }else{ /*this is a NOTIFY*/ + op->handleNotify(req, eventname, (SalBodyHandler *)body_handler); + return; + } + } + dialog_state=belle_sip_dialog_get_state(op->mDialog); + switch(dialog_state) { + + case BELLE_SIP_DIALOG_NULL: { + const char *type = NULL; + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); + if (content_type) type = belle_sip_header_content_type_get_type(content_type); + op->mRoot->mCallbacks.subscribe_received(op, eventname, type ? (SalBodyHandler *)body_handler : NULL); + break; + } + case BELLE_SIP_DIALOG_EARLY: + ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",belle_sip_request_get_method(req),op->mDialog); + break; + + case BELLE_SIP_DIALOG_CONFIRMED: + if (strcmp("NOTIFY",method)==0) { + op->handleNotify(req, eventname, (SalBodyHandler *)body_handler); + } else if (strcmp("SUBSCRIBE",method)==0) { + /*either a refresh of an unsubscribe*/ + if (expires && belle_sip_header_expires_get_expires(expires)>0) { + resp=op->createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } else if(expires) { + ms_message("Unsubscribe received from [%s]",op->getFrom().c_str()); + resp=op->createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + op->mRoot->mCallbacks.incoming_subscribe_closed(op); + } + } + break; + default: { + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + } + } +} + +void SalSubscribeOp::subscribeProcessDialogTerminatedCb(void *ctx, const belle_sip_dialog_terminated_event_t *event) { + belle_sip_dialog_t *dialog = belle_sip_dialog_terminated_event_get_dialog(event); + SalSubscribeOp * op= (SalSubscribeOp *)ctx; + if (op->mDialog) { + if (belle_sip_dialog_terminated_event_is_expired(event)){ + if (!belle_sip_dialog_is_server(dialog)){ + /*notify the app that our subscription is dead*/ + const char *eventname = NULL; + if (op->mEvent){ + eventname = belle_sip_header_event_get_package_name(op->mEvent); + } + op->mRoot->mCallbacks.notify(op, SalSubscribeTerminated, eventname, NULL); + }else{ + op->mRoot->mCallbacks.incoming_subscribe_closed(op); + } + } + op->setOrUpdateDialog(NULL); + } +} + +void SalSubscribeOp::releaseCb(SalOp *op_base) { + auto *op =reinterpret_cast(op_base); + if(op->mRefresher) { + belle_sip_refresher_stop(op->mRefresher); + belle_sip_object_unref(op->mRefresher); + op->mRefresher=NULL; + op->setOrUpdateDialog(NULL); /*only if we have refresher. else dialog terminated event will remove association*/ + } +} + +void SalSubscribeOp::fillCallbacks() { + static belle_sip_listener_callbacks_t op_subscribe_callbacks={0}; + if (op_subscribe_callbacks.process_io_error==NULL){ + op_subscribe_callbacks.process_io_error=subscribeProcessIoErrorCb; + op_subscribe_callbacks.process_response_event=subscribeResponseEventCb; + op_subscribe_callbacks.process_timeout=subscribeProcessTimeoutCb; + op_subscribe_callbacks.process_transaction_terminated=subscribeProcessTransactionTerminatedCb; + op_subscribe_callbacks.process_request_event=subscribeProcessRequestEventCb; + op_subscribe_callbacks.process_dialog_terminated=subscribeProcessDialogTerminatedCb; + } + mCallbacks=&op_subscribe_callbacks; + mType=Type::Subscribe; + mReleaseCb=releaseCb; +} + +void SalSubscribeOp::subscribeRefresherListenerCb (belle_sip_refresher_t* refresher,void* user_pointer,unsigned int status_code,const char* reason_phrase, int will_retry) { + SalSubscribeOp * op = (SalSubscribeOp *)user_pointer; + belle_sip_transaction_t *tr=BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)); + /*belle_sip_response_t* response=belle_sip_transaction_get_response(tr);*/ + SalSubscribeStatus sss=SalSubscribeTerminated; + + ms_message("Subscribe refresher [%i] reason [%s] ",status_code,reason_phrase?reason_phrase:"none"); + if (status_code>=200 && status_code<300){ + if (status_code==200) sss=SalSubscribeActive; + else if (status_code==202) sss=SalSubscribePending; + op->setOrUpdateDialog(belle_sip_transaction_get_dialog(tr)); + op->mRoot->mCallbacks.subscribe_response(op,sss, will_retry); + } else if (status_code >= 300) { + SalReason reason = SalReasonUnknown; + if (status_code == 503) { /*refresher returns 503 for IO error*/ + reason = SalReasonIOError; + } + sal_error_info_set(&op->mErrorInfo, reason, "SIP", (int)status_code, reason_phrase, NULL); + op->mRoot->mCallbacks.subscribe_response(op,sss, will_retry); + }else if (status_code==0){ + op->mRoot->mCallbacks.on_expire(op); + } + +} + +int SalSubscribeOp::subscribe(const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler) { + belle_sip_request_t *req=NULL; + + if (from) + setFrom(from); + if (to) + setTo(to); + + if (!mDialog){ + fillCallbacks(); + req=buildRequest("SUBSCRIBE"); + if( req == NULL ) { + return -1; + } + setEvent(eventname); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(mEvent)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); + return sendRequestAndCreateRefresher(req,expires,subscribeRefresherListenerCb); + }else if (mRefresher){ + const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(mRefresher); + belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); + /* modify last request to update body*/ + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_req), BELLE_SIP_BODY_HANDLER(body_handler)); + return belle_sip_refresher_refresh(mRefresher,expires); + } + ms_warning("sal_subscribe(): no dialog and no refresher ?"); + return -1; +} + +int SalSubscribeOp::accept() { + belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(mPendingServerTransaction)); + belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t); + belle_sip_response_t* resp = createResponseFromRequest(req,200); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires)); + belle_sip_server_transaction_send_response(mPendingServerTransaction,resp); + return 0; +} + +int SalSubscribeOp::decline(SalReason reason) { + belle_sip_response_t* resp = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(mPendingServerTransaction)), + to_sip_code(reason)); + belle_sip_server_transaction_send_response(mPendingServerTransaction,resp); + return 0; +} + +int SalSubscribeOp::notifyPendingState() { + + if (mDialog != NULL && mPendingServerTransaction) { + belle_sip_request_t* notify; + belle_sip_header_subscription_state_t* sub_state; + ms_message("Sending NOTIFY with subscription state pending for op [%p]", this); + if (!(notify=belle_sip_dialog_create_request(mDialog,"NOTIFY"))) { + ms_error("Cannot create NOTIFY on op [%p]", this); + return -1; + } + if (mEvent) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(mEvent)); + sub_state=belle_sip_header_subscription_state_new(); + belle_sip_header_subscription_state_set_state(sub_state,BELLE_SIP_SUBSCRIPTION_STATE_PENDING); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify), BELLE_SIP_HEADER(sub_state)); + return sendRequest(notify); + } else { + ms_warning("NOTIFY with subscription state pending for op [%p] not implemented in this case (either dialog pending trans does not exist", this); + } + + return 0; +} + +int SalSubscribeOp::notify(const SalBodyHandler *body_handler) { + belle_sip_request_t* notify; + + if (mDialog){ + if (!(notify=belle_sip_dialog_create_queued_request(mDialog,"NOTIFY"))) return -1; + }else{ + fillCallbacks(); + notify = buildRequest("NOTIFY"); + } + + if (mEvent) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(mEvent)); + + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + , mDialog ? + BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600)) : + BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,0)) + ); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(notify), BELLE_SIP_BODY_HANDLER(body_handler)); + return sendRequest(notify); +} + +int SalSubscribeOp::closeNotify() { + belle_sip_request_t* notify; + if (!mDialog) return -1; + if (!(notify=belle_sip_dialog_create_queued_request(mDialog,"NOTIFY"))) return -1; + if (mEvent) belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify),BELLE_SIP_HEADER(mEvent)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); + return sendRequest(notify); +} + +void SalPublishOp::publishResponseEventCb(void *userctx, const belle_sip_response_event_t *event) { + SalPublishOp *op=(SalPublishOp *)userctx; + op->setErrorInfoFromResponse(belle_sip_response_event_get_response(event)); + if (op->mErrorInfo.protocol_code>=200){ + op->mRoot->mCallbacks.on_publish_response(op); + } +} + +void SalPublishOp::fillCallbacks() { + static belle_sip_listener_callbacks_t op_publish_callbacks={0}; + if (op_publish_callbacks.process_response_event==NULL){ + op_publish_callbacks.process_response_event=publishResponseEventCb; + } + + mCallbacks=&op_publish_callbacks; + mType=Type::Publish; +} + +void SalPublishOp::publishRefresherListenerCb (belle_sip_refresher_t* refresher,void* user_pointer,unsigned int status_code,const char* reason_phrase, int will_retry) { + SalPublishOp * op = (SalPublishOp *)user_pointer; + const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->mRefresher); + belle_sip_response_t *response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(last_publish_trans)); + ms_message("Publish refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase?reason_phrase:"none",op->getProxy().c_str()); + if (status_code==0){ + op->mRoot->mCallbacks.on_expire(op); + }else if (status_code>=200){ + belle_sip_header_t *sip_etag; + string sipEtagStr; + if (response && (sip_etag = belle_sip_message_get_header(BELLE_SIP_MESSAGE(response), "SIP-ETag"))) { + sipEtagStr = belle_sip_header_get_unparsed_value(sip_etag); + } + op->setEntityTag(sipEtagStr); + sal_error_info_set(&op->mErrorInfo,SalReasonUnknown, "SIP", (int)status_code, reason_phrase, NULL); + op->assignRecvHeaders((belle_sip_message_t*)response); + op->mRoot->mCallbacks.on_publish_response(op); + } +} + +int SalPublishOp::publish(const char *from, const char *to, const char *eventname, int expires, const SalBodyHandler *body_handler) { + belle_sip_request_t *req=NULL; + if(!mRefresher || !belle_sip_refresher_get_transaction(mRefresher)) { + if (from) + setFrom(from); + if (to) + setTo(to); + + fillCallbacks(); + req=buildRequest("PUBLISH"); + if( req == NULL ){ + return -1; + } + + if (!mEntityTag.empty()) + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), belle_sip_header_create("SIP-If-Match", mEntityTag.c_str())); + + if (getContactAddress()){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(createContact())); + } + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname)); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(req), BELLE_SIP_BODY_HANDLER(body_handler)); + if (expires!=-1) + return sendRequestAndCreateRefresher(req,expires,publishRefresherListenerCb); + else return sendRequest(req); + } else { + /*update status*/ + const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(mRefresher); + belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans)); + /*update body*/ + if (expires == 0) { + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_publish), NULL, 0); + } else { + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(last_publish), BELLE_SIP_BODY_HANDLER(body_handler)); + } + return belle_sip_refresher_refresh(mRefresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires); + } +} + +int SalPublishOp::unpublish() { + if (mRefresher){ + const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(mRefresher); + belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); + belle_sip_refresher_refresh(mRefresher,0); + return 0; + } + return -1; +} + +LINPHONE_END_NAMESPACE diff --git a/src/sal/event-op.h b/src/sal/event-op.h new file mode 100644 index 000000000..4b4f3b7f0 --- /dev/null +++ b/src/sal/event-op.h @@ -0,0 +1,74 @@ +/* + * event-op.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_EVENT_OP_H_ +#define _L_SAL_EVENT_OP_H_ + +#include "sal/op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalEventOp : public SalOp { +public: + SalEventOp (Sal *sal) : SalOp(sal) {} +}; + +class SalSubscribeOp: public SalEventOp { +public: + SalSubscribeOp (Sal *sal): SalEventOp(sal) {} + + int subscribe (const char *from, const char *to, const char *eventName, int expires, const SalBodyHandler *bodyHandler); + int unsubscribe () { return SalOp::unsubscribe(); } + int accept (); + int decline (SalReason reason); + int notifyPendingState (); + int notify (const SalBodyHandler *bodyHandler); + int closeNotify (); + +private: + virtual void fillCallbacks () override; + void handleNotify (belle_sip_request_t *request, const char *eventName, SalBodyHandler *bodyHandler); + + static void subscribeProcessIoErrorCb (void *userCtx, const belle_sip_io_error_event_t *event); + static void subscribeResponseEventCb (void *userCtx, const belle_sip_response_event_t *event); + static void subscribeProcessTimeoutCb (void *userCtx, const belle_sip_timeout_event_t *event); + static void subscribeProcessTransactionTerminatedCb (void *userCtx, const belle_sip_transaction_terminated_event_t *event) {} + static void subscribeProcessRequestEventCb (void *userCtx, const belle_sip_request_event_t *event); + static void subscribeProcessDialogTerminatedCb (void *userCtx, const belle_sip_dialog_terminated_event_t *event); + static void releaseCb (SalOp *op); + static void subscribeRefresherListenerCb (belle_sip_refresher_t *refresher, void *userCtx, unsigned int statusCode, const char *reasonPhrase, int willRetry); +}; + +class SalPublishOp : public SalEventOp { +public: + SalPublishOp (Sal *sal) : SalEventOp(sal) {} + + int publish (const char *from, const char *to, const char *eventName, int expires, const SalBodyHandler *bodyHandler); + int unpublish (); + +private: + virtual void fillCallbacks () override; + + static void publishResponseEventCb (void *userCtx, const belle_sip_response_event_t *event); + static void publishRefresherListenerCb (belle_sip_refresher_t *refresher, void *userCtx, unsigned int statusCode, const char *reasonPhrase, int willRetry); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_EVENT_OP_H_ diff --git a/src/sal/message-op-interface.h b/src/sal/message-op-interface.h new file mode 100644 index 000000000..79ee4debd --- /dev/null +++ b/src/sal/message-op-interface.h @@ -0,0 +1,76 @@ +/* + * message-op-interface.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_MESSAGE_OP_INTERFACE_H_ +#define _L_SAL_MESSAGE_OP_INTERFACE_H_ + +#include + +#include "content/content.h" +#include "content/content-type.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalMessageOpInterface { +public: + virtual ~SalMessageOpInterface() = default; + + virtual int sendMessage (const Content &content) = 0; + virtual int reply (SalReason reason) = 0; + +protected: + void prepareMessageRequest (belle_sip_request_t *req, const Content &content) { + time_t curtime = std::time(nullptr); + belle_sip_message_add_header( + BELLE_SIP_MESSAGE(req), + BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime)) + ); + std::string contentEncoding = content.getContentEncoding(); + if (!contentEncoding.empty()) + belle_sip_message_add_header( + BELLE_SIP_MESSAGE(req), + belle_sip_header_create("Content-Encoding", contentEncoding.c_str()) + ); + const ContentType &contentType = content.getContentType(); + std::string contentTypeStr = std::string(BELLE_SIP_CONTENT_TYPE ": ") + contentType.asString(); + belle_sip_message_add_header( + BELLE_SIP_MESSAGE(req), + BELLE_SIP_HEADER(belle_sip_header_content_type_parse(contentTypeStr.c_str())) + ); + if (content.isEmpty()) { + belle_sip_message_add_header( + BELLE_SIP_MESSAGE(req), + BELLE_SIP_HEADER(belle_sip_header_content_length_create(0)) + ); + } else { + std::string body = content.getBodyAsUtf8String(); + size_t contentLength = body.size(); + belle_sip_message_add_header( + BELLE_SIP_MESSAGE(req), + BELLE_SIP_HEADER(belle_sip_header_content_length_create(contentLength)) + ); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(req), body.c_str(), contentLength); + } + } + +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_MESSAGE_OP_INTERFACE_H_ diff --git a/src/sal/message-op.cpp b/src/sal/message-op.cpp new file mode 100644 index 000000000..c7d882b39 --- /dev/null +++ b/src/sal/message-op.cpp @@ -0,0 +1,90 @@ +/* + * message-op.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "sal/message-op.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void SalMessageOp::processError() { + if (mDir == Dir::Outgoing) { + mRoot->mCallbacks.message_delivery_update(this, SalMessageDeliveryFailed); + } else { + ms_warning("unexpected io error for incoming message on op [%p]", this); + } + mState=State::Terminated; +} + +void SalMessageOp::processIoErrorCb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalMessageOp * op = (SalMessageOp *)user_ctx; + sal_error_info_set(&op->mErrorInfo,SalReasonIOError, "SIP", 503,"IO Error",NULL); + op->processError(); +} + +void SalMessageOp::processResponseEventCb(void *op_base, const belle_sip_response_event_t *event) { + SalMessageOp * op = (SalMessageOp *)op_base; + int code = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event)); + SalMessageDeliveryStatus status; + op->setErrorInfoFromResponse(belle_sip_response_event_get_response(event)); + + if (code>=100 && code <200) + status=SalMessageDeliveryInProgress; + else if (code>=200 && code <300) + status=SalMessageDeliveryDone; + else + status=SalMessageDeliveryFailed; + + op->mRoot->mCallbacks.message_delivery_update(op,status); +} + +void SalMessageOp::processTimeoutCb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalMessageOp * op=(SalMessageOp *)user_ctx; + sal_error_info_set(&op->mErrorInfo,SalReasonRequestTimeout, "SIP", 408,"Request timeout",NULL); + op->processError(); +} + +void SalMessageOp::processRequestEventCb(void *op_base, const belle_sip_request_event_t *event) { + SalMessageOp * op = (SalMessageOp *)op_base; + op->processIncomingMessage(event); +} + +void SalMessageOp::fillCallbacks() { + static belle_sip_listener_callbacks_t op_message_callbacks = {0}; + if (op_message_callbacks.process_io_error==NULL) { + op_message_callbacks.process_io_error=processIoErrorCb; + op_message_callbacks.process_response_event=processResponseEventCb; + op_message_callbacks.process_timeout=processTimeoutCb; + op_message_callbacks.process_request_event=processRequestEventCb; + } + mCallbacks=&op_message_callbacks; + mType=Type::Message; +} + +int SalMessageOp::sendMessage (const Content &content) { + fillCallbacks(); + mDir = Dir::Outgoing; + belle_sip_request_t *req = buildRequest("MESSAGE"); + if (!req) + return -1; + prepareMessageRequest(req, content); + return sendRequest(req); +} + +LINPHONE_END_NAMESPACE diff --git a/src/sal/message-op.h b/src/sal/message-op.h new file mode 100644 index 000000000..73cd9efae --- /dev/null +++ b/src/sal/message-op.h @@ -0,0 +1,47 @@ +/* + * message-op.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_MESSAGE_OP_H_ +#define _L_SAL_MESSAGE_OP_H_ + +#include "sal/op.h" +#include "sal/message-op-interface.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalMessageOp : public SalOp, public SalMessageOpInterface { +public: + SalMessageOp (Sal *sal) : SalOp(sal) {} + + int sendMessage (const Content &content) override; + int reply (SalReason reason) override { return SalOp::replyMessage(reason); } + +private: + virtual void fillCallbacks () override; + void processError (); + + static void processIoErrorCb (void *userCtx, const belle_sip_io_error_event_t *event); + static void processResponseEventCb (void *userCtx, const belle_sip_response_event_t *event); + static void processTimeoutCb (void *userCtx, const belle_sip_timeout_event_t *event); + static void processRequestEventCb (void *userCtx, const belle_sip_request_event_t *event); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_MESSAGE_OP_H_ diff --git a/src/sal/op.cpp b/src/sal/op.cpp new file mode 100644 index 000000000..61dd347f1 --- /dev/null +++ b/src/sal/op.cpp @@ -0,0 +1,1038 @@ +/* + * op.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "c-wrapper/internal/c-tools.h" +#include "sal/op.h" +#include "bellesip_sal/sal_impl.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +SalOp::SalOp(Sal *sal) { + mRoot = sal; + mSdpHandling = sal->mDefaultSdpHandling; + memset(&mErrorInfo, 0, sizeof(mErrorInfo)); + memset(&mReasonErrorInfo, 0, sizeof(mReasonErrorInfo)); + ref(); +} + +SalOp::~SalOp() { + lInfo() << "Destroying op [" << this << "] of type [" << toString(mType) << "]"; + + if (mPendingAuthTransaction) belle_sip_object_unref(mPendingAuthTransaction); + mRoot->removePendingAuth(this); + if (mAuthInfo) { + sal_auth_info_delete(mAuthInfo); + } + if (mSdpAnswer) belle_sip_object_unref(mSdpAnswer); + if (mRefresher) { + belle_sip_object_unref(mRefresher); + mRefresher=NULL; + } + if (mResult) + sal_media_description_unref(mResult); + if(mReplaces) belle_sip_object_unref(mReplaces); + if(mReferredBy) belle_sip_object_unref(mReferredBy); + + if (mPendingClientTransaction) belle_sip_object_unref(mPendingClientTransaction); + if (mPendingServerTransaction) belle_sip_object_unref(mPendingServerTransaction); + if (mPendingUpdateServerTransaction) belle_sip_object_unref(mPendingUpdateServerTransaction); + if (mEvent) belle_sip_object_unref(mEvent); + + sal_error_info_reset(&mErrorInfo); + if (mFromAddress){ + sal_address_destroy(mFromAddress); + mFromAddress=NULL; + } + if (mToAddress){ + sal_address_destroy(mToAddress); + mToAddress=NULL; + } + + if (mServiceRoute){ + sal_address_destroy(mServiceRoute); + mServiceRoute=NULL; + } + + if (mOriginAddress){ + sal_address_destroy(mOriginAddress); + mOriginAddress=NULL; + } + + if (mContactAddress) { + sal_address_destroy(mContactAddress); + } + if (mRemoteContactAddress){ + sal_address_destroy(mRemoteContactAddress); + } + if (mServiceRoute) { + sal_address_destroy(mServiceRoute); + } + for (auto &addr : mRouteAddresses) + sal_address_unref(addr); + if (mRecvCustomHeaders) + sal_custom_header_free(mRecvCustomHeaders); + if (mSentCustomHeaders) + sal_custom_header_free(mSentCustomHeaders); +} + +SalOp *SalOp::ref() { + mRef++; + return this; +} + +void *SalOp::unref() { + mRef--; + if (mRef == 0) + delete this; + else if (mRef < 0) + ms_fatal("SalOp [%p]: too many unrefs.",this); + return NULL; +} + +void SalOp::setContactAddress(const SalAddress *address) { + if (mContactAddress) sal_address_destroy(mContactAddress); + mContactAddress=address?sal_address_clone(address):NULL; +} + +void SalOp::assignAddress (SalAddress **address, const string &value) { + if (*address) { + sal_address_destroy(*address); + *address = nullptr; + } + if (!value.empty()) + *address = sal_address_new(value.c_str()); +} + +void SalOp::setRoute (const string &value) { + for (auto &address : mRouteAddresses) + sal_address_unref(address); + mRouteAddresses.clear(); + if (value.empty()) { + mRoute.clear(); + } else { + auto address = sal_address_new(value.c_str()); + mRouteAddresses.push_back(address); + char *routeStr = sal_address_as_string(address); + mRoute = routeStr; + ms_free(routeStr); + } +} + +void SalOp::setRouteAddress(const SalAddress *address){ + char* address_string=sal_address_as_string(address); /*can probably be optimized*/ + setRoute(address_string); + ms_free(address_string); +} + +void SalOp::addRouteAddress (const SalAddress *address) { + if (mRouteAddresses.empty()) + setRouteAddress(address); + else + mRouteAddresses.push_back(sal_address_clone(address)); +} + +void SalOp::setFrom (const string &value) { + assignAddress(&mFromAddress, value); + if (mFromAddress) { + char *valueStr = sal_address_as_string(mFromAddress); + mFrom = valueStr; + ms_free(valueStr); + } else { + mFrom.clear(); + } +} + +void SalOp::setFromAddress(const SalAddress *from) { + char* address_string=sal_address_as_string(from); /*can probably be optimized*/ + setFrom(address_string); + ms_free(address_string); +} + +void SalOp::setTo (const string &value) { + assignAddress(&mToAddress, value); + if (mToAddress) { + char *valueStr = sal_address_as_string(mToAddress); + mTo = valueStr; + ms_free(valueStr); + } else { + mTo.clear(); + } +} + +void SalOp::setToAddress(const SalAddress *to) { + char* address_string=sal_address_as_string(to); /*can probably be optimized*/ + setTo(address_string); + ms_free(address_string); +} + +void SalOp::setDiversionAddress(const SalAddress *diversion) { + if (mDiversionAddress) sal_address_destroy(mDiversionAddress); + mDiversionAddress=diversion ? sal_address_clone(diversion) : NULL; +} + +int SalOp::refresh() { + if (mRefresher) { + belle_sip_refresher_refresh(mRefresher,belle_sip_refresher_get_expires(mRefresher)); + return 0; + } + lWarning() << "No refresher on op [" << this << "] of type [" << toString(mType) << "]"; + return -1; +} + +void SalOp::killDialog() { + ms_warning("op [%p]: force kill of dialog [%p]", this, mDialog); + belle_sip_dialog_delete(mDialog); +} + +void SalOp::release() { + /*if in terminating state, keep this state because it means we are waiting for a response to be able to terminate the operation.*/ + if (mState!=State::Terminating) + mState=State::Terminated; + setUserPointer(NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/ + if (mReleaseCb) + mReleaseCb(this); + if (mRefresher) { + belle_sip_refresher_stop(mRefresher); + } + mOpReleased = TRUE; + unref(); +} + +int SalOp::sendRequestWithContact(belle_sip_request_t* request, bool add_contact) { + belle_sip_client_transaction_t* client_transaction; + belle_sip_provider_t* prov=mRoot->mProvider; + belle_sip_header_contact_t* contact; + int result =-1; + belle_sip_uri_t *next_hop_uri=NULL; + + if (add_contact && !belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t)) { + contact = createContact(); + belle_sip_message_set_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(contact)); + } /*keep existing*/ + + addCustomHeaders((belle_sip_message_t*)request); + + if (!mDialog || belle_sip_dialog_get_state(mDialog) == BELLE_SIP_DIALOG_NULL) { + /*don't put route header if dialog is in confirmed state*/ + auto routeAddresses = getRouteAddresses(); + const char *transport; + const char *method=belle_sip_request_get_method(request); + belle_sip_listening_point_t *udplp=belle_sip_provider_get_listening_point(prov,"UDP"); + + if (routeAddresses.empty()) + next_hop_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)belle_sip_request_get_uri(request)); + else + next_hop_uri = belle_sip_header_address_get_uri((belle_sip_header_address_t*)routeAddresses.front()); + transport=belle_sip_uri_get_transport_param(next_hop_uri); + if (transport==NULL){ + /*compatibility mode: by default it should be udp as not explicitely set and if no udp listening point is available, then use + * the first available transport*/ + if (!belle_sip_uri_is_secure(next_hop_uri)){ + if (udplp==NULL){ + if (belle_sip_provider_get_listening_point(prov,"TCP")!=NULL){ + transport="tcp"; + }else if (belle_sip_provider_get_listening_point(prov,"TLS")!=NULL ){ + transport="tls"; + } + } + if (transport){ + belle_sip_message("Transport is not specified, using %s because UDP is not available.",transport); + belle_sip_uri_set_transport_param(next_hop_uri,transport); + } + } + }else{ +#ifdef TUNNEL_ENABLED + if (udplp && BELLE_SIP_OBJECT_IS_INSTANCE_OF(udplp,belle_sip_tunnel_listening_point_t)){ + /* our tunnel mode only supports UDP. Force transport to be set to UDP */ + belle_sip_uri_set_transport_param(next_hop_uri,"udp"); + } +#endif + } + /*because in case of tunnel, transport can be changed*/ + transport=belle_sip_uri_get_transport_param(next_hop_uri); + + if ((strcmp(method,"REGISTER")==0 || strcmp(method,"SUBSCRIBE")==0) && transport && + (strcasecmp(transport,"TCP")==0 || strcasecmp(transport,"TLS")==0)){ + /*RFC 5923: add 'alias' parameter to tell the server that we want it to keep the connection for future requests*/ + belle_sip_header_via_t *via=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_via_t); + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(via),"alias",NULL); + } + } + + client_transaction = belle_sip_provider_create_client_transaction(prov,request); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(client_transaction),ref()); + if (mPendingClientTransaction) belle_sip_object_unref(mPendingClientTransaction); + + mPendingClientTransaction=client_transaction; /*update pending inv for being able to cancel*/ + belle_sip_object_ref(mPendingClientTransaction); + + if (belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_user_agent_t)==NULL) + belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(mRoot->mUserAgentHeader)); + + 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(mRoot->mProvider,request,NULL,NULL,NULL,L_STRING_TO_C(mRealm)); + } + result = belle_sip_client_transaction_send_request_to(client_transaction,next_hop_uri/*might be null*/); + + /*update call id if not set yet for this OP*/ + if (result == 0 && mCallId.empty()) { + mCallId = belle_sip_header_call_id_get_call_id( + BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request), belle_sip_header_call_id_t))); + } + + return result; + +} + +int SalOp::sendRequest(belle_sip_request_t* request) { + bool need_contact=FALSE; + if (request==NULL) { + return -1; /*sanity check*/ + } + // Header field where proxy ACK BYE CAN INV OPT REG + // ___________________________________________________________ + // Contact R o - - m o o + if (strcmp(belle_sip_request_get_method(request),"INVITE")==0 + ||strcmp(belle_sip_request_get_method(request),"REGISTER")==0 + ||strcmp(belle_sip_request_get_method(request),"SUBSCRIBE")==0 + ||strcmp(belle_sip_request_get_method(request),"OPTIONS")==0 + ||strcmp(belle_sip_request_get_method(request),"REFER")==0) /* Despite contact seems not mandatory, call flow example show a Contact in REFER requests*/ + need_contact=true; + + return sendRequestWithContact(request,need_contact); +} + +void SalOp::resendRequest(belle_sip_request_t* request) { + belle_sip_header_cseq_t* cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ); + belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1); + sendRequest(request); +} + +int SalOp::processRedirect(){ + belle_sip_request_t* request = belle_sip_transaction_get_request((belle_sip_transaction_t*)mPendingClientTransaction); + belle_sip_response_t *response = belle_sip_transaction_get_response((belle_sip_transaction_t*)mPendingClientTransaction); + belle_sip_header_contact_t *redirect_contact = belle_sip_message_get_header_by_type((belle_sip_message_t*)response, belle_sip_header_contact_t); + belle_sip_uri_t *redirect_uri; + belle_sip_header_call_id_t *callid = belle_sip_message_get_header_by_type((belle_sip_message_t*)request, belle_sip_header_call_id_t); + belle_sip_header_to_t *to = belle_sip_message_get_header_by_type((belle_sip_message_t*)request, belle_sip_header_to_t); + + if (!redirect_contact){ + ms_warning("Redirect not handled, there is no redirect contact header in response"); + return -1; + } + + redirect_uri = belle_sip_header_address_get_uri((belle_sip_header_address_t*) redirect_contact); + + if (!redirect_uri){ + ms_warning("Redirect not handled, there is no usable uri in contact."); + return -1; + } + + if (mDialog && belle_sip_dialog_get_state(mDialog)==BELLE_SIP_DIALOG_CONFIRMED){ + ms_warning("Redirect not handled within established dialogs. Does it make sense ?"); + return -1; + } + setOrUpdateDialog(NULL); + belle_sip_message_remove_header_from_ptr((belle_sip_message_t*)request, (belle_sip_header_t*)callid); + belle_sip_message_add_header((belle_sip_message_t*)request, (belle_sip_header_t*)(callid = belle_sip_provider_create_call_id(getSal()->mProvider))); + mCallId.clear(); // Reset the call-id of op, it will be set when new request will be sent + belle_sip_request_set_uri(request, redirect_uri); + redirect_uri = BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(redirect_uri))); + belle_sip_uri_set_port(redirect_uri, 0); + belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(redirect_uri), "transport"); + belle_sip_header_address_set_uri((belle_sip_header_address_t*)to, redirect_uri); + sendRequest(request); + return 0; +} + +void SalOp::processAuthentication() { + belle_sip_request_t* initial_request=belle_sip_transaction_get_request((belle_sip_transaction_t*)mPendingAuthTransaction); + belle_sip_request_t* new_request; + bool is_within_dialog=false; + belle_sip_list_t* auth_list=NULL; + belle_sip_auth_event_t* auth_event; + belle_sip_response_t *response=belle_sip_transaction_get_response((belle_sip_transaction_t*)mPendingAuthTransaction); + belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(initial_request,belle_sip_header_from_t); + belle_sip_uri_t *from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)from); + + if (strcasecmp(belle_sip_uri_get_host(from_uri),"anonymous.invalid")==0){ + /*prefer using the from from the SalOp*/ + from_uri=belle_sip_header_address_get_uri((belle_sip_header_address_t*)getFromAddress()); + } + + if (mDialog && belle_sip_dialog_get_state(mDialog)==BELLE_SIP_DIALOG_CONFIRMED) { + new_request = belle_sip_dialog_create_request_from(mDialog,initial_request); + if (!new_request) + new_request = belle_sip_dialog_create_queued_request_from(mDialog,initial_request); + is_within_dialog=true; + } else { + new_request=initial_request; + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_AUTHORIZATION); + belle_sip_message_remove_header(BELLE_SIP_MESSAGE(new_request),BELLE_SIP_PROXY_AUTHORIZATION); + } + if (new_request==NULL) { + bctbx_error("sal_process_authentication() op=[%p] cannot obtain new request from dialog.",this); + return; + } + + if (belle_sip_provider_add_authorization(mRoot->mProvider,new_request,response,from_uri,&auth_list,L_STRING_TO_C(mRealm))) { + if (is_within_dialog) + sendRequest(new_request); + else + resendRequest(new_request); + mRoot->removePendingAuth(this); + }else { + belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(response,belle_sip_header_from_t); + char *tmp=belle_sip_object_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); + ms_message("No auth info found for [%s]",tmp); + belle_sip_free(tmp); + mRoot->addPendingAuth(this); + + if (is_within_dialog) { + belle_sip_object_unref(new_request); + } + } + /*always store auth info, for case of wrong credential*/ + if (mAuthInfo) { + sal_auth_info_delete(mAuthInfo); + mAuthInfo=NULL; + } + if (auth_list){ + auth_event=(belle_sip_auth_event_t*)(auth_list->data); + mAuthInfo=sal_auth_info_create(auth_event); + belle_sip_list_free_with_data(auth_list,(void (*)(void*))belle_sip_auth_event_destroy); + } +} + +string SalOp::getDialogId () const { + if (!mDialog) + return string(); + stringstream ss; + ss << mCallId << ";to-tag=" << belle_sip_dialog_get_remote_tag(mDialog) << ";from-tag=" << belle_sip_dialog_get_local_tag(mDialog); + return ss.str(); +} + +int SalOp::getAddressFamily() const { + belle_sip_transaction_t *tr=NULL; + belle_sip_header_address_t *contact; + + + if (mRefresher) + tr=(belle_sip_transaction_t *)belle_sip_refresher_get_transaction(mRefresher); + + if (tr==NULL) + tr=(belle_sip_transaction_t *)mPendingClientTransaction; + if (tr==NULL) + tr=(belle_sip_transaction_t *)mPendingServerTransaction; + + if (tr==NULL){ + bctbx_error("Unable to determine IP version from signaling operation."); + return AF_UNSPEC; + } + + if (mRefresher) { + belle_sip_message_t *msg = belle_sip_transaction_get_response(tr) ? (belle_sip_message_t*) belle_sip_transaction_get_response(tr) : (belle_sip_message_t*) belle_sip_transaction_get_request(tr); + belle_sip_header_via_t *via = msg ? belle_sip_message_get_header_by_type(msg,belle_sip_header_via_t):NULL; + if (!via) { + bctbx_error("Unable to determine IP version from signaling operation, no via header found."); + return AF_UNSPEC; + } + const char *host = belle_sip_header_via_get_host(via); + if (!host){ + bctbx_error("Unable to determine IP version from signaling operation, no via header is not yet completed."); + return AF_UNSPEC; + } + return strchr(host,':') ? AF_INET6 : AF_INET; + } + + belle_sip_request_t *req = belle_sip_transaction_get_request(tr); + contact = reinterpret_cast( + belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t) + ); + if (!contact) + bctbx_error("Unable to determine IP version from signaling operation, no contact header found."); + return sal_address_is_ipv6(reinterpret_cast(contact)) ? AF_INET6 : AF_INET; +} + +bool SalOp::isIdle() const { + if (mDialog) + return !belle_sip_dialog_request_pending(mDialog); + return true; +} + +void SalOp::setEvent (const string &eventName) { + belle_sip_header_event_t *header = nullptr; + if (mEvent) + belle_sip_object_unref(mEvent); + if (!eventName.empty()) { + header = belle_sip_header_event_create(eventName.c_str()); + belle_sip_object_ref(header); + } + mEvent = header; +} + +void SalOp::addInitialRouteSet (belle_sip_request_t *request, const list &routeAddresses) { + bool uniqueRoute = routeAddresses.size() == 1; + for (const auto &address : routeAddresses) { + // Optimization: if the initial route set only contains one URI which is the same as the request URI, ommit it + if (uniqueRoute) { + belle_sip_uri_t *requestUri = belle_sip_request_get_uri(request); + // Skip the first route it is the same as the request uri + if (strcmp(sal_address_get_domain(address), belle_sip_uri_get_host(requestUri)) == 0) { + ms_message("Skipping top route of initial route-set because same as request-uri"); + continue; + } + } + + belle_sip_header_route_t *route = belle_sip_header_route_create((belle_sip_header_address_t *)address); + belle_sip_uri_t *uri = belle_sip_header_address_get_uri((belle_sip_header_address_t *)route); + belle_sip_uri_set_lr_param(uri, 1); + belle_sip_message_add_header((belle_sip_message_t *)request, (belle_sip_header_t *)route); + } +} + +belle_sip_request_t* SalOp::buildRequest (const string &method) { + belle_sip_header_from_t* from_header; + belle_sip_header_to_t* to_header; + belle_sip_provider_t* prov=mRoot->mProvider; + belle_sip_request_t *req; + belle_sip_uri_t* req_uri; + belle_sip_uri_t* to_uri; + belle_sip_header_call_id_t *call_id_header; + + const SalAddress* to_address; + char token[10]; + + /* check that the op has a correct to address */ + to_address = getToAddress(); + if( to_address == NULL ){ + bctbx_error("No To: address, cannot build request"); + return NULL; + } + + to_uri = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to_address)); + if( to_uri == NULL ){ + bctbx_error("To: address is invalid, cannot build request"); + return NULL; + } + + if ((method == "REGISTER") || (mPrivacy == SalPrivacyNone)) { + from_header = belle_sip_header_from_create(BELLE_SIP_HEADER_ADDRESS(getFromAddress()) + ,belle_sip_random_token(token,sizeof(token))); + } else { + from_header=belle_sip_header_from_create2("Anonymous ",belle_sip_random_token(token,sizeof(token))); + } + /*make sure to preserve components like headers or port*/ + + req_uri = (belle_sip_uri_t*)belle_sip_object_clone((belle_sip_object_t*)to_uri); + belle_sip_uri_set_secure(req_uri,isSecure()); + + to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(to_address),NULL); + call_id_header = belle_sip_provider_create_call_id(prov); + if (!mCallId.empty()) + belle_sip_header_call_id_set_call_id(call_id_header, mCallId.c_str()); + + req=belle_sip_request_create( + req_uri, + method.c_str(), + call_id_header, + belle_sip_header_cseq_create(20,method.c_str()), + from_header, + to_header, + belle_sip_header_via_new(), + 70); + + if (mPrivacy & SalPrivacyId) { + belle_sip_header_p_preferred_identity_t* p_preferred_identity=belle_sip_header_p_preferred_identity_create(BELLE_SIP_HEADER_ADDRESS(getFromAddress())); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(p_preferred_identity)); + } + + auto routeAddresses = getRouteAddresses(); + if (!routeAddresses.empty() && (method != "REGISTER") && !mRoot->mNoInitialRoute) + addInitialRouteSet(req, routeAddresses); + + if ((method != "REGISTER") && (mPrivacy != SalPrivacyNone)) { + belle_sip_header_privacy_t* privacy_header=belle_sip_header_privacy_new(); + if (mPrivacy&SalPrivacyCritical) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyCritical)); + if (mPrivacy&SalPrivacyHeader) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyHeader)); + if (mPrivacy&SalPrivacyId) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyId)); + if (mPrivacy&SalPrivacyNone) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacyNone)); + if (mPrivacy&SalPrivacySession) + belle_sip_header_privacy_add_privacy(privacy_header,sal_privacy_to_string(SalPrivacySession)); + if (mPrivacy&SalPrivacyUser) + 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),mRoot->mSupportedHeader); + return req; +} + +void SalOp::setErrorInfoFromResponse(belle_sip_response_t *response) { + int code = belle_sip_response_get_status_code(response); + const char *reason_phrase=belle_sip_response_get_reason_phrase(response); + belle_sip_header_t *warning=belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),"Warning"); + SalErrorInfo *ei=&mErrorInfo; + const char *warnings; + + warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL; + sal_error_info_set(ei,SalReasonUnknown,"SIP", code,reason_phrase,warnings); + setReasonErrorInfo(BELLE_SIP_MESSAGE(response)); +} + +string SalOp::toString (const State value) { + switch (value) { + case State::Early: + return"SalOpStateEarly"; + case State::Active: + return "SalOpStateActive"; + case State::Terminating: + return "SalOpStateTerminating"; + case State::Terminated: + return "SalOpStateTerminated"; + default: + return "Unknown"; + } +} + +void SalOp::setReasonErrorInfo(belle_sip_message_t *msg) { + belle_sip_header_reason_t* reason_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_reason_t); + if (reason_header){ + SalErrorInfo *ei=&mReasonErrorInfo; // ?// + const char *protocol = belle_sip_header_reason_get_protocol(reason_header); + int code = belle_sip_header_reason_get_cause(reason_header); + const char *text = belle_sip_header_reason_get_text(reason_header); + sal_error_info_set(ei, SalReasonUnknown, protocol, code, text, NULL); + } +} + +void SalOp::setReferredBy(belle_sip_header_referred_by_t* referred_by) { + if (mReferredBy){ + belle_sip_object_unref(mReferredBy); + } + + mReferredBy=referred_by; + belle_sip_object_ref(mReferredBy); +} + +void SalOp::setReplaces(belle_sip_header_replaces_t* replaces) { + if (mReplaces){ + belle_sip_object_unref(mReplaces); + } + + mReplaces=replaces; + belle_sip_object_ref(mReplaces); +} + +int SalOp::sendRequestWithExpires(belle_sip_request_t* request,int expires) { + belle_sip_header_expires_t* expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_EXPIRES); + + if (!expires_header && expires>=0) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_HEADER(expires_header=belle_sip_header_expires_new())); + } + if (expires_header) belle_sip_header_expires_set_expires(expires_header,expires); + return sendRequest(request); +} + +int SalOp::sendRequestAndCreateRefresher(belle_sip_request_t* req, int expires,belle_sip_refresher_listener_t listener) { + if (sendRequestWithExpires(req,expires)==0) { + if (mRefresher) { + belle_sip_refresher_stop(mRefresher); + belle_sip_object_unref(mRefresher); + } + if ((mRefresher = belle_sip_client_transaction_create_refresher(mPendingClientTransaction))) { + /*since refresher acquires the transaction, we should remove our context from the transaction, because we won't be notified + * that it is terminated anymore.*/ + unref();/*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(). + Something in the design is not very good here, it makes things complicated to the belle-sip user. + Possible ideas to improve things: refresher shall not use belle_sip_transaction_set_application_data() internally, refresher should let the first transaction + notify the user as a normal transaction*/ + belle_sip_refresher_set_listener(mRefresher,listener, this); + belle_sip_refresher_set_retry_after(mRefresher,mRoot->mRefresherRetryAfter); + belle_sip_refresher_set_realm(mRefresher,L_STRING_TO_C(mRealm)); + belle_sip_refresher_enable_manual_mode(mRefresher, mManualRefresher); + return 0; + } else { + return -1; + } + } + return -1; +} + +belle_sip_header_contact_t *SalOp::createContact() { + belle_sip_header_contact_t* contact_header; + belle_sip_uri_t* contact_uri; + + if (getContactAddress()) { + contact_header = belle_sip_header_contact_create(BELLE_SIP_HEADER_ADDRESS(getContactAddress())); + } else { + contact_header= belle_sip_header_contact_new(); + } + + if (!(contact_uri=belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header)))) { + /*no uri, just creating a new one*/ + contact_uri=belle_sip_uri_new(); + belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact_header),contact_uri); + } + + belle_sip_uri_set_user_password(contact_uri,NULL); + belle_sip_uri_set_secure(contact_uri,isSecure()); + if (mPrivacy!=SalPrivacyNone){ + belle_sip_uri_set_user(contact_uri,NULL); + } + /*don't touch contact in case of gruu*/ + if (!belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header))),"gr")) { + belle_sip_header_contact_set_automatic(contact_header,mRoot->mAutoContacts); + if (!mRoot->mUuid.empty() + && !belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header), "+sip.instance") + ) { + stringstream ss; + ss << "\"mUuid << ">\""; + string instanceId = ss.str(); + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header), "+sip.instance", instanceId.c_str()); + } + } + if (!mRoot->mLinphoneSpecs.empty() + && !belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header), "+org.linphone.specs") + ) { + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header), "+org.linphone.specs", mRoot->mLinphoneSpecs.c_str()); + } + return contact_header; +} + +void SalOp::unlinkOpFromDialog(belle_sip_dialog_t* dialog) { + belle_sip_dialog_set_application_data(dialog,NULL); + unref(); + belle_sip_object_unref(dialog); +} + +belle_sip_dialog_t *SalOp::linkOpWithDialog(belle_sip_dialog_t* dialog) { + belle_sip_dialog_set_application_data(dialog,ref()); + belle_sip_object_ref(dialog); + return dialog; +} + +void SalOp::setOrUpdateDialog(belle_sip_dialog_t* dialog) { + ms_message("op [%p] : set_or_update_dialog() current=[%p] new=[%p]", this, mDialog,dialog); + ref(); + if (mDialog!=dialog){ + if (mDialog){ + // FIXME: Shouldn't we delete unconfirmed dialogs? + unlinkOpFromDialog(mDialog); + mDialog = nullptr; + } + if (dialog) { + mDialog=linkOpWithDialog(dialog); + belle_sip_dialog_enable_pending_trans_checking(dialog,mRoot->mPendingTransactionChecking); + } + } + unref(); +} + +int SalOp::ping (const string &from, const string &to) { + setFrom(from); + setTo(to); + return sendRequest(buildRequest("OPTIONS")); +} + +int SalOp::sendInfo (const SalBodyHandler *bodyHandler) { + if (mDialog && (belle_sip_dialog_get_state(mDialog) == BELLE_SIP_DIALOG_CONFIRMED)) { + belle_sip_dialog_enable_pending_trans_checking(mDialog, mRoot->mPendingTransactionChecking); + belle_sip_request_t *request = belle_sip_dialog_create_queued_request(mDialog, "INFO"); + belle_sip_message_set_body_handler(BELLE_SIP_MESSAGE(request), BELLE_SIP_BODY_HANDLER(bodyHandler)); + return sendRequest(request); + } else { + lError() << "Cannot send INFO message on op [" << this << "] because dialog is not in confirmed state yet"; + } + return -1; +} + +SalBodyHandler *SalOp::getBodyHandler(belle_sip_message_t *msg) { + belle_sip_body_handler_t *body_handler = belle_sip_message_get_body_handler(msg); + if (body_handler != NULL) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_type_t); + belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(msg, belle_sip_header_content_length_t); + belle_sip_header_t *content_encoding = belle_sip_message_get_header(msg, "Content-Encoding"); + if (content_type != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_type)); + if (content_length != NULL) belle_sip_body_handler_add_header(body_handler, BELLE_SIP_HEADER(content_length)); + if (content_encoding != NULL) belle_sip_body_handler_add_header(body_handler, content_encoding); + } + return (SalBodyHandler *)body_handler; +} + +void SalOp::assignRecvHeaders(belle_sip_message_t *incoming) { + if (incoming) belle_sip_object_ref(incoming); + if (mRecvCustomHeaders){ + belle_sip_object_unref(mRecvCustomHeaders); + mRecvCustomHeaders=NULL; + } + if (incoming){ + mRecvCustomHeaders=(SalCustomHeader*)incoming; + } +} + +void SalOp::setRemoteContact (const string &value) { + assignAddress(&mRemoteContactAddress, value); + mRemoteContact = value; // To preserve header params +} + +void SalOp::setNetworkOrigin (const string &value) { + assignAddress(&mOriginAddress, value); + if (mOriginAddress) { + char *valueStr = sal_address_as_string(mOriginAddress); + mOrigin = valueStr; + ms_free(valueStr); + } else { + mOrigin.clear(); + } +} + +void SalOp::setNetworkOriginAddress (SalAddress *value) { + char *valueStr = sal_address_as_string(value); // Can probably be optimized + setNetworkOrigin(valueStr); + ms_free(valueStr); +} + +/* +rfc3323 +4.2 Expressing Privacy Preferences +When a Privacy header is constructed, it MUST consist of either the +value 'none', or one or more of the values 'user', 'header' and +'session' (each of which MUST appear at most once) which MAY in turn +be followed by the 'critical' indicator. +*/ +void SalOp::setPrivacyFromMessage(belle_sip_message_t* msg) { + belle_sip_header_privacy_t* privacy = belle_sip_message_get_header_by_type(msg,belle_sip_header_privacy_t); + if (!privacy) { + setPrivacy(SalPrivacyNone); + } else { + belle_sip_list_t* privacy_list=belle_sip_header_privacy_get_privacy(privacy); + setPrivacy(0); + for (;privacy_list!=NULL;privacy_list=privacy_list->next) { + char* privacy_value=(char*)privacy_list->data; + if(strcmp(sal_privacy_to_string(SalPrivacyCritical),privacy_value) == 0) + setPrivacy(getPrivacy()|SalPrivacyCritical); + if(strcmp(sal_privacy_to_string(SalPrivacyHeader),privacy_value) == 0) + setPrivacy(getPrivacy()|SalPrivacyHeader); + if(strcmp(sal_privacy_to_string(SalPrivacyId),privacy_value) == 0) + setPrivacy(getPrivacy()|SalPrivacyId); + if(strcmp(sal_privacy_to_string(SalPrivacyNone),privacy_value) == 0) { + setPrivacy(SalPrivacyNone); + break; + } + if(strcmp(sal_privacy_to_string(SalPrivacySession),privacy_value) == 0) + setPrivacy(getPrivacy()|SalPrivacySession); + if(strcmp(sal_privacy_to_string(SalPrivacyUser),privacy_value) == 0) + setPrivacy(getPrivacy()|SalPrivacyUser); + } + } +} + +void SalOp::setRemoteUserAgent (belle_sip_message_t *message) { + belle_sip_header_user_agent_t *userAgentHeader = belle_sip_message_get_header_by_type(message, belle_sip_header_user_agent_t); + char userAgentStr[256]; + if (userAgentHeader + && belle_sip_header_user_agent_get_products_as_string(userAgentHeader, userAgentStr, sizeof(userAgentStr)) > 0 + ) { + mRemoteUserAgent = userAgentStr; + } +} + +string SalOp::toString (const Type type) { + switch (type) { + case Type::Register: + return "SalOpRegister"; + case Type::Call: + return "SalOpCall"; + case Type::Message: + return "SalOpMessage"; + case Type::Presence: + return "SalOpPresence"; + default: + return "SalOpUnknown"; + } +} + +bool SalOp::isSecure() const { + const SalAddress* from = getFromAddress(); + const SalAddress* to = getToAddress(); + return from && to && strcasecmp("sips",sal_address_get_scheme(from))==0 && strcasecmp("sips",sal_address_get_scheme(to))==0; +} + +/* + * Warning: this function takes owneship of the custom headers + */ +void SalOp::setSentCustomHeaders(SalCustomHeader* ch){ + if (mSentCustomHeaders){ + sal_custom_header_free(mSentCustomHeaders); + mSentCustomHeaders=NULL; + } + if (ch) belle_sip_object_ref((belle_sip_message_t*)ch); + mSentCustomHeaders=ch; +} + +void SalOp::addHeaders(belle_sip_header_t *h, belle_sip_message_t *msg){ + + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(h,belle_sip_header_contact_t)){ + belle_sip_header_contact_t* newct; + /*special case for contact, we want to keep everything from the custom contact but set automatic mode and add our own parameters as well*/ + setContactAddress((SalAddress*)BELLE_SIP_HEADER_ADDRESS(h)); + newct = createContact(); + belle_sip_message_set_header(BELLE_SIP_MESSAGE(msg),BELLE_SIP_HEADER(newct)); + return; + } + /*if a header already exists in the message, replace it*/ + belle_sip_message_set_header(msg,h); + +} + +void SalOp::addCustomHeaders(belle_sip_message_t *msg){ + if (mSentCustomHeaders){ + belle_sip_message_t *ch=(belle_sip_message_t*)mSentCustomHeaders; + belle_sip_list_t *l=belle_sip_message_get_all_headers(ch); + belle_sip_list_t *elem; + for(elem=l;elem!=NULL;elem=elem->next){ + addHeaders((belle_sip_header_t*)elem->data,msg); + } + belle_sip_list_free(l); + } +} + +int SalOp::unsubscribe(){ + if (mRefresher){ + const belle_sip_transaction_t *tr=(const belle_sip_transaction_t*) belle_sip_refresher_get_transaction(mRefresher); + belle_sip_request_t *last_req=belle_sip_transaction_get_request(tr); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(last_req), NULL, 0); + belle_sip_refresher_refresh(mRefresher,0); + return 0; + } + return -1; +} + +void SalOp::processIncomingMessage(const belle_sip_request_event_t *event) { + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(mRoot->mProvider,req); + belle_sip_header_address_t* address; + belle_sip_header_from_t* from_header; + belle_sip_header_content_type_t* content_type; + belle_sip_response_t* resp; + int errcode = 500; + belle_sip_header_call_id_t* call_id = belle_sip_message_get_header_by_type(req,belle_sip_header_call_id_t); + belle_sip_header_cseq_t* cseq = belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t); + belle_sip_header_date_t *date=belle_sip_message_get_header_by_type(req,belle_sip_header_date_t); + char* from; + bool external_body = false; + + from_header=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); + content_type=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_content_type_t); + + if (content_type) { + SalMessage salmsg; + char message_id[256]={0}; + + if (mPendingServerTransaction) belle_sip_object_unref(mPendingServerTransaction); + + mPendingServerTransaction=server_transaction; + belle_sip_object_ref(mPendingServerTransaction); + + external_body=isExternalBody(content_type); + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); + from=belle_sip_object_to_string(BELLE_SIP_OBJECT(address)); + snprintf(message_id,sizeof(message_id)-1,"%s%i" + ,belle_sip_header_call_id_get_call_id(call_id) + ,belle_sip_header_cseq_get_seq_number(cseq)); + salmsg.from=from; + /* if we just deciphered a message, use the deciphered part(which can be a rcs xml body pointing to the file to retreive from server)*/ + salmsg.text=(!external_body)?belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)):NULL; + salmsg.url=NULL; + + char buffer[1024]; + size_t offset = 0; + belle_sip_parameters_marshal(BELLE_SIP_PARAMETERS(content_type), buffer, 1024, &offset); + buffer[offset] = '\0'; + salmsg.content_type = ms_strdup_printf("%s/%s%s", belle_sip_header_content_type_get_type(content_type), belle_sip_header_content_type_get_subtype(content_type), buffer); + if (external_body && belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")) { + size_t url_length=strlen(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")); + salmsg.url = ms_strdup(belle_sip_parameters_get_parameter(BELLE_SIP_PARAMETERS(content_type),"URL")+1); /* skip first "*/ + ((char*)salmsg.url)[url_length-2]='\0'; /*remove trailing "*/ + } + + salmsg.message_id=message_id; + salmsg.time=date ? belle_sip_header_date_get_time(date) : time(NULL); + mRoot->mCallbacks.message_received(this,&salmsg); + + belle_sip_object_unref(address); + belle_sip_free(from); + if (salmsg.url) ms_free((char*)salmsg.url); + ms_free((char *)salmsg.content_type); + } else { + bctbx_error("Unsupported MESSAGE (no Content-Type)"); + resp = belle_sip_response_create_from_request(req, errcode); + addMessageAccept((belle_sip_message_t*)resp); + belle_sip_server_transaction_send_response(server_transaction,resp); + release(); + } +} + +bool SalOp::isExternalBody(belle_sip_header_content_type_t* content_type) { + return strcmp("message",belle_sip_header_content_type_get_type(content_type))==0 + && strcmp("external-body",belle_sip_header_content_type_get_subtype(content_type))==0; +} + +int SalOp::replyMessage(SalReason reason) { + if (mPendingServerTransaction){ + int code=to_sip_code(reason); + belle_sip_response_t *resp = belle_sip_response_create_from_request( + belle_sip_transaction_get_request((belle_sip_transaction_t*)mPendingServerTransaction),code); + belle_sip_server_transaction_send_response(mPendingServerTransaction,resp); + return 0; + } + + bctbx_error("sal_message_reply(): no server transaction"); + return -1; +} + +void SalOp::addMessageAccept (belle_sip_message_t *message) { + stringstream ss; + ss << "xml/cipher, application/cipher.vnd.gsma.rcs-ft-http+xml"; + for (const auto &supportedContentType : mRoot->mSupportedContentTypes) + ss << ", " << supportedContentType; + string headerValue = ss.str(); + belle_sip_message_add_header(message, belle_sip_header_create("Accept", headerValue.c_str())); +} + +void SalOp::setServiceRoute(const SalAddress* service_route) { + if (mServiceRoute) + sal_address_destroy(mServiceRoute); + + mServiceRoute=service_route?sal_address_clone(service_route):NULL; +} + +LINPHONE_END_NAMESPACE diff --git a/src/sal/op.h b/src/sal/op.h new file mode 100644 index 000000000..501ee2f60 --- /dev/null +++ b/src/sal/op.h @@ -0,0 +1,274 @@ +/* + * op.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_OP_H_ +#define _L_SAL_OP_H_ + +#include +#include +#include + +#include "c-wrapper/internal/c-sal.h" +#include "content/content.h" +#include "logger/logger.h" +#include "sal/sal.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalOp { +public: + SalOp (Sal *sal); + virtual ~SalOp (); + + SalOp *ref (); + void *unref (); + + Sal *getSal () const { return mRoot; } + + void setUserPointer (void *value) { mUserPointer = value; } + void *getUserPointer () const { return mUserPointer; } + + void setSubject (const std::string &value) { mSubject = value; } + const std::string &getSubject () const { return mSubject; } + + void setFrom (const std::string &value); + void setFromAddress (const SalAddress *value); + const std::string &getFrom () const { return mFrom; } + const SalAddress *getFromAddress () const { return mFromAddress; } + + void setTo (const std::string &value); + void setToAddress (const SalAddress *value); + const std::string &getTo () const { return mTo; } + const SalAddress *getToAddress () const { return mToAddress; } + + void setContactAddress (const SalAddress* value); + const SalAddress *getContactAddress() const { return mContactAddress; } + + void setRoute (const std::string &value); + void setRouteAddress (const SalAddress *value); + const std::list &getRouteAddresses () const { return mRouteAddresses; } + void addRouteAddress (const SalAddress *address); + + void setDiversionAddress (const SalAddress *value); + const SalAddress *getDiversionAddress () const { return mDiversionAddress; } + + void setServiceRoute (const SalAddress *value); + const SalAddress *getServiceRoute () const { return mServiceRoute; } + + void setManualRefresherMode (bool value) { mManualRefresher = value; } + + void setEntityTag (const std::string &value) { mEntityTag = value; } + const std::string &getEntityTag() const { return mEntityTag; } + + void setEvent (const std::string &eventName); + + void setPrivacy (SalPrivacyMask value) { mPrivacy = value; } + SalPrivacyMask getPrivacy() const { return mPrivacy; } + + void setRealm (const std::string &value) { mRealm = value; } + + void setSentCustomHeaders (SalCustomHeader *ch); + + void enableCnxIpTo0000IfSendOnly (bool value) { mCnxIpTo0000IfSendOnlyEnabled = value; } + bool cnxIpTo0000IfSendOnlyEnabled () const { return mCnxIpTo0000IfSendOnlyEnabled; } + + const std::string &getProxy () const { return mRoute; } + const std::string &getNetworkOrigin () const { return mOrigin; } + const std::string &getCallId () const { return mCallId; } + std::string getDialogId () const; + int getAddressFamily () const; + const SalCustomHeader *getRecvCustomHeaders () const { return mRecvCustomHeaders; } + const std::string &getRemoteContact () const { return mRemoteContact; } + const SalAddress *getRemoteContactAddress () const { return mRemoteContactAddress; } + const std::string &getRemoteUserAgent () const { return mRemoteUserAgent; } + + const char *getPublicAddress (int *port) { + return mRefresher ? belle_sip_refresher_get_public_address(mRefresher, port) : nullptr; + } + const char *getLocalAddress (int *port) { + return mRefresher ? belle_sip_refresher_get_local_address(mRefresher, port) : nullptr; + } + + const SalErrorInfo *getErrorInfo () const { return &mErrorInfo; } + const SalErrorInfo *getReasonErrorInfo () const { return &mReasonErrorInfo; } + + bool isForkedOf (const SalOp *op) const { + return !mCallId.empty() && !op->mCallId.empty() && (mCallId == op->mCallId); + } + bool isIdle () const; + + void stopRefreshing () { + if (mRefresher) + belle_sip_refresher_stop(mRefresher); + } + int refresh (); + void killDialog (); + void release (); + + virtual void authenticate (const SalAuthInfo *info) { + processAuthentication(); } + void cancelAuthentication () { lFatal() << "SalOp::cancelAuthentication not implemented yet"; } + SalAuthInfo *getAuthRequested () { return mAuthInfo; } + + int ping (const std::string &from, const std::string &to); + int sendInfo (const SalBodyHandler *bodyHandler); + +protected: + enum class State { + Early = 0, + Active, + Terminating, // This state is used to wait until a proceeding state, so we can send the cancel + Terminated + }; + + static std::string toString (const State value); + + enum class Dir { + Incoming = 0, + Outgoing + }; + + enum class Type { + Unknown, + Register, + Call, + Message, + Presence, + Publish, + Subscribe, + Refer // For out of dialog refer only + }; + + static std::string toString (const Type type); + + using ReleaseCb = void (*) (SalOp *op); + + virtual void fillCallbacks () {} + void releaseImpl (); + void processAuthentication (); + int processRedirect (); + + belle_sip_request_t *buildRequest (const std::string &method); + int sendRequest (belle_sip_request_t *request); + int sendRequestWithContact (belle_sip_request_t *request, bool addContact); + int sendRequestWithExpires (belle_sip_request_t *request, int expires); + void resendRequest (belle_sip_request_t *request); + int sendRequestAndCreateRefresher (belle_sip_request_t *request, int expires, belle_sip_refresher_listener_t listener); + + void setReasonErrorInfo (belle_sip_message_t *message); + void setErrorInfoFromResponse (belle_sip_response_t *response); + + void setReferredBy (belle_sip_header_referred_by_t *referredByHeader); + void setReplaces (belle_sip_header_replaces_t *replacesHeader); + + void setRemoteContact (const std::string &value); + void setNetworkOrigin (const std::string &value); + void setNetworkOriginAddress (SalAddress *value); + void setPrivacyFromMessage (belle_sip_message_t *message); + void setRemoteUserAgent (belle_sip_message_t *message); + + belle_sip_response_t *createResponseFromRequest (belle_sip_request_t *request, int code) { + return mRoot->createResponseFromRequest(request, code); + } + belle_sip_header_contact_t *createContact (); + + void setOrUpdateDialog (belle_sip_dialog_t *dialog); + belle_sip_dialog_t *linkOpWithDialog (belle_sip_dialog_t *dialog); + void unlinkOpFromDialog (belle_sip_dialog_t *dialog); + + SalBodyHandler *getBodyHandler (belle_sip_message_t *message); + + void assignRecvHeaders (belle_sip_message_t *message); + + bool isSecure () const; + void addHeaders (belle_sip_header_t *h, belle_sip_message_t *message); + void addCustomHeaders (belle_sip_message_t *message); + int unsubscribe (); + + void processIncomingMessage (const belle_sip_request_event_t *event); + int replyMessage (SalReason reason); + void addMessageAccept (belle_sip_message_t *message); + + static bool isExternalBody (belle_sip_header_content_type_t* contentType); + + static void assignAddress (SalAddress **address, const std::string &value); + static void addInitialRouteSet (belle_sip_request_t *request, const std::list &routeAddresses); + + // SalOpBase + Sal *mRoot = nullptr; + std::string mRoute; // Or request-uri for REGISTER + std::list mRouteAddresses; + SalAddress *mContactAddress = nullptr; + std::string mSubject; + std::string mFrom; + SalAddress* mFromAddress = nullptr; + std::string mTo; + SalAddress *mToAddress = nullptr; + std::string mOrigin; + SalAddress *mOriginAddress = nullptr; + SalAddress *mDiversionAddress = nullptr; + std::string mRemoteUserAgent; + SalAddress *mRemoteContactAddress = nullptr; + std::string mRemoteContact; + void *mUserPointer = nullptr; + std::string mCallId; + std::string mRealm; + SalAddress *mServiceRoute = nullptr; // As defined by rfc3608, might be a list + SalCustomHeader *mSentCustomHeaders = nullptr; + SalCustomHeader *mRecvCustomHeaders = nullptr; + std::string mEntityTag; // As defined by rfc3903 (I.E publih) + ReleaseCb mReleaseCb = nullptr; + + const belle_sip_listener_callbacks_t *mCallbacks = nullptr; + SalErrorInfo mErrorInfo; + SalErrorInfo mReasonErrorInfo; + belle_sip_client_transaction_t *mPendingAuthTransaction = nullptr; + belle_sip_server_transaction_t *mPendingServerTransaction = nullptr; + belle_sip_server_transaction_t *mPendingUpdateServerTransaction = nullptr; + belle_sip_client_transaction_t *mPendingClientTransaction = nullptr; + SalAuthInfo *mAuthInfo = nullptr; + belle_sip_dialog_t *mDialog = nullptr; + belle_sip_header_replaces_t *mReplaces = nullptr; + belle_sip_header_referred_by_t *mReferredBy = nullptr; + SalMediaDescription *mResult = nullptr; + belle_sdp_session_description_t *mSdpAnswer = nullptr; + State mState = State::Early; + Dir mDir = Dir::Incoming; + belle_sip_refresher_t *mRefresher = nullptr; + int mRef = 0; + Type mType = Type::Unknown; + SalPrivacyMask mPrivacy = SalPrivacyNone; + belle_sip_header_event_t *mEvent = nullptr; // Used by SalOpSubscribe kinds + SalOpSDPHandling mSdpHandling = SalOpSDPNormal; + int mAuthRequests = 0; // number of auth requested for this op + bool mCnxIpTo0000IfSendOnlyEnabled = false; + bool mAutoAnswerAsked = false; + bool mSdpOffering = false; + bool mCallReleased = false; + bool mManualRefresher = false; + bool mHasAuthPending = false; + bool mSupportsSessionTimers = false; + bool mOpReleased = false; + + friend class Sal; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_OP_H_ diff --git a/src/sal/presence-op.cpp b/src/sal/presence-op.cpp new file mode 100644 index 000000000..4ba469ebd --- /dev/null +++ b/src/sal/presence-op.cpp @@ -0,0 +1,453 @@ +/* + * presence-op.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "c-wrapper/internal/c-tools.h" +#include "sal/presence-op.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void SalPresenceOp::presenceProcessIoErrorCb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)user_ctx; + belle_sip_request_t* request; + belle_sip_client_transaction_t* client_transaction = NULL; + + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event), + belle_sip_client_transaction_t)){ + client_transaction = (belle_sip_client_transaction_t*)belle_sip_io_error_event_get_source(event); + } + + if (!client_transaction) return; + + request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + + if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ + if (op->mRefresher){ + ms_warning("presence_process_io_error() refresher is present, should not happen"); + return; + } + ms_message("subscription to [%s] io error",op->getTo().c_str()); + if (!op->mOpReleased){ + op->mRoot->mCallbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ + } + } +} + +void SalPresenceOp::presenceRefresherListenerCb(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry) { + SalPresenceOp * op = (SalPresenceOp *)user_pointer; + if (status_code >= 300) { + ms_message("The SUBSCRIBE dialog no longer works. Let's restart a new one."); + belle_sip_refresher_stop(op->mRefresher); + if (op->mDialog) { /*delete previous dialog if any*/ + op->setOrUpdateDialog(NULL); + } + + if (op->getContactAddress()) { + /*contact is also probably not good*/ + SalAddress* contact=sal_address_clone(op->getContactAddress()); + sal_address_set_port(contact,-1); + sal_address_set_domain(contact,NULL); + op->setContactAddress(contact); + sal_address_destroy(contact); + } + /*send a new SUBSCRIBE, that will attempt to establish a new dialog*/ + op->subscribe(NULL,NULL,-1); + } + if (status_code == 0 || status_code == 503){ + /*timeout or io error: the remote doesn't seem reachable.*/ + if (!op->mOpReleased){ + op->mRoot->mCallbacks.notify_presence(op,SalSubscribeActive, NULL,NULL); /*NULL = offline*/ + } + } +} + +void SalPresenceOp::presenceResponseEventCb(void *op_base, const belle_sip_response_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)op_base; + belle_sip_dialog_state_t dialog_state; + belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); + belle_sip_response_t* response=belle_sip_response_event_get_response(event); + 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; + + op->setErrorInfoFromResponse(response); + + if (code>=300) { + if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ + ms_message("subscription to [%s] rejected",op->getTo().c_str()); + if (!op->mOpReleased){ + op->mRoot->mCallbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ + } + return; + } + } + op->setOrUpdateDialog(belle_sip_response_event_get_dialog(event)); + if (!op->mDialog) { + ms_message("presence op [%p] receive out of dialog answer [%i]",op,code); + return; + } + dialog_state=belle_sip_dialog_get_state(op->mDialog); + + switch(dialog_state) { + case BELLE_SIP_DIALOG_NULL: + case BELLE_SIP_DIALOG_EARLY: { + ms_error("presence op [%p] receive an unexpected answer [%i]",op,code); + break; + } + case BELLE_SIP_DIALOG_CONFIRMED: { + if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0) { + expires=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t); + if(op->mRefresher) { + belle_sip_refresher_stop(op->mRefresher); + belle_sip_object_unref(op->mRefresher); + op->mRefresher=NULL; + } + if ((expires != NULL) && (belle_sip_header_expires_get_expires(expires) > 0)) { + op->mRefresher=belle_sip_client_transaction_create_refresher(client_transaction); + belle_sip_refresher_set_listener(op->mRefresher,presenceRefresherListenerCb,op); + belle_sip_refresher_set_realm(op->mRefresher,L_STRING_TO_C(op->mRealm)); + } + } + break; + } + default: { + ms_error("presence op [%p] receive answer [%i] not implemented",op,code); + } + /* no break */ + } +} + +void SalPresenceOp::presenceProcessTimeoutCb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)user_ctx; + belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); + belle_sip_request_t* request; + + if (!client_transaction) return; + + request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + + if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0){ + ms_message("subscription to [%s] timeout",op->getTo().c_str()); + if (!op->mOpReleased){ + op->mRoot->mCallbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/ + } + } +} + +void SalPresenceOp::presenceProcessTransactionTerminatedCb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { + ms_message("presence_process_transaction_terminated not implemented yet"); +} + +SalPresenceModel *SalPresenceOp::processPresenceNotification(belle_sip_request_t *req) { + belle_sip_header_content_type_t *content_type = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_type_t); + belle_sip_header_content_length_t *content_length = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_content_length_t); + const char *body = belle_sip_message_get_body(BELLE_SIP_MESSAGE(req)); + SalPresenceModel *result = NULL; + + if ((content_type == NULL) || (content_length == NULL)) + return NULL; + if (belle_sip_header_content_length_get_content_length(content_length) == 0) + return NULL; + + if (body==NULL) return NULL; + if (!mOpReleased){ + mRoot->mCallbacks.parse_presence_requested(this, + belle_sip_header_content_type_get_type(content_type), + belle_sip_header_content_type_get_subtype(content_type), + body, + &result); + } + + return result; +} + +void SalPresenceOp::handleNotify(belle_sip_request_t *req, belle_sip_dialog_t *dialog) { + belle_sip_response_t* resp=NULL; + belle_sip_server_transaction_t* server_transaction= mPendingServerTransaction; + 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)); + + if (mDialog !=NULL && dialog != mDialog){ + ms_warning("Receiving a NOTIFY from a dialog we haven't stored (op->dialog=%p dialog=%p)", mDialog, dialog); + } + if (!subscription_state_header || strcasecmp(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,belle_sip_header_subscription_state_get_state(subscription_state_header)) ==0) { + sub_state=SalSubscribeTerminated; + ms_message("Outgoing subscription terminated by remote [%s]",getTo().c_str()); + } else { + sub_state=getSubscriptionState(BELLE_SIP_MESSAGE(req)); + } + presence_model = processPresenceNotification(req); + if (presence_model != NULL || body==NULL) { + /* Presence notification body parsed successfully. */ + + resp = createResponseFromRequest(req, 200); /*create first because the op may be destroyed by notify_presence */ + if (!mOpReleased){ + mRoot->mCallbacks.notify_presence(this, sub_state, presence_model, NULL); + } + } else if (body){ + /* Formatting error in presence notification body. */ + ms_warning("Wrongly formatted presence document."); + resp = createResponseFromRequest(req, 488); + } + if (resp) belle_sip_server_transaction_send_response(server_transaction,resp); + } +} + +void SalPresenceOp::presenceProcessRequestEventCb(void *op_base, const belle_sip_request_event_t *event) { + SalPresenceOp * op = (SalPresenceOp *)op_base; + belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->mRoot->mProvider,belle_sip_request_event_get_request(event)); + belle_sip_request_t* req = belle_sip_request_event_get_request(event); + belle_sip_dialog_state_t dialog_state; + belle_sip_response_t* resp; + const char *method=belle_sip_request_get_method(req); + belle_sip_header_event_t *event_header; + belle_sip_object_ref(server_transaction); + if (op->mPendingServerTransaction) belle_sip_object_unref(op->mPendingServerTransaction); + op->mPendingServerTransaction=server_transaction; + event_header=belle_sip_message_get_header_by_type(req,belle_sip_header_event_t); + + if (event_header==NULL){ + ms_warning("No event header in incoming SUBSCRIBE."); + resp=op->createResponseFromRequest(req,400); + belle_sip_server_transaction_send_response(server_transaction,resp); + if (!op->mDialog) op->release(); + return; + } + if (op->mEvent==NULL) { + op->mEvent=event_header; + belle_sip_object_ref(op->mEvent); + } + + + if (!op->mDialog) { + if (strcmp(method,"SUBSCRIBE")==0){ + belle_sip_dialog_t *dialog = belle_sip_provider_create_dialog(op->mRoot->mProvider,BELLE_SIP_TRANSACTION(server_transaction)); + if (!dialog){ + resp=op->createResponseFromRequest(req,481); + belle_sip_server_transaction_send_response(server_transaction,resp); + op->release(); + return; + } + op->setOrUpdateDialog(dialog); + ms_message("new incoming subscription from [%s] to [%s]",op->getFrom().c_str(),op->getTo().c_str()); + }else if (strcmp(method,"NOTIFY")==0 && belle_sip_request_event_get_dialog(event)) { + /*special case of dialog created by notify matching subscribe*/ + op->setOrUpdateDialog(belle_sip_request_event_get_dialog(event)); + } else {/* this is a NOTIFY */ + ms_message("Receiving out of dialog notify"); + op->handleNotify(req, belle_sip_request_event_get_dialog(event)); + return; + } + } + dialog_state=belle_sip_dialog_get_state(op->mDialog); + switch(dialog_state) { + case BELLE_SIP_DIALOG_NULL: { + if (strcmp("NOTIFY",method)==0) { + op->handleNotify(req, belle_sip_request_event_get_dialog(event)); + } else if (strcmp("SUBSCRIBE",method)==0) { + op->mRoot->mCallbacks.subscribe_presence_received(op,op->getFrom().c_str()); + } + break; + } + case BELLE_SIP_DIALOG_EARLY: + ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",method,op->mDialog); + break; + + case BELLE_SIP_DIALOG_CONFIRMED: + if (strcmp("NOTIFY",method)==0) { + op->handleNotify(req, belle_sip_request_event_get_dialog(event)); + } else if (strcmp("SUBSCRIBE",method)==0) { + /*either a refresh or an unsubscribe. + If it is a refresh there is nothing to notify to the app. If it is an unSUBSCRIBE, then the dialog + will be terminated shortly, and this will be notified to the app through the dialog_terminated callback.*/ + resp=op->createResponseFromRequest(req,200); + belle_sip_server_transaction_send_response(server_transaction,resp); + } + break; + default: + ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state)); + break; + } +} + +void SalPresenceOp::presenceProcessDialogTerminatedCb(void *ctx, const belle_sip_dialog_terminated_event_t *event) { + SalPresenceOp * op= (SalPresenceOp *)ctx; + if (op->mDialog && belle_sip_dialog_is_server(op->mDialog)) { + ms_message("Incoming subscribtion from [%s] terminated",op->getFrom().c_str()); + if (!op->mOpReleased){ + op->mRoot->mCallbacks.subscribe_presence_closed(op, op->getFrom().c_str()); + } + op->setOrUpdateDialog(NULL); + }/* else client dialog is managed by refresher*/ +} + +void SalPresenceOp::releaseCb(SalOp *op_base) { + SalPresenceOp *op =(SalPresenceOp *)op_base; + if(op->mRefresher) { + belle_sip_refresher_stop(op->mRefresher); + belle_sip_object_unref(op->mRefresher); + op->mRefresher=NULL; + op->setOrUpdateDialog(NULL); /*only if we have refresher. else dialog terminated event will remove association*/ + } +} + +void SalPresenceOp::fillCallbacks() { + static belle_sip_listener_callbacks_t op_presence_callbacks={0}; + if (op_presence_callbacks.process_request_event==NULL){ + op_presence_callbacks.process_io_error=presenceProcessIoErrorCb; + op_presence_callbacks.process_response_event=presenceResponseEventCb; + op_presence_callbacks.process_timeout= presenceProcessTimeoutCb; + op_presence_callbacks.process_transaction_terminated=presenceProcessTransactionTerminatedCb; + op_presence_callbacks.process_request_event=presenceProcessRequestEventCb; + op_presence_callbacks.process_dialog_terminated=presenceProcessDialogTerminatedCb; + } + mCallbacks=&op_presence_callbacks; + mType=Type::Presence; + mReleaseCb=releaseCb; +} + +int SalPresenceOp::subscribe(const char *from, const char *to, int expires) { + belle_sip_request_t *req=NULL; + if (from) + setFrom(from); + if (to) + setTo(to); + + fillCallbacks(); + + if (expires==-1){ + if (mRefresher){ + expires=belle_sip_refresher_get_expires(mRefresher); + belle_sip_object_unref(mRefresher); + mRefresher=NULL; + }else{ + ms_error("sal_subscribe_presence(): cannot guess expires from previous refresher."); + return -1; + } + } + if (!mEvent){ + mEvent=belle_sip_header_event_create("presence"); + belle_sip_object_ref(mEvent); + } + belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(mFromAddress),"tag"); + belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(mToAddress),"tag"); + req=buildRequest("SUBSCRIBE"); + if( req ){ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(mEvent)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(expires))); + } + + return sendRequest(req); +} + +int SalPresenceOp::checkDialogState() { + belle_sip_dialog_state_t state= mDialog?belle_sip_dialog_get_state(mDialog): BELLE_SIP_DIALOG_NULL; + if (state != BELLE_SIP_DIALOG_CONFIRMED) { + ms_warning("Cannot notify presence for op [%p] because dialog in state [%s]", this, belle_sip_dialog_state_to_string(state)); + return -1; + } else + return 0; +} + +belle_sip_request_t *SalPresenceOp::createPresenceNotify() { + belle_sip_request_t* notify=belle_sip_dialog_create_queued_request(mDialog,"NOTIFY"); + if (!notify) return NULL; + + belle_sip_message_add_header((belle_sip_message_t*)notify,belle_sip_header_create("Event","presence")); + return notify; +} + +void SalPresenceOp::addPresenceInfo(belle_sip_message_t *notify, SalPresenceModel *presence) { + char *contact_info; + char *content = NULL; + size_t content_length; + + if (presence){ + belle_sip_header_from_t *from=belle_sip_message_get_header_by_type(notify,belle_sip_header_from_t); + contact_info=belle_sip_uri_to_string(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from))); + mRoot->mCallbacks.convert_presence_to_xml_requested(this, presence, contact_info, &content); + belle_sip_free(contact_info); + if (content == NULL) return; + } + + 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"))); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_content_length_create(content_length=strlen(content)))); + belle_sip_message_set_body(BELLE_SIP_MESSAGE(notify),content,content_length); + ms_free(content); + } +} + +int SalPresenceOp::notifyPresence(SalPresenceModel *presence) { + belle_sip_request_t* notify=NULL; + if (checkDialogState()) { + return -1; + } + notify=createPresenceNotify(); + if (!notify) return-1; + + addPresenceInfo(BELLE_SIP_MESSAGE(notify),presence); /*FIXME, what about expires ??*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE,600))); + return sendRequest(notify); +} + +int SalPresenceOp::notifyPresenceClose() { + belle_sip_request_t* notify=NULL; + int status; + if (checkDialogState()) { + return -1; + } + notify=createPresenceNotify(); + if (!notify) return-1; + + addPresenceInfo(BELLE_SIP_MESSAGE(notify),NULL); /*FIXME, what about expires ??*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(notify) + ,BELLE_SIP_HEADER(belle_sip_header_subscription_state_create(BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED,-1))); + status = sendRequest(notify); + setOrUpdateDialog(NULL); /*because we may be chalanged for the notify, so we must release dialog right now*/ + return status; +} + +SalSubscribeStatus SalPresenceOp::getSubscriptionState(const belle_sip_message_t *msg) { + belle_sip_header_subscription_state_t* subscription_state_header=belle_sip_message_get_header_by_type(msg,belle_sip_header_subscription_state_t); + SalSubscribeStatus sss=SalSubscribeNone; + if (subscription_state_header){ + if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_TERMINATED)==0) + sss=SalSubscribeTerminated; + else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_PENDING)==0) + sss=SalSubscribePending; + else if (strcmp(belle_sip_header_subscription_state_get_state(subscription_state_header),BELLE_SIP_SUBSCRIPTION_STATE_ACTIVE)==0) + sss=SalSubscribeActive; + } + return sss; +} + +LINPHONE_END_NAMESPACE diff --git a/src/sal/presence-op.h b/src/sal/presence-op.h new file mode 100644 index 000000000..72e5238a5 --- /dev/null +++ b/src/sal/presence-op.h @@ -0,0 +1,58 @@ +/* + * presence-op.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_PRESENCE_OP_H_ +#define _L_SAL_PRESENCE_OP_H_ + +#include "sal/event-op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalPresenceOp : public SalSubscribeOp { +public: + SalPresenceOp (Sal *sal) : SalSubscribeOp(sal) {} + + int subscribe (const char *from, const char *to, int expires); + int unsubscribe () { return SalOp::unsubscribe(); } + int notifyPresence (SalPresenceModel *presence); + int notifyPresenceClose (); + +private: + virtual void fillCallbacks () override; + void handleNotify (belle_sip_request_t *request, belle_sip_dialog_t *dialog); + SalPresenceModel *processPresenceNotification (belle_sip_request_t *request); + int checkDialogState (); + belle_sip_request_t *createPresenceNotify (); + void addPresenceInfo (belle_sip_message_t *notify, SalPresenceModel *presence); + + static SalSubscribeStatus getSubscriptionState (const belle_sip_message_t *message); + + static void presenceProcessIoErrorCb (void *userCtx, const belle_sip_io_error_event_t *event); + static void presenceResponseEventCb (void *userCtx, const belle_sip_response_event_t *event); + static void presenceRefresherListenerCb (belle_sip_refresher_t *refresher, void *userCtx, unsigned int statusCode, const char *reasonPhrase, int willRetry); + static void presenceProcessTimeoutCb (void *userCtx, const belle_sip_timeout_event_t *event); + static void presenceProcessTransactionTerminatedCb (void *userCtx, const belle_sip_transaction_terminated_event_t *event); + static void presenceProcessRequestEventCb (void *userCtx, const belle_sip_request_event_t *event); + static void presenceProcessDialogTerminatedCb (void *userCtx, const belle_sip_dialog_terminated_event_t *event); + static void releaseCb (SalOp *op); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_PRESENCE_OP_H_ diff --git a/src/sal/refer-op.cpp b/src/sal/refer-op.cpp new file mode 100644 index 000000000..93d36e1dd --- /dev/null +++ b/src/sal/refer-op.cpp @@ -0,0 +1,114 @@ +/* + Linphone library + Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "sal/refer-op.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void SalReferOp::processError() { + mState=State::Terminated; +} + +void SalReferOp::processIoErrorCb(void *user_ctx, const belle_sip_io_error_event_t *event) { + SalReferOp * op = (SalReferOp *)user_ctx; + sal_error_info_set(&op->mErrorInfo,SalReasonIOError, "SIP", 503,"IO Error",NULL); + op->processError(); +} + +void SalReferOp::processResponseEventCb(void *op_base, const belle_sip_response_event_t *event) { + SalReferOp * op = (SalReferOp *)op_base; + op->setErrorInfoFromResponse(belle_sip_response_event_get_response(event)); + /*the response is not notified to the app*/ + /*To be done when necessary*/ +} + +void SalReferOp::processTimeoutCb(void *user_ctx, const belle_sip_timeout_event_t *event) { + SalReferOp * op=(SalReferOp *)user_ctx; + sal_error_info_set(&op->mErrorInfo,SalReasonRequestTimeout, "SIP", 408,"Request timeout",NULL); + op->processError(); +} + +void SalReferOp::processRequestEventCb(void *op_base, const belle_sip_request_event_t *event) { + SalReferOp * op = (SalReferOp *)op_base; + belle_sip_request_t *req = belle_sip_request_event_get_request(event); + belle_sip_header_refer_to_t *refer_to= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_refer_to_t); + belle_sip_server_transaction_t *server_transaction = belle_sip_provider_create_server_transaction(op->mRoot->mProvider,belle_sip_request_event_get_request(event)); + + belle_sip_object_ref(server_transaction); + belle_sip_transaction_set_application_data(BELLE_SIP_TRANSACTION(server_transaction),op->ref()); + op->mPendingServerTransaction = server_transaction; + + if (!refer_to){ + ms_warning("cannot do anything with the refer without destination"); + op->reply(SalReasonUnknown);/*is mapped on bad request*/ + op->unref(); + return; + } + SalAddress *referToAddr = sal_address_new(belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(refer_to))); + op->mRoot->mCallbacks.refer_received(op, referToAddr); + /*the app is expected to reply in the callback*/ + sal_address_unref(referToAddr); + op->unref(); +} + +void SalReferOp::fillCallbacks() { + static belle_sip_listener_callbacks_t op_refer_callbacks = {0}; + if (op_refer_callbacks.process_io_error==NULL) { + op_refer_callbacks.process_io_error=processIoErrorCb; + op_refer_callbacks.process_response_event=processResponseEventCb; + op_refer_callbacks.process_timeout=processTimeoutCb; + op_refer_callbacks.process_request_event=processRequestEventCb; + } + mCallbacks=&op_refer_callbacks; + mType=Type::Refer; +} + +SalReferOp::SalReferOp(Sal *sal) : SalOp(sal){ + fillCallbacks(); +} + +int SalReferOp::sendRefer(const SalAddress *refer_to) { + mDir=Dir::Outgoing; + + belle_sip_request_t* req=buildRequest("REFER"); + if (req == NULL ) return -1; + if (getContactAddress()) belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(createContact())); + belle_sip_header_address_t *address = BELLE_SIP_HEADER_ADDRESS(refer_to); + belle_sip_uri_t *uri = belle_sip_header_address_get_uri(address); + if (!belle_sip_uri_get_host(uri)) + belle_sip_header_address_set_automatic(address, true); + belle_sip_header_refer_to_t *refer_to_header = belle_sip_header_refer_to_create(address); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(refer_to_header)); + return sendRequest(req); +} + +int SalReferOp::reply(SalReason reason){ + if (mPendingServerTransaction){ + int code=to_sip_code(reason); + belle_sip_response_t *resp = belle_sip_response_create_from_request( + belle_sip_transaction_get_request((belle_sip_transaction_t*)mPendingServerTransaction),code); + belle_sip_server_transaction_send_response(mPendingServerTransaction,resp); + return 0; + }else ms_error("SalReferOp::reply: no server transaction"); + return -1; +} + +LINPHONE_END_NAMESPACE diff --git a/src/sal/refer-op.h b/src/sal/refer-op.h new file mode 100644 index 000000000..74300e7f9 --- /dev/null +++ b/src/sal/refer-op.h @@ -0,0 +1,46 @@ +/* + Linphone library + Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_REFER_OP_H_ +#define _L_SAL_REFER_OP_H_ + +#include "sal/op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalReferOp : public SalOp { +public: + SalReferOp (Sal *sal); + + int sendRefer (const SalAddress *referTo); + int reply (SalReason reason); + +private: + virtual void fillCallbacks () override; + void processError (); + + static void processIoErrorCb (void *userCtx, const belle_sip_io_error_event_t *event); + static void processResponseEventCb (void *userCtx, const belle_sip_response_event_t *event); + static void processTimeoutCb (void *userCtx, const belle_sip_timeout_event_t *event); + static void processRequestEventCb (void *userCtx, const belle_sip_request_event_t *event); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_REFER_OP_H_ diff --git a/coreapi/bellesip_sal/sal_op_registration.c b/src/sal/register-op.cpp similarity index 50% rename from coreapi/bellesip_sal/sal_op_registration.c rename to src/sal/register-op.cpp index 3526152e0..63c0e8759 100644 --- a/coreapi/bellesip_sal/sal_op_registration.c +++ b/src/sal/register-op.cpp @@ -1,40 +1,83 @@ /* -linphone -Copyright (C) 2012 Belledonne Communications, Grenoble, France + * register-op.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ -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. +#include "sal/register-op.h" +#include "bellesip_sal/sal_impl.h" -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. +using namespace std; -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -*/ -#include "sal_impl.h" +LINPHONE_BEGIN_NAMESPACE +int SalRegisterOp::sendRegister(const char *proxy, const char *from, int expires, const SalAddress* old_contact) { + belle_sip_request_t *req; + belle_sip_uri_t* req_uri; + belle_sip_header_t* accept_header; -static void register_refresher_listener (belle_sip_refresher_t* refresher - ,void* user_pointer - ,unsigned int status_code - ,const char* reason_phrase, int will_retry) { - SalOp* op = (SalOp*)user_pointer; + if (mRefresher){ + belle_sip_refresher_stop(mRefresher); + belle_sip_object_unref(mRefresher); + mRefresher=NULL; + } + + mType=Type::Register; + setFrom(from); + setTo(from); + setRoute(proxy); + req = buildRequest("REGISTER"); + req_uri = belle_sip_request_get_uri(req); + belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ + if (mRoot->mUseDates) { + time_t curtime=time(NULL); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); + } + accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header); + belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)createContact()); + if (old_contact) { + belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact); + if (contact) { + char * tmp; + belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/ + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact)); + tmp = belle_sip_object_to_string(contact); + ms_message("Clearing contact [%s] for op [%p]",tmp,this); + ms_free(tmp); + } else { + ms_error("Cannot add old contact header to op [%p]",this); + } + } + return sendRequestAndCreateRefresher(req,expires,registerRefresherListener); +} + +void SalRegisterOp::registerRefresherListener(belle_sip_refresher_t* refresher, void* user_pointer, unsigned int status_code, const char* reason_phrase, int will_retry) { + SalRegisterOp * op = (SalRegisterOp *)user_pointer; belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher))); - ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op)); + ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,op->getProxy().c_str()); if (belle_sip_refresher_get_auth_events(refresher)) { - if (op->auth_info) sal_auth_info_delete(op->auth_info); + if (op->mAuthInfo) sal_auth_info_delete(op->mAuthInfo); /*only take first one for now*/ - op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data)); + op->mAuthInfo=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data)); } - sal_error_info_set(&op->error_info,SalReasonUnknown, "SIP", status_code,reason_phrase,NULL); + sal_error_info_set(&op->mErrorInfo,SalReasonUnknown, "SIP", (int)status_code, reason_phrase, NULL); if (status_code>=200){ - sal_op_assign_recv_headers(op,(belle_sip_message_t*)response); + op->assignRecvHeaders((belle_sip_message_t*)response); } if(status_code == 200) { /*check service route rfc3608*/ @@ -44,23 +87,24 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) { service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route))); } - sal_op_set_service_route(op,(const SalAddress*)service_route_address); + op->setServiceRoute((const SalAddress*)service_route_address); if (service_route_address) belle_sip_object_unref(service_route_address); - sal_remove_pending_auth(op->base.root,op); /*just in case*/ + op->mRoot->removePendingAuth(op); /*just in case*/ if (contact) { const char *gruu; belle_sip_parameters_t* p = (BELLE_SIP_PARAMETERS(contact)); if((gruu = belle_sip_parameters_get_parameter(p, "pub-gruu"))) { char *unquoted = belle_sip_unquote_strdup(gruu); - sal_op_set_contact_address(op, (SalAddress*)belle_sip_header_address_parse(unquoted)); + op->setContactAddress((SalAddress*)belle_sip_header_address_parse(unquoted)); + bctbx_free(unquoted); belle_sip_parameters_remove_parameter(p, "pub-gruu"); } else { - sal_op_set_contact_address(op, (SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ + op->setContactAddress((SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/ } } - op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0); + op->mRoot->mCallbacks.register_success(op,belle_sip_refresher_get_expires(op->mRefresher)>0); } else if (status_code>=400) { /* from rfc3608, 6.1. If the UA refreshes the registration, the stored value of the Service- @@ -71,69 +115,17 @@ static void register_refresher_listener (belle_sip_refresher_t* refresher request is refused or if an existing registration expires and the UA chooses not to re-register, the UA SHOULD discard any stored service route for that address-of-record. */ - sal_op_set_service_route(op,NULL); - sal_op_ref(op); /*take a ref while invoking the callback to make sure the operations done after are valid*/ - op->base.root->callbacks.register_failure(op); - if (op->state!=SalOpStateTerminated && op->auth_info) { + op->setServiceRoute(NULL); + op->ref(); /*take a ref while invoking the callback to make sure the operations done after are valid*/ + op->mRoot->mCallbacks.register_failure(op); + if (op->mState!=State::Terminated && op->mAuthInfo) { /*add pending auth*/ - sal_add_pending_auth(op->base.root,op); + op->mRoot->addPendingAuth(op); if (status_code==403 || status_code==401 || status_code==407 ) - op->base.root->callbacks.auth_failure(op,op->auth_info); + op->mRoot->mCallbacks.auth_failure(op,op->mAuthInfo); } - sal_op_unref(op); + op->unref(); } } -int sal_register(SalOp *op, const char *proxy, const char *from, int expires,SalAddress* old_contact){ - belle_sip_request_t *req; - belle_sip_uri_t* req_uri; - belle_sip_header_t* accept_header; - - if (op->refresher){ - belle_sip_refresher_stop(op->refresher); - belle_sip_object_unref(op->refresher); - op->refresher=NULL; - } - - op->type=SalOpRegister; - sal_op_set_from(op,from); - sal_op_set_to(op,from); - sal_op_set_route(op,proxy); - req = sal_op_build_request(op,"REGISTER"); - req_uri = belle_sip_request_get_uri(req); - belle_sip_uri_set_user(req_uri,NULL); /*remove userinfo if any*/ - if (op->base.root->use_dates){ - time_t curtime=time(NULL); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_date_create_from_time(&curtime))); - } - accept_header = belle_sip_header_create("Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), accept_header); - belle_sip_message_set_header(BELLE_SIP_MESSAGE(req),(belle_sip_header_t*)sal_op_create_contact(op)); - if (old_contact) { - belle_sip_header_contact_t *contact=belle_sip_header_contact_create((const belle_sip_header_address_t *)old_contact); - if (contact) { - char * tmp; - belle_sip_header_contact_set_expires(contact,0); /*remove old aor*/ - belle_sip_message_add_header(BELLE_SIP_MESSAGE(req), BELLE_SIP_HEADER(contact)); - tmp = belle_sip_object_to_string(contact); - ms_message("Clearing contact [%s] for op [%p]",tmp,op); - ms_free(tmp); - } else { - ms_error("Cannot add old contact header to op [%p]",op); - } - } - return sal_op_send_and_create_refresher(op,req,expires,register_refresher_listener); -} - -int sal_register_refresh(SalOp *op, int expires){ - if (op->refresher) - return belle_sip_refresher_refresh(op->refresher,expires); - else - return -1; -} - -int sal_unregister(SalOp *op){ - return sal_register_refresh(op,0); -} - - +LINPHONE_END_NAMESPACE diff --git a/src/sal/register-op.h b/src/sal/register-op.h new file mode 100644 index 000000000..e7e06791c --- /dev/null +++ b/src/sal/register-op.h @@ -0,0 +1,47 @@ +/* + * register-op.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_REGISTER_OP_H_ +#define _L_SAL_REGISTER_OP_H_ + +#include "sal/op.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalRegisterOp : public SalOp { +public: + SalRegisterOp(Sal *sal) : SalOp(sal) {} + + int sendRegister (const char *proxy, const char *from, int expires, const SalAddress *oldContact); + int refreshRegister (int expires) { + return mRefresher ? belle_sip_refresher_refresh(mRefresher, expires) : -1; + } + int unregister() { return refreshRegister(0); } + + void authenticate (const SalAuthInfo *info) override { + refreshRegister(-1); } + +private: + virtual void fillCallbacks () override {}; + static void registerRefresherListener (belle_sip_refresher_t *refresher, void *userCtx, unsigned int statusCode, const char *reasonPhrase, int willRetry); +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_REGISTER_OP_H_ diff --git a/src/sal/sal.cpp b/src/sal/sal.cpp new file mode 100644 index 000000000..193588ca4 --- /dev/null +++ b/src/sal/sal.cpp @@ -0,0 +1,1070 @@ +/* + * sal.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "sal/sal.h" +#include "sal/call-op.h" +#include "sal/presence-op.h" +#include "sal/refer-op.h" +#include "sal/event-op.h" +#include "sal/message-op.h" +#include "bellesip_sal/sal_impl.h" +#include "tester_utils.h" +#include "private.h" + +#include "c-wrapper/internal/c-tools.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void Sal::processDialogTerminatedCb(void *sal, const belle_sip_dialog_terminated_event_t *event) { + belle_sip_dialog_t* dialog = belle_sip_dialog_terminated_event_get_dialog(event); + SalOp* op = reinterpret_cast(belle_sip_dialog_get_application_data(dialog)); + if (op && op->mCallbacks && op->mCallbacks->process_dialog_terminated) { + op->mCallbacks->process_dialog_terminated(op,event); + } else { + ms_error("sal process_dialog_terminated no op found for this dialog [%p], ignoring",dialog); + } +} + +void Sal::processIoErrorCb(void *user_ctx, const belle_sip_io_error_event_t *event){ + belle_sip_client_transaction_t*client_transaction; + SalOp* op; + if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) { + client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event)); + op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); + /*also reset auth count on IO error*/ + op->mAuthRequests=0; + if (op->mCallbacks && op->mCallbacks->process_io_error) { + op->mCallbacks->process_io_error(op,event); + } + } else { + /*ms_error("sal process_io_error not implemented yet for non transaction");*/ + /*nop, because already handle at transaction layer*/ + } +} + +void Sal::processRequestEventCb (void *ud, const belle_sip_request_event_t *event) { + Sal *sal = (Sal *)ud; + SalOp *op = NULL; + belle_sip_request_t *req = belle_sip_request_event_get_request(event); + belle_sip_dialog_t *dialog = belle_sip_request_event_get_dialog(event); + belle_sip_header_address_t *origin_address; + belle_sip_header_address_t *address=NULL; + belle_sip_header_from_t *from_header; + belle_sip_header_to_t *to; + belle_sip_header_diversion_t *diversion; + belle_sip_response_t *resp; + belle_sip_header_t *evh; + const char *method = belle_sip_request_get_method(req); + belle_sip_header_contact_t *remote_contact = belle_sip_message_get_header_by_type(req, belle_sip_header_contact_t); + belle_sip_header_t *subjectHeader = belle_sip_message_get_header(BELLE_SIP_MESSAGE(req), "Subject"); + + from_header = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_from_t); + + if (dialog) { + op = (SalOp *)belle_sip_dialog_get_application_data(dialog); + + if (op == NULL && strcmp("NOTIFY",method) == 0) { + /*special case for Dialog created by notify mathing subscribe*/ + belle_sip_transaction_t * sub_trans = belle_sip_dialog_get_last_transaction(dialog); + op = (SalOp*)belle_sip_transaction_get_application_data(sub_trans); + } + if (op == NULL || op->mState == SalOp::State::Terminated){ + ms_warning("Receiving request for null or terminated op [%p], ignored",op); + return; + } + } else { + /*handle the case where we are receiving a request with to tag but it is not belonging to any dialog*/ + belle_sip_header_to_t *to = belle_sip_message_get_header_by_type(req, belle_sip_header_to_t); + if ((strcmp("INVITE",method)==0 || strcmp("NOTIFY",method)==0) && (belle_sip_header_to_get_tag(to) != NULL)) { + ms_warning("Receiving %s with to-tag but no know dialog here. Rejecting.", method); + resp=belle_sip_response_create_from_request(req,481); + belle_sip_provider_send_response(sal->mProvider,resp); + return; + /* by default (eg. when a to-tag is present), out of dialog ACK are automatically + handled in lower layers (belle-sip) but in case it misses, it will be forwarded to us */ + } else if (strcmp("ACK",method)==0 && (belle_sip_header_to_get_tag(to) == NULL)) { + ms_warning("Receiving ACK without to-tag but no know dialog here. Ignoring"); + return; + } + + if (strcmp("INVITE",method)==0) { + op=new SalCallOp(sal); + op->fillCallbacks(); + }else if ((strcmp("SUBSCRIBE",method)==0 || strcmp("NOTIFY",method)==0) && (evh=belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),"Event"))!=NULL) { + if (strncmp(belle_sip_header_get_unparsed_value(evh),"presence",strlen("presence"))==0){ + op=new SalPresenceOp(sal); + } else { + op=new SalSubscribeOp(sal); + } + op->fillCallbacks(); + }else if (strcmp("MESSAGE",method)==0) { + op=new SalMessageOp(sal); + op->fillCallbacks(); + }else if (strcmp("REFER",method)==0) { + op=new SalReferOp(sal); + }else if (strcmp("OPTIONS",method)==0) { + resp=belle_sip_response_create_from_request(req,200); + belle_sip_provider_send_response(sal->mProvider,resp); + return; + }else if (strcmp("INFO",method)==0) { + resp=belle_sip_response_create_from_request(req,481);/*INFO out of call dialogs are not allowed*/ + belle_sip_provider_send_response(sal->mProvider,resp); + return; + }else if (strcmp("BYE",method)==0) { + resp=belle_sip_response_create_from_request(req,481);/*out of dialog BYE */ + belle_sip_provider_send_response(sal->mProvider,resp); + return; + }else if (strcmp("CANCEL",method)==0) { + resp=belle_sip_response_create_from_request(req,481);/*out of dialog CANCEL */ + belle_sip_provider_send_response(sal->mProvider,resp); + return; + }else if (sal->mEnableTestFeatures && strcmp("PUBLISH",method)==0) { + resp=belle_sip_response_create_from_request(req,200);/*out of dialog PUBLISH */ + belle_sip_message_add_header((belle_sip_message_t*)resp,belle_sip_header_create("SIP-Etag","4441929FFFZQOA")); + belle_sip_provider_send_response(sal->mProvider,resp); + return; + }else { + ms_error("sal process_request_event not implemented yet for method [%s]",belle_sip_request_get_method(req)); + resp=belle_sip_response_create_from_request(req,405); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp) + ,BELLE_SIP_HEADER(belle_sip_header_allow_create("INVITE, CANCEL, ACK, BYE, SUBSCRIBE, NOTIFY, MESSAGE, OPTIONS, INFO"))); + belle_sip_provider_send_response(sal->mProvider,resp); + return; + } + op->mDir=SalOp::Dir::Incoming; + } + + if (!op->mFromAddress) { + if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))) + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); + else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header)))) + address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(from_header)) + ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(from_header))); + else + ms_error("Cannot not find from uri from request [%p]",req); + op->setFromAddress((SalAddress*)address); + belle_sip_object_unref(address); + } + + if( remote_contact ){ + op->setRemoteContact(belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); + } + + if (!op->mToAddress) { + to=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_to_t); + if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))) + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to))); + else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to)))) + address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(to)) + ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(to))); + else + ms_error("Cannot not find to uri from request [%p]",req); + + op->setToAddress((SalAddress*)address); + belle_sip_object_unref(address); + } + + if (subjectHeader) { + const char *subject = belle_sip_header_get_unparsed_value(subjectHeader); + op->setSubject(subject); + } + + if(!op->mDiversionAddress){ + diversion=belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req),belle_sip_header_diversion_t); + if (diversion) { + if (belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))) + address=belle_sip_header_address_create(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) + ,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); + else if ((belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion)))) + address=belle_sip_header_address_create2(belle_sip_header_address_get_displayname(BELLE_SIP_HEADER_ADDRESS(diversion)) + ,belle_sip_header_address_get_absolute_uri(BELLE_SIP_HEADER_ADDRESS(diversion))); + else + ms_warning("Cannot not find diversion header from request [%p]",req); + if (address) { + op->setDiversionAddress((SalAddress*)address); + belle_sip_object_unref(address); + } + } + } + + if (op->mOrigin.empty()) { + /*set origin uri*/ + origin_address=belle_sip_header_address_create(NULL,belle_sip_request_extract_origin(req)); + op->setNetworkOriginAddress((SalAddress*)origin_address); + belle_sip_object_unref(origin_address); + } + if (op->mRemoteUserAgent.empty()) + op->setRemoteUserAgent(BELLE_SIP_MESSAGE(req)); + + if (op->mCallId.empty()) { + op->mCallId = belle_sip_header_call_id_get_call_id( + BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(req), belle_sip_header_call_id_t)) + ); + } + + /*It is worth noting that proxies can (and will) remove this header field*/ + op->setPrivacyFromMessage((belle_sip_message_t*)req); + + if (strcmp("ACK",method) != 0){ + /*The ACK custom header is processed specifically later on*/ + op->assignRecvHeaders((belle_sip_message_t*)req); + } + + if (op->mCallbacks && op->mCallbacks->process_request_event) { + op->mCallbacks->process_request_event(op,event); + } else { + ms_error("sal process_request_event not implemented yet"); + } + +} + +void Sal::processResponseEventCb(void *user_ctx, const belle_sip_response_event_t *event) { + belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event); + belle_sip_response_t* response = belle_sip_response_event_get_response(event); + int response_code = belle_sip_response_get_status_code(response); + + if (!client_transaction) { + ms_warning("Discarding stateless response [%i]",response_code); + return; + } else { + SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)); + belle_sip_header_contact_t* remote_contact = belle_sip_message_get_header_by_type(response, belle_sip_header_contact_t); + + if (op->mState == SalOp::State::Terminated) { + belle_sip_message("Op [%p] is terminated, nothing to do with this [%i]", op, response_code); + return; + } + /*do it all the time, since we can receive provisional responses from a different instance than the final one*/ + op->setRemoteUserAgent(BELLE_SIP_MESSAGE(response)); + + if(remote_contact) { + op->setRemoteContact(belle_sip_header_get_unparsed_value(BELLE_SIP_HEADER(remote_contact))); + } + + if (op->mCallId.empty()) { + op->mCallId = belle_sip_header_call_id_get_call_id( + BELLE_SIP_HEADER_CALL_ID(belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(response), belle_sip_header_call_id_t)) + ); + } + + op->assignRecvHeaders((belle_sip_message_t*)response); + + if (op->mCallbacks && op->mCallbacks->process_response_event) { + /*handle authorization*/ + switch (response_code) { + case 200: + break; + case 401: + case 407: + if (op->mState == SalOp::State::Terminating && strcmp("BYE",belle_sip_request_get_method(request))!=0) { + /*only bye are completed*/ + belle_sip_message("Op is in state terminating, nothing else to do "); + } else { + if (op->mPendingAuthTransaction){ + belle_sip_object_unref(op->mPendingAuthTransaction); + op->mPendingAuthTransaction=NULL; + } + if (++op->mAuthRequests > 2) { + ms_warning("Auth info cannot be found for op [%s/%s] after 2 attempts, giving up",op->getFrom().c_str() + ,op->getTo().c_str()); + op->mRoot->mCallbacks.auth_failure(op,op->mAuthInfo); + op->mRoot->removePendingAuth(op); + } else { + op->mPendingAuthTransaction=(belle_sip_client_transaction_t*)belle_sip_object_ref(client_transaction); + op->processAuthentication(); + return; + } + } + break; + case 403: + if (op->mAuthInfo) op->mRoot->mCallbacks.auth_failure(op,op->mAuthInfo); + break; + case 302: + case 301: + if (op->processRedirect() == 0) + return; + break; + } + if (response_code >= 180 && response_code !=401 && response_code !=407 && response_code !=403) { + /*not an auth request*/ + op->mAuthRequests=0; + } + op->mCallbacks->process_response_event(op,event); + } else { + ms_error("Unhandled event response [%p]",event); + } + } +} + +void Sal::processTimeoutCb(void *user_ctx, const belle_sip_timeout_event_t *event) { + belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event); + SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction)); + if (op && op->mCallbacks && op->mCallbacks->process_timeout) { + op->mCallbacks->process_timeout(op,event); + } else { + ms_error("Unhandled event timeout [%p]",event); + } +} + +void Sal::processTransactionTerminatedCb(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) { + belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event); + belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event); + belle_sip_transaction_t* trans; + SalOp* op; + + if(client_transaction) + trans=BELLE_SIP_TRANSACTION(client_transaction); + else + trans=BELLE_SIP_TRANSACTION(server_transaction); + + op = (SalOp*)belle_sip_transaction_get_application_data(trans); + if (op && op->mCallbacks && op->mCallbacks->process_transaction_terminated) { + op->mCallbacks->process_transaction_terminated(op,event); + } else { + ms_message("Unhandled transaction terminated [%p]",trans); + } + if (op) { + op->unref(); /*because every transaction ref op*/ + belle_sip_transaction_set_application_data(trans,NULL); /*no longuer reference something we do not ref to avoid futur access of a released op*/ + } +} + +void Sal::processAuthRequestedCb(void *sal, belle_sip_auth_event_t *event) { + SalAuthInfo* auth_info = sal_auth_info_create(event); + ((Sal*)sal)->mCallbacks.auth_requested(reinterpret_cast(sal),auth_info); + belle_sip_auth_event_set_passwd(event,(const char*)auth_info->password); + belle_sip_auth_event_set_ha1(event,(const char*)auth_info->ha1); + belle_sip_auth_event_set_userid(event,(const char*)auth_info->userid); + belle_sip_auth_event_set_signing_key(event,(belle_sip_signing_key_t *)auth_info->key); + belle_sip_auth_event_set_client_certificates_chain(event,(belle_sip_certificates_chain_t* )auth_info->certificates); + sal_auth_info_delete(auth_info); +} + +Sal::Sal(MSFactory *factory){ + belle_sip_listener_callbacks_t listener_callbacks = {0}; + + /*belle_sip_object_enable_marshal_check(TRUE);*/ + mFactory = factory; + /*first create the stack, which initializes the belle-sip object's pool for this thread*/ + mStack = belle_sip_stack_new(NULL); + + mUserAgentHeader=belle_sip_header_user_agent_new(); +#if defined(PACKAGE_NAME) && defined(LIBLINPHONE_VERSION) + belle_sip_header_user_agent_add_product(user_agent, PACKAGE_NAME "/" LIBLINPHONE_VERSION); +#else + belle_sip_header_user_agent_add_product(mUserAgentHeader, "Unknown"); +#endif + appendStackStringToUserAgent(); + belle_sip_object_ref(mUserAgentHeader); + + mProvider = belle_sip_stack_create_provider(mStack,NULL); + enableNatHelper(TRUE); + + listener_callbacks.process_dialog_terminated=processDialogTerminatedCb; + listener_callbacks.process_io_error=processIoErrorCb; + listener_callbacks.process_request_event=processRequestEventCb; + listener_callbacks.process_response_event=processResponseEventCb; + listener_callbacks.process_timeout=processTimeoutCb; + listener_callbacks.process_transaction_terminated=processTransactionTerminatedCb; + listener_callbacks.process_auth_requested=processAuthRequestedCb; + mListener=belle_sip_listener_create_from_callbacks(&listener_callbacks, this); + belle_sip_provider_add_sip_listener(mProvider, mListener); +} + +Sal::~Sal() { + belle_sip_object_unref(mUserAgentHeader); + belle_sip_object_unref(mProvider); + belle_sip_object_unref(mStack); + belle_sip_object_unref(mListener); + if (mSupportedHeader) + belle_sip_object_unref(mSupportedHeader); +} + +void Sal::setCallbacks(const Callbacks *cbs) { + memcpy(&mCallbacks,cbs,sizeof(*cbs)); + if (mCallbacks.call_received==NULL) + mCallbacks.call_received=(OnCallReceivedCb)unimplementedStub; + if (mCallbacks.call_ringing==NULL) + mCallbacks.call_ringing=(OnCallRingingCb)unimplementedStub; + if (mCallbacks.call_accepted==NULL) + mCallbacks.call_accepted=(OnCallAcceptedCb)unimplementedStub; + if (mCallbacks.call_failure==NULL) + mCallbacks.call_failure=(OnCallFailureCb)unimplementedStub; + if (mCallbacks.call_terminated==NULL) + mCallbacks.call_terminated=(OnCallTerminatedCb)unimplementedStub; + if (mCallbacks.call_released==NULL) + mCallbacks.call_released=(OnCallReleasedCb)unimplementedStub; + if (mCallbacks.call_updating==NULL) + mCallbacks.call_updating=(OnCallUpdatingCb)unimplementedStub; + if (mCallbacks.auth_failure==NULL) + mCallbacks.auth_failure=(OnAuthFailureCb)unimplementedStub; + if (mCallbacks.register_success==NULL) + mCallbacks.register_success=(OnRegisterSuccessCb)unimplementedStub; + if (mCallbacks.register_failure==NULL) + mCallbacks.register_failure=(OnRegisterFailureCb)unimplementedStub; + if (mCallbacks.dtmf_received==NULL) + mCallbacks.dtmf_received=(OnDtmfReceivedCb)unimplementedStub; + if (mCallbacks.notify==NULL) + mCallbacks.notify=(OnNotifyCb)unimplementedStub; + if (mCallbacks.subscribe_received==NULL) + mCallbacks.subscribe_received=(OnSubscribeReceivedCb)unimplementedStub; + if (mCallbacks.incoming_subscribe_closed==NULL) + mCallbacks.incoming_subscribe_closed=(OnIncomingSubscribeClosedCb)unimplementedStub; + if (mCallbacks.parse_presence_requested==NULL) + mCallbacks.parse_presence_requested=(OnParsePresenceRequestedCb)unimplementedStub; + if (mCallbacks.convert_presence_to_xml_requested==NULL) + mCallbacks.convert_presence_to_xml_requested=(OnConvertPresenceToXMLRequestedCb)unimplementedStub; + if (mCallbacks.notify_presence==NULL) + mCallbacks.notify_presence=(OnNotifyPresenceCb)unimplementedStub; + if (mCallbacks.subscribe_presence_received==NULL) + mCallbacks.subscribe_presence_received=(OnSubscribePresenceReceivedCb)unimplementedStub; + if (mCallbacks.message_received==NULL) + mCallbacks.message_received=(OnMessageReceivedCb)unimplementedStub; + if (mCallbacks.ping_reply==NULL) + mCallbacks.ping_reply=(OnPingReplyCb)unimplementedStub; + if (mCallbacks.auth_requested==NULL) + mCallbacks.auth_requested=(OnAuthRequestedCb)unimplementedStub; + if (mCallbacks.info_received==NULL) + mCallbacks.info_received=(OnInfoReceivedCb)unimplementedStub; + if (mCallbacks.on_publish_response==NULL) + mCallbacks.on_publish_response=(OnPublishResponseCb)unimplementedStub; + if (mCallbacks.on_expire==NULL) + mCallbacks.on_expire=(OnExpireCb)unimplementedStub; +} + +void Sal::setTlsProperties(){ + belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(mProvider,"TLS"); + if (lp){ + belle_sip_tls_listening_point_t *tlp=BELLE_SIP_TLS_LISTENING_POINT(lp); + belle_tls_crypto_config_t *crypto_config = belle_tls_crypto_config_new(); + int verify_exceptions = BELLE_TLS_VERIFY_NONE; + if (!mTlsVerify) verify_exceptions = BELLE_TLS_VERIFY_ANY_REASON; + else if (!mTlsVerifyCn) verify_exceptions = BELLE_TLS_VERIFY_CN_MISMATCH; + belle_tls_crypto_config_set_verify_exceptions(crypto_config, verify_exceptions); + if (!mRootCa.empty()) + belle_tls_crypto_config_set_root_ca(crypto_config, mRootCa.c_str()); + if (!mRootCaData.empty()) + belle_tls_crypto_config_set_root_ca_data(crypto_config, mRootCaData.c_str()); + if (mSslConfig != NULL) belle_tls_crypto_config_set_ssl_config(crypto_config, mSslConfig); + if (mTlsPostcheckCb) belle_tls_crypto_config_set_postcheck_callback(crypto_config, mTlsPostcheckCb, mTlsPostcheckCbData); + belle_sip_tls_listening_point_set_crypto_config(tlp, crypto_config); + belle_sip_object_unref(crypto_config); + } +} + +int Sal::addListenPort(SalAddress* addr, bool is_tunneled) { + int result; + belle_sip_listening_point_t* lp; + if (is_tunneled){ +#ifdef TUNNEL_ENABLED + if (sal_address_get_transport(addr)!=SalTransportUDP){ + ms_error("Tunneled mode is only available for UDP kind of transports."); + return -1; + } + lp = belle_sip_tunnel_listening_point_new(mStack, mTunnelClient); + if (!lp){ + ms_error("Could not create tunnel listening point."); + return -1; + } +#else + ms_error("No tunnel support in library."); + return -1; +#endif + }else{ + lp = belle_sip_stack_create_listening_point(mStack, + sal_address_get_domain(addr), + sal_address_get_port(addr), + sal_transport_to_string(sal_address_get_transport(addr))); + } + if (lp) { + belle_sip_listening_point_set_keep_alive(lp,(int)mKeepAlive); + result = belle_sip_provider_add_listening_point(mProvider,lp); + if (sal_address_get_transport(addr)==SalTransportTLS) { + setTlsProperties(); + } + } else { + return -1; + } + return result; +} + +int Sal::setListenPort (const string &addr, int port, SalTransport tr, bool isTunneled) { + SalAddress *salAddr = sal_address_new(nullptr); + sal_address_set_domain(salAddr, L_STRING_TO_C(addr)); + sal_address_set_port(salAddr, port); + sal_address_set_transport(salAddr, tr); + int result = addListenPort(salAddr, isTunneled); + sal_address_destroy(salAddr); + return result; +} + +int Sal::getListeningPort(SalTransport tr){ + const char *tpn=sal_transport_to_string(tr); + belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(mProvider, tpn); + if (lp){ + return belle_sip_listening_point_get_port(lp); + } + return 0; +} + +int Sal::unlistenPorts(){ + const belle_sip_list_t * lps = belle_sip_provider_get_listening_points(mProvider); + belle_sip_list_t * tmp_list = belle_sip_list_copy(lps); + belle_sip_list_for_each2 (tmp_list,(void (*)(void*,void*))removeListeningPoint,mProvider); + belle_sip_list_free(tmp_list); + ms_message("sal_unlisten_ports done"); + return 0; +} + +int Sal::isTransportAvailable(SalTransport t) { + switch(t){ + case SalTransportUDP: + case SalTransportTCP: + return TRUE; + case SalTransportTLS: + return belle_sip_stack_tls_available(mStack); + case SalTransportDTLS: + return FALSE; + } + return FALSE; +} + +void Sal::makeSupportedHeader () { + if (mSupportedHeader) { + belle_sip_object_unref(mSupportedHeader); + mSupportedHeader = nullptr; + } + string tags = Utils::join(mSupportedTags, ", "); + if (tags.empty()) + return; + mSupportedHeader = belle_sip_header_create("Supported", tags.c_str()); + if (mSupportedHeader) + belle_sip_object_ref(mSupportedHeader); +} + +void Sal::setSupportedTags (const string &tags) { + vector splittedTags = Utils::split(tags, ","); + mSupportedTags.clear(); + for (const auto &tag : splittedTags) + mSupportedTags.push_back(Utils::trim(tag)); + makeSupportedHeader(); +} + +const string &Sal::getSupportedTags () const { + if (mSupportedHeader) + mSupported = belle_sip_header_get_unparsed_value(mSupportedHeader); + else + mSupported.clear(); + return mSupported; +} + +void Sal::addSupportedTag (const string &tag) { + auto it = find(mSupportedTags.cbegin(), mSupportedTags.cend(), tag); + if (it == mSupportedTags.cend()) { + mSupportedTags.push_back(tag); + makeSupportedHeader(); + } +} + +void Sal::removeSupportedTag (const string &tag) { + auto it = find(mSupportedTags.begin(), mSupportedTags.end(), tag); + if (it != mSupportedTags.end()) { + mSupportedTags.erase(it); + makeSupportedHeader(); + } +} + +int Sal::resetTransports() { + ms_message("Reseting transports"); + belle_sip_provider_clean_channels(mProvider); + return 0; +} + +ortp_socket_t Sal::getSocket() const { + ms_warning("sal_get_socket is deprecated"); + return -1; +} + +void Sal::setUserAgent (const string &value) { + belle_sip_header_user_agent_set_products(mUserAgentHeader, nullptr); + belle_sip_header_user_agent_add_product(mUserAgentHeader, L_STRING_TO_C(value)); +} + +const string &Sal::getUserAgent () const { + char userAgent[256]; + belle_sip_header_user_agent_get_products_as_string(mUserAgentHeader, userAgent, (unsigned int)sizeof(userAgent) - 1); + mUserAgent = userAgent; + return mUserAgent; +} + +void Sal::appendStackStringToUserAgent () { + stringstream ss; + ss << "(belle-sip/" << belle_sip_version_to_string() << ")"; + string stackStr = ss.str(); + belle_sip_header_user_agent_add_product(mUserAgentHeader, stackStr.c_str()); +} + +void Sal::setKeepAlivePeriod(unsigned int value) { + const belle_sip_list_t* iterator; + belle_sip_listening_point_t* lp; + mKeepAlive=value; + for (iterator=belle_sip_provider_get_listening_points(mProvider);iterator!=NULL;iterator=iterator->next) { + lp=(belle_sip_listening_point_t*)iterator->data; + if (mUseTcpTlsKeepAlive || strcasecmp(belle_sip_listening_point_get_transport(lp),"udp")==0) { + belle_sip_listening_point_set_keep_alive(lp,(int)mKeepAlive); + } + } +} + +int Sal::setTunnel(void *tunnelclient) { +#ifdef TUNNEL_ENABLED + mTunnelClient=tunnelclient; + return 0; +#else + return -1; +#endif +} + +void Sal::setHttpProxyHost (const string &value) { + belle_sip_stack_set_http_proxy_host(mStack, L_STRING_TO_C(value)); +} + +const string &Sal::getHttpProxyHost () const { + mHttpProxyHost = belle_sip_stack_get_http_proxy_host(mStack); + return mHttpProxyHost; +} + +bool Sal::isContentEncodingAvailable (const string &contentEncoding) const { + return !!belle_sip_stack_content_encoding_available(mStack, L_STRING_TO_C(contentEncoding)); +} + +bool Sal::isContentTypeSupported (const string &contentType) const { + auto it = find_if(mSupportedContentTypes.cbegin(), mSupportedContentTypes.cend(), + [contentType](string supportedContentType) { return contentType == supportedContentType; }); + return it != mSupportedContentTypes.cend(); +} + +void Sal::addContentTypeSupport (const string &contentType) { + if (!contentType.empty() && !isContentTypeSupported(contentType)) + mSupportedContentTypes.push_back(contentType); +} + +void Sal::removeContentTypeSupport (const string &contentType) { + auto it = find(mSupportedContentTypes.begin(), mSupportedContentTypes.end(), contentType); + if (it != mSupportedContentTypes.end()) + mSupportedContentTypes.erase(it); +} + +void Sal::useRport(bool use_rports) { + belle_sip_provider_enable_rport(mProvider,use_rports); + ms_message("Sal use rport [%s]", use_rports ? "enabled" : "disabled"); +} + +void Sal::setRootCa (const string &value) { + mRootCa = value; + setTlsProperties(); +} + +void Sal::setRootCaData (const string &value) { + mRootCaData = value; + setTlsProperties(); +} + +void Sal::verifyServerCertificates(bool verify) { + mTlsVerify=verify; + setTlsProperties(); +} + +void Sal::verifyServerCn(bool verify) { + mTlsVerifyCn = verify; + setTlsProperties(); +} + +void Sal::setSslConfig(void *ssl_config) { + mSslConfig = ssl_config; + setTlsProperties(); +} + +void Sal::setTlsPostcheckCallback(int (*cb)(void *, const bctbx_x509_certificate_t *), void *data){ + mTlsPostcheckCb = cb; + mTlsPostcheckCbData = data; +} + +int Sal::createUuid(char *uuid, size_t len) { + if (generateUuid(uuid, len) == 0) { + setUuid(uuid); + return 0; + } + return -1; +} + +int Sal::generateUuid(char *uuid, size_t len) { + SalUuid uuid_struct; + int i; + int written; + + if (len==0) return -1; + /*create an UUID as described in RFC4122, 4.4 */ + belle_sip_random_bytes((unsigned char*)&uuid_struct, sizeof(SalUuid)); + uuid_struct.clockSeqHiAndReserved&=(unsigned char)~(1<<6); + uuid_struct.clockSeqHiAndReserved|=(unsigned char)1<<7; + uuid_struct.timeHiAndVersion&=(unsigned char)~(0xf<<12); + uuid_struct.timeHiAndVersion|=(unsigned char)4<<12; + + written=snprintf(uuid,len,"%8.8x-%4.4x-%4.4x-%2.2x%2.2x-", uuid_struct.timeLow, uuid_struct.timeMid, + uuid_struct.timeHiAndVersion, uuid_struct.clockSeqHiAndReserved, + uuid_struct.clockSeqLow); + if ((written < 0) || ((size_t)written > (len +13))) { + ms_error("sal_create_uuid(): buffer is too short !"); + return -1; + } + for (i = 0; i < 6; i++) + written+=snprintf(uuid+written,len-(unsigned long)written,"%2.2x", uuid_struct.node[i]); + uuid[len-1]='\0'; + return 0; +} + +void Sal::addPendingAuth (SalOp *op) { + auto it = find(mPendingAuths.cbegin(), mPendingAuths.cend(), op); + if (it == mPendingAuths.cend()) { + mPendingAuths.push_back(op); + op->mHasAuthPending = true; + } +} + +void Sal::removePendingAuth (SalOp *op) { + if (op->mHasAuthPending) { + op->mHasAuthPending = false; + mPendingAuths.remove(op); + } +} + +void Sal::setDefaultSdpHandling(SalOpSDPHandling sdp_handling_method) { + if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", this); + mDefaultSdpHandling = sdp_handling_method; +} + +void Sal::enableNatHelper(bool enable) { + mNatHelperEnabled=enable; + belle_sip_provider_enable_nat_helper(mProvider,enable); + ms_message("Sal nat helper [%s]",enable?"enabled":"disabled"); +} + +void Sal::getDefaultLocalIp(int address_family, char *ip, size_t iplen) { + strncpy(ip,address_family==AF_INET6 ? "::1" : "127.0.0.1",iplen); + ms_error("sal_get_default_local_ip() is deprecated."); +} + +void Sal::setDnsServers(const bctbx_list_t *servers){ + belle_sip_list_t *l = NULL; + + /*we have to convert the bctbx_list_t into a belle_sip_list_t first*/ + for (; servers != NULL; servers = servers->next){ + l = belle_sip_list_append(l, servers->data); + } + belle_sip_stack_set_dns_servers(mStack, l); + belle_sip_list_free(l); +} + +void Sal::setDnsUserHostsFile (const string &value) { + belle_sip_stack_set_dns_user_hosts_file(mStack, value.c_str()); +} + +const string &Sal::getDnsUserHostsFile () const { + mDnsUserHostsFile = belle_sip_stack_get_dns_user_hosts_file(mStack); + return mDnsUserHostsFile; +} + +belle_sip_resolver_context_t *Sal::resolveA (const string &name, int port, int family, belle_sip_resolver_callback_t cb, void *data) { + return belle_sip_stack_resolve_a(mStack, L_STRING_TO_C(name), port, family, cb, data); +} + +belle_sip_resolver_context_t *Sal::resolve (const string &service, const string &transport, const string &name, int port, int family, belle_sip_resolver_callback_t cb, void *data) { + return belle_sip_stack_resolve(mStack, L_STRING_TO_C(service), L_STRING_TO_C(transport), L_STRING_TO_C(name), port, family, cb, data); +} + +belle_sip_source_t *Sal::createTimer (belle_sip_source_func_t func, void *data, unsigned int timeoutValueMs, const string &timerName) { + belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(mStack); + return belle_sip_main_loop_create_timeout(ml, func, data, timeoutValueMs, L_STRING_TO_C(timerName)); +} + +void Sal::cancelTimer(belle_sip_source_t *timer) { + belle_sip_main_loop_t *ml = belle_sip_stack_get_main_loop(mStack); + belle_sip_main_loop_remove_source(ml, timer); +} + +belle_sip_response_t* Sal::createResponseFromRequest (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(mUserAgentHeader)); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp), mSupportedHeader); + return resp; +} + + + + +/***********************************/ +/* Global functions implementation */ +/***********************************/ + +int to_sip_code(SalReason r) { + int ret=500; + switch(r){ + case SalReasonNone: + ret=200; + break; + case SalReasonIOError: + ret=503; + break; + case SalReasonUnknown: + ret=400; + break; + case SalReasonBusy: + ret=486; + break; + case SalReasonDeclined: + ret=603; + break; + case SalReasonDoNotDisturb: + ret=600; + break; + case SalReasonForbidden: + ret=403; + break; + case SalReasonUnsupportedContent: + ret=415; + break; + case SalReasonNotFound: + ret=404; + break; + case SalReasonRedirect: + ret=302; + break; + case SalReasonTemporarilyUnavailable: + ret=480; + break; + case SalReasonServiceUnavailable: + ret=503; + break; + case SalReasonRequestPending: + ret=491; + break; + case SalReasonUnauthorized: + ret=401; + break; + case SalReasonNotAcceptable: + ret=488; /*or maybe 606 Not Acceptable ?*/ + break; + case SalReasonNoMatch: + ret=481; + break; + case SalReasonRequestTimeout: + ret=408; + break; + case SalReasonMovedPermanently: + ret=301; + break; + case SalReasonGone: + ret=410; + break; + case SalReasonAddressIncomplete: + ret=484; + break; + case SalReasonNotImplemented: + ret=501; + break; + case SalReasonServerTimeout: + ret=504; + break; + case SalReasonBadGateway: + ret=502; + break; + case SalReasonInternalError: + ret=500; + break; + } + return ret; +} + +LINPHONE_END_NAMESPACE + +/*******************************/ +/* C++ to C wrapping functions */ +/*******************************/ + +using namespace LinphonePrivate; + +// NOTE: This is ugly but it's not possible to export simply this set of functions in tester_utils... +// Because tester_utils and private files are ill-thought. +// A workaround is to use LINPHONE_PUBLIC here. + +extern "C" { + +LINPHONE_PUBLIC Sal *linphone_core_get_sal(const LinphoneCore *lc) { + return lc->sal; +} + +LINPHONE_PUBLIC SalOp *linphone_proxy_config_get_sal_op(const LinphoneProxyConfig *cfg) { + return cfg->op; +} + +LINPHONE_PUBLIC SalOp *linphone_call_get_op_as_sal_op(const LinphoneCall *call) { + return linphone_call_get_op(call); +} + +LINPHONE_PUBLIC Sal *sal_init(MSFactory *factory) { + return new Sal(factory); +} + +LINPHONE_PUBLIC void sal_uninit(Sal* sal) { + delete sal; +} + +LINPHONE_PUBLIC int sal_create_uuid(Sal *ctx, char *uuid, size_t len) { + return ctx->createUuid(uuid, len); +} + +LINPHONE_PUBLIC void sal_set_uuid(Sal *ctx, const char *uuid) { + ctx->setUuid(L_C_TO_STRING(uuid)); +} + +LINPHONE_PUBLIC void sal_default_set_sdp_handling(Sal* h, SalOpSDPHandling handling_method) { + h->setDefaultSdpHandling(handling_method); +} + +LINPHONE_PUBLIC void sal_set_send_error(Sal *sal,int value) { + sal->setSendError(value); +} + +LINPHONE_PUBLIC void sal_set_recv_error(Sal *sal,int value) { + sal->setRecvError(value); +} + +LINPHONE_PUBLIC void sal_enable_pending_trans_checking(Sal *sal, bool value) { + sal->enablePendingTransactionChecking(value); +} + +LINPHONE_PUBLIC void sal_enable_unconditional_answer(Sal *sal,int value) { + sal->enableUnconditionalAnswer(value); +} + +LINPHONE_PUBLIC void sal_set_dns_timeout(Sal* sal,int timeout) { + sal->setDnsTimeout(timeout); +} + +LINPHONE_PUBLIC void sal_set_dns_user_hosts_file(Sal *sal, const char *hosts_file) { + sal->setDnsUserHostsFile(hosts_file); +} + +LINPHONE_PUBLIC void *sal_get_stack_impl(Sal *sal) { + return sal->getStackImpl(); +} + +LINPHONE_PUBLIC void sal_set_refresher_retry_after(Sal *sal,int value) { + sal->setRefresherRetryAfter(value); +} + +LINPHONE_PUBLIC int sal_get_refresher_retry_after(const Sal *sal) { + return sal->getRefresherRetryAfter(); +} + +LINPHONE_PUBLIC void sal_set_transport_timeout(Sal* sal,int timeout) { + sal->setTransportTimeout(timeout); +} + +LINPHONE_PUBLIC void sal_enable_test_features(Sal*ctx, bool enabled) { + ctx->enableTestFeatures(enabled); +} + +LINPHONE_PUBLIC int sal_transport_available(Sal *ctx, SalTransport t) { + return ctx->isTransportAvailable(t); +} + +LINPHONE_PUBLIC const SalErrorInfo *sal_op_get_error_info(const SalOp *op) { + return op->getErrorInfo(); +} + +LINPHONE_PUBLIC bool sal_call_dialog_request_pending(const SalOp *op) { + auto callOp = dynamic_cast(op); + return callOp->dialogRequestPending(); +} + +LINPHONE_PUBLIC void sal_call_set_sdp_handling(SalOp *h, SalOpSDPHandling handling) { + auto callOp = dynamic_cast(h); + callOp->setSdpHandling(handling); +} + +LINPHONE_PUBLIC SalMediaDescription * sal_call_get_final_media_description(SalOp *h) { + auto callOp = dynamic_cast(h); + return callOp->getFinalMediaDescription(); +} + +LINPHONE_PUBLIC belle_sip_resolver_context_t *sal_resolve_a(Sal *sal, const char *name, int port, int family, belle_sip_resolver_callback_t cb, void *data) { + return sal->resolveA(name, port, family, cb, data); +} + +LINPHONE_PUBLIC Sal *sal_op_get_sal(SalOp *op) { + return op->getSal(); +} + +LINPHONE_PUBLIC SalOp *sal_create_refer_op(Sal *sal) { + return new SalReferOp(sal); +} + +LINPHONE_PUBLIC void sal_release_op(SalOp *op) { + op->release(); +} + +LINPHONE_PUBLIC void sal_op_set_from(SalOp *sal_refer_op, const char* from) { + auto referOp = dynamic_cast(sal_refer_op); + referOp->setFrom(from); +} + +LINPHONE_PUBLIC void sal_op_set_to(SalOp *sal_refer_op, const char* to) { + auto referOp = dynamic_cast(sal_refer_op); + referOp->setTo(to); +} + +LINPHONE_PUBLIC void sal_op_send_refer(SalOp *sal_refer_op, SalAddress* refer_to) { + auto referOp = dynamic_cast(sal_refer_op); + referOp->sendRefer(refer_to); +} + +LINPHONE_PUBLIC void sal_set_user_pointer(Sal *sal, void *user_pointer) { + sal->setUserPointer(user_pointer); +} + +LINPHONE_PUBLIC void *sal_get_user_pointer(Sal *sal) { + return sal->getUserPointer(); +} + +LINPHONE_PUBLIC void sal_set_call_refer_callback(Sal *sal, void (*OnReferCb)(SalOp *op, const SalAddress *referto)) { + struct Sal::Callbacks cbs = {NULL}; + cbs.refer_received = OnReferCb; + sal->setCallbacks(&cbs); +} + +} diff --git a/src/sal/sal.h b/src/sal/sal.h new file mode 100644 index 000000000..1de178d5f --- /dev/null +++ b/src/sal/sal.h @@ -0,0 +1,344 @@ +/* + * sal.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SAL_H_ +#define _L_SAL_H_ + +#include +#include + +#include "linphone/utils/general.h" + +#include "c-wrapper/internal/c-sal.h" +#include "logger/logger.h" + +LINPHONE_BEGIN_NAMESPACE + +class SalOp; +class SalCallOp; +class SalMessageOp; +class SalSubscribeOp; +class SalPresenceOp; +class SalReferOp; + +class Sal { +public: + using OnCallReceivedCb = void (*) (SalCallOp *op); + using OnCallRingingCb = void (*) (SalOp *op); + using OnCallAcceptedCb = void (*) (SalOp *op); + using OnCallAckReceivedCb = void (*) (SalOp *op, SalCustomHeader *ack); + using OnCallAckBeingSentCb = void (*) (SalOp *op, SalCustomHeader *ack); + using OnCallUpdatingCb = void (*) (SalOp *op, bool_t isUpdate); // Called when a reINVITE/UPDATE is received + using OnCallTerminatedCb = void (*) (SalOp *op, const char *from); + using OnCallFailureCb = void (*) (SalOp *op); + using OnCallReleasedCb = void (*) (SalOp *op); + using OnCallCancelDoneCb = void (*) (SalOp *op); + using OnAuthRequestedLegacyCb = void (*) (SalOp *op, const char *realm, const char *username); + using OnAuthRequestedCb = bool_t (*) (Sal *sal, SalAuthInfo *info); + using OnAuthFailureCb = void (*) (SalOp *op, SalAuthInfo *info); + using OnRegisterSuccessCb = void (*) (SalOp *op, bool_t registered); + using OnRegisterFailureCb = void (*) (SalOp *op); + using OnVfuRequestCb = void (*) (SalOp *op); + using OnDtmfReceivedCb = void (*) (SalOp *op, char dtmf); + using OnCallReferCb = void (*) (SalOp *op, const SalAddress *referTo); + using OnReferCb = void (*) (SalOp *op, const SalAddress *referTo); + using OnMessageReceivedCb = void (*) (SalOp *op, const SalMessage *msg); + using OnMessageDeliveryUpdateCb = void (*) (SalOp *op, SalMessageDeliveryStatus status); + using OnNotifyReferCb = void (*) (SalOp *op, SalReferStatus status); + using OnSubscribeResponseCb = void (*) (SalOp *op, SalSubscribeStatus status, int willRetry); + using OnNotifyCb = void (*) (SalSubscribeOp *op, SalSubscribeStatus status, const char *event, SalBodyHandler *body); + using OnSubscribeReceivedCb = void (*) (SalSubscribeOp *op, const char *event, const SalBodyHandler *body); + using OnIncomingSubscribeClosedCb = void (*) (SalOp *op); + using OnParsePresenceRequestedCb = void (*) (SalOp *op, const char *contentType, const char *contentSubtype, const char *content, SalPresenceModel **result); + using OnConvertPresenceToXMLRequestedCb = void (*) (SalOp *op, SalPresenceModel *presence, const char *contact, char **content); + using OnNotifyPresenceCb = void (*) (SalOp *op, SalSubscribeStatus ss, SalPresenceModel *model, const char *msg); + using OnSubscribePresenceReceivedCb = void (*) (SalPresenceOp *op, const char *from); + using OnSubscribePresenceClosedCb = void (*) (SalPresenceOp *op, const char *from); + using OnPingReplyCb = void (*) (SalOp *op); + using OnInfoReceivedCb = void (*) (SalOp *op, SalBodyHandler *body); + using OnPublishResponseCb = void (*) (SalOp *op); + using OnNotifyResponseCb = void (*) (SalOp *op); + using OnExpireCb = void (*) (SalOp *op); + + struct Callbacks { + OnCallReceivedCb call_received; + OnCallReceivedCb call_rejected; + OnCallRingingCb call_ringing; + OnCallAcceptedCb call_accepted; + OnCallAckReceivedCb call_ack_received; + OnCallAckBeingSentCb call_ack_being_sent; + OnCallUpdatingCb call_updating; + OnCallTerminatedCb call_terminated; + OnCallFailureCb call_failure; + OnCallReleasedCb call_released; + OnCallCancelDoneCb call_cancel_done; + OnCallReferCb call_refer_received; + OnAuthFailureCb auth_failure; + OnRegisterSuccessCb register_success; + OnRegisterFailureCb register_failure; + OnVfuRequestCb vfu_request; + OnDtmfReceivedCb dtmf_received; + + OnMessageReceivedCb message_received; + OnMessageDeliveryUpdateCb message_delivery_update; + OnNotifyReferCb notify_refer; + OnSubscribeReceivedCb subscribe_received; + OnIncomingSubscribeClosedCb incoming_subscribe_closed; + OnSubscribeResponseCb subscribe_response; + OnNotifyCb notify; + OnSubscribePresenceReceivedCb subscribe_presence_received; + OnSubscribePresenceClosedCb subscribe_presence_closed; + OnParsePresenceRequestedCb parse_presence_requested; + OnConvertPresenceToXMLRequestedCb convert_presence_to_xml_requested; + OnNotifyPresenceCb notify_presence; + OnPingReplyCb ping_reply; + OnAuthRequestedCb auth_requested; + OnInfoReceivedCb info_received; + OnPublishResponseCb on_publish_response; + OnExpireCb on_expire; + OnNotifyResponseCb on_notify_response; + OnReferCb refer_received; // For out of dialog refer + }; + + Sal(MSFactory *factory); + ~Sal(); + + void setFactory (MSFactory *value) { mFactory = value; } + + void setUserPointer (void *value) { mUserPointer = value; } + void *getUserPointer () const { return mUserPointer; } + + void setCallbacks (const Callbacks *cbs); + + void *getStackImpl() const { return mStack; } + + int iterate () { belle_sip_stack_sleep(mStack, 0); return 0; } + + void setSendError (int value) { belle_sip_stack_set_send_error(mStack, value); } + void setRecvError (int value) { belle_sip_provider_set_recv_error(mProvider, value); } + + + // --------------------------------------------------------------------------- + // SIP parameters + // --------------------------------------------------------------------------- + void setSupportedTags (const std::string &tags); + const std::string &getSupportedTags () const; + void addSupportedTag (const std::string &tag); + void removeSupportedTag (const std::string &tag); + + void setUserAgent (const std::string &value); + const std::string &getUserAgent () const; + void appendStackStringToUserAgent (); + + bool isContentEncodingAvailable (const std::string &contentEncoding) const; + bool isContentTypeSupported (const std::string &contentType) const; + void addContentTypeSupport (const std::string &contentType); + void removeContentTypeSupport (const std::string &contentType); + + void setDefaultSdpHandling (SalOpSDPHandling sdpHandlingMethod); + + void setUuid (const std::string &value) { mUuid = value; } + int createUuid (char *uuid, size_t len); + static int generateUuid (char *uuid, size_t len); + + void enableNatHelper (bool value); + bool natHelperEnabled () const { return mNatHelperEnabled; } + + bool pendingTransactionCheckingEnabled () const { return mPendingTransactionChecking; } + void enablePendingTransactionChecking (bool value) { mPendingTransactionChecking = value; } + + void setRefresherRetryAfter (int value) { mRefresherRetryAfter = value; } + int getRefresherRetryAfter () const { return mRefresherRetryAfter; } + + void enableSipUpdateMethod (bool value) { mEnableSipUpdate = value; } + void useSessionTimers (int expires) { mSessionExpires = expires; } + void useDates (bool value) { mUseDates = value; } + void useOneMatchingCodecPolicy (bool value) { mOneMatchingCodec = value; } + void useRport (bool value); + void enableAutoContacts (bool value) { mAutoContacts = value; } + void enableTestFeatures (bool value) { mEnableTestFeatures = value; } + void useNoInitialRoute (bool value) { mNoInitialRoute = value; } + void enableUnconditionalAnswer (int value) { belle_sip_provider_enable_unconditional_answer(mProvider, value); } + void enableReconnectToPrimaryAsap (bool value) { belle_sip_stack_enable_reconnect_to_primary_asap(mStack, value); } + + const std::list &getPendingAuths () const { return mPendingAuths; } + + void setContactLinphoneSpecs (const std::string &value) { mLinphoneSpecs = value; } + + + // --------------------------------------------------------------------------- + // Network parameters + // --------------------------------------------------------------------------- + int setListenPort (const std::string &addr, int port, SalTransport tr, bool isTunneled); + int getListeningPort (SalTransport tr); + int isTransportAvailable (SalTransport t); + + void getDefaultLocalIp (int addressFamily, char *ip, size_t ipLen); + + void setTransportTimeout (int value) { belle_sip_stack_set_transport_timeout(mStack, value); } + int getTransportTimeout () const { return belle_sip_stack_get_transport_timeout(mStack); } + + void setKeepAlivePeriod (unsigned int value); + unsigned int getKeepAlivePeriod () const { return mKeepAlive; } + void useTcpTlsKeepAlive (bool value) { mUseTcpTlsKeepAlive = value; } + + void setDscp (int dscp) { belle_sip_stack_set_default_dscp(mStack, dscp); } + + int setTunnel (void *tunnelClient); + + void setHttpProxyHost (const std::string &value); + const std::string &getHttpProxyHost () const; + + void setHttpProxyPort (int value) { belle_sip_stack_set_http_proxy_port(mStack, value); } + int getHttpProxyPort () const { return belle_sip_stack_get_http_proxy_port(mStack); } + + ortp_socket_t getSocket () const; + + int unlistenPorts (); + int resetTransports (); + + + // --------------------------------------------------------------------------- + // TLS parameters + // --------------------------------------------------------------------------- + void setSslConfig (void *sslConfig); + void setRootCa (const std::string &value); + void setRootCaData (const std::string &value); + const std::string &getRootCa () const { return mRootCa; } + + void verifyServerCertificates (bool value); + void verifyServerCn (bool value); + void setTlsPostcheckCallback(int (*cb)(void *, const bctbx_x509_certificate_t *), void *data); + + // --------------------------------------------------------------------------- + // DNS resolution + // --------------------------------------------------------------------------- + void setDnsTimeout (int value) { belle_sip_stack_set_dns_timeout(mStack, value); } + int getDnsTimeout () const { return belle_sip_stack_get_dns_timeout(mStack); } + + void setDnsServers (const bctbx_list_t *servers); + + void enableDnsSearch (bool value) { belle_sip_stack_enable_dns_search(mStack, (unsigned char)value); } + bool dnsSearchEnabled () const { return !!belle_sip_stack_dns_search_enabled(mStack); } + + void enableDnsSrv (bool value) { belle_sip_stack_enable_dns_srv(mStack, (unsigned char)value); } + bool dnsSrvEnabled () const { return !!belle_sip_stack_dns_srv_enabled(mStack); } + + void setDnsUserHostsFile (const std::string &value); + const std::string &getDnsUserHostsFile () const; + + belle_sip_resolver_context_t *resolveA (const std::string &name, int port, int family, belle_sip_resolver_callback_t cb, void *data); + belle_sip_resolver_context_t *resolve (const std::string &service, const std::string &transport, const std::string &name, int port, int family, belle_sip_resolver_callback_t cb, void *data); + + + // --------------------------------------------------------------------------- + // Timers + // --------------------------------------------------------------------------- + belle_sip_source_t *createTimer (belle_sip_source_func_t func, void *data, unsigned int timeoutValueMs, const std::string &timerName); + void cancelTimer (belle_sip_source_t *timer); + + +private: + struct SalUuid { + unsigned int timeLow; + unsigned short timeMid; + unsigned short timeHiAndVersion; + unsigned char clockSeqHiAndReserved; + unsigned char clockSeqLow; + unsigned char node[6]; + }; + + void setTlsProperties (); + int addListenPort (SalAddress *addr, bool isTunneled); + void makeSupportedHeader (); + void addPendingAuth (SalOp *op); + void removePendingAuth (SalOp *op); + belle_sip_response_t *createResponseFromRequest (belle_sip_request_t *req, int code); + + static void unimplementedStub() { lWarning() << "Unimplemented SAL callback"; } + static void removeListeningPoint (belle_sip_listening_point_t *lp,belle_sip_provider_t *prov) { + belle_sip_provider_remove_listening_point(prov, lp); + } + + // Internal callbacks + static void processDialogTerminatedCb (void *userCtx, const belle_sip_dialog_terminated_event_t *event); + static void processIoErrorCb (void *userCtx, const belle_sip_io_error_event_t *event); + static void processRequestEventCb (void *userCtx, const belle_sip_request_event_t *event); + static void processResponseEventCb (void *userCtx, const belle_sip_response_event_t *event); + static void processTimeoutCb (void *userCtx, const belle_sip_timeout_event_t *event); + static void processTransactionTerminatedCb (void *userCtx, const belle_sip_transaction_terminated_event_t *event); + static void processAuthRequestedCb (void *userCtx, belle_sip_auth_event_t *event); + + MSFactory *mFactory = nullptr; + Callbacks mCallbacks = { 0 }; + std::list mPendingAuths; + belle_sip_stack_t *mStack = nullptr; + belle_sip_provider_t *mProvider = nullptr; + belle_sip_header_user_agent_t *mUserAgentHeader = nullptr; + belle_sip_listener_t *mListener = nullptr; + void *mTunnelClient = nullptr; + void *mUserPointer = nullptr; // User pointer + int mSessionExpires = 0; + unsigned int mKeepAlive = 0; + std::string mRootCa; + std::string mRootCaData; + std::string mUuid; + int mRefresherRetryAfter = 60000; // Retry after value for refresher + std::vector mSupportedTags; + belle_sip_header_t *mSupportedHeader = nullptr; + bool mOneMatchingCodec = false; + bool mUseTcpTlsKeepAlive = false; + bool mNatHelperEnabled = false; + bool mTlsVerify = true; + bool mTlsVerifyCn = true; + bool mUseDates = false; + bool mAutoContacts = true; + bool mEnableTestFeatures = false; + bool mNoInitialRoute = false; + bool mEnableSipUpdate = true; + SalOpSDPHandling mDefaultSdpHandling = SalOpSDPNormal; + bool mPendingTransactionChecking = true; // For testing purposes + void *mSslConfig = nullptr; + std::vector mSupportedContentTypes; + std::string mLinphoneSpecs; + belle_tls_crypto_config_postcheck_callback_t mTlsPostcheckCb; + void *mTlsPostcheckCbData; + + // Cache values + mutable std::string mDnsUserHostsFile; + mutable std::string mHttpProxyHost; + mutable std::string mSupported; + mutable std::string mUserAgent; + + friend class SalOp; + friend class SalCallOp; + friend class SalRegisterOp; + friend class SalMessageOp; + friend class SalPresenceOp; + friend class SalSubscribeOp; + friend class SalPublishOp; + friend class SalReferOp; +}; + +int to_sip_code(SalReason r); + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_SAL_H_ + diff --git a/src/search/magic-search-p.h b/src/search/magic-search-p.h new file mode 100644 index 000000000..0a75e5cab --- /dev/null +++ b/src/search/magic-search-p.h @@ -0,0 +1,44 @@ +/* + * magic-search-p.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAGIC_SEARCH_P_H_ +#define _L_MAGIC_SEARCH_P_H_ + +#include "magic-search.h" +#include "object/object-p.h" + +LINPHONE_BEGIN_NAMESPACE + +class MagicSearchPrivate : public ObjectPrivate{ +private: + unsigned int mMaxWeight; + unsigned int mMinWeight; + unsigned int mSearchLimit; // Number of ResultSearch maximum when the search is limited + bool mLimitedSearch; // Limit the search + std::string mDelimiter; // Delimiter use for the search + bool mUseDelimiter; + std::list *mCacheResult; + + L_DECLARE_PUBLIC(MagicSearch); +}; + +LINPHONE_END_NAMESPACE + +#endif //_L_MAGIC_SEARCH_P_H_ + diff --git a/src/search/magic-search.cpp b/src/search/magic-search.cpp new file mode 100644 index 000000000..b88b35aa2 --- /dev/null +++ b/src/search/magic-search.cpp @@ -0,0 +1,538 @@ +/* + * magic-search.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "magic-search-p.h" + +#include +#include + +#include "c-wrapper/internal/c-tools.h" +#include "linphone/utils/utils.h" +#include "linphone/core.h" +#include "linphone/types.h" +#include "logger/logger.h" +#include "private.h" + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +MagicSearch::MagicSearch(const std::shared_ptr &core) : CoreAccessor(core), Object(*new MagicSearchPrivate){ + L_D(); + d->mMinWeight = 0; + d->mMaxWeight = 1000; + d->mSearchLimit = 30; + d->mLimitedSearch = true; + d->mDelimiter = "+_-"; + d->mUseDelimiter = true; + d->mCacheResult = nullptr; +} + +MagicSearch::~MagicSearch() { + resetSearchCache(); +} + +void MagicSearch::setMinWeight(const unsigned int weight) { + L_D(); + d->mMinWeight = weight; +} + +unsigned int MagicSearch::getMinWeight() const { + L_D(); + return d->mMinWeight; +} + +void MagicSearch::setMaxWeight(const unsigned int weight) { + L_D(); + d->mMaxWeight = weight; +} + +unsigned int MagicSearch::getMaxWeight() const { + L_D(); + return d->mMaxWeight; +} + +const string &MagicSearch::getDelimiter() const { + L_D(); + return d->mDelimiter; +} + +void MagicSearch::setDelimiter(const string &delimiter) { + L_D(); + d->mDelimiter = delimiter; +} + +bool MagicSearch::getUseDelimiter() const { + L_D(); + return d->mUseDelimiter; +} + +void MagicSearch::setUseDelimiter(bool enable) { + L_D(); + d->mUseDelimiter = enable; +} + +unsigned int MagicSearch::getSearchLimit() const { + L_D(); + return d->mSearchLimit; +} + +void MagicSearch::setSearchLimit(const unsigned int limit) { + L_D(); + d->mSearchLimit = limit; +} + +bool MagicSearch::getLimitedSearch() const { + L_D(); + return d->mLimitedSearch; +} + +void MagicSearch::setLimitedSearch(const bool limited) { + L_D(); + d->mLimitedSearch = limited; +} + +void MagicSearch::resetSearchCache() { + L_D(); + if (d->mCacheResult) { + delete d->mCacheResult; + d->mCacheResult = nullptr; + } +} + +list MagicSearch::getContactListFromFilter(const string &filter, const string &withDomain) { + list *resultList; + list returnList; + LinphoneProxyConfig *proxy = nullptr; + + if (filter.empty()) return getFriends(withDomain); + + if (getSearchCache() != nullptr) { + resultList = continueSearch(filter, withDomain); + resetSearchCache(); + } else { + resultList = beginNewSearch(filter, withDomain); + } + + resultList->sort([](const SearchResult& lsr, const SearchResult& rsr){ + return (!rsr.getFriend() && lsr.getFriend()) || lsr >= rsr; + }); + + setSearchCache(resultList); + returnList = *resultList; + + if (getLimitedSearch() && returnList.size() > getSearchLimit()) { + auto limitIterator = returnList.begin(); + advance(limitIterator, (int)getSearchLimit()); + returnList.erase(limitIterator, returnList.end()); + } + + proxy = linphone_core_get_default_proxy_config(this->getCore()->getCCore()); + // Adding last item if proxy exist + if (proxy) { + const char *domain = linphone_proxy_config_get_domain(proxy); + if (domain) { + string strTmp = filter; + transform(strTmp.begin(), strTmp.end(), strTmp.begin(), [](unsigned char c){ return tolower(c); }); + string filterAddress = "sip:" + strTmp + "@" + domain; + LinphoneAddress *lastResult = linphone_core_create_address(this->getCore()->getCCore(), filterAddress.c_str()); + if (lastResult) { + returnList.push_back(SearchResult(0, lastResult, "", nullptr)); + linphone_address_unref(lastResult); + } + } + } + + return returnList; +} + +///////////////////// +// Private Methods // +///////////////////// + +list *MagicSearch::getSearchCache() const { + L_D(); + return d->mCacheResult; +} + +void MagicSearch::setSearchCache(list *cache) { + L_D(); + if (d->mCacheResult != cache) resetSearchCache(); + d->mCacheResult = cache; +} + +static bool findAddress(const list &list, const LinphoneAddress *addr) { + bool returnValue = false; + char *charAddr = linphone_address_as_string_uri_only(addr); + string sAddr = charAddr; + for (auto r : list) { + if (r.getAddress()) { + char *charTmp = linphone_address_as_string_uri_only(r.getAddress()); + string tmp = charTmp; + if (sAddr == tmp){ + returnValue = true; + if (charTmp) bctbx_free(charTmp); + break; + } + if (charTmp) bctbx_free(charTmp); + } + } + if (charAddr) bctbx_free(charAddr); + return returnValue; +} + +list MagicSearch::getAddressFromCallLog(const string &filter, const string &withDomain, const list ¤tList) { + list resultList; + const bctbx_list_t *callLog = linphone_core_get_call_logs(this->getCore()->getCCore()); + + // For all call log or when we reach the search limit + for (const bctbx_list_t *f = callLog ; f != nullptr ; f = bctbx_list_next(f)) { + LinphoneCallLog *log = reinterpret_cast(f->data); + const LinphoneAddress *addr = (linphone_call_log_get_dir(log) == LinphoneCallDir::LinphoneCallIncoming) ? + linphone_call_log_get_from_address(log) : linphone_call_log_get_to_address(log); + if (addr) { + if (filter.empty()) { + if (findAddress(currentList, addr)) continue; + resultList.push_back(SearchResult(0, addr, "", nullptr)); + } else { + unsigned int weight = searchInAddress(addr, filter, withDomain); + if (weight > getMinWeight()) { + if (findAddress(currentList, addr)) continue; + resultList.push_back(SearchResult(weight, addr, "", nullptr)); + } + } + } + } + + return resultList; +} + +list MagicSearch::getFriends(const string &withDomain) { + list returnList; + list clResults; + LinphoneFriendList *list = linphone_core_get_default_friend_list(this->getCore()->getCCore()); + + for (bctbx_list_t *f = list->friends ; f != nullptr ; f = bctbx_list_next(f)) { + LinphoneAddress *phoneAddress = nullptr; + const LinphoneFriend *lFriend = reinterpret_cast(f->data); + const LinphoneAddress *lAddress = linphone_friend_get_address(lFriend); + bctbx_list_t *lPhoneNumbers = linphone_friend_get_phone_numbers(lFriend); + string lPhoneNumber = (lPhoneNumbers != nullptr) ? static_cast(lPhoneNumbers->data) : ""; + const LinphonePresenceModel *presence = linphone_friend_get_presence_model(lFriend); + if (lPhoneNumbers) bctbx_list_free(lPhoneNumbers); + + if (presence && !lAddress) { + char *contact = linphone_presence_model_get_contact(presence); + if (contact) { + phoneAddress = linphone_core_create_address(this->getCore()->getCCore(), contact); + bctbx_free(contact); + } + } + + if (!withDomain.empty()) { + if (!lAddress && !phoneAddress) + continue; + if (withDomain != "*" && + withDomain != ((lAddress) ? linphone_address_get_domain(lAddress) : "") && + withDomain != ((phoneAddress) ? linphone_address_get_domain(phoneAddress) : "")) + continue; + } + + if (phoneAddress) linphone_address_unref(phoneAddress); + + returnList.push_back(SearchResult(1, lAddress, lPhoneNumber, lFriend)); + } + + clResults = getAddressFromCallLog("", withDomain, clResults); + addResultsToResultsList(clResults, returnList); + + returnList.sort([](const SearchResult& lsr, const SearchResult& rsr){ + unsigned int cpt = 0; + string name1 = ""; + string name2 = ""; + if (lsr.getFriend()) { + name1 = linphone_friend_get_name(lsr.getFriend()); + } else if (lsr.getAddress()){ + name1 = linphone_address_get_display_name(lsr.getAddress()) ? + linphone_address_get_display_name(lsr.getAddress()) : linphone_address_get_username(lsr.getAddress()); + } + + if (rsr.getFriend()) { + name2 = linphone_friend_get_name(rsr.getFriend()); + } else if (rsr.getAddress()){ + name2 = linphone_address_get_display_name(rsr.getAddress()) ? + linphone_address_get_display_name(rsr.getAddress()) : linphone_address_get_username(rsr.getAddress()); + } + + while (name1.size() > cpt && name2.size() > cpt) { + int char1 = tolower(name1.at(cpt)); + int char2 = tolower(name2.at(cpt)); + if (char1 < char2) { + return true; + } else if (char1 > char2) { + return false; + } + cpt++; + } + return name1.size() < name2.size(); + }); + + return *uniqueItemsList(returnList); +} + +list *MagicSearch::beginNewSearch(const string &filter, const string &withDomain) { + list clResults; + list *resultList = new list(); + LinphoneFriendList *fList = linphone_core_get_default_friend_list(this->getCore()->getCCore()); + + // For all friends or when we reach the search limit + for (bctbx_list_t *f = fList->friends ; f != nullptr ; f = bctbx_list_next(f)) { + list fResults = searchInFriend(reinterpret_cast(f->data), filter, withDomain); + addResultsToResultsList(fResults, *resultList); + } + + clResults = getAddressFromCallLog(filter, withDomain, *resultList); + addResultsToResultsList(clResults, *resultList); + + return uniqueItemsList(*resultList); +} + +list *MagicSearch::continueSearch(const string &filter, const string &withDomain) { + list *resultList = new list(); + const list *cacheList = getSearchCache(); + + for (const auto sr : *cacheList) { + if (sr.getAddress() || !sr.getPhoneNumber().empty()) { + if (sr.getFriend()) { + list results = searchInFriend(sr.getFriend(), filter, withDomain); + addResultsToResultsList(results, *resultList); + } else { + unsigned int weight = searchInAddress(sr.getAddress(), filter, withDomain); + if (weight > getMinWeight()) { + resultList->push_back(SearchResult(weight, sr.getAddress(), sr.getPhoneNumber(), nullptr)); + } + } + } + } + + return uniqueItemsList(*resultList); +} + +list MagicSearch::searchInFriend(const LinphoneFriend *lFriend, const string &filter, const string &withDomain) { + list friendResult; + string phoneNumber = ""; + unsigned int weight = getMinWeight(); + + // NAME + if (linphone_core_vcard_supported()) { + if (linphone_friend_get_vcard(lFriend)) { + weight += getWeight(linphone_vcard_get_full_name(linphone_friend_get_vcard(lFriend)), filter) * 3; + } + } + + //SIP URI + for (const bctbx_list_t *listAddress = linphone_friend_get_addresses(lFriend); + listAddress != nullptr && listAddress->data != nullptr; + listAddress = listAddress->next) { + const LinphoneAddress *lAddress = static_cast(listAddress->data); + if (!checkDomain(lFriend, lAddress, withDomain)) { + if (!withDomain.empty()) { + continue; + } + } + + unsigned int weightAddress = searchInAddress(lAddress, filter, withDomain) * 1; + + if ((weightAddress + weight) > getMinWeight()) { + friendResult.push_back(SearchResult(weight + weightAddress, lAddress, phoneNumber, lFriend)); + } + } + + // PHONE NUMBER + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(this->getCore()->getCCore()); + bctbx_list_t *begin, *phoneNumbers = linphone_friend_get_phone_numbers(lFriend); + begin = phoneNumbers; + while (phoneNumbers && phoneNumbers->data) { + bool domainOk = (withDomain.empty()); + string number = static_cast(phoneNumbers->data); + const LinphonePresenceModel *presence = linphone_friend_get_presence_model_for_uri_or_tel(lFriend, number.c_str()); + phoneNumber = number; + if (proxy) { + char * buff = linphone_proxy_config_normalize_phone_number(proxy, phoneNumber.c_str()); + if (buff) { + phoneNumber = buff; + bctbx_free(buff); + } + } + unsigned int weightNumber = getWeight(phoneNumber.c_str(), filter); + if (presence) { + char *contact = linphone_presence_model_get_contact(presence); + if (contact) { + if (!domainOk) { + LinphoneAddress *tmpAdd = linphone_core_create_address(this->getCore()->getCCore(), contact); + if (tmpAdd) { + string tmpDomain = linphone_address_get_domain(tmpAdd); + domainOk = (tmpDomain == withDomain) || withDomain == "*"; + linphone_address_unref(tmpAdd); + } + } + weightNumber += getWeight(contact, filter) * 2; + bctbx_free(contact); + } + } + if ((weightNumber + weight) > getMinWeight()) { + if (!domainOk && linphone_friend_get_address(lFriend)) { + string tmpDomain = linphone_address_get_domain(linphone_friend_get_address(lFriend)); + domainOk = (tmpDomain == withDomain) || withDomain == "*"; + } + if (domainOk) + friendResult.push_back(SearchResult(weight + weightNumber, linphone_friend_get_address(lFriend), phoneNumber, lFriend)); + } + phoneNumbers = phoneNumbers->next; + } + if (begin) bctbx_list_free(begin); + + return friendResult; +} + +unsigned int MagicSearch::searchInAddress(const LinphoneAddress *lAddress, const string &filter, const string &withDomain) { + unsigned int weight = getMinWeight(); + if (lAddress != nullptr && checkDomain(nullptr, lAddress, withDomain)) { + // SIPURI + if (linphone_address_get_username(lAddress) != nullptr) { + weight += getWeight(linphone_address_get_username(lAddress), filter); + } + // DISPLAYNAME + if (linphone_address_get_display_name(lAddress) != nullptr) { + weight += getWeight(linphone_address_get_display_name(lAddress), filter); + } + } + return weight; +} + +unsigned int MagicSearch::getWeight(const string &stringWords, const string &filter) const { + locale loc; + string filterLC = filter; + string stringWordsLC = stringWords; + size_t weight = string::npos; + + transform(stringWordsLC.begin(), stringWordsLC.end(), stringWordsLC.begin(), [](unsigned char c){ return tolower(c); }); + transform(filterLC.begin(), filterLC.end(), filterLC.begin(), [](unsigned char c){ return tolower(c); }); + + // Finding all occurrences of "filterLC" in "stringWordsLC" + for (size_t w = stringWordsLC.find(filterLC); + w != string::npos; + w = stringWordsLC.find(filterLC, w + filterLC.length()) + ) { + // weight max if occurence find at beginning + if (w == 0) { + weight = getMaxWeight(); + } else { + bool isDelimiter = false; + if (getUseDelimiter()) { + // get the char before the matched filterLC + const char l = stringWordsLC.at(w - 1); + // Check if it's a delimiter + for (const char d : getDelimiter()) { + if (l == d) { + isDelimiter = true; + break; + } + } + } + unsigned int newWeight = getMaxWeight() - (unsigned int)((isDelimiter) ? 1 : w + 1); + weight = (weight != string::npos) ? weight + newWeight : newWeight; + } + // Only one search on the stringWordsLC for the moment + // due to weight calcul which dos not take into the case of multiple occurence + break; + } + + return (weight != string::npos) ? (unsigned int)(weight) : getMinWeight(); +} + +bool MagicSearch::checkDomain(const LinphoneFriend *lFriend, const LinphoneAddress *lAddress, const string &withDomain) const { + bool onlyOneDomain = !withDomain.empty() && withDomain != "*"; + const LinphonePresenceModel *presenceModel = lFriend ? linphone_friend_get_presence_model(lFriend) : nullptr; + char *contactPresence = presenceModel ? linphone_presence_model_get_contact(presenceModel) : nullptr; + + LinphoneAddress *addrPresence = nullptr; + if (contactPresence) { + addrPresence = linphone_core_create_address(this->getCore()->getCCore(), contactPresence); + bctbx_free(contactPresence); + } + + bool soFarSoGood = + !onlyOneDomain || ( + // If we don't want Sip URI only or Address or Presence model + (lAddress || presenceModel) && + // And If we don't want Sip URI only or Address match or Address presence match + ((lAddress && withDomain == linphone_address_get_domain(lAddress)) || + (addrPresence && withDomain == linphone_address_get_domain(addrPresence))) + ); + + if (addrPresence) linphone_address_unref(addrPresence); + + return soFarSoGood; +} + +void MagicSearch::addResultsToResultsList(std::list &results, std::list &srL) { + if (results.size() > 0) { + srL.merge(results); + } +} + +static string getAddressFromSearchResult(const SearchResult &sr, const shared_ptr lc) { + string sAddress = ""; + if (!sr.getAddress() && sr.getFriend()) { + const LinphonePresenceModel *presenceModel = linphone_friend_get_presence_model(sr.getFriend()); + char *contactPresence = presenceModel ? linphone_presence_model_get_contact(presenceModel) : nullptr; + + LinphoneAddress *addrPresence = nullptr; + if (contactPresence) { + addrPresence = linphone_core_create_address(lc->getCCore(), contactPresence); + if (addrPresence) { + char *tmp = linphone_address_as_string_uri_only(addrPresence); + sAddress = tmp; + if (tmp) bctbx_free(tmp); + linphone_address_unref(addrPresence); + } + bctbx_free(contactPresence); + } + } else { + char *tmp = linphone_address_as_string_uri_only(sr.getAddress()); + sAddress = tmp; + if (tmp) bctbx_free(tmp); + } + + return sAddress; +} + +list *MagicSearch::uniqueItemsList(list &list) { + auto lc = this->getCore(); + list.unique([lc](const SearchResult& lsr, const SearchResult& rsr){ + string left = getAddressFromSearchResult(lsr, lc); + string right = getAddressFromSearchResult(rsr, lc); + + return (!left.empty() || !right.empty()) && left == right; + }); + return &list; +} + +LINPHONE_END_NAMESPACE diff --git a/src/search/magic-search.h b/src/search/magic-search.h new file mode 100644 index 000000000..13348bac0 --- /dev/null +++ b/src/search/magic-search.h @@ -0,0 +1,223 @@ +/* + * magic-search.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_MAGIC_SEARCH_H_ +#define _L_MAGIC_SEARCH_H_ + +#include +#include +#include + +#include "core/core.h" +#include "core/core-accessor.h" +#include "search-result.h" + +LINPHONE_BEGIN_NAMESPACE + +class MagicSearchPrivate; + +class LINPHONE_PUBLIC MagicSearch : public CoreAccessor, public Object{ +public: + + MagicSearch(const std::shared_ptr &core); + MagicSearch(const MagicSearch &ms) = delete; + ~MagicSearch(); + + /** + * Set the minimum value used to calculate the weight in search + * @param[in] weight minimum weight + **/ + void setMinWeight(const unsigned int weight); + + /** + * @return the minimum value used to calculate the weight in search + **/ + unsigned int getMinWeight() const; + + /** + * Set the maximum value used to calculate the weight in search + * @param[in] weight maximum weight + **/ + void setMaxWeight(const unsigned int weight); + + /** + * @return the maximum value used to calculate the weight in search + **/ + unsigned int getMaxWeight() const; + + /** + * @return the delimiter used to find matched filter word + **/ + const std::string& getDelimiter() const; + + /** + * Set the delimiter used to find matched filter word + * @param[in] delimiter delimiter (example "-_.,") + **/ + void setDelimiter(const std::string &delimiter); + + /** + * @return if the delimiter search is used + **/ + bool getUseDelimiter() const; + + /** + * Enable or disable the delimiter in search + * @param[in] enable + **/ + void setUseDelimiter(bool enable); + + /** + * @return the number of the maximum SearchResult which will be return + **/ + unsigned int getSearchLimit() const; + + /** + * Set the number of the maximum SearchResult which will be return + * @param[in] limit + **/ + void setSearchLimit(const unsigned int limit); + + /** + * @return if the search is limited + **/ + bool getLimitedSearch() const; + + /** + * Enable or disable the limited search + * @param[in] limited + **/ + void setLimitedSearch(const bool limited); + + /** + * Reset the cache to begin a new search + **/ + void resetSearchCache(); + + /** + * Create a sorted list of SearchResult from SipUri, Contact name, + * Contact displayname, Contact phone number, which match with a filter word + * The last item list will be an address formed with "filter" if a proxy config exist + * During the first search, a cache is created and used for the next search + * Use resetSearchCache() to begin a new search + * @param[in] filter word we search + * @param[in] withDomain + * - "" for searching in all contact + * - "*" for searching in contact with sip SipUri + * - "yourdomain" for searching in contact from "yourdomain" domain + * @return sorted list of SearchResult with "filter" or an empty list if "filter" is empty + **/ + std::list getContactListFromFilter(const std::string &filter, const std::string &withDomain = ""); + +private: + + /** + * @return the cache of precedent result + * @private + **/ + std::list *getSearchCache() const; + + /** + * Save a result for future search + * @param[in] cache result we want to save + * @private + **/ + void setSearchCache(std::list *cache); + + /** + * Get all address from call log + * @param[in] filter word we search + * @param[in] withDomain domain which we want to search only + * @param[in] currentList current list where we will check if address already exist + * @return all address from call log which match in a SearchResult list + * @private + **/ + std::list getAddressFromCallLog(const std::string &filter, const std::string &withDomain, const std::list ¤tList); + + /** + * Get all friends as SearchResult + * @param[in] withDomain domain which we want to search only + * @return all friends in a SearchResult list + * @private + **/ + std::list getFriends(const std::string &withDomain); + + /** + * Begin the search from friend list + * @param[in] filter word we search + * @param[in] withDomain domain which we want to search only + * @private + **/ + std::list *beginNewSearch(const std::string &filter, const std::string &withDomain); + + /** + * Continue the search from the cache of precedent search + * @param[in] filter word we search + * @param[in] withDomain domain which we want to search only + * @private + **/ + std::list *continueSearch(const std::string &filter, const std::string &withDomain); + + /** + * Search informations in friend given + * @param[in] lFriend friend whose informations will be check + * @param[in] filter word we search + * @param[in] withDomain domain which we want to search only + * @return list of result from friend + * @private + **/ + std::list searchInFriend(const LinphoneFriend* lFriend, const std::string &filter, const std::string &withDomain); + + /** + * Search informations in address given + * @param[in] lAddress address whose informations will be check + * @param[in] filter word we search + * @param[in] withDomain domain which we want to search only + * @private + **/ + unsigned int searchInAddress(const LinphoneAddress *lAddress, const std::string &filter, const std::string &withDomain); + + /** + * Return a weight for a searched in with a filter + * @param[in] stringWords which where we are searching + * @param[in] filter what we are searching + * @return calculate weight + * @private + **/ + unsigned int getWeight(const std::string &stringWords, const std::string &filter) const; + + /** + * Return if the given address match domain policy + * @param[in] lFriend friend whose domain will be check + * @param[in] lAddress address whose domain will be check + * @param[in] withDomain domain policy + * @private + **/ + bool checkDomain(const LinphoneFriend* lFriend, const LinphoneAddress *lAddress, const std::string &withDomain) const; + + void addResultsToResultsList(std::list &results, std::list &srL); + + std::list *uniqueItemsList(std::list &list); + + L_DECLARE_PRIVATE(MagicSearch); +}; + +LINPHONE_END_NAMESPACE + +#endif //_L_MAGIC_SEARCH_H_ diff --git a/src/search/search-result.cpp b/src/search/search-result.cpp new file mode 100644 index 000000000..c7494768a --- /dev/null +++ b/src/search/search-result.cpp @@ -0,0 +1,101 @@ +/* + * search-result.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/api/c-address.h" + +#include "object/clonable-object-p.h" +#include "search-result.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class SearchResultPrivate : public ClonableObjectPrivate { +private: + const LinphoneFriend *mFriend; + const LinphoneAddress *mAddress; + std::string mPhoneNumber; + unsigned int mWeight; + + L_DECLARE_PUBLIC(SearchResult); +}; + +using namespace std; + +SearchResult::SearchResult(const unsigned int weight, const LinphoneAddress *a, const string &pn, const LinphoneFriend *f) : ClonableObject(*new SearchResultPrivate) { + L_D(); + d->mWeight = weight; + d->mAddress = a; + if (d->mAddress) linphone_address_ref(const_cast(d->mAddress)); + d->mFriend = f; + d->mPhoneNumber = pn; +} + +SearchResult::SearchResult(const SearchResult &sr) : ClonableObject(*new SearchResultPrivate) { + L_D(); + d->mWeight = sr.getWeight(); + d->mAddress = sr.getAddress(); + if (d->mAddress) linphone_address_ref(const_cast(d->mAddress)); + d->mFriend = sr.getFriend(); + d->mPhoneNumber = sr.getPhoneNumber(); +} + +SearchResult::~SearchResult() { + L_D(); + // FIXME: Ugly temporary workaround to solve weak. Remove me later. + if (d->mAddress) linphone_address_unref(const_cast(d->mAddress)); +}; + +bool SearchResult::operator<(const SearchResult &other) const { + return getWeight() < other.getWeight(); +} + +bool SearchResult::operator>(const SearchResult &other) const { + return getWeight() > other.getWeight(); +} + +bool SearchResult::operator>=(const SearchResult &other) const { + return getWeight() >= other.getWeight(); +} + +bool SearchResult::operator=(const SearchResult &other) const { + return getWeight() == other.getWeight(); +} + +const LinphoneFriend *SearchResult::getFriend() const { + L_D(); + return d->mFriend; +} + +const LinphoneAddress *SearchResult::getAddress() const { + L_D(); + return d->mAddress; +} + +const string &SearchResult::getPhoneNumber() const { + L_D(); + return d->mPhoneNumber; +} + +unsigned int SearchResult::getWeight() const { + L_D(); + return d->mWeight; +} + +LINPHONE_END_NAMESPACE diff --git a/src/search/search-result.h b/src/search/search-result.h new file mode 100644 index 000000000..cee73aafc --- /dev/null +++ b/src/search/search-result.h @@ -0,0 +1,72 @@ +/* + * search-result.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SEARCH_RESULT_H_ +#define _L_SEARCH_RESULT_H_ + +#include "linphone/utils/general.h" +#include "linphone/types.h" + +#include "object/clonable-object.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class SearchResultPrivate; + +class LINPHONE_PUBLIC SearchResult : public ClonableObject { +public: + // TODO: Use C++ Address! Not LinphoneAddress. + SearchResult(const unsigned int weight, const LinphoneAddress *a, const std::string &pn, const LinphoneFriend *f = nullptr); + SearchResult(const SearchResult &other); + ~SearchResult(); + + bool operator<(const SearchResult &other) const; + bool operator>(const SearchResult &other) const; + bool operator>=(const SearchResult &other) const; + bool operator=(const SearchResult &other) const; + + /** + * @return LinphoneFriend associed + **/ + const LinphoneFriend *getFriend()const; + + /** + * @return LinphoneAddress associed + **/ + const LinphoneAddress *getAddress() const; + + /** + * @return Phone Number associed + **/ + const std::string &getPhoneNumber() const; + + /** + * @return the result weight + **/ + unsigned int getWeight() const; + +private: + L_DECLARE_PRIVATE(SearchResult); +}; + +LINPHONE_END_NAMESPACE + +#endif //_L_SEARCH_RESULT_H_ diff --git a/src/sip-tools/sip-headers.h b/src/sip-tools/sip-headers.h new file mode 100644 index 000000000..788fec285 --- /dev/null +++ b/src/sip-tools/sip-headers.h @@ -0,0 +1,43 @@ +/* + * sip-headers.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_SIP_HEADERS_H_ +#define _L_SIP_HEADERS_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +namespace PriorityHeader { + constexpr char HeaderName[] = "Priority"; + + // Values + constexpr char NonUrgent[] = "non-urgent"; + constexpr char Urgent[] = "urgent"; + constexpr char Emergency[] = "emergency"; + constexpr char Normal[] = "normal"; +} + +LINPHONE_END_NAMESPACE + +#endif // _L_SIP_HEADERS_H_ diff --git a/src/utils/background-task.cpp b/src/utils/background-task.cpp new file mode 100644 index 000000000..fcea4f2f3 --- /dev/null +++ b/src/utils/background-task.cpp @@ -0,0 +1,88 @@ +/* + * background-task.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "background-task.h" +#include "c-wrapper/internal/c-sal.h" +#include "logger/logger.h" +#include "core/core-p.h" + +// TODO: Remove me +#include "private.h" // To get access to the Sal + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +void BackgroundTask::sHandleTimeout (void *context) { + static_cast(context)->handleTimeout(); +} + +int BackgroundTask::sHandleSalTimeout (void *data, unsigned int events) { + static_cast(data)->handleSalTimeout(); + return BELLE_SIP_STOP; +} + +void BackgroundTask::handleSalTimeout () { + lWarning() << "Background task [" << mId << "] with name: [" << mName << "] is now expiring"; + stop(); +} + +void BackgroundTask::start (const shared_ptr &core, int maxDurationSeconds) { + if (mName.empty()) { + lError() << "No name was set on background task"; + return; + } + + unsigned long newId = sal_begin_background_task(mName.c_str(), sHandleTimeout, this); + stop(); + if (newId == 0) + return; + + lInfo() << "Starting background task [" << newId << "] with name: [" << mName + << "] and expiration of [" << maxDurationSeconds << "]"; + mId = newId; + if (maxDurationSeconds > 0) { + mSal = core->getCCore()->sal; + mTimeout = mSal->createTimer(sHandleSalTimeout, this, (unsigned int)maxDurationSeconds * 1000, mName.c_str()); + } +} + +void BackgroundTask::stop () { + if (mId == 0) + return; + + lInfo() << "Ending background task [" << mId << "] with name: [" << mName << "]"; + sal_end_background_task(mId); + if (mTimeout) { + mSal->cancelTimer(mTimeout); + belle_sip_object_unref(mTimeout); + mTimeout = nullptr; + } + mId = 0; +} + +void BackgroundTask::handleTimeout () { + lWarning() << "Background task [" << mId << "] with name: [" << mName + << "] is expiring from OS before completion..."; + stop(); +} + +LINPHONE_END_NAMESPACE diff --git a/src/utils/background-task.h b/src/utils/background-task.h new file mode 100644 index 000000000..fbf11106f --- /dev/null +++ b/src/utils/background-task.h @@ -0,0 +1,67 @@ +/* + * background-task.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_BACKGROUND_TASK_H_ +#define _L_BACKGROUND_TASK_H_ + +#include + +#include "linphone/utils/general.h" +#include "sal/sal.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +class Sal; +class Core; + +class BackgroundTask { +public: + BackgroundTask () {} + BackgroundTask (const std::string &name) : mName(name) {} + virtual ~BackgroundTask () { stop(); } + + void setName (const std::string &name) { mName = name; } + + const std::string &getName () const { return mName; } + + /** + * Start a long running task for at most max_duration_seconds, after which it is automatically terminated + */ + void start (const std::shared_ptr &core, int maxDurationSeconds = 15 * 60); // 15 min by default, like on iOS + void stop (); + +protected: + virtual void handleTimeout (); + +private: + static int sHandleSalTimeout(void *data, unsigned int events); + static void sHandleTimeout(void *data); + void handleSalTimeout(); + + belle_sip_source_t *mTimeout = nullptr; + Sal *mSal = nullptr; + std::string mName; + unsigned long mId = 0; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_BACKGROUND_TASK_H_ diff --git a/src/utils/enum-generator.h b/src/utils/enum-generator.h deleted file mode 100644 index 994948d57..000000000 --- a/src/utils/enum-generator.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * enum-generator.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _ENUM_GENERATOR_H_ -#define _ENUM_GENERATOR_H_ - -#include "magic-macros.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -#define L_ENUM_VALUE(C, VALUE) C ## VALUE - -#ifndef L_USE_C_ENUM - #define L_DECLARE_ENUM_VALUES(CLASS_NAME, ENUM_NAME, ...) \ - MM_APPLY_COMMA(L_ENUM_VALUE, ENUM_NAME, __VA_ARGS__) -#else - #define L_DECLARE_ENUM_VALUES(CLASS_NAME, ENUM_NAME, ...) \ - MM_APPLY_COMMA(L_ENUM_VALUE, Linphone ## CLASS_NAME ## ENUM_NAME, __VA_ARGS__) -#endif // ifndef L_USE_C_ENUM - -LINPHONE_END_NAMESPACE - -#endif // ifndef _ENUM_GENERATOR_H_ diff --git a/src/utils/fs.cpp b/src/utils/fs.cpp new file mode 100644 index 000000000..ec9175857 --- /dev/null +++ b/src/utils/fs.cpp @@ -0,0 +1,39 @@ +/* + * fs.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "linphone/utils/fs.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +namespace Fs { + bool copy (const string &srcPath, const string &destPath) { + ifstream src(srcPath, ios::binary); + ofstream dest(destPath, ios::binary); + dest << src.rdbuf(); + return !dest.fail(); + } +} + +LINPHONE_END_NAMESPACE diff --git a/src/utils/general-internal.h b/src/utils/general-internal.h new file mode 100644 index 000000000..c2e765339 --- /dev/null +++ b/src/utils/general-internal.h @@ -0,0 +1,51 @@ +/* + * general-internal.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_GENERAL_INTERNAL_H_ +#define _L_GENERAL_INTERNAL_H_ + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- +// Export. +// ----------------------------------------------------------------------------- + +#ifndef LINPHONE_INTERNAL_PUBLIC + #if defined(_MSC_VER) + #ifdef LINPHONE_STATIC + #define LINPHONE_INTERNAL_PUBLIC + #else + #ifdef LINPHONE_EXPORTS + #define LINPHONE_INTERNAL_PUBLIC __declspec(dllexport) + #else + #define LINPHONE_INTERNAL_PUBLIC __declspec(dllimport) + #endif + #endif + #else + #define LINPHONE_INTERNAL_PUBLIC + #endif +#endif + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_GENERAL_INTERNAL_H_ diff --git a/src/utils/general.cpp b/src/utils/general.cpp index 9ed357c03..73ac6f1b8 100644 --- a/src/utils/general.cpp +++ b/src/utils/general.cpp @@ -1,11 +1,11 @@ /* * general.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,18 +13,19 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "logger/logger.h" +#include "linphone/utils/general.h" -#include "general.h" +#include "logger/logger.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE -void l_assert (const char *condition, const char *file, int line) { +void lAssert (const char *condition, const char *file, int line) { lFatal() << "ASSERT: " << condition << " in " << file << " line " << line << "."; } diff --git a/src/utils/general.h b/src/utils/general.h deleted file mode 100644 index fd1ebb9eb..000000000 --- a/src/utils/general.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * general.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _GENERAL_H_ -#define _GENERAL_H_ - -// ============================================================================= - -#define LINPHONE_NAMESPACE LinphonePrivate - -#ifdef __cplusplus - #define LINPHONE_BEGIN_NAMESPACE namespace LINPHONE_NAMESPACE { - #define LINPHONE_END_NAMESPACE } -#else - #define LINPHONE_BEGIN_NAMESPACE - #define LINPHONE_END_NAMESPACE -#endif - -// ----------------------------------------------------------------------------- - -LINPHONE_BEGIN_NAMESPACE - -#ifndef LINPHONE_PUBLIC - #if defined(_MSC_VER) - #ifdef LINPHONE_STATIC - #define LINPHONE_PUBLIC - #else - #ifdef LINPHONE_EXPORTS - #define LINPHONE_PUBLIC __declspec(dllexport) - #else - #define LINPHONE_PUBLIC __declspec(dllimport) - #endif - #endif - #else - #define LINPHONE_PUBLIC - #endif -#endif - -// ----------------------------------------------------------------------------- - -#ifdef __cplusplus - -void l_assert (const char *condition, const char *file, int line); - -#ifdef DEBUG - #define L_ASSERT(CONDITION) static_cast(false && (CONDITION)) -#else - #define L_ASSERT(CONDITION) ((CONDITION) ? static_cast(0) : l_assert(#CONDITION, __FILE__, __LINE__)) -#endif - -#define L_DECLARE_PRIVATE(CLASS) \ - inline CLASS ## Private * getPrivate() { \ - return reinterpret_cast(mPrivate); \ - } \ - inline const CLASS ## Private *getPrivate() const { \ - return reinterpret_cast(mPrivate); \ - } \ - friend class CLASS ## Private; - -class ClonableObject; -class ClonableObjectPrivate; -class Object; -class ObjectPrivate; - -template -inline ClonableObject *getPublicHelper (T *object, ClonableObjectPrivate *context) { - auto it = object->find(context); - L_ASSERT(it != object->end()); - return it->second; -} - -template -inline const ClonableObject *getPublicHelper (const T *object, const ClonableObjectPrivate *context) { - auto it = object->find(context); - L_ASSERT(it != object->cend()); - return it->second; -} - -template -inline Object *getPublicHelper (T *object, ObjectPrivate *) { - return object; -} - -template -inline const Object *getPublicHelper (const T *object, const ObjectPrivate *) { - return object; -} - -#define L_DECLARE_PUBLIC(CLASS) \ - inline CLASS * getPublic () { \ - return static_cast(getPublicHelper(mPublic, this)); \ - } \ - inline const CLASS *getPublic () const { \ - return static_cast(getPublicHelper(mPublic, this)); \ - } \ - friend class CLASS; - -#define L_DISABLE_COPY(CLASS) \ - CLASS(const CLASS &) = delete; \ - CLASS &operator= (const CLASS &) = delete; - -#define L_D(CLASS) CLASS ## Private * const d = getPrivate(); -#define L_Q(CLASS) CLASS * const q = getPublic(); - -#define L_USE_DEFAULT_SHARE_IMPL(CLASS, PARENT_CLASS) \ - CLASS::CLASS (const CLASS &src) : PARENT_CLASS(*src.getPrivate()) {} \ - CLASS &CLASS::operator= (const CLASS &src) { \ - if (this != &src) \ - setRef(*src.getPrivate()); \ - return *this; \ - } - -#endif - -LINPHONE_END_NAMESPACE - -#endif // ifndef _GENERAL_H_ diff --git a/src/utils/magic-macros.h b/src/utils/magic-macros.h deleted file mode 100644 index 95b2f9774..000000000 --- a/src/utils/magic-macros.h +++ /dev/null @@ -1,240 +0,0 @@ -/* - * magic-macros.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _MAGIC_MACROS_H_ -#define _MAGIC_MACROS_H_ - -#include "general.h" - -// ============================================================================= -// Original header. -// Source: https://github.com/facebookresearch/ELF/blob/master/elf/pybind_helper.h -// ============================================================================= - -/** - * Copyright (c) 2017-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -// File: macros.h -// Author: Yuxin Wu - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -#define MM_CONCAT__(A, B) A ## B -#define MM_CONCAT_(A, B) MM_CONCAT__(A, B) -#define MM_CONCAT(A, B) MM_CONCAT_(A, B) - -#define MM_INVOKE(MACRO, ARGS) MACRO ARGS -#define MM_INVOKE_B(MACRO, ARGS) MACRO ARGS - -#define MM_APPLY_1(MACRONAME, C, A1) \ - MM_INVOKE_B(MACRONAME, (C, A1)) - -#define MM_APPLY_2(MACRONAME, C, A1, A2) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_1(MACRONAME, C, A2) - -#define MM_APPLY_3(MACRONAME, C, A1, A2, A3) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_2(MACRONAME, C, A2, A3) - -#define MM_APPLY_4(MACRONAME, C, A1, A2, A3, A4) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_3(MACRONAME, C, A2, A3, A4) - -#define MM_APPLY_5(MACRONAME, C, A1, A2, A3, A4, A5) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_4(MACRONAME, C, A2, A3, A4, A5) - -#define MM_APPLY_6(MACRONAME, C, A1, A2, A3, A4, A5, A6) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_5(MACRONAME, C, A2, A3, A4, A5, A6) - -#define MM_APPLY_7(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_6(MACRONAME, C, A2, A3, A4, A5, A6, A7) - -#define MM_APPLY_8(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_7(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8) - -#define MM_APPLY_9(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_8(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9) - -#define MM_APPLY_10(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_9(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10) - -#define MM_APPLY_11(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_10(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) - -#define MM_APPLY_12(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_11(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) - -#define MM_APPLY_13(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_12(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) - -#define MM_APPLY_14(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_13(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) - -#define MM_APPLY_15(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_14(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) - -#define MM_APPLY_16(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_15(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) - -#define MM_APPLY_17(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_16(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17) - -#define MM_APPLY_18(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_17(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18) - -#define MM_APPLY_19(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_18(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19) - -#define MM_APPLY_20(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_19(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20) - -#define MM_APPLY_21(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_20(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21) - -#define MM_APPLY_22(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22) \ - MM_INVOKE_B(MACRONAME, (C, A1)) \ - MM_APPLY_21(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16, A17, A18, A19, A20, A21, A22) - -#define MM_NARG(...) \ - MM_NARG_(__VA_ARGS__, MM_RSEQ_N()) - -#define MM_NARG_(...) \ - MM_ARG_N(__VA_ARGS__) - -#define MM_ARG_N( \ - _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ - _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ - _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ - _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ - _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ - _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ - _61, _62, _63, N, ...) N - -#define MM_RSEQ_N() \ - 63, 62, 61, 60, \ - 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ - 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ - 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ - 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ - 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ - 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 - -#define MM_APPLY(MACRONAME, C, ...) \ - MM_INVOKE( \ - MM_CONCAT(MM_APPLY_, MM_NARG(__VA_ARGS__)), \ - (MACRONAME, C, __VA_ARGS__) \ - ) - -#define MM_APPLY_COMMA(MACRONAME, C, ...) \ - MM_INVOKE( \ - MM_CONCAT(MM_APPLY_COMMA_, MM_NARG(__VA_ARGS__)), \ - (MACRONAME, C, __VA_ARGS__) \ - ) - -#define MM_APPLY_COMMA_1(MACRONAME, C, A1) \ - MM_INVOKE_B(MACRONAME, (C, A1)) - -#define MM_APPLY_COMMA_2(MACRONAME, C, A1, A2) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_1(MACRONAME, C, A2) - -#define MM_APPLY_COMMA_3(MACRONAME, C, A1, A2, A3) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_2(MACRONAME, C, A2, A3) - -#define MM_APPLY_COMMA_4(MACRONAME, C, A1, A2, A3, A4) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_3(MACRONAME, C, A2, A3, A4) - -#define MM_APPLY_COMMA_5(MACRONAME, C, A1, A2, A3, A4, A5) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_4(MACRONAME, C, A2, A3, A4, A5) - -#define MM_APPLY_COMMA_6(MACRONAME, C, A1, A2, A3, A4, A5, A6) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_5(MACRONAME, C, A2, A3, A4, A5, A6) - -#define MM_APPLY_COMMA_7(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_6(MACRONAME, C, A2, A3, A4, A5, A6, A7) - -#define MM_APPLY_COMMA_8(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_7(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8) - -#define MM_APPLY_COMMA_9(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_8(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9) - -#define MM_APPLY_COMMA_10(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_9(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10) - -#define MM_APPLY_COMMA_11(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_10(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) - -#define MM_APPLY_COMMA_12(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_11(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) - -#define MM_APPLY_COMMA_13(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_12(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13) - -#define MM_APPLY_COMMA_14(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_13(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14) - -#define MM_APPLY_COMMA_15(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_14(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15) - -#define MM_APPLY_COMMA_16(MACRONAME, C, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) \ - MM_INVOKE_B(MACRONAME, (C, A1)), \ - MM_APPLY_COMMA_15(MACRONAME, C, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16) - -LINPHONE_END_NAMESPACE - -#endif // ifndef _MAGIC_MACROS_H_ diff --git a/src/utils/payload-type-handler.cpp b/src/utils/payload-type-handler.cpp new file mode 100644 index 000000000..f1a3c8483 --- /dev/null +++ b/src/utils/payload-type-handler.cpp @@ -0,0 +1,326 @@ +/* + * payload-type-handler.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include "private.h" + +#include "logger/logger.h" + +#include "payload-type-handler.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +const int PayloadTypeHandler::udpHeaderSize = 8; +const int PayloadTypeHandler::rtpHeaderSize = 12; + +// 20 is the minimum, but there may be some options. +const int PayloadTypeHandler::ipv4HeaderSize = 20; + +const VbrCodecBitrate PayloadTypeHandler::defaultVbrCodecBitrates[] = { + { 64, 44100, 50 }, + { 64, 16000, 40 }, + { 32, 16000, 32 }, + { 32, 8000, 32 }, + { 0, 8000, 24 }, + { 0, 0, 0 } +}; + +// ============================================================================= + +int PayloadTypeHandler::findPayloadTypeNumber (const bctbx_list_t *assigned, const OrtpPayloadType *pt) { + const OrtpPayloadType *candidate = nullptr; + for (const bctbx_list_t *elem = assigned; elem != nullptr; elem = bctbx_list_next(elem)) { + const OrtpPayloadType *it = reinterpret_cast(bctbx_list_get_data(elem)); + if ( + strcasecmp(pt->mime_type, payload_type_get_mime(it)) == 0 && + it->clock_rate == pt->clock_rate && + ((it->channels == pt->channels) || (pt->channels <= 0)) + ) { + candidate = it; + if ( + (it->recv_fmtp && pt->recv_fmtp && (strcasecmp(it->recv_fmtp, pt->recv_fmtp) == 0)) || + (!it->recv_fmtp && !pt->recv_fmtp) + ) + // Exact match. + break; + } + } + return candidate ? payload_type_get_number(candidate) : -1; +} + +bool PayloadTypeHandler::hasTelephoneEventPayloadType (const bctbx_list_t *tev, int rate) { + for (const bctbx_list_t *it = tev; it != nullptr; it = bctbx_list_next(it)) { + const OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(it)); + if (pt->clock_rate == rate) + return true; + } + return false; +} + +bool PayloadTypeHandler::isPayloadTypeUsableForBandwidth (const OrtpPayloadType *pt, int bandwidthLimit) { + const int videoEnablementLimit = 99; + double codecBand = 0; + switch (pt->type) { + case PAYLOAD_AUDIO_CONTINUOUS: + case PAYLOAD_AUDIO_PACKETIZED: + codecBand = getAudioPayloadTypeBandwidth(pt, bandwidthLimit); + return bandwidthIsGreater(bandwidthLimit, (int)codecBand); + case PAYLOAD_VIDEO: + // Infinite or greater than videoEnablementLimit. + if (bandwidthLimit <= 0 || bandwidthLimit >= videoEnablementLimit) + return true; + break; + case PAYLOAD_TEXT: + return true; + } + return false; +} + +int PayloadTypeHandler::lookupTypicalVbrBitrate (int maxBandwidth, int clockRate) { + if (maxBandwidth <= 0) + maxBandwidth = defaultVbrCodecBitrates[0].maxAvailableBitrate; + for (const VbrCodecBitrate *it = &defaultVbrCodecBitrates[0]; it->minClockRate != 0; it++) { + if ((maxBandwidth >= it->maxAvailableBitrate) && (clockRate >= it->minClockRate)) + return it->recommendedBitrate; + } + lError() << "lookupTypicalVbrBitrate(): should not happen"; + return 32; +} + +// ----------------------------------------------------------------------------- + +void PayloadTypeHandler::assignPayloadTypeNumbers (const bctbx_list_t *codecs) { + OrtpPayloadType *red = nullptr; + OrtpPayloadType *t140 = nullptr; + + for (const bctbx_list_t *elem = codecs; elem != nullptr; elem = bctbx_list_next(elem)) { + OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(elem)); + int number = payload_type_get_number(pt); + + // Check if number is duplicated: it could be the case if the remote forced us to use a mapping with a previous offer. + if ((number != -1) && !(pt->flags & PAYLOAD_TYPE_FROZEN_NUMBER)) { + if (!isPayloadTypeNumberAvailable(codecs, number, pt)) { + lInfo() << "Reassigning payload type " << number << " " << pt->mime_type << "/" << pt->clock_rate << " because already offered"; + // Need to be re-assigned. + number = -1; + } + } + + if (number == -1) { + int dynNumber = getCore()->getCCore()->codecs_conf.dyn_pt; + while (dynNumber < 127) { + if (isPayloadTypeNumberAvailable(codecs, dynNumber, nullptr)) { + payload_type_set_number(pt, dynNumber); + dynNumber++; + break; + } + dynNumber++; + } + if (dynNumber == 127) { + lError() << "Too many payload types configured ! codec " << pt->mime_type << "/" << pt->clock_rate << " is disabled"; + payload_type_set_enable(pt, false); + } + } + + if (strcmp(pt->mime_type, payload_type_t140_red.mime_type) == 0) + red = pt; + else if (strcmp(pt->mime_type, payload_type_t140.mime_type) == 0) + t140 = pt; + } + + if (t140 && red) { + int t140_payload_type_number = payload_type_get_number(t140); + char *red_fmtp = ms_strdup_printf("%i/%i/%i", t140_payload_type_number, t140_payload_type_number, t140_payload_type_number); + payload_type_set_recv_fmtp(red, red_fmtp); + ms_free(red_fmtp); + } +} + +bctbx_list_t *PayloadTypeHandler::createSpecialPayloadTypes (const bctbx_list_t *codecs) { + bctbx_list_t *result = createTelephoneEventPayloadTypes(codecs); + if (linphone_core_generic_comfort_noise_enabled(getCore()->getCCore())) { + OrtpPayloadType *cn = payload_type_clone(&payload_type_cn); + payload_type_set_number(cn, 13); + result = bctbx_list_append(result, cn); + } + return result; +} + +bctbx_list_t *PayloadTypeHandler::createTelephoneEventPayloadTypes (const bctbx_list_t *codecs) { + bctbx_list_t *result = nullptr; + for (const bctbx_list_t *it = codecs; it != nullptr; it = bctbx_list_next(it)) { + const OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(it)); + if (hasTelephoneEventPayloadType(result, pt->clock_rate)) + continue; + + OrtpPayloadType *tev = payload_type_clone(&payload_type_telephone_event); + tev->clock_rate = pt->clock_rate; + // Let it choose the number dynamically as for normal codecs. + payload_type_set_number(tev, -1); + // But for first telephone-event, prefer the number that was configured in the core. + if (!result && isPayloadTypeNumberAvailable(codecs, getCore()->getCCore()->codecs_conf.telephone_event_pt, nullptr)) + payload_type_set_number(tev, getCore()->getCCore()->codecs_conf.telephone_event_pt); + result = bctbx_list_append(result, tev); + } + return result; +} + +bool PayloadTypeHandler::isPayloadTypeUsable (const OrtpPayloadType *pt) { + return isPayloadTypeUsableForBandwidth( + pt, getMinBandwidth( + linphone_core_get_download_bandwidth(getCore()->getCCore()), + linphone_core_get_upload_bandwidth(getCore()->getCCore()) + ) + ); +} + +// ----------------------------------------------------------------------------- + +bool PayloadTypeHandler::bandwidthIsGreater (int bandwidth1, int bandwidth2) { + if (bandwidth1 <= 0) return true; + if (bandwidth2 <= 0) return false; + return bandwidth1 >= bandwidth2; +} + +int PayloadTypeHandler::getAudioPayloadTypeBandwidth (const OrtpPayloadType *pt, int maxBandwidth) { + if (payload_type_is_vbr(pt)) { + if (pt->flags & PAYLOAD_TYPE_BITRATE_OVERRIDE) { + lDebug() << "PayloadType " << pt->mime_type << "/" << pt->clock_rate << " has bitrate override"; + return pt->normal_bitrate / 1000; + } + return lookupTypicalVbrBitrate(maxBandwidth, pt->clock_rate); + } + /* Rounding codec bandwidth should be avoid, specially for AMR */ + return (int)ceil(getAudioPayloadTypeBandwidthFromCodecBitrate(pt) / 1000.0); +} + +/* + *((codec-birate*ptime/8) + RTP header + UDP header + IP header)*8/ptime; + * ptime=1/npacket + */ +double PayloadTypeHandler::getAudioPayloadTypeBandwidthFromCodecBitrate (const OrtpPayloadType *pt) { + double npacket = 50; + 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; + else if (strcmp(payload_type_get_mime(&payload_type_ilbc), payload_type_get_mime(pt)) == 0) + npacket = 1000 / 30.0; + + int bitrate = pt->normal_bitrate; + double packet_size = (((double)bitrate) / (npacket * 8)) + udpHeaderSize + rtpHeaderSize + ipv4HeaderSize; + return packet_size * 8.0 * npacket; +} + +int PayloadTypeHandler::getMaxCodecSampleRate (const bctbx_list_t *codecs) { + int maxSampleRate = 0; + for (const bctbx_list_t *it = codecs; it != nullptr; it = bctbx_list_next(it)) { + OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(it)); + int sampleRate; + if (strcasecmp("G722", pt->mime_type) == 0) + // G722 spec says 8000 but the codec actually requires 16000. + sampleRate = 16000; + else + sampleRate = pt->clock_rate; + + if (sampleRate > maxSampleRate) + maxSampleRate = sampleRate; + } + return maxSampleRate; +} + +int PayloadTypeHandler::getMinBandwidth (int downBandwidth, int upBandwidth) { + if (downBandwidth <= 0) return upBandwidth; + if (upBandwidth <= 0) return downBandwidth; + return MIN(downBandwidth, upBandwidth); +} + +int PayloadTypeHandler::getRemainingBandwidthForVideo (int total, int audio) { + int remaining = total - audio - 10; + if (remaining < 0) remaining = 0; + return remaining; +} + +bool PayloadTypeHandler::isPayloadTypeNumberAvailable (const bctbx_list_t *codecs, int number, const OrtpPayloadType *ignore) { + for (const bctbx_list_t *elem = codecs; elem != nullptr; elem = bctbx_list_next(elem)) { + const OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(elem)); + if ((pt != ignore) && (payload_type_get_number(pt) == number)) return false; + } + return true; +} + +// ----------------------------------------------------------------------------- + +bctbx_list_t *PayloadTypeHandler::makeCodecsList (SalStreamType type, int bandwidthLimit, int maxCodecs, const bctbx_list_t *previousList) { + const bctbx_list_t *allCodecs = nullptr; + switch (type) { + default: + case SalAudio: + allCodecs = getCore()->getCCore()->codecs_conf.audio_codecs; + break; + case SalVideo: + allCodecs = getCore()->getCCore()->codecs_conf.video_codecs; + break; + case SalText: + allCodecs = getCore()->getCCore()->codecs_conf.text_codecs; + break; + } + + int nb = 0; + bctbx_list_t *result = nullptr; + for (const bctbx_list_t *it = allCodecs; it != nullptr; it = bctbx_list_next(it)) { + OrtpPayloadType *pt = reinterpret_cast(bctbx_list_get_data(it)); + if (!payload_type_enabled(pt)) + continue; + + if (bandwidthLimit > 0 && !isPayloadTypeUsableForBandwidth(pt, bandwidthLimit)) { + lInfo() << "Codec " << pt->mime_type << "/" << pt->clock_rate << " eliminated because of audio bandwidth constraint of " << + bandwidthLimit << " kbit/s"; + continue; + } + + if (!isPayloadTypeUsable(pt)) + continue; + + pt = payload_type_clone(pt); + + /* Look for a previously assigned number for this codec */ + int num = findPayloadTypeNumber(previousList, pt); + if (num != -1) { + payload_type_set_number(pt, num); + payload_type_set_flag(pt, PAYLOAD_TYPE_FROZEN_NUMBER); + } + + result = bctbx_list_append(result, pt); + nb++; + if ((maxCodecs > 0) && (nb >= maxCodecs)) break; + } + if (type == SalAudio) { + bctbx_list_t *specials = createSpecialPayloadTypes(result); + result = bctbx_list_concat(result, specials); + } + assignPayloadTypeNumbers(result); + return result; +} + +LINPHONE_END_NAMESPACE diff --git a/src/utils/payload-type-handler.h b/src/utils/payload-type-handler.h new file mode 100644 index 000000000..12c51c6ef --- /dev/null +++ b/src/utils/payload-type-handler.h @@ -0,0 +1,78 @@ +/* + * payload-type-handler.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_PAYLOAD_TYPE_HANDLER_H_ +#define _L_PAYLOAD_TYPE_HANDLER_H_ + +#include "linphone/utils/general.h" + +#include "c-wrapper/internal/c-sal.h" +#include "core/core.h" +#include "core/core-accessor.h" + +#define PAYLOAD_TYPE_ENABLED PAYLOAD_TYPE_USER_FLAG_0 +#define PAYLOAD_TYPE_BITRATE_OVERRIDE PAYLOAD_TYPE_USER_FLAG_3 +#define PAYLOAD_TYPE_FROZEN_NUMBER PAYLOAD_TYPE_USER_FLAG_4 + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +struct VbrCodecBitrate { + int maxAvailableBitrate; + int minClockRate; + int recommendedBitrate; +}; + +class Core; + +class PayloadTypeHandler : public CoreAccessor { +public: + explicit PayloadTypeHandler (const std::shared_ptr &core) : CoreAccessor(core) {} + + bctbx_list_t *makeCodecsList (SalStreamType type, int bandwidthLimit, int maxCodecs, const bctbx_list_t *previousList); + + static bool bandwidthIsGreater (int bandwidth1, int bandwidth2); + static int getAudioPayloadTypeBandwidth (const OrtpPayloadType *pt, int maxBandwidth); + static double getAudioPayloadTypeBandwidthFromCodecBitrate (const OrtpPayloadType *pt); + static int getMaxCodecSampleRate (const bctbx_list_t *codecs); + static int getMinBandwidth (int downBandwidth, int upBandwidth); + static int getRemainingBandwidthForVideo (int total, int audio); + static bool isPayloadTypeNumberAvailable (const bctbx_list_t *codecs, int number, const OrtpPayloadType *ignore); + +private: + static int findPayloadTypeNumber (const bctbx_list_t *assigned, const OrtpPayloadType *pt); + static bool hasTelephoneEventPayloadType (const bctbx_list_t *tev, int rate); + static bool isPayloadTypeUsableForBandwidth (const OrtpPayloadType *pt, int bandwidthLimit); + static int lookupTypicalVbrBitrate (int maxBandwidth, int clockRate); + + void assignPayloadTypeNumbers (const bctbx_list_t *codecs); + bctbx_list_t *createSpecialPayloadTypes (const bctbx_list_t *codecs); + bctbx_list_t *createTelephoneEventPayloadTypes (const bctbx_list_t *codecs); + bool isPayloadTypeUsable (const OrtpPayloadType *pt); + + static const int udpHeaderSize; + static const int rtpHeaderSize; + static const int ipv4HeaderSize; + static const VbrCodecBitrate defaultVbrCodecBitrates[]; +}; + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_PAYLOAD_TYPE_HANDLER_H_ diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 55e8d2026..14de24c8d 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -1,11 +1,11 @@ /* * utils.cpp - * Copyright (C) 2017 Belledonne Communications SARL + * Copyright (C) 2010-2018 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 3 of the License, or - * (at your option) any later version. + * 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 @@ -13,12 +13,23 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include +#include +#include -#include "utils.h" +#include +#include + +#include "linphone/utils/utils.h" + +#include "logger/logger.h" + +#include "private.h" // ============================================================================= @@ -26,6 +37,8 @@ using namespace std; LINPHONE_BEGIN_NAMESPACE +// ----------------------------------------------------------------------------- + bool Utils::iequals (const string &a, const string &b) { size_t size = a.size(); if (b.size() != size) @@ -39,6 +52,8 @@ bool Utils::iequals (const string &a, const string &b) { return true; } +// ----------------------------------------------------------------------------- + vector Utils::split (const string &str, const string &delimiter) { vector out; @@ -50,14 +65,189 @@ vector Utils::split (const string &str, const string &delimiter) { return out; } -int Utils::stoi (const string &str, size_t *idx, int base) { - char *p; - int v = strtol(str.c_str(), &p, base); +// ----------------------------------------------------------------------------- - if (idx) - *idx = p - str.c_str(); +#ifndef __ANDROID__ +#define TO_STRING_IMPL(TYPE) \ + string Utils::toString (TYPE val) { \ + return to_string(val); \ + } +#else +#define TO_STRING_IMPL(TYPE) \ + string Utils::toString (TYPE val) { \ + ostringstream os; \ + os << val; \ + return os.str(); \ + } +#endif // ifndef __ANDROID__ - return v; +TO_STRING_IMPL(int) +TO_STRING_IMPL(long) +TO_STRING_IMPL(long long) +TO_STRING_IMPL(unsigned) +TO_STRING_IMPL(unsigned long) +TO_STRING_IMPL(unsigned long long) +TO_STRING_IMPL(float) +TO_STRING_IMPL(double) +TO_STRING_IMPL(long double) + +#undef TO_STRING_IMPL + +string Utils::toString (const void *val) { + ostringstream ss; + ss << val; + return ss.str(); +} + +// ----------------------------------------------------------------------------- + +#define STRING_TO_NUMBER_IMPL(TYPE, SUFFIX) \ + TYPE Utils::sto ## SUFFIX (const string &str, size_t *idx, int base) { \ + return sto ## SUFFIX(str.c_str(), idx, base); \ + } \ + TYPE Utils::sto ## SUFFIX (const char *str, size_t *idx, int base) { \ + char *p; \ + TYPE v = strto ## SUFFIX(str, &p, base); \ + if (idx) \ + *idx = static_cast(p - str); \ + return v; \ + } \ + +#define STRING_TO_NUMBER_IMPL_BASE_LESS(TYPE, SUFFIX) \ + TYPE Utils::sto ## SUFFIX(const string &str, size_t * idx) { \ + return sto ## SUFFIX(str.c_str(), idx); \ + } \ + TYPE Utils::sto ## SUFFIX(const char *str, size_t * idx) { \ + char *p; \ + TYPE v = strto ## SUFFIX(str, &p); \ + if (idx) \ + *idx = static_cast(p - str); \ + return v; \ + } \ + +#define strtoi(STR, IDX, BASE) static_cast(strtol(STR, IDX, BASE)) +STRING_TO_NUMBER_IMPL(int, i) +#undef strtoi + +STRING_TO_NUMBER_IMPL(long long, ll) +STRING_TO_NUMBER_IMPL(unsigned long long, ull) + +STRING_TO_NUMBER_IMPL_BASE_LESS(double, d) +STRING_TO_NUMBER_IMPL_BASE_LESS(float, f) + +#undef STRING_TO_NUMBER_IMPL +#undef STRING_TO_NUMBER_IMPL_BASE_LESS + +bool Utils::stob (const string &str) { + const string lowerStr = stringToLower(str); + return !lowerStr.empty() && (lowerStr == "true" || lowerStr == "1"); +} + +// ----------------------------------------------------------------------------- + +string Utils::stringToLower (const string &str) { + string result(str.size(), ' '); + transform(str.cbegin(), str.cend(), result.begin(), ::tolower); + return result; +} + +// ----------------------------------------------------------------------------- + +char *Utils::utf8ToChar (uint32_t ic) { + char *result = new char[5]; + int size = 0; + if (ic < 0x80) { + result[0] = static_cast(ic); + size = 1; + } else if (ic < 0x800) { + result[1] = static_cast(0x80 + ((ic & 0x3F))); + result[0] = static_cast(0xC0 + ((ic >> 6) & 0x1F)); + size = 2; + } else if (ic < 0x100000) { + result[2] = static_cast(0x80 + (ic & 0x3F)); + result[1] = static_cast(0x80 + ((ic >> 6) & 0x3F)); + result[0] = static_cast(0xE0 + ((ic >> 12) & 0xF)); + size = 3; + } else if (ic < 0x110000) { + result[3] = static_cast(0x80 + (ic & 0x3F)); + result[2] = static_cast(0x80 + ((ic >> 6) & 0x3F)); + result[1] = static_cast(0x80 + ((ic >> 12) & 0x3F)); + result[0] = static_cast(0xF0 + ((ic >> 18) & 0x7)); + size = 4; + } + result[size] = '\0'; + return result; +} + +string Utils::trim (const string &str) { + auto itFront = find_if_not(str.begin(), str.end(), [] (int c) { return isspace(c); }); + auto itBack = find_if_not(str.rbegin(), str.rend(), [] (int c) { return isspace(c); }).base(); + return (itBack <= itFront ? string() : string(itFront, itBack)); +} + +// ----------------------------------------------------------------------------- + +tm Utils::getTimeTAsTm (time_t time) { + #ifdef _WIN32 + return *gmtime(&time); + #else + tm result; + return *gmtime_r(&time, &result); + #endif +} + +time_t Utils::getTmAsTimeT (const tm &time) { + time_t result; + + #if defined(LINPHONE_WINDOWS_UNIVERSAL) || defined(LINPHONE_MSC_VER_GREATER_19) + long adjust_timezone; + #else + time_t adjust_timezone; + #endif + + #if TARGET_IPHONE_SIMULATOR + result = timegm(&const_cast(time)); + adjust_timezone = 0; + #else + result = mktime(&const_cast(time)); + + #if defined(LINPHONE_WINDOWS_UNIVERSAL) || defined(LINPHONE_MSC_VER_GREATER_19) + _get_timezone(&adjust_timezone); + #else + adjust_timezone = timezone; + #endif + #endif + + if (result == (time_t)-1) { + lError() << "mktime failed: " << strerror(errno); + return (time_t)-1; + } + + return result - (time_t)adjust_timezone; +} + +// ----------------------------------------------------------------------------- + +// TODO: Improve perf!!! Avoid c <--> cpp string conversions. +string Utils::localeToUtf8 (const string &str) { + char *cStr = bctbx_locale_to_utf8(str.c_str()); + string utf8Str = cStringToCppString(cStr); + bctbx_free(cStr); + return utf8Str; +} + +string Utils::utf8ToLocale (const string &str) { + char *cStr = bctbx_utf8_to_locale(str.c_str()); + string localeStr = cStringToCppString(cStr); + bctbx_free(cStr); + return localeStr; +} + +string Utils::convertAnyToUtf8 (const string &str, const string &encoding) { + char *cStr = bctbx_convert_any_to_utf8(str.c_str(), encoding.c_str()); + string convertedStr = cStringToCppString(cStr); + bctbx_free(cStr); + return convertedStr; } LINPHONE_END_NAMESPACE diff --git a/src/utils/utils.h b/src/utils/utils.h deleted file mode 100644 index e64dc4e7e..000000000 --- a/src/utils/utils.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * utils.h - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _UTILS_H_ -#define _UTILS_H_ - -#include -#include - -#include "general.h" - -// ============================================================================= - -LINPHONE_BEGIN_NAMESPACE - -namespace Utils { - LINPHONE_PUBLIC bool iequals (const std::string &a, const std::string &b); - - LINPHONE_PUBLIC std::vector split (const std::string &str, const std::string &delimiter); - - LINPHONE_PUBLIC inline std::vector split (const std::string &str, char delimiter) { - return split(str, std::string(1, delimiter)); - } - - LINPHONE_PUBLIC int stoi (const std::string &str, size_t *idx = 0, int base = 10); -} - -LINPHONE_END_NAMESPACE - -#endif // ifndef _UTILS_H_ diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp new file mode 100644 index 000000000..b8fe58a54 --- /dev/null +++ b/src/variant/variant.cpp @@ -0,0 +1,607 @@ +/* + * variant.cpp + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "linphone/utils/utils.h" + +#include "variant.h" + +// ============================================================================= + +using namespace std; + +LINPHONE_BEGIN_NAMESPACE + +// ----------------------------------------------------------------------------- + +class VariantPrivate { +public: + union Value { + int i; + unsigned int ui; + short s; + unsigned short us; + long l; + unsigned long ul; + long long ll; + unsigned long long ull; + char c; + bool b; + double d; + float f; + string *str; + void *g; + }; + + ~VariantPrivate () { + deleteString(); + } + + inline int getType () const { + return type; + } + + inline void setType (int newType) { + L_ASSERT(newType >= Variant::Invalid && newType != Variant::MaxDefaultTypes); + + if (newType != Variant::String) + deleteString(); + else if (type != Variant::String) + value.str = new string(); + + type = newType; + } + + Value value = {}; + +private: + inline void deleteString () { + if (type == Variant::String) + delete value.str; + } + + // Integer, because type can be a custom type. + int type = Variant::Invalid; +}; + +// ----------------------------------------------------------------------------- + +Variant::Variant () { + // Private can exist. (placement new) + if (!mPrivate) + mPrivate = new VariantPrivate(); +} + +Variant::Variant (Type type) : Variant() { + L_D(); + d->setType(type); +} + +Variant::Variant (const Variant &other) { + // Don't call placement new. + L_ASSERT(!mPrivate); + mPrivate = new VariantPrivate(); + + L_D(); + + int type = other.getPrivate()->getType(); + d->setType(type); + + const VariantPrivate::Value &value = other.getPrivate()->value; + if (type == String) + *d->value.str = *value.str; + else + d->value = value; +} + +Variant::Variant (Variant &&other) { + // Don't call placement new. + L_ASSERT(!mPrivate); + ::swap(mPrivate, other.mPrivate); +} + +Variant::Variant (int value) : Variant(Int) { + L_D(); + d->value.i = value; +} + +Variant::Variant (unsigned int value) : Variant(UnsignedInt) { + L_D(); + d->value.ui = value; +} + +Variant::Variant (short value) : Variant(Short) { + L_D(); + d->value.s = value; +} + +Variant::Variant (unsigned short value) : Variant(UnsignedShort) { + L_D(); + d->value.us = value; +} + +Variant::Variant (long value) : Variant(Long) { + L_D(); + d->value.l = value; +} + +Variant::Variant (unsigned long value) : Variant(UnsignedLong) { + L_D(); + d->value.ul = value; +} + +Variant::Variant (long long value) : Variant(LongLong) { + L_D(); + d->value.ll = value; +} + +Variant::Variant (unsigned long long value) : Variant(UnsignedLongLong) { + L_D(); + d->value.ull = value; +} + +Variant::Variant (char value) : Variant(Char) { + L_D(); + d->value.c = value; +} + +Variant::Variant (bool value) : Variant(Bool) { + L_D(); + d->value.b = value; +} + +Variant::Variant (double value) : Variant(Double) { + L_D(); + d->value.d = value; +} + +Variant::Variant (float value) : Variant(Float) { + L_D(); + d->value.f = value; +} + +Variant::Variant (const string &value) : Variant(String) { + L_D(); + *d->value.str = value; +} + +Variant::~Variant () { + L_D(); + + // Note: Private data can be stolen by copy operator (r-value). + // It can be null, but it useless to test it. + delete d; +} + +Variant &Variant::operator= (const Variant &other) { + L_D(); + + if (this != &other) { + // Update type. + int type = other.getPrivate()->getType(); + d->setType(type); + + // Update value. + const VariantPrivate::Value &value = other.getPrivate()->value; + if (type == String) + *d->value.str = *value.str; + else + d->value = value; + } + + return *this; +} + +Variant &Variant::operator= (Variant &&other) { + ::swap(mPrivate, other.mPrivate); + return *this; +} + +bool Variant::isValid () const { + L_D(); + return d->getType() != Invalid; +} + +void Variant::clear () { + L_D(); + d->setType(Invalid); +} + +void Variant::swap (const Variant &other) { + // TODO. +} + +// ----------------------------------------------------------------------------- +// Number helpers. +// ----------------------------------------------------------------------------- + +static inline long long getAssumedNumber (const VariantPrivate &p) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::Int: + return p.value.i; + case Variant::Short: + return p.value.s; + case Variant::Long: + return p.value.l; + case Variant::LongLong: + return p.value.ll; + case Variant::Char: + return p.value.c; + case Variant::Double: + return static_cast(p.value.d); + case Variant::Float: + return static_cast(p.value.f); + + default: + L_ASSERT(false); + } + + return 0; +} + +static inline unsigned long long getAssumedUnsignedNumber (const VariantPrivate &p) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::UnsignedInt: + return p.value.ui; + case Variant::UnsignedShort: + return p.value.us; + case Variant::UnsignedLong: + return p.value.ul; + case Variant::UnsignedLongLong: + return p.value.ull; + + default: + L_ASSERT(false); + } + + return 0; +} + +// ----------------------------------------------------------------------------- +// Number conversions. +// ----------------------------------------------------------------------------- + +static inline long long getValueAsNumber (const VariantPrivate &p, bool *soFarSoGood) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::Int: + case Variant::Short: + case Variant::Long: + case Variant::LongLong: + case Variant::Char: + case Variant::Double: + case Variant::Float: + return getAssumedNumber(p); + + case Variant::UnsignedInt: + case Variant::UnsignedShort: + case Variant::UnsignedLong: + case Variant::UnsignedLongLong: + return static_cast(getAssumedUnsignedNumber(p)); + + case Variant::Bool: + return static_cast(p.value.b); + + case Variant::String: + return Utils::stoll(*p.value.str); + + case Variant::Generic: + return static_cast(!!p.value.g); + + default: + *soFarSoGood = false; + } + + return 0; +} + +static inline unsigned long long getValueAsUnsignedNumber (const VariantPrivate &p, bool *soFarSoGood) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::Int: + case Variant::Short: + case Variant::Long: + case Variant::LongLong: + case Variant::Char: + case Variant::Double: + case Variant::Float: + return static_cast(getAssumedNumber(p)); + + case Variant::UnsignedInt: + case Variant::UnsignedShort: + case Variant::UnsignedLong: + case Variant::UnsignedLongLong: + return getAssumedUnsignedNumber(p); + + case Variant::Bool: + return static_cast(p.value.b); + + case Variant::String: + return Utils::stoull(*p.value.str); + + case Variant::Generic: + return static_cast(!!p.value.g); + + default: + *soFarSoGood = false; + } + + return 0; +} + +// ----------------------------------------------------------------------------- +// Specific conversions. +// ----------------------------------------------------------------------------- + +static inline bool getValueAsBool (const VariantPrivate &p, bool *soFarSoGood) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::Int: + case Variant::Short: + case Variant::Long: + case Variant::LongLong: + case Variant::Char: + case Variant::Double: + case Variant::Float: + return!!getAssumedNumber(p); + + case Variant::UnsignedInt: + case Variant::UnsignedShort: + case Variant::UnsignedLong: + case Variant::UnsignedLongLong: + return !!getAssumedUnsignedNumber(p); + + case Variant::Bool: + return p.value.b; + + case Variant::String: + return Utils::stob(*p.value.str); + + case Variant::Generic: + return !!p.value.g; + + default: + *soFarSoGood = false; + break; + } + + return false; +} + +static inline double getValueAsDouble (const VariantPrivate &p, bool *soFarSoGood) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::Int: + case Variant::Short: + case Variant::Long: + case Variant::LongLong: + case Variant::Char: + return static_cast(getAssumedNumber(p)); + + case Variant::UnsignedInt: + case Variant::UnsignedShort: + case Variant::UnsignedLong: + case Variant::UnsignedLongLong: + return static_cast(getAssumedUnsignedNumber(p)); + + case Variant::Float: + return static_cast(p.value.f); + + case Variant::Double: + return p.value.d; + + case Variant::Bool: + return static_cast(p.value.b); + + case Variant::String: + return Utils::stod(*p.value.str); + + case Variant::Generic: + return static_cast(!!p.value.g); + + default: + *soFarSoGood = false; + break; + } + + return 0.0; +} + +static inline float getValueAsFloat (const VariantPrivate &p, bool *soFarSoGood) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::Int: + case Variant::Short: + case Variant::Long: + case Variant::LongLong: + case Variant::Char: + return static_cast(getAssumedNumber(p)); + + case Variant::UnsignedInt: + case Variant::UnsignedShort: + case Variant::UnsignedLong: + case Variant::UnsignedLongLong: + return static_cast(getAssumedUnsignedNumber(p)); + + case Variant::Float: + return p.value.f; + + case Variant::Double: + return static_cast(p.value.d); + + case Variant::Bool: + return static_cast(p.value.b); + + case Variant::String: + return Utils::stof(*p.value.str); + + case Variant::Generic: + return static_cast(!!p.value.g); + + default: + *soFarSoGood = false; + break; + } + + return 0.f; +} + +static inline string getValueAsString (const VariantPrivate &p, bool *soFarSoGood) { + const int type = p.getType(); + L_ASSERT(type > Variant::Invalid && type < Variant::MaxDefaultTypes); + + switch (static_cast(type)) { + case Variant::Int: + case Variant::Short: + case Variant::Long: + case Variant::LongLong: + return Utils::toString(getAssumedNumber(p)); + + case Variant::UnsignedInt: + case Variant::UnsignedShort: + case Variant::UnsignedLong: + case Variant::UnsignedLongLong: + return Utils::toString(getAssumedUnsignedNumber(p)); + + case Variant::Char: + return string(1, p.value.c); + + case Variant::Bool: + return string(p.value.b ? "true" : "false"); + + case Variant::Double: + return Utils::toString(p.value.d); + + case Variant::Float: + return Utils::toString(p.value.f); + + case Variant::String: + return *p.value.str; + + case Variant::Generic: + return Utils::toString(p.value.g); + + default: + *soFarSoGood = false; + } + + return string(); +} + +static inline void *getValueAsGeneric (const VariantPrivate &p, bool *soFarSoGood) { + if (p.getType() == Variant::Generic) + return p.value.g; + + *soFarSoGood = false; + return nullptr; +} + +// ----------------------------------------------------------------------------- + +void Variant::getValue (int type, void *value, bool *soFarSoGood) const { + L_ASSERT(type > Invalid && type != MaxDefaultTypes); + + L_D(); + + *soFarSoGood = true; + + if (type > MaxDefaultTypes) { + *soFarSoGood = false; + // TODO: Unable to get value. It will be great to support custom types. + return; + } + + switch (static_cast(type)) { + // Cast as Number. + case Int: + *static_cast(value) = static_cast(getValueAsNumber(*d, soFarSoGood)); + break; + case Short: + *static_cast(value) = static_cast(getValueAsNumber(*d, soFarSoGood)); + break; + case Long: + *static_cast(value) = static_cast(getValueAsNumber(*d, soFarSoGood)); + break; + case LongLong: + *static_cast(value) = getValueAsNumber(*d, soFarSoGood); + break; + case Char: + *static_cast(value) = static_cast(getValueAsNumber(*d, soFarSoGood)); + break; + + // Cast as Unsigned number. + case UnsignedInt: + *static_cast(value) = static_cast(getValueAsUnsignedNumber(*d, soFarSoGood)); + break; + case UnsignedShort: + *static_cast(value) = static_cast(getValueAsUnsignedNumber(*d, soFarSoGood)); + break; + case UnsignedLong: + *static_cast(value) = static_cast(getValueAsUnsignedNumber(*d, soFarSoGood)); + break; + case UnsignedLongLong: + *static_cast(value) = getValueAsUnsignedNumber(*d, soFarSoGood); + break; + + // Cast as specific value. + case Bool: + *static_cast(value) = getValueAsBool(*d, soFarSoGood); + break; + case Double: + *static_cast(value) = getValueAsDouble(*d, soFarSoGood); + break; + case Float: + *static_cast(value) = getValueAsFloat(*d, soFarSoGood); + break; + case String: + *static_cast(value) = getValueAsString(*d, soFarSoGood); + break; + case Generic: + *static_cast(value) = getValueAsGeneric(*d, soFarSoGood); + break; + + case Invalid: + case MaxDefaultTypes: + *soFarSoGood = false; + break; + } +} + +Variant Variant::createGeneric (void *value) { + Variant variant(Generic); + variant.getPrivate()->value.g = value; + return variant; +} + +LINPHONE_END_NAMESPACE diff --git a/src/variant/variant.h b/src/variant/variant.h new file mode 100644 index 000000000..5036712d9 --- /dev/null +++ b/src/variant/variant.h @@ -0,0 +1,142 @@ +/* + * variant.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_VARIANT_H_ +#define _L_VARIANT_H_ + +#include + +#include "linphone/utils/general.h" + +// ============================================================================= + +LINPHONE_BEGIN_NAMESPACE + +#define L_DECLARE_VARIANT_TYPES(FUNC) \ + FUNC(int, Int, 1) \ + FUNC(unsigned int, UnsignedInt, 2) \ + FUNC(short, Short, 3) \ + FUNC(unsigned short, UnsignedShort, 4) \ + FUNC(long, Long, 5) \ + FUNC(unsigned long, UnsignedLong, 6) \ + FUNC(long long, LongLong, 7) \ + FUNC(unsigned long long, UnsignedLongLong, 8) \ + FUNC(char, Char, 9) \ + FUNC(bool, Bool, 10) \ + FUNC(double, Double, 11) \ + FUNC(float, Float, 12) \ + FUNC(std::string, String, 13) \ + FUNC(void *, Generic, 14) + +#define L_DECLARE_VARIANT_ENUM_TYPE(TYPE, NAME, ID) NAME = ID, +#define L_DECLARE_VARIANT_TRAIT_TYPE(TYPE, NAME, ID) \ + template<> \ + struct Variant::IdOfType { \ + static const int id = ID; \ + }; + +class VariantPrivate; + +class LINPHONE_PUBLIC Variant { +public: + enum Type { + Invalid = 0, + L_DECLARE_VARIANT_TYPES(L_DECLARE_VARIANT_ENUM_TYPE) + MaxDefaultTypes + }; + + Variant (); + Variant (Type type); + + Variant (const Variant &other); + Variant (Variant &&other); + + Variant (int value); + Variant (unsigned int value); + Variant (short value); + Variant (unsigned short value); + Variant (long value); + Variant (unsigned long value); + Variant (long long value); + Variant (unsigned long long value); + Variant (char value); + Variant (bool value); + Variant (double value); + Variant (float value); + Variant (const std::string &value); + + // void* constructor. Must be explicitly called. + template::value>> + Variant (T value) : Variant (Variant::createGeneric(value)) {} + + ~Variant (); + + Variant &operator= (const Variant &other); + Variant &operator= (Variant &&other); + + template + void setValue (const T &value) { + // Yeah, I'm crazy but it's useful to avoid code duplication. + new(this) Variant(value); + } + + template + T getValue (bool *soFarSoGood = nullptr) const { + constexpr int id = IdOfType::id; + static_assert(id != Invalid, "Unable to get value of unsupported type."); + + T value; + + bool ok; + getValue(id, static_cast(&value), &ok); + if (soFarSoGood) + *soFarSoGood = ok; + + return value; + } + + bool isValid () const; + + void clear (); + void swap (const Variant &variant); + +private: + template + struct IdOfType { + static const int id = Invalid; + }; + + void getValue (int type, void *value, bool *soFarSoGood) const; + + static Variant createGeneric (void *value); + + VariantPrivate *mPrivate = nullptr; + + L_DECLARE_PRIVATE(Variant); +}; + +L_DECLARE_VARIANT_TYPES(L_DECLARE_VARIANT_TRAIT_TYPE); + +#undef L_DECLARE_VARIANT_TYPES +#undef L_DECLARE_VARIANT_ENUM_TYPE +#undef L_DECLARE_VARIANT_TRAIT_TYPE + +LINPHONE_END_NAMESPACE + +#endif // ifndef _L_VARIANT_H_ diff --git a/src/xml/conference-info.cpp b/src/xml/conference-info.cpp new file mode 100644 index 000000000..59f648483 --- /dev/null +++ b/src/xml/conference-info.cpp @@ -0,0 +1,9352 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#include "conference-info.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + // ConferenceType + // + + const ConferenceType::ConferenceDescriptionOptional& ConferenceType:: + getConferenceDescription () const + { + return this->conference_description_; + } + + ConferenceType::ConferenceDescriptionOptional& ConferenceType:: + getConferenceDescription () + { + return this->conference_description_; + } + + void ConferenceType:: + setConferenceDescription (const ConferenceDescriptionType& x) + { + this->conference_description_.set (x); + } + + void ConferenceType:: + setConferenceDescription (const ConferenceDescriptionOptional& x) + { + this->conference_description_ = x; + } + + void ConferenceType:: + setConferenceDescription (::std::unique_ptr< ConferenceDescriptionType > x) + { + this->conference_description_.set (std::move (x)); + } + + const ConferenceType::HostInfoOptional& ConferenceType:: + getHostInfo () const + { + return this->host_info_; + } + + ConferenceType::HostInfoOptional& ConferenceType:: + getHostInfo () + { + return this->host_info_; + } + + void ConferenceType:: + setHostInfo (const HostInfoType& x) + { + this->host_info_.set (x); + } + + void ConferenceType:: + setHostInfo (const HostInfoOptional& x) + { + this->host_info_ = x; + } + + void ConferenceType:: + setHostInfo (::std::unique_ptr< HostInfoType > x) + { + this->host_info_.set (std::move (x)); + } + + const ConferenceType::ConferenceStateOptional& ConferenceType:: + getConferenceState () const + { + return this->conference_state_; + } + + ConferenceType::ConferenceStateOptional& ConferenceType:: + getConferenceState () + { + return this->conference_state_; + } + + void ConferenceType:: + setConferenceState (const ConferenceStateType& x) + { + this->conference_state_.set (x); + } + + void ConferenceType:: + setConferenceState (const ConferenceStateOptional& x) + { + this->conference_state_ = x; + } + + void ConferenceType:: + setConferenceState (::std::unique_ptr< ConferenceStateType > x) + { + this->conference_state_.set (std::move (x)); + } + + const ConferenceType::UsersOptional& ConferenceType:: + getUsers () const + { + return this->users_; + } + + ConferenceType::UsersOptional& ConferenceType:: + getUsers () + { + return this->users_; + } + + void ConferenceType:: + setUsers (const UsersType& x) + { + this->users_.set (x); + } + + void ConferenceType:: + setUsers (const UsersOptional& x) + { + this->users_ = x; + } + + void ConferenceType:: + setUsers (::std::unique_ptr< UsersType > x) + { + this->users_.set (std::move (x)); + } + + const ConferenceType::SidebarsByRefOptional& ConferenceType:: + getSidebarsByRef () const + { + return this->sidebars_by_ref_; + } + + ConferenceType::SidebarsByRefOptional& ConferenceType:: + getSidebarsByRef () + { + return this->sidebars_by_ref_; + } + + void ConferenceType:: + setSidebarsByRef (const SidebarsByRefType& x) + { + this->sidebars_by_ref_.set (x); + } + + void ConferenceType:: + setSidebarsByRef (const SidebarsByRefOptional& x) + { + this->sidebars_by_ref_ = x; + } + + void ConferenceType:: + setSidebarsByRef (::std::unique_ptr< SidebarsByRefType > x) + { + this->sidebars_by_ref_.set (std::move (x)); + } + + const ConferenceType::SidebarsByValOptional& ConferenceType:: + getSidebarsByVal () const + { + return this->sidebars_by_val_; + } + + ConferenceType::SidebarsByValOptional& ConferenceType:: + getSidebarsByVal () + { + return this->sidebars_by_val_; + } + + void ConferenceType:: + setSidebarsByVal (const SidebarsByValType& x) + { + this->sidebars_by_val_.set (x); + } + + void ConferenceType:: + setSidebarsByVal (const SidebarsByValOptional& x) + { + this->sidebars_by_val_ = x; + } + + void ConferenceType:: + setSidebarsByVal (::std::unique_ptr< SidebarsByValType > x) + { + this->sidebars_by_val_.set (std::move (x)); + } + + const ConferenceType::AnySequence& ConferenceType:: + getAny () const + { + return this->any_; + } + + ConferenceType::AnySequence& ConferenceType:: + getAny () + { + return this->any_; + } + + void ConferenceType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ConferenceType::EntityType& ConferenceType:: + getEntity () const + { + return this->entity_.get (); + } + + ConferenceType::EntityType& ConferenceType:: + getEntity () + { + return this->entity_.get (); + } + + void ConferenceType:: + setEntity (const EntityType& x) + { + this->entity_.set (x); + } + + void ConferenceType:: + setEntity (::std::unique_ptr< EntityType > x) + { + this->entity_.set (std::move (x)); + } + + ::std::unique_ptr< ConferenceType::EntityType > ConferenceType:: + setDetachEntity () + { + return this->entity_.detach (); + } + + const ConferenceType::StateType& ConferenceType:: + getState () const + { + return this->state_.get (); + } + + ConferenceType::StateType& ConferenceType:: + getState () + { + return this->state_.get (); + } + + void ConferenceType:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void ConferenceType:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< ConferenceType::StateType > ConferenceType:: + setDetachState () + { + return this->state_.detach (); + } + + const ConferenceType::StateType& ConferenceType:: + getStateDefaultValue () + { + return state_default_value_; + } + + const ConferenceType::VersionOptional& ConferenceType:: + getVersion () const + { + return this->version_; + } + + ConferenceType::VersionOptional& ConferenceType:: + getVersion () + { + return this->version_; + } + + void ConferenceType:: + setVersion (const VersionType& x) + { + this->version_.set (x); + } + + void ConferenceType:: + setVersion (const VersionOptional& x) + { + this->version_ = x; + } + + const ConferenceType::AnyAttributeSet& ConferenceType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ConferenceType::AnyAttributeSet& ConferenceType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ConferenceType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ConferenceType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ConferenceType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // StateType + // + + StateType:: + StateType (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_StateType_literals_[v]) + { + } + + StateType:: + StateType (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + StateType:: + StateType (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + StateType:: + StateType (const ::LinphonePrivate::Xsd::XmlSchema::String& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + StateType:: + StateType (const StateType& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (v, f, c) + { + } + + StateType& StateType:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_StateType_literals_[v]); + + return *this; + } + + + // ConferenceDescriptionType + // + + const ConferenceDescriptionType::DisplayTextOptional& ConferenceDescriptionType:: + getDisplayText () const + { + return this->display_text_; + } + + ConferenceDescriptionType::DisplayTextOptional& ConferenceDescriptionType:: + getDisplayText () + { + return this->display_text_; + } + + void ConferenceDescriptionType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void ConferenceDescriptionType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void ConferenceDescriptionType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const ConferenceDescriptionType::SubjectOptional& ConferenceDescriptionType:: + getSubject () const + { + return this->subject_; + } + + ConferenceDescriptionType::SubjectOptional& ConferenceDescriptionType:: + getSubject () + { + return this->subject_; + } + + void ConferenceDescriptionType:: + setSubject (const SubjectType& x) + { + this->subject_.set (x); + } + + void ConferenceDescriptionType:: + setSubject (const SubjectOptional& x) + { + this->subject_ = x; + } + + void ConferenceDescriptionType:: + setSubject (::std::unique_ptr< SubjectType > x) + { + this->subject_.set (std::move (x)); + } + + const ConferenceDescriptionType::FreeTextOptional& ConferenceDescriptionType:: + getFreeText () const + { + return this->free_text_; + } + + ConferenceDescriptionType::FreeTextOptional& ConferenceDescriptionType:: + getFreeText () + { + return this->free_text_; + } + + void ConferenceDescriptionType:: + setFreeText (const FreeTextType& x) + { + this->free_text_.set (x); + } + + void ConferenceDescriptionType:: + setFreeText (const FreeTextOptional& x) + { + this->free_text_ = x; + } + + void ConferenceDescriptionType:: + setFreeText (::std::unique_ptr< FreeTextType > x) + { + this->free_text_.set (std::move (x)); + } + + const ConferenceDescriptionType::KeywordsOptional& ConferenceDescriptionType:: + getKeywords () const + { + return this->keywords_; + } + + ConferenceDescriptionType::KeywordsOptional& ConferenceDescriptionType:: + getKeywords () + { + return this->keywords_; + } + + void ConferenceDescriptionType:: + setKeywords (const KeywordsType& x) + { + this->keywords_.set (x); + } + + void ConferenceDescriptionType:: + setKeywords (const KeywordsOptional& x) + { + this->keywords_ = x; + } + + void ConferenceDescriptionType:: + setKeywords (::std::unique_ptr< KeywordsType > x) + { + this->keywords_.set (std::move (x)); + } + + const ConferenceDescriptionType::ConfUrisOptional& ConferenceDescriptionType:: + getConfUris () const + { + return this->conf_uris_; + } + + ConferenceDescriptionType::ConfUrisOptional& ConferenceDescriptionType:: + getConfUris () + { + return this->conf_uris_; + } + + void ConferenceDescriptionType:: + setConfUris (const ConfUrisType& x) + { + this->conf_uris_.set (x); + } + + void ConferenceDescriptionType:: + setConfUris (const ConfUrisOptional& x) + { + this->conf_uris_ = x; + } + + void ConferenceDescriptionType:: + setConfUris (::std::unique_ptr< ConfUrisType > x) + { + this->conf_uris_.set (std::move (x)); + } + + const ConferenceDescriptionType::ServiceUrisOptional& ConferenceDescriptionType:: + getServiceUris () const + { + return this->service_uris_; + } + + ConferenceDescriptionType::ServiceUrisOptional& ConferenceDescriptionType:: + getServiceUris () + { + return this->service_uris_; + } + + void ConferenceDescriptionType:: + setServiceUris (const ServiceUrisType& x) + { + this->service_uris_.set (x); + } + + void ConferenceDescriptionType:: + setServiceUris (const ServiceUrisOptional& x) + { + this->service_uris_ = x; + } + + void ConferenceDescriptionType:: + setServiceUris (::std::unique_ptr< ServiceUrisType > x) + { + this->service_uris_.set (std::move (x)); + } + + const ConferenceDescriptionType::MaximumUserCountOptional& ConferenceDescriptionType:: + getMaximumUserCount () const + { + return this->maximum_user_count_; + } + + ConferenceDescriptionType::MaximumUserCountOptional& ConferenceDescriptionType:: + getMaximumUserCount () + { + return this->maximum_user_count_; + } + + void ConferenceDescriptionType:: + setMaximumUserCount (const MaximumUserCountType& x) + { + this->maximum_user_count_.set (x); + } + + void ConferenceDescriptionType:: + setMaximumUserCount (const MaximumUserCountOptional& x) + { + this->maximum_user_count_ = x; + } + + const ConferenceDescriptionType::AvailableMediaOptional& ConferenceDescriptionType:: + getAvailableMedia () const + { + return this->available_media_; + } + + ConferenceDescriptionType::AvailableMediaOptional& ConferenceDescriptionType:: + getAvailableMedia () + { + return this->available_media_; + } + + void ConferenceDescriptionType:: + setAvailableMedia (const AvailableMediaType& x) + { + this->available_media_.set (x); + } + + void ConferenceDescriptionType:: + setAvailableMedia (const AvailableMediaOptional& x) + { + this->available_media_ = x; + } + + void ConferenceDescriptionType:: + setAvailableMedia (::std::unique_ptr< AvailableMediaType > x) + { + this->available_media_.set (std::move (x)); + } + + const ConferenceDescriptionType::AnySequence& ConferenceDescriptionType:: + getAny () const + { + return this->any_; + } + + ConferenceDescriptionType::AnySequence& ConferenceDescriptionType:: + getAny () + { + return this->any_; + } + + void ConferenceDescriptionType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ConferenceDescriptionType::AnyAttributeSet& ConferenceDescriptionType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ConferenceDescriptionType::AnyAttributeSet& ConferenceDescriptionType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ConferenceDescriptionType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ConferenceDescriptionType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ConferenceDescriptionType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // HostType + // + + const HostType::DisplayTextOptional& HostType:: + getDisplayText () const + { + return this->display_text_; + } + + HostType::DisplayTextOptional& HostType:: + getDisplayText () + { + return this->display_text_; + } + + void HostType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void HostType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void HostType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const HostType::WebPageOptional& HostType:: + getWebPage () const + { + return this->web_page_; + } + + HostType::WebPageOptional& HostType:: + getWebPage () + { + return this->web_page_; + } + + void HostType:: + setWebPage (const WebPageType& x) + { + this->web_page_.set (x); + } + + void HostType:: + setWebPage (const WebPageOptional& x) + { + this->web_page_ = x; + } + + void HostType:: + setWebPage (::std::unique_ptr< WebPageType > x) + { + this->web_page_.set (std::move (x)); + } + + const HostType::UrisOptional& HostType:: + getUris () const + { + return this->uris_; + } + + HostType::UrisOptional& HostType:: + getUris () + { + return this->uris_; + } + + void HostType:: + setUris (const UrisType& x) + { + this->uris_.set (x); + } + + void HostType:: + setUris (const UrisOptional& x) + { + this->uris_ = x; + } + + void HostType:: + setUris (::std::unique_ptr< UrisType > x) + { + this->uris_.set (std::move (x)); + } + + const HostType::AnySequence& HostType:: + getAny () const + { + return this->any_; + } + + HostType::AnySequence& HostType:: + getAny () + { + return this->any_; + } + + void HostType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const HostType::AnyAttributeSet& HostType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + HostType::AnyAttributeSet& HostType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void HostType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& HostType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& HostType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // ConferenceStateType + // + + const ConferenceStateType::UserCountOptional& ConferenceStateType:: + getUserCount () const + { + return this->user_count_; + } + + ConferenceStateType::UserCountOptional& ConferenceStateType:: + getUserCount () + { + return this->user_count_; + } + + void ConferenceStateType:: + setUserCount (const UserCountType& x) + { + this->user_count_.set (x); + } + + void ConferenceStateType:: + setUserCount (const UserCountOptional& x) + { + this->user_count_ = x; + } + + const ConferenceStateType::ActiveOptional& ConferenceStateType:: + getActive () const + { + return this->active_; + } + + ConferenceStateType::ActiveOptional& ConferenceStateType:: + getActive () + { + return this->active_; + } + + void ConferenceStateType:: + setActive (const ActiveType& x) + { + this->active_.set (x); + } + + void ConferenceStateType:: + setActive (const ActiveOptional& x) + { + this->active_ = x; + } + + const ConferenceStateType::LockedOptional& ConferenceStateType:: + getLocked () const + { + return this->locked_; + } + + ConferenceStateType::LockedOptional& ConferenceStateType:: + getLocked () + { + return this->locked_; + } + + void ConferenceStateType:: + setLocked (const LockedType& x) + { + this->locked_.set (x); + } + + void ConferenceStateType:: + setLocked (const LockedOptional& x) + { + this->locked_ = x; + } + + const ConferenceStateType::AnySequence& ConferenceStateType:: + getAny () const + { + return this->any_; + } + + ConferenceStateType::AnySequence& ConferenceStateType:: + getAny () + { + return this->any_; + } + + void ConferenceStateType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ConferenceStateType::AnyAttributeSet& ConferenceStateType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ConferenceStateType::AnyAttributeSet& ConferenceStateType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ConferenceStateType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ConferenceStateType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ConferenceStateType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // ConferenceMediaType + // + + const ConferenceMediaType::EntrySequence& ConferenceMediaType:: + getEntry () const + { + return this->entry_; + } + + ConferenceMediaType::EntrySequence& ConferenceMediaType:: + getEntry () + { + return this->entry_; + } + + void ConferenceMediaType:: + setEntry (const EntrySequence& s) + { + this->entry_ = s; + } + + const ConferenceMediaType::AnyAttributeSet& ConferenceMediaType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ConferenceMediaType::AnyAttributeSet& ConferenceMediaType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ConferenceMediaType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ConferenceMediaType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ConferenceMediaType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // ConferenceMediumType + // + + const ConferenceMediumType::DisplayTextOptional& ConferenceMediumType:: + getDisplayText () const + { + return this->display_text_; + } + + ConferenceMediumType::DisplayTextOptional& ConferenceMediumType:: + getDisplayText () + { + return this->display_text_; + } + + void ConferenceMediumType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void ConferenceMediumType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void ConferenceMediumType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const ConferenceMediumType::TypeType& ConferenceMediumType:: + getType () const + { + return this->type_.get (); + } + + ConferenceMediumType::TypeType& ConferenceMediumType:: + getType () + { + return this->type_.get (); + } + + void ConferenceMediumType:: + setType (const TypeType& x) + { + this->type_.set (x); + } + + void ConferenceMediumType:: + setType (::std::unique_ptr< TypeType > x) + { + this->type_.set (std::move (x)); + } + + ::std::unique_ptr< ConferenceMediumType::TypeType > ConferenceMediumType:: + setDetachType () + { + return this->type_.detach (); + } + + const ConferenceMediumType::StatusOptional& ConferenceMediumType:: + getStatus () const + { + return this->status_; + } + + ConferenceMediumType::StatusOptional& ConferenceMediumType:: + getStatus () + { + return this->status_; + } + + void ConferenceMediumType:: + setStatus (const StatusType& x) + { + this->status_.set (x); + } + + void ConferenceMediumType:: + setStatus (const StatusOptional& x) + { + this->status_ = x; + } + + void ConferenceMediumType:: + setStatus (::std::unique_ptr< StatusType > x) + { + this->status_.set (std::move (x)); + } + + const ConferenceMediumType::AnySequence& ConferenceMediumType:: + getAny () const + { + return this->any_; + } + + ConferenceMediumType::AnySequence& ConferenceMediumType:: + getAny () + { + return this->any_; + } + + void ConferenceMediumType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ConferenceMediumType::LabelType& ConferenceMediumType:: + getLabel () const + { + return this->label_.get (); + } + + ConferenceMediumType::LabelType& ConferenceMediumType:: + getLabel () + { + return this->label_.get (); + } + + void ConferenceMediumType:: + setLabel (const LabelType& x) + { + this->label_.set (x); + } + + void ConferenceMediumType:: + setLabel (::std::unique_ptr< LabelType > x) + { + this->label_.set (std::move (x)); + } + + ::std::unique_ptr< ConferenceMediumType::LabelType > ConferenceMediumType:: + setDetachLabel () + { + return this->label_.detach (); + } + + const ConferenceMediumType::AnyAttributeSet& ConferenceMediumType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ConferenceMediumType::AnyAttributeSet& ConferenceMediumType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ConferenceMediumType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ConferenceMediumType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ConferenceMediumType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // UrisType + // + + const UrisType::EntrySequence& UrisType:: + getEntry () const + { + return this->entry_; + } + + UrisType::EntrySequence& UrisType:: + getEntry () + { + return this->entry_; + } + + void UrisType:: + setEntry (const EntrySequence& s) + { + this->entry_ = s; + } + + const UrisType::StateType& UrisType:: + getState () const + { + return this->state_.get (); + } + + UrisType::StateType& UrisType:: + getState () + { + return this->state_.get (); + } + + void UrisType:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void UrisType:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< UrisType::StateType > UrisType:: + setDetachState () + { + return this->state_.detach (); + } + + const UrisType::StateType& UrisType:: + getStateDefaultValue () + { + return state_default_value_; + } + + const UrisType::AnyAttributeSet& UrisType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + UrisType::AnyAttributeSet& UrisType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void UrisType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& UrisType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& UrisType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // UriType + // + + const UriType::UriType1& UriType:: + getUri () const + { + return this->uri_.get (); + } + + UriType::UriType1& UriType:: + getUri () + { + return this->uri_.get (); + } + + void UriType:: + setUri (const UriType1& x) + { + this->uri_.set (x); + } + + void UriType:: + setUri (::std::unique_ptr< UriType1 > x) + { + this->uri_.set (std::move (x)); + } + + ::std::unique_ptr< UriType::UriType1 > UriType:: + setDetachUri () + { + return this->uri_.detach (); + } + + const UriType::DisplayTextOptional& UriType:: + getDisplayText () const + { + return this->display_text_; + } + + UriType::DisplayTextOptional& UriType:: + getDisplayText () + { + return this->display_text_; + } + + void UriType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void UriType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void UriType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const UriType::PurposeOptional& UriType:: + getPurpose () const + { + return this->purpose_; + } + + UriType::PurposeOptional& UriType:: + getPurpose () + { + return this->purpose_; + } + + void UriType:: + setPurpose (const PurposeType& x) + { + this->purpose_.set (x); + } + + void UriType:: + setPurpose (const PurposeOptional& x) + { + this->purpose_ = x; + } + + void UriType:: + setPurpose (::std::unique_ptr< PurposeType > x) + { + this->purpose_.set (std::move (x)); + } + + const UriType::ModifiedOptional& UriType:: + getModified () const + { + return this->modified_; + } + + UriType::ModifiedOptional& UriType:: + getModified () + { + return this->modified_; + } + + void UriType:: + setModified (const ModifiedType& x) + { + this->modified_.set (x); + } + + void UriType:: + setModified (const ModifiedOptional& x) + { + this->modified_ = x; + } + + void UriType:: + setModified (::std::unique_ptr< ModifiedType > x) + { + this->modified_.set (std::move (x)); + } + + const UriType::AnySequence& UriType:: + getAny () const + { + return this->any_; + } + + UriType::AnySequence& UriType:: + getAny () + { + return this->any_; + } + + void UriType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const UriType::AnyAttributeSet& UriType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + UriType::AnyAttributeSet& UriType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void UriType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& UriType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& UriType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // KeywordsType + // + + KeywordsType:: + KeywordsType () + : ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > (this) + { + } + + KeywordsType:: + KeywordsType (size_type n, const ::LinphonePrivate::Xsd::XmlSchema::String& x) + : ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > (n, x, this) + { + } + + KeywordsType:: + KeywordsType (const KeywordsType& o, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (o, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > (o, f, this) + { + } + + // UsersType + // + + const UsersType::UserSequence& UsersType:: + getUser () const + { + return this->user_; + } + + UsersType::UserSequence& UsersType:: + getUser () + { + return this->user_; + } + + void UsersType:: + setUser (const UserSequence& s) + { + this->user_ = s; + } + + const UsersType::AnySequence& UsersType:: + getAny () const + { + return this->any_; + } + + UsersType::AnySequence& UsersType:: + getAny () + { + return this->any_; + } + + void UsersType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const UsersType::StateType& UsersType:: + getState () const + { + return this->state_.get (); + } + + UsersType::StateType& UsersType:: + getState () + { + return this->state_.get (); + } + + void UsersType:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void UsersType:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< UsersType::StateType > UsersType:: + setDetachState () + { + return this->state_.detach (); + } + + const UsersType::StateType& UsersType:: + getStateDefaultValue () + { + return state_default_value_; + } + + const UsersType::AnyAttributeSet& UsersType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + UsersType::AnyAttributeSet& UsersType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void UsersType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& UsersType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& UsersType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // UserType + // + + const UserType::DisplayTextOptional& UserType:: + getDisplayText () const + { + return this->display_text_; + } + + UserType::DisplayTextOptional& UserType:: + getDisplayText () + { + return this->display_text_; + } + + void UserType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void UserType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void UserType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const UserType::AssociatedAorsOptional& UserType:: + getAssociatedAors () const + { + return this->associated_aors_; + } + + UserType::AssociatedAorsOptional& UserType:: + getAssociatedAors () + { + return this->associated_aors_; + } + + void UserType:: + setAssociatedAors (const AssociatedAorsType& x) + { + this->associated_aors_.set (x); + } + + void UserType:: + setAssociatedAors (const AssociatedAorsOptional& x) + { + this->associated_aors_ = x; + } + + void UserType:: + setAssociatedAors (::std::unique_ptr< AssociatedAorsType > x) + { + this->associated_aors_.set (std::move (x)); + } + + const UserType::RolesOptional& UserType:: + getRoles () const + { + return this->roles_; + } + + UserType::RolesOptional& UserType:: + getRoles () + { + return this->roles_; + } + + void UserType:: + setRoles (const RolesType& x) + { + this->roles_.set (x); + } + + void UserType:: + setRoles (const RolesOptional& x) + { + this->roles_ = x; + } + + void UserType:: + setRoles (::std::unique_ptr< RolesType > x) + { + this->roles_.set (std::move (x)); + } + + const UserType::LanguagesOptional& UserType:: + getLanguages () const + { + return this->languages_; + } + + UserType::LanguagesOptional& UserType:: + getLanguages () + { + return this->languages_; + } + + void UserType:: + setLanguages (const LanguagesType& x) + { + this->languages_.set (x); + } + + void UserType:: + setLanguages (const LanguagesOptional& x) + { + this->languages_ = x; + } + + void UserType:: + setLanguages (::std::unique_ptr< LanguagesType > x) + { + this->languages_.set (std::move (x)); + } + + const UserType::CascadedFocusOptional& UserType:: + getCascadedFocus () const + { + return this->cascaded_focus_; + } + + UserType::CascadedFocusOptional& UserType:: + getCascadedFocus () + { + return this->cascaded_focus_; + } + + void UserType:: + setCascadedFocus (const CascadedFocusType& x) + { + this->cascaded_focus_.set (x); + } + + void UserType:: + setCascadedFocus (const CascadedFocusOptional& x) + { + this->cascaded_focus_ = x; + } + + void UserType:: + setCascadedFocus (::std::unique_ptr< CascadedFocusType > x) + { + this->cascaded_focus_.set (std::move (x)); + } + + const UserType::EndpointSequence& UserType:: + getEndpoint () const + { + return this->endpoint_; + } + + UserType::EndpointSequence& UserType:: + getEndpoint () + { + return this->endpoint_; + } + + void UserType:: + setEndpoint (const EndpointSequence& s) + { + this->endpoint_ = s; + } + + const UserType::AnySequence& UserType:: + getAny () const + { + return this->any_; + } + + UserType::AnySequence& UserType:: + getAny () + { + return this->any_; + } + + void UserType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const UserType::EntityOptional& UserType:: + getEntity () const + { + return this->entity_; + } + + UserType::EntityOptional& UserType:: + getEntity () + { + return this->entity_; + } + + void UserType:: + setEntity (const EntityType& x) + { + this->entity_.set (x); + } + + void UserType:: + setEntity (const EntityOptional& x) + { + this->entity_ = x; + } + + void UserType:: + setEntity (::std::unique_ptr< EntityType > x) + { + this->entity_.set (std::move (x)); + } + + const UserType::StateType& UserType:: + getState () const + { + return this->state_.get (); + } + + UserType::StateType& UserType:: + getState () + { + return this->state_.get (); + } + + void UserType:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void UserType:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< UserType::StateType > UserType:: + setDetachState () + { + return this->state_.detach (); + } + + const UserType::StateType& UserType:: + getStateDefaultValue () + { + return state_default_value_; + } + + const UserType::AnyAttributeSet& UserType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + UserType::AnyAttributeSet& UserType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void UserType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& UserType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& UserType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // UserRolesType + // + + const UserRolesType::EntrySequence& UserRolesType:: + getEntry () const + { + return this->entry_; + } + + UserRolesType::EntrySequence& UserRolesType:: + getEntry () + { + return this->entry_; + } + + void UserRolesType:: + setEntry (const EntrySequence& s) + { + this->entry_ = s; + } + + const UserRolesType::AnyAttributeSet& UserRolesType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + UserRolesType::AnyAttributeSet& UserRolesType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void UserRolesType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& UserRolesType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& UserRolesType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // UserLanguagesType + // + + UserLanguagesType:: + UserLanguagesType () + : ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > (this) + { + } + + UserLanguagesType:: + UserLanguagesType (size_type n, const ::LinphonePrivate::Xsd::XmlSchema::Language& x) + : ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > (n, x, this) + { + } + + UserLanguagesType:: + UserLanguagesType (const UserLanguagesType& o, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (o, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > (o, f, this) + { + } + + // EndpointType + // + + const EndpointType::DisplayTextOptional& EndpointType:: + getDisplayText () const + { + return this->display_text_; + } + + EndpointType::DisplayTextOptional& EndpointType:: + getDisplayText () + { + return this->display_text_; + } + + void EndpointType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void EndpointType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void EndpointType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const EndpointType::ReferredOptional& EndpointType:: + getReferred () const + { + return this->referred_; + } + + EndpointType::ReferredOptional& EndpointType:: + getReferred () + { + return this->referred_; + } + + void EndpointType:: + setReferred (const ReferredType& x) + { + this->referred_.set (x); + } + + void EndpointType:: + setReferred (const ReferredOptional& x) + { + this->referred_ = x; + } + + void EndpointType:: + setReferred (::std::unique_ptr< ReferredType > x) + { + this->referred_.set (std::move (x)); + } + + const EndpointType::StatusOptional& EndpointType:: + getStatus () const + { + return this->status_; + } + + EndpointType::StatusOptional& EndpointType:: + getStatus () + { + return this->status_; + } + + void EndpointType:: + setStatus (const StatusType& x) + { + this->status_.set (x); + } + + void EndpointType:: + setStatus (const StatusOptional& x) + { + this->status_ = x; + } + + void EndpointType:: + setStatus (::std::unique_ptr< StatusType > x) + { + this->status_.set (std::move (x)); + } + + const EndpointType::JoiningMethodOptional& EndpointType:: + getJoiningMethod () const + { + return this->joining_method_; + } + + EndpointType::JoiningMethodOptional& EndpointType:: + getJoiningMethod () + { + return this->joining_method_; + } + + void EndpointType:: + setJoiningMethod (const JoiningMethodType& x) + { + this->joining_method_.set (x); + } + + void EndpointType:: + setJoiningMethod (const JoiningMethodOptional& x) + { + this->joining_method_ = x; + } + + void EndpointType:: + setJoiningMethod (::std::unique_ptr< JoiningMethodType > x) + { + this->joining_method_.set (std::move (x)); + } + + const EndpointType::JoiningInfoOptional& EndpointType:: + getJoiningInfo () const + { + return this->joining_info_; + } + + EndpointType::JoiningInfoOptional& EndpointType:: + getJoiningInfo () + { + return this->joining_info_; + } + + void EndpointType:: + setJoiningInfo (const JoiningInfoType& x) + { + this->joining_info_.set (x); + } + + void EndpointType:: + setJoiningInfo (const JoiningInfoOptional& x) + { + this->joining_info_ = x; + } + + void EndpointType:: + setJoiningInfo (::std::unique_ptr< JoiningInfoType > x) + { + this->joining_info_.set (std::move (x)); + } + + const EndpointType::DisconnectionMethodOptional& EndpointType:: + getDisconnectionMethod () const + { + return this->disconnection_method_; + } + + EndpointType::DisconnectionMethodOptional& EndpointType:: + getDisconnectionMethod () + { + return this->disconnection_method_; + } + + void EndpointType:: + setDisconnectionMethod (const DisconnectionMethodType& x) + { + this->disconnection_method_.set (x); + } + + void EndpointType:: + setDisconnectionMethod (const DisconnectionMethodOptional& x) + { + this->disconnection_method_ = x; + } + + void EndpointType:: + setDisconnectionMethod (::std::unique_ptr< DisconnectionMethodType > x) + { + this->disconnection_method_.set (std::move (x)); + } + + const EndpointType::DisconnectionInfoOptional& EndpointType:: + getDisconnectionInfo () const + { + return this->disconnection_info_; + } + + EndpointType::DisconnectionInfoOptional& EndpointType:: + getDisconnectionInfo () + { + return this->disconnection_info_; + } + + void EndpointType:: + setDisconnectionInfo (const DisconnectionInfoType& x) + { + this->disconnection_info_.set (x); + } + + void EndpointType:: + setDisconnectionInfo (const DisconnectionInfoOptional& x) + { + this->disconnection_info_ = x; + } + + void EndpointType:: + setDisconnectionInfo (::std::unique_ptr< DisconnectionInfoType > x) + { + this->disconnection_info_.set (std::move (x)); + } + + const EndpointType::MediaSequence& EndpointType:: + getMedia () const + { + return this->media_; + } + + EndpointType::MediaSequence& EndpointType:: + getMedia () + { + return this->media_; + } + + void EndpointType:: + setMedia (const MediaSequence& s) + { + this->media_ = s; + } + + const EndpointType::CallInfoOptional& EndpointType:: + getCallInfo () const + { + return this->call_info_; + } + + EndpointType::CallInfoOptional& EndpointType:: + getCallInfo () + { + return this->call_info_; + } + + void EndpointType:: + setCallInfo (const CallInfoType& x) + { + this->call_info_.set (x); + } + + void EndpointType:: + setCallInfo (const CallInfoOptional& x) + { + this->call_info_ = x; + } + + void EndpointType:: + setCallInfo (::std::unique_ptr< CallInfoType > x) + { + this->call_info_.set (std::move (x)); + } + + const EndpointType::AnySequence& EndpointType:: + getAny () const + { + return this->any_; + } + + EndpointType::AnySequence& EndpointType:: + getAny () + { + return this->any_; + } + + void EndpointType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const EndpointType::EntityOptional& EndpointType:: + getEntity () const + { + return this->entity_; + } + + EndpointType::EntityOptional& EndpointType:: + getEntity () + { + return this->entity_; + } + + void EndpointType:: + setEntity (const EntityType& x) + { + this->entity_.set (x); + } + + void EndpointType:: + setEntity (const EntityOptional& x) + { + this->entity_ = x; + } + + void EndpointType:: + setEntity (::std::unique_ptr< EntityType > x) + { + this->entity_.set (std::move (x)); + } + + const EndpointType::StateType& EndpointType:: + getState () const + { + return this->state_.get (); + } + + EndpointType::StateType& EndpointType:: + getState () + { + return this->state_.get (); + } + + void EndpointType:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void EndpointType:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< EndpointType::StateType > EndpointType:: + setDetachState () + { + return this->state_.detach (); + } + + const EndpointType::StateType& EndpointType:: + getStateDefaultValue () + { + return state_default_value_; + } + + const EndpointType::AnyAttributeSet& EndpointType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + EndpointType::AnyAttributeSet& EndpointType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void EndpointType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& EndpointType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& EndpointType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // EndpointStatusType + // + + EndpointStatusType:: + EndpointStatusType (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_EndpointStatusType_literals_[v]) + { + } + + EndpointStatusType:: + EndpointStatusType (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + EndpointStatusType:: + EndpointStatusType (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + EndpointStatusType:: + EndpointStatusType (const ::LinphonePrivate::Xsd::XmlSchema::String& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + EndpointStatusType:: + EndpointStatusType (const EndpointStatusType& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (v, f, c) + { + } + + EndpointStatusType& EndpointStatusType:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_EndpointStatusType_literals_[v]); + + return *this; + } + + + // JoiningType + // + + JoiningType:: + JoiningType (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_JoiningType_literals_[v]) + { + } + + JoiningType:: + JoiningType (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + JoiningType:: + JoiningType (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + JoiningType:: + JoiningType (const ::LinphonePrivate::Xsd::XmlSchema::String& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + JoiningType:: + JoiningType (const JoiningType& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (v, f, c) + { + } + + JoiningType& JoiningType:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_JoiningType_literals_[v]); + + return *this; + } + + + // DisconnectionType + // + + DisconnectionType:: + DisconnectionType (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_DisconnectionType_literals_[v]) + { + } + + DisconnectionType:: + DisconnectionType (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + DisconnectionType:: + DisconnectionType (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + DisconnectionType:: + DisconnectionType (const ::LinphonePrivate::Xsd::XmlSchema::String& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + DisconnectionType:: + DisconnectionType (const DisconnectionType& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (v, f, c) + { + } + + DisconnectionType& DisconnectionType:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_DisconnectionType_literals_[v]); + + return *this; + } + + + // ExecutionType + // + + const ExecutionType::WhenOptional& ExecutionType:: + getWhen () const + { + return this->when_; + } + + ExecutionType::WhenOptional& ExecutionType:: + getWhen () + { + return this->when_; + } + + void ExecutionType:: + setWhen (const WhenType& x) + { + this->when_.set (x); + } + + void ExecutionType:: + setWhen (const WhenOptional& x) + { + this->when_ = x; + } + + void ExecutionType:: + setWhen (::std::unique_ptr< WhenType > x) + { + this->when_.set (std::move (x)); + } + + const ExecutionType::ReasonOptional& ExecutionType:: + getReason () const + { + return this->reason_; + } + + ExecutionType::ReasonOptional& ExecutionType:: + getReason () + { + return this->reason_; + } + + void ExecutionType:: + setReason (const ReasonType& x) + { + this->reason_.set (x); + } + + void ExecutionType:: + setReason (const ReasonOptional& x) + { + this->reason_ = x; + } + + void ExecutionType:: + setReason (::std::unique_ptr< ReasonType > x) + { + this->reason_.set (std::move (x)); + } + + const ExecutionType::ByOptional& ExecutionType:: + getBy () const + { + return this->by_; + } + + ExecutionType::ByOptional& ExecutionType:: + getBy () + { + return this->by_; + } + + void ExecutionType:: + setBy (const ByType& x) + { + this->by_.set (x); + } + + void ExecutionType:: + setBy (const ByOptional& x) + { + this->by_ = x; + } + + void ExecutionType:: + setBy (::std::unique_ptr< ByType > x) + { + this->by_.set (std::move (x)); + } + + const ExecutionType::AnyAttributeSet& ExecutionType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ExecutionType::AnyAttributeSet& ExecutionType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ExecutionType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ExecutionType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ExecutionType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // CallType + // + + const CallType::SipOptional& CallType:: + getSip () const + { + return this->sip_; + } + + CallType::SipOptional& CallType:: + getSip () + { + return this->sip_; + } + + void CallType:: + setSip (const SipType& x) + { + this->sip_.set (x); + } + + void CallType:: + setSip (const SipOptional& x) + { + this->sip_ = x; + } + + void CallType:: + setSip (::std::unique_ptr< SipType > x) + { + this->sip_.set (std::move (x)); + } + + const CallType::AnySequence& CallType:: + getAny () const + { + return this->any_; + } + + CallType::AnySequence& CallType:: + getAny () + { + return this->any_; + } + + void CallType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const CallType::AnyAttributeSet& CallType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + CallType::AnyAttributeSet& CallType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void CallType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& CallType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& CallType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // SipDialogIdType + // + + const SipDialogIdType::DisplayTextOptional& SipDialogIdType:: + getDisplayText () const + { + return this->display_text_; + } + + SipDialogIdType::DisplayTextOptional& SipDialogIdType:: + getDisplayText () + { + return this->display_text_; + } + + void SipDialogIdType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void SipDialogIdType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void SipDialogIdType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const SipDialogIdType::CallIdType& SipDialogIdType:: + getCallId () const + { + return this->call_id_.get (); + } + + SipDialogIdType::CallIdType& SipDialogIdType:: + getCallId () + { + return this->call_id_.get (); + } + + void SipDialogIdType:: + setCallId (const CallIdType& x) + { + this->call_id_.set (x); + } + + void SipDialogIdType:: + setCallId (::std::unique_ptr< CallIdType > x) + { + this->call_id_.set (std::move (x)); + } + + ::std::unique_ptr< SipDialogIdType::CallIdType > SipDialogIdType:: + setDetachCall_id () + { + return this->call_id_.detach (); + } + + const SipDialogIdType::FromTagType& SipDialogIdType:: + getFromTag () const + { + return this->from_tag_.get (); + } + + SipDialogIdType::FromTagType& SipDialogIdType:: + getFromTag () + { + return this->from_tag_.get (); + } + + void SipDialogIdType:: + setFromTag (const FromTagType& x) + { + this->from_tag_.set (x); + } + + void SipDialogIdType:: + setFromTag (::std::unique_ptr< FromTagType > x) + { + this->from_tag_.set (std::move (x)); + } + + ::std::unique_ptr< SipDialogIdType::FromTagType > SipDialogIdType:: + setDetachFrom_tag () + { + return this->from_tag_.detach (); + } + + const SipDialogIdType::ToTagType& SipDialogIdType:: + getToTag () const + { + return this->to_tag_.get (); + } + + SipDialogIdType::ToTagType& SipDialogIdType:: + getToTag () + { + return this->to_tag_.get (); + } + + void SipDialogIdType:: + setToTag (const ToTagType& x) + { + this->to_tag_.set (x); + } + + void SipDialogIdType:: + setToTag (::std::unique_ptr< ToTagType > x) + { + this->to_tag_.set (std::move (x)); + } + + ::std::unique_ptr< SipDialogIdType::ToTagType > SipDialogIdType:: + setDetachTo_tag () + { + return this->to_tag_.detach (); + } + + const SipDialogIdType::AnySequence& SipDialogIdType:: + getAny () const + { + return this->any_; + } + + SipDialogIdType::AnySequence& SipDialogIdType:: + getAny () + { + return this->any_; + } + + void SipDialogIdType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const SipDialogIdType::AnyAttributeSet& SipDialogIdType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + SipDialogIdType::AnyAttributeSet& SipDialogIdType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void SipDialogIdType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& SipDialogIdType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& SipDialogIdType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // MediaType + // + + const MediaType::DisplayTextOptional& MediaType:: + getDisplayText () const + { + return this->display_text_; + } + + MediaType::DisplayTextOptional& MediaType:: + getDisplayText () + { + return this->display_text_; + } + + void MediaType:: + setDisplayText (const DisplayTextType& x) + { + this->display_text_.set (x); + } + + void MediaType:: + setDisplayText (const DisplayTextOptional& x) + { + this->display_text_ = x; + } + + void MediaType:: + setDisplayText (::std::unique_ptr< DisplayTextType > x) + { + this->display_text_.set (std::move (x)); + } + + const MediaType::TypeOptional& MediaType:: + getType () const + { + return this->type_; + } + + MediaType::TypeOptional& MediaType:: + getType () + { + return this->type_; + } + + void MediaType:: + setType (const TypeType& x) + { + this->type_.set (x); + } + + void MediaType:: + setType (const TypeOptional& x) + { + this->type_ = x; + } + + void MediaType:: + setType (::std::unique_ptr< TypeType > x) + { + this->type_.set (std::move (x)); + } + + const MediaType::LabelOptional& MediaType:: + getLabel () const + { + return this->label_; + } + + MediaType::LabelOptional& MediaType:: + getLabel () + { + return this->label_; + } + + void MediaType:: + setLabel (const LabelType& x) + { + this->label_.set (x); + } + + void MediaType:: + setLabel (const LabelOptional& x) + { + this->label_ = x; + } + + void MediaType:: + setLabel (::std::unique_ptr< LabelType > x) + { + this->label_.set (std::move (x)); + } + + const MediaType::SrcIdOptional& MediaType:: + getSrcId () const + { + return this->src_id_; + } + + MediaType::SrcIdOptional& MediaType:: + getSrcId () + { + return this->src_id_; + } + + void MediaType:: + setSrcId (const SrcIdType& x) + { + this->src_id_.set (x); + } + + void MediaType:: + setSrcId (const SrcIdOptional& x) + { + this->src_id_ = x; + } + + void MediaType:: + setSrcId (::std::unique_ptr< SrcIdType > x) + { + this->src_id_.set (std::move (x)); + } + + const MediaType::StatusOptional& MediaType:: + getStatus () const + { + return this->status_; + } + + MediaType::StatusOptional& MediaType:: + getStatus () + { + return this->status_; + } + + void MediaType:: + setStatus (const StatusType& x) + { + this->status_.set (x); + } + + void MediaType:: + setStatus (const StatusOptional& x) + { + this->status_ = x; + } + + void MediaType:: + setStatus (::std::unique_ptr< StatusType > x) + { + this->status_.set (std::move (x)); + } + + const MediaType::AnySequence& MediaType:: + getAny () const + { + return this->any_; + } + + MediaType::AnySequence& MediaType:: + getAny () + { + return this->any_; + } + + void MediaType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const MediaType::IdType& MediaType:: + getId () const + { + return this->id_.get (); + } + + MediaType::IdType& MediaType:: + getId () + { + return this->id_.get (); + } + + void MediaType:: + setId (const IdType& x) + { + this->id_.set (x); + } + + void MediaType:: + setId (::std::unique_ptr< IdType > x) + { + this->id_.set (std::move (x)); + } + + ::std::unique_ptr< MediaType::IdType > MediaType:: + setDetachId () + { + return this->id_.detach (); + } + + const MediaType::AnyAttributeSet& MediaType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + MediaType::AnyAttributeSet& MediaType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void MediaType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& MediaType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& MediaType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // MediaStatusType + // + + MediaStatusType:: + MediaStatusType (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_MediaStatusType_literals_[v]) + { + } + + MediaStatusType:: + MediaStatusType (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + MediaStatusType:: + MediaStatusType (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + MediaStatusType:: + MediaStatusType (const ::LinphonePrivate::Xsd::XmlSchema::String& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + MediaStatusType:: + MediaStatusType (const MediaStatusType& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (v, f, c) + { + } + + MediaStatusType& MediaStatusType:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_MediaStatusType_literals_[v]); + + return *this; + } + + + // SidebarsByValType + // + + const SidebarsByValType::EntrySequence& SidebarsByValType:: + getEntry () const + { + return this->entry_; + } + + SidebarsByValType::EntrySequence& SidebarsByValType:: + getEntry () + { + return this->entry_; + } + + void SidebarsByValType:: + setEntry (const EntrySequence& s) + { + this->entry_ = s; + } + + const SidebarsByValType::StateType& SidebarsByValType:: + getState () const + { + return this->state_.get (); + } + + SidebarsByValType::StateType& SidebarsByValType:: + getState () + { + return this->state_.get (); + } + + void SidebarsByValType:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void SidebarsByValType:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< SidebarsByValType::StateType > SidebarsByValType:: + setDetachState () + { + return this->state_.detach (); + } + + const SidebarsByValType::StateType& SidebarsByValType:: + getStateDefaultValue () + { + return state_default_value_; + } + + const SidebarsByValType::AnyAttributeSet& SidebarsByValType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + SidebarsByValType::AnyAttributeSet& SidebarsByValType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void SidebarsByValType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& SidebarsByValType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& SidebarsByValType:: + getDomDocument () + { + return *this->dom_document_; + } + } + } +} + +#include + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_factory_plate< 0, char > + type_factory_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + // ConferenceType + // + + const ConferenceType::StateType ConferenceType::state_default_value_ ( + "full"); + + ConferenceType:: + ConferenceType (const EntityType& entity) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + conference_description_ (this), + host_info_ (this), + conference_state_ (this), + users_ (this), + sidebars_by_ref_ (this), + sidebars_by_val_ (this), + any_ (this->getDomDocument ()), + entity_ (entity, this), + state_ (getStateDefaultValue (), this), + version_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + ConferenceType:: + ConferenceType (const ConferenceType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + conference_description_ (x.conference_description_, f, this), + host_info_ (x.host_info_, f, this), + conference_state_ (x.conference_state_, f, this), + users_ (x.users_, f, this), + sidebars_by_ref_ (x.sidebars_by_ref_, f, this), + sidebars_by_val_ (x.sidebars_by_val_, f, this), + any_ (x.any_, this->getDomDocument ()), + entity_ (x.entity_, f, this), + state_ (x.state_, f, this), + version_ (x.version_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ConferenceType:: + ConferenceType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + conference_description_ (this), + host_info_ (this), + conference_state_ (this), + users_ (this), + sidebars_by_ref_ (this), + sidebars_by_val_ (this), + any_ (this->getDomDocument ()), + entity_ (this), + state_ (this), + version_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ConferenceType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // conference-description + // + if (n.name () == "conference-description" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ConferenceDescriptionType > r ( + ConferenceDescriptionTraits::create (i, f, this)); + + if (!this->conference_description_) + { + this->conference_description_.set (::std::move (r)); + continue; + } + } + + // host-info + // + if (n.name () == "host-info" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< HostInfoType > r ( + HostInfoTraits::create (i, f, this)); + + if (!this->host_info_) + { + this->host_info_.set (::std::move (r)); + continue; + } + } + + // conference-state + // + if (n.name () == "conference-state" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ConferenceStateType > r ( + ConferenceStateTraits::create (i, f, this)); + + if (!this->conference_state_) + { + this->conference_state_.set (::std::move (r)); + continue; + } + } + + // users + // + if (n.name () == "users" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< UsersType > r ( + UsersTraits::create (i, f, this)); + + if (!this->users_) + { + this->users_.set (::std::move (r)); + continue; + } + } + + // sidebars-by-ref + // + if (n.name () == "sidebars-by-ref" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< SidebarsByRefType > r ( + SidebarsByRefTraits::create (i, f, this)); + + if (!this->sidebars_by_ref_) + { + this->sidebars_by_ref_.set (::std::move (r)); + continue; + } + } + + // sidebars-by-val + // + if (n.name () == "sidebars-by-val" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< SidebarsByValType > r ( + SidebarsByValTraits::create (i, f, this)); + + if (!this->sidebars_by_val_) + { + this->sidebars_by_val_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "entity" && n.namespace_ ().empty ()) + { + this->entity_.set (EntityTraits::create (i, f, this)); + continue; + } + + if (n.name () == "state" && n.namespace_ ().empty ()) + { + this->state_.set (StateTraits::create (i, f, this)); + continue; + } + + if (n.name () == "version" && n.namespace_ ().empty ()) + { + this->version_.set (VersionTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!entity_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "entity", + ""); + } + + if (!state_.present ()) + { + this->state_.set (getStateDefaultValue ()); + } + } + + ConferenceType* ConferenceType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ConferenceType (*this, f, c); + } + + ConferenceType& ConferenceType:: + operator= (const ConferenceType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->conference_description_ = x.conference_description_; + this->host_info_ = x.host_info_; + this->conference_state_ = x.conference_state_; + this->users_ = x.users_; + this->sidebars_by_ref_ = x.sidebars_by_ref_; + this->sidebars_by_val_ = x.sidebars_by_val_; + this->any_ = x.any_; + this->entity_ = x.entity_; + this->state_ = x.state_; + this->version_ = x.version_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ConferenceType:: + ~ConferenceType () + { + } + + // StateType + // + + StateType:: + StateType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + _xsd_StateType_convert (); + } + + StateType:: + StateType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + _xsd_StateType_convert (); + } + + StateType:: + StateType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + _xsd_StateType_convert (); + } + + StateType* StateType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class StateType (*this, f, c); + } + + StateType::Value StateType:: + _xsd_StateType_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_StateType_literals_); + const Value* i (::std::lower_bound ( + _xsd_StateType_indexes_, + _xsd_StateType_indexes_ + 3, + *this, + c)); + + if (i == _xsd_StateType_indexes_ + 3 || _xsd_StateType_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const StateType:: + _xsd_StateType_literals_[3] = + { + "full", + "partial", + "deleted" + }; + + const StateType::Value StateType:: + _xsd_StateType_indexes_[3] = + { + ::LinphonePrivate::Xsd::ConferenceInfo::StateType::deleted, + ::LinphonePrivate::Xsd::ConferenceInfo::StateType::full, + ::LinphonePrivate::Xsd::ConferenceInfo::StateType::partial + }; + + // ConferenceDescriptionType + // + + ConferenceDescriptionType:: + ConferenceDescriptionType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + subject_ (this), + free_text_ (this), + keywords_ (this), + conf_uris_ (this), + service_uris_ (this), + maximum_user_count_ (this), + available_media_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + } + + ConferenceDescriptionType:: + ConferenceDescriptionType (const ConferenceDescriptionType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (x.display_text_, f, this), + subject_ (x.subject_, f, this), + free_text_ (x.free_text_, f, this), + keywords_ (x.keywords_, f, this), + conf_uris_ (x.conf_uris_, f, this), + service_uris_ (x.service_uris_, f, this), + maximum_user_count_ (x.maximum_user_count_, f, this), + available_media_ (x.available_media_, f, this), + any_ (x.any_, this->getDomDocument ()), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ConferenceDescriptionType:: + ConferenceDescriptionType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + subject_ (this), + free_text_ (this), + keywords_ (this), + conf_uris_ (this), + service_uris_ (this), + maximum_user_count_ (this), + available_media_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ConferenceDescriptionType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // subject + // + if (n.name () == "subject" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< SubjectType > r ( + SubjectTraits::create (i, f, this)); + + if (!this->subject_) + { + this->subject_.set (::std::move (r)); + continue; + } + } + + // free-text + // + if (n.name () == "free-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< FreeTextType > r ( + FreeTextTraits::create (i, f, this)); + + if (!this->free_text_) + { + this->free_text_.set (::std::move (r)); + continue; + } + } + + // keywords + // + if (n.name () == "keywords" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< KeywordsType > r ( + KeywordsTraits::create (i, f, this)); + + if (!this->keywords_) + { + this->keywords_.set (::std::move (r)); + continue; + } + } + + // conf-uris + // + if (n.name () == "conf-uris" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ConfUrisType > r ( + ConfUrisTraits::create (i, f, this)); + + if (!this->conf_uris_) + { + this->conf_uris_.set (::std::move (r)); + continue; + } + } + + // service-uris + // + if (n.name () == "service-uris" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ServiceUrisType > r ( + ServiceUrisTraits::create (i, f, this)); + + if (!this->service_uris_) + { + this->service_uris_.set (::std::move (r)); + continue; + } + } + + // maximum-user-count + // + if (n.name () == "maximum-user-count" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + if (!this->maximum_user_count_) + { + this->maximum_user_count_.set (MaximumUserCountTraits::create (i, f, this)); + continue; + } + } + + // available-media + // + if (n.name () == "available-media" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< AvailableMediaType > r ( + AvailableMediaTraits::create (i, f, this)); + + if (!this->available_media_) + { + this->available_media_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + ConferenceDescriptionType* ConferenceDescriptionType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ConferenceDescriptionType (*this, f, c); + } + + ConferenceDescriptionType& ConferenceDescriptionType:: + operator= (const ConferenceDescriptionType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_text_ = x.display_text_; + this->subject_ = x.subject_; + this->free_text_ = x.free_text_; + this->keywords_ = x.keywords_; + this->conf_uris_ = x.conf_uris_; + this->service_uris_ = x.service_uris_; + this->maximum_user_count_ = x.maximum_user_count_; + this->available_media_ = x.available_media_; + this->any_ = x.any_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ConferenceDescriptionType:: + ~ConferenceDescriptionType () + { + } + + // HostType + // + + HostType:: + HostType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + web_page_ (this), + uris_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + } + + HostType:: + HostType (const HostType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (x.display_text_, f, this), + web_page_ (x.web_page_, f, this), + uris_ (x.uris_, f, this), + any_ (x.any_, this->getDomDocument ()), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + HostType:: + HostType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + web_page_ (this), + uris_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void HostType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // web-page + // + if (n.name () == "web-page" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< WebPageType > r ( + WebPageTraits::create (i, f, this)); + + if (!this->web_page_) + { + this->web_page_.set (::std::move (r)); + continue; + } + } + + // uris + // + if (n.name () == "uris" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< UrisType > r ( + UrisTraits::create (i, f, this)); + + if (!this->uris_) + { + this->uris_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + HostType* HostType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class HostType (*this, f, c); + } + + HostType& HostType:: + operator= (const HostType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_text_ = x.display_text_; + this->web_page_ = x.web_page_; + this->uris_ = x.uris_; + this->any_ = x.any_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + HostType:: + ~HostType () + { + } + + // ConferenceStateType + // + + ConferenceStateType:: + ConferenceStateType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + user_count_ (this), + active_ (this), + locked_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + } + + ConferenceStateType:: + ConferenceStateType (const ConferenceStateType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + user_count_ (x.user_count_, f, this), + active_ (x.active_, f, this), + locked_ (x.locked_, f, this), + any_ (x.any_, this->getDomDocument ()), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ConferenceStateType:: + ConferenceStateType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + user_count_ (this), + active_ (this), + locked_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ConferenceStateType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // user-count + // + if (n.name () == "user-count" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + if (!this->user_count_) + { + this->user_count_.set (UserCountTraits::create (i, f, this)); + continue; + } + } + + // active + // + if (n.name () == "active" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + if (!this->active_) + { + this->active_.set (ActiveTraits::create (i, f, this)); + continue; + } + } + + // locked + // + if (n.name () == "locked" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + if (!this->locked_) + { + this->locked_.set (LockedTraits::create (i, f, this)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + ConferenceStateType* ConferenceStateType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ConferenceStateType (*this, f, c); + } + + ConferenceStateType& ConferenceStateType:: + operator= (const ConferenceStateType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->user_count_ = x.user_count_; + this->active_ = x.active_; + this->locked_ = x.locked_; + this->any_ = x.any_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ConferenceStateType:: + ~ConferenceStateType () + { + } + + // ConferenceMediaType + // + + ConferenceMediaType:: + ConferenceMediaType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + ConferenceMediaType:: + ConferenceMediaType (const ConferenceMediaType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (x.entry_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ConferenceMediaType:: + ConferenceMediaType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ConferenceMediaType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // entry + // + if (n.name () == "entry" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< EntryType > r ( + EntryTraits::create (i, f, this)); + + this->entry_.push_back (::std::move (r)); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + ConferenceMediaType* ConferenceMediaType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ConferenceMediaType (*this, f, c); + } + + ConferenceMediaType& ConferenceMediaType:: + operator= (const ConferenceMediaType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->entry_ = x.entry_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ConferenceMediaType:: + ~ConferenceMediaType () + { + } + + // ConferenceMediumType + // + + ConferenceMediumType:: + ConferenceMediumType (const TypeType& type, + const LabelType& label) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + type_ (type, this), + status_ (this), + any_ (this->getDomDocument ()), + label_ (label, this), + any_attribute_ (this->getDomDocument ()) + { + } + + ConferenceMediumType:: + ConferenceMediumType (const ConferenceMediumType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (x.display_text_, f, this), + type_ (x.type_, f, this), + status_ (x.status_, f, this), + any_ (x.any_, this->getDomDocument ()), + label_ (x.label_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ConferenceMediumType:: + ConferenceMediumType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + type_ (this), + status_ (this), + any_ (this->getDomDocument ()), + label_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ConferenceMediumType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // type + // + if (n.name () == "type" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< TypeType > r ( + TypeTraits::create (i, f, this)); + + if (!type_.present ()) + { + this->type_.set (::std::move (r)); + continue; + } + } + + // status + // + if (n.name () == "status" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< StatusType > r ( + StatusTraits::create (i, f, this)); + + if (!this->status_) + { + this->status_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + if (!type_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "type", + "urn:ietf:params:xml:ns:conference-info"); + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "label" && n.namespace_ ().empty ()) + { + this->label_.set (LabelTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!label_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "label", + ""); + } + } + + ConferenceMediumType* ConferenceMediumType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ConferenceMediumType (*this, f, c); + } + + ConferenceMediumType& ConferenceMediumType:: + operator= (const ConferenceMediumType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_text_ = x.display_text_; + this->type_ = x.type_; + this->status_ = x.status_; + this->any_ = x.any_; + this->label_ = x.label_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ConferenceMediumType:: + ~ConferenceMediumType () + { + } + + // UrisType + // + + const UrisType::StateType UrisType::state_default_value_ ( + "full"); + + UrisType:: + UrisType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + state_ (getStateDefaultValue (), this), + any_attribute_ (this->getDomDocument ()) + { + } + + UrisType:: + UrisType (const UrisType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (x.entry_, f, this), + state_ (x.state_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + UrisType:: + UrisType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + state_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void UrisType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // entry + // + if (n.name () == "entry" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< EntryType > r ( + EntryTraits::create (i, f, this)); + + this->entry_.push_back (::std::move (r)); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "state" && n.namespace_ ().empty ()) + { + this->state_.set (StateTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!state_.present ()) + { + this->state_.set (getStateDefaultValue ()); + } + } + + UrisType* UrisType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class UrisType (*this, f, c); + } + + UrisType& UrisType:: + operator= (const UrisType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->entry_ = x.entry_; + this->state_ = x.state_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + UrisType:: + ~UrisType () + { + } + + // UriType + // + + UriType:: + UriType (const UriType1& uri) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + uri_ (uri, this), + display_text_ (this), + purpose_ (this), + modified_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + } + + UriType:: + UriType (const UriType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + uri_ (x.uri_, f, this), + display_text_ (x.display_text_, f, this), + purpose_ (x.purpose_, f, this), + modified_ (x.modified_, f, this), + any_ (x.any_, this->getDomDocument ()), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + UriType:: + UriType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + uri_ (this), + display_text_ (this), + purpose_ (this), + modified_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void UriType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // uri + // + if (n.name () == "uri" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< UriType1 > r ( + UriTraits::create (i, f, this)); + + if (!uri_.present ()) + { + this->uri_.set (::std::move (r)); + continue; + } + } + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // purpose + // + if (n.name () == "purpose" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< PurposeType > r ( + PurposeTraits::create (i, f, this)); + + if (!this->purpose_) + { + this->purpose_.set (::std::move (r)); + continue; + } + } + + // modified + // + if (n.name () == "modified" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ModifiedType > r ( + ModifiedTraits::create (i, f, this)); + + if (!this->modified_) + { + this->modified_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + if (!uri_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "uri", + "urn:ietf:params:xml:ns:conference-info"); + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + UriType* UriType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class UriType (*this, f, c); + } + + UriType& UriType:: + operator= (const UriType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->uri_ = x.uri_; + this->display_text_ = x.display_text_; + this->purpose_ = x.purpose_; + this->modified_ = x.modified_; + this->any_ = x.any_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + UriType:: + ~UriType () + { + } + + // KeywordsType + // + + KeywordsType:: + KeywordsType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (e, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > (e, f, this) + { + } + + KeywordsType:: + KeywordsType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (a, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > (a, f, this) + { + } + + KeywordsType:: + KeywordsType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (s, e, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > (s, e, f, this) + { + } + + KeywordsType* KeywordsType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class KeywordsType (*this, f, c); + } + + KeywordsType:: + ~KeywordsType () + { + } + + // UsersType + // + + const UsersType::StateType UsersType::state_default_value_ ( + "full"); + + UsersType:: + UsersType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + user_ (this), + any_ (this->getDomDocument ()), + state_ (getStateDefaultValue (), this), + any_attribute_ (this->getDomDocument ()) + { + } + + UsersType:: + UsersType (const UsersType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + user_ (x.user_, f, this), + any_ (x.any_, this->getDomDocument ()), + state_ (x.state_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + UsersType:: + UsersType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + user_ (this), + any_ (this->getDomDocument ()), + state_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void UsersType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // user + // + if (n.name () == "user" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< UserType > r ( + UserTraits::create (i, f, this)); + + this->user_.push_back (::std::move (r)); + continue; + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "state" && n.namespace_ ().empty ()) + { + this->state_.set (StateTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!state_.present ()) + { + this->state_.set (getStateDefaultValue ()); + } + } + + UsersType* UsersType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class UsersType (*this, f, c); + } + + UsersType& UsersType:: + operator= (const UsersType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->user_ = x.user_; + this->any_ = x.any_; + this->state_ = x.state_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + UsersType:: + ~UsersType () + { + } + + // UserType + // + + const UserType::StateType UserType::state_default_value_ ( + "full"); + + UserType:: + UserType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + associated_aors_ (this), + roles_ (this), + languages_ (this), + cascaded_focus_ (this), + endpoint_ (this), + any_ (this->getDomDocument ()), + entity_ (this), + state_ (getStateDefaultValue (), this), + any_attribute_ (this->getDomDocument ()) + { + } + + UserType:: + UserType (const UserType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (x.display_text_, f, this), + associated_aors_ (x.associated_aors_, f, this), + roles_ (x.roles_, f, this), + languages_ (x.languages_, f, this), + cascaded_focus_ (x.cascaded_focus_, f, this), + endpoint_ (x.endpoint_, f, this), + any_ (x.any_, this->getDomDocument ()), + entity_ (x.entity_, f, this), + state_ (x.state_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + UserType:: + UserType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + associated_aors_ (this), + roles_ (this), + languages_ (this), + cascaded_focus_ (this), + endpoint_ (this), + any_ (this->getDomDocument ()), + entity_ (this), + state_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void UserType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // associated-aors + // + if (n.name () == "associated-aors" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< AssociatedAorsType > r ( + AssociatedAorsTraits::create (i, f, this)); + + if (!this->associated_aors_) + { + this->associated_aors_.set (::std::move (r)); + continue; + } + } + + // roles + // + if (n.name () == "roles" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< RolesType > r ( + RolesTraits::create (i, f, this)); + + if (!this->roles_) + { + this->roles_.set (::std::move (r)); + continue; + } + } + + // languages + // + if (n.name () == "languages" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< LanguagesType > r ( + LanguagesTraits::create (i, f, this)); + + if (!this->languages_) + { + this->languages_.set (::std::move (r)); + continue; + } + } + + // cascaded-focus + // + if (n.name () == "cascaded-focus" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< CascadedFocusType > r ( + CascadedFocusTraits::create (i, f, this)); + + if (!this->cascaded_focus_) + { + this->cascaded_focus_.set (::std::move (r)); + continue; + } + } + + // endpoint + // + if (n.name () == "endpoint" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< EndpointType > r ( + EndpointTraits::create (i, f, this)); + + this->endpoint_.push_back (::std::move (r)); + continue; + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "entity" && n.namespace_ ().empty ()) + { + this->entity_.set (EntityTraits::create (i, f, this)); + continue; + } + + if (n.name () == "state" && n.namespace_ ().empty ()) + { + this->state_.set (StateTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!state_.present ()) + { + this->state_.set (getStateDefaultValue ()); + } + } + + UserType* UserType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class UserType (*this, f, c); + } + + UserType& UserType:: + operator= (const UserType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_text_ = x.display_text_; + this->associated_aors_ = x.associated_aors_; + this->roles_ = x.roles_; + this->languages_ = x.languages_; + this->cascaded_focus_ = x.cascaded_focus_; + this->endpoint_ = x.endpoint_; + this->any_ = x.any_; + this->entity_ = x.entity_; + this->state_ = x.state_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + UserType:: + ~UserType () + { + } + + // UserRolesType + // + + UserRolesType:: + UserRolesType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + UserRolesType:: + UserRolesType (const UserRolesType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (x.entry_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + UserRolesType:: + UserRolesType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void UserRolesType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // entry + // + if (n.name () == "entry" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< EntryType > r ( + EntryTraits::create (i, f, this)); + + this->entry_.push_back (::std::move (r)); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + UserRolesType* UserRolesType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class UserRolesType (*this, f, c); + } + + UserRolesType& UserRolesType:: + operator= (const UserRolesType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->entry_ = x.entry_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + UserRolesType:: + ~UserRolesType () + { + } + + // UserLanguagesType + // + + UserLanguagesType:: + UserLanguagesType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (e, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > (e, f, this) + { + } + + UserLanguagesType:: + UserLanguagesType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (a, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > (a, f, this) + { + } + + UserLanguagesType:: + UserLanguagesType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::SimpleType (s, e, f, c), + ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > (s, e, f, this) + { + } + + UserLanguagesType* UserLanguagesType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class UserLanguagesType (*this, f, c); + } + + UserLanguagesType:: + ~UserLanguagesType () + { + } + + // EndpointType + // + + const EndpointType::StateType EndpointType::state_default_value_ ( + "full"); + + EndpointType:: + EndpointType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + referred_ (this), + status_ (this), + joining_method_ (this), + joining_info_ (this), + disconnection_method_ (this), + disconnection_info_ (this), + media_ (this), + call_info_ (this), + any_ (this->getDomDocument ()), + entity_ (this), + state_ (getStateDefaultValue (), this), + any_attribute_ (this->getDomDocument ()) + { + } + + EndpointType:: + EndpointType (const EndpointType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (x.display_text_, f, this), + referred_ (x.referred_, f, this), + status_ (x.status_, f, this), + joining_method_ (x.joining_method_, f, this), + joining_info_ (x.joining_info_, f, this), + disconnection_method_ (x.disconnection_method_, f, this), + disconnection_info_ (x.disconnection_info_, f, this), + media_ (x.media_, f, this), + call_info_ (x.call_info_, f, this), + any_ (x.any_, this->getDomDocument ()), + entity_ (x.entity_, f, this), + state_ (x.state_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + EndpointType:: + EndpointType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + referred_ (this), + status_ (this), + joining_method_ (this), + joining_info_ (this), + disconnection_method_ (this), + disconnection_info_ (this), + media_ (this), + call_info_ (this), + any_ (this->getDomDocument ()), + entity_ (this), + state_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void EndpointType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // referred + // + if (n.name () == "referred" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ReferredType > r ( + ReferredTraits::create (i, f, this)); + + if (!this->referred_) + { + this->referred_.set (::std::move (r)); + continue; + } + } + + // status + // + if (n.name () == "status" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< StatusType > r ( + StatusTraits::create (i, f, this)); + + if (!this->status_) + { + this->status_.set (::std::move (r)); + continue; + } + } + + // joining-method + // + if (n.name () == "joining-method" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< JoiningMethodType > r ( + JoiningMethodTraits::create (i, f, this)); + + if (!this->joining_method_) + { + this->joining_method_.set (::std::move (r)); + continue; + } + } + + // joining-info + // + if (n.name () == "joining-info" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< JoiningInfoType > r ( + JoiningInfoTraits::create (i, f, this)); + + if (!this->joining_info_) + { + this->joining_info_.set (::std::move (r)); + continue; + } + } + + // disconnection-method + // + if (n.name () == "disconnection-method" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisconnectionMethodType > r ( + DisconnectionMethodTraits::create (i, f, this)); + + if (!this->disconnection_method_) + { + this->disconnection_method_.set (::std::move (r)); + continue; + } + } + + // disconnection-info + // + if (n.name () == "disconnection-info" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisconnectionInfoType > r ( + DisconnectionInfoTraits::create (i, f, this)); + + if (!this->disconnection_info_) + { + this->disconnection_info_.set (::std::move (r)); + continue; + } + } + + // media + // + if (n.name () == "media" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< MediaType > r ( + MediaTraits::create (i, f, this)); + + this->media_.push_back (::std::move (r)); + continue; + } + + // call-info + // + if (n.name () == "call-info" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< CallInfoType > r ( + CallInfoTraits::create (i, f, this)); + + if (!this->call_info_) + { + this->call_info_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "entity" && n.namespace_ ().empty ()) + { + this->entity_.set (EntityTraits::create (i, f, this)); + continue; + } + + if (n.name () == "state" && n.namespace_ ().empty ()) + { + this->state_.set (StateTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!state_.present ()) + { + this->state_.set (getStateDefaultValue ()); + } + } + + EndpointType* EndpointType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class EndpointType (*this, f, c); + } + + EndpointType& EndpointType:: + operator= (const EndpointType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_text_ = x.display_text_; + this->referred_ = x.referred_; + this->status_ = x.status_; + this->joining_method_ = x.joining_method_; + this->joining_info_ = x.joining_info_; + this->disconnection_method_ = x.disconnection_method_; + this->disconnection_info_ = x.disconnection_info_; + this->media_ = x.media_; + this->call_info_ = x.call_info_; + this->any_ = x.any_; + this->entity_ = x.entity_; + this->state_ = x.state_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + EndpointType:: + ~EndpointType () + { + } + + // EndpointStatusType + // + + EndpointStatusType:: + EndpointStatusType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + _xsd_EndpointStatusType_convert (); + } + + EndpointStatusType:: + EndpointStatusType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + _xsd_EndpointStatusType_convert (); + } + + EndpointStatusType:: + EndpointStatusType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + _xsd_EndpointStatusType_convert (); + } + + EndpointStatusType* EndpointStatusType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class EndpointStatusType (*this, f, c); + } + + EndpointStatusType::Value EndpointStatusType:: + _xsd_EndpointStatusType_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_EndpointStatusType_literals_); + const Value* i (::std::lower_bound ( + _xsd_EndpointStatusType_indexes_, + _xsd_EndpointStatusType_indexes_ + 9, + *this, + c)); + + if (i == _xsd_EndpointStatusType_indexes_ + 9 || _xsd_EndpointStatusType_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const EndpointStatusType:: + _xsd_EndpointStatusType_literals_[9] = + { + "pending", + "dialing-out", + "dialing-in", + "alerting", + "on-hold", + "connected", + "muted-via-focus", + "disconnecting", + "disconnected" + }; + + const EndpointStatusType::Value EndpointStatusType:: + _xsd_EndpointStatusType_indexes_[9] = + { + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::alerting, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::connected, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::dialing_in, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::dialing_out, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::disconnected, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::disconnecting, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::muted_via_focus, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::on_hold, + ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType::pending + }; + + // JoiningType + // + + JoiningType:: + JoiningType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + _xsd_JoiningType_convert (); + } + + JoiningType:: + JoiningType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + _xsd_JoiningType_convert (); + } + + JoiningType:: + JoiningType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + _xsd_JoiningType_convert (); + } + + JoiningType* JoiningType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class JoiningType (*this, f, c); + } + + JoiningType::Value JoiningType:: + _xsd_JoiningType_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_JoiningType_literals_); + const Value* i (::std::lower_bound ( + _xsd_JoiningType_indexes_, + _xsd_JoiningType_indexes_ + 3, + *this, + c)); + + if (i == _xsd_JoiningType_indexes_ + 3 || _xsd_JoiningType_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const JoiningType:: + _xsd_JoiningType_literals_[3] = + { + "dialed-in", + "dialed-out", + "focus-owner" + }; + + const JoiningType::Value JoiningType:: + _xsd_JoiningType_indexes_[3] = + { + ::LinphonePrivate::Xsd::ConferenceInfo::JoiningType::dialed_in, + ::LinphonePrivate::Xsd::ConferenceInfo::JoiningType::dialed_out, + ::LinphonePrivate::Xsd::ConferenceInfo::JoiningType::focus_owner + }; + + // DisconnectionType + // + + DisconnectionType:: + DisconnectionType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + _xsd_DisconnectionType_convert (); + } + + DisconnectionType:: + DisconnectionType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + _xsd_DisconnectionType_convert (); + } + + DisconnectionType:: + DisconnectionType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + _xsd_DisconnectionType_convert (); + } + + DisconnectionType* DisconnectionType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class DisconnectionType (*this, f, c); + } + + DisconnectionType::Value DisconnectionType:: + _xsd_DisconnectionType_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_DisconnectionType_literals_); + const Value* i (::std::lower_bound ( + _xsd_DisconnectionType_indexes_, + _xsd_DisconnectionType_indexes_ + 4, + *this, + c)); + + if (i == _xsd_DisconnectionType_indexes_ + 4 || _xsd_DisconnectionType_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const DisconnectionType:: + _xsd_DisconnectionType_literals_[4] = + { + "departed", + "booted", + "failed", + "busy" + }; + + const DisconnectionType::Value DisconnectionType:: + _xsd_DisconnectionType_indexes_[4] = + { + ::LinphonePrivate::Xsd::ConferenceInfo::DisconnectionType::booted, + ::LinphonePrivate::Xsd::ConferenceInfo::DisconnectionType::busy, + ::LinphonePrivate::Xsd::ConferenceInfo::DisconnectionType::departed, + ::LinphonePrivate::Xsd::ConferenceInfo::DisconnectionType::failed + }; + + // ExecutionType + // + + ExecutionType:: + ExecutionType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + when_ (this), + reason_ (this), + by_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + ExecutionType:: + ExecutionType (const ExecutionType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + when_ (x.when_, f, this), + reason_ (x.reason_, f, this), + by_ (x.by_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ExecutionType:: + ExecutionType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + when_ (this), + reason_ (this), + by_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ExecutionType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // when + // + if (n.name () == "when" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< WhenType > r ( + WhenTraits::create (i, f, this)); + + if (!this->when_) + { + this->when_.set (::std::move (r)); + continue; + } + } + + // reason + // + if (n.name () == "reason" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ReasonType > r ( + ReasonTraits::create (i, f, this)); + + if (!this->reason_) + { + this->reason_.set (::std::move (r)); + continue; + } + } + + // by + // + if (n.name () == "by" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ByType > r ( + ByTraits::create (i, f, this)); + + if (!this->by_) + { + this->by_.set (::std::move (r)); + continue; + } + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + ExecutionType* ExecutionType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ExecutionType (*this, f, c); + } + + ExecutionType& ExecutionType:: + operator= (const ExecutionType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->when_ = x.when_; + this->reason_ = x.reason_; + this->by_ = x.by_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ExecutionType:: + ~ExecutionType () + { + } + + // CallType + // + + CallType:: + CallType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + sip_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + } + + CallType:: + CallType (const CallType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + sip_ (x.sip_, f, this), + any_ (x.any_, this->getDomDocument ()), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + CallType:: + CallType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + sip_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void CallType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // sip + // + if (n.name () == "sip" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< SipType > r ( + SipTraits::create (i, f, this)); + + if (!this->sip_) + { + this->sip_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + CallType* CallType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class CallType (*this, f, c); + } + + CallType& CallType:: + operator= (const CallType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->sip_ = x.sip_; + this->any_ = x.any_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + CallType:: + ~CallType () + { + } + + // SipDialogIdType + // + + SipDialogIdType:: + SipDialogIdType (const CallIdType& call_id, + const FromTagType& from_tag, + const ToTagType& to_tag) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + call_id_ (call_id, this), + from_tag_ (from_tag, this), + to_tag_ (to_tag, this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + } + + SipDialogIdType:: + SipDialogIdType (const SipDialogIdType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (x.display_text_, f, this), + call_id_ (x.call_id_, f, this), + from_tag_ (x.from_tag_, f, this), + to_tag_ (x.to_tag_, f, this), + any_ (x.any_, this->getDomDocument ()), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + SipDialogIdType:: + SipDialogIdType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + call_id_ (this), + from_tag_ (this), + to_tag_ (this), + any_ (this->getDomDocument ()), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void SipDialogIdType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // call-id + // + if (n.name () == "call-id" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< CallIdType > r ( + CallIdTraits::create (i, f, this)); + + if (!call_id_.present ()) + { + this->call_id_.set (::std::move (r)); + continue; + } + } + + // from-tag + // + if (n.name () == "from-tag" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< FromTagType > r ( + FromTagTraits::create (i, f, this)); + + if (!from_tag_.present ()) + { + this->from_tag_.set (::std::move (r)); + continue; + } + } + + // to-tag + // + if (n.name () == "to-tag" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ToTagType > r ( + ToTagTraits::create (i, f, this)); + + if (!to_tag_.present ()) + { + this->to_tag_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + if (!call_id_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "call-id", + "urn:ietf:params:xml:ns:conference-info"); + } + + if (!from_tag_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "from-tag", + "urn:ietf:params:xml:ns:conference-info"); + } + + if (!to_tag_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "to-tag", + "urn:ietf:params:xml:ns:conference-info"); + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + SipDialogIdType* SipDialogIdType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class SipDialogIdType (*this, f, c); + } + + SipDialogIdType& SipDialogIdType:: + operator= (const SipDialogIdType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_text_ = x.display_text_; + this->call_id_ = x.call_id_; + this->from_tag_ = x.from_tag_; + this->to_tag_ = x.to_tag_; + this->any_ = x.any_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + SipDialogIdType:: + ~SipDialogIdType () + { + } + + // MediaType + // + + MediaType:: + MediaType (const IdType& id) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + type_ (this), + label_ (this), + src_id_ (this), + status_ (this), + any_ (this->getDomDocument ()), + id_ (id, this), + any_attribute_ (this->getDomDocument ()) + { + } + + MediaType:: + MediaType (const MediaType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (x.display_text_, f, this), + type_ (x.type_, f, this), + label_ (x.label_, f, this), + src_id_ (x.src_id_, f, this), + status_ (x.status_, f, this), + any_ (x.any_, this->getDomDocument ()), + id_ (x.id_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + MediaType:: + MediaType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_text_ (this), + type_ (this), + label_ (this), + src_id_ (this), + status_ (this), + any_ (this->getDomDocument ()), + id_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void MediaType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-text + // + if (n.name () == "display-text" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< DisplayTextType > r ( + DisplayTextTraits::create (i, f, this)); + + if (!this->display_text_) + { + this->display_text_.set (::std::move (r)); + continue; + } + } + + // type + // + if (n.name () == "type" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< TypeType > r ( + TypeTraits::create (i, f, this)); + + if (!this->type_) + { + this->type_.set (::std::move (r)); + continue; + } + } + + // label + // + if (n.name () == "label" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< LabelType > r ( + LabelTraits::create (i, f, this)); + + if (!this->label_) + { + this->label_.set (::std::move (r)); + continue; + } + } + + // src-id + // + if (n.name () == "src-id" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< SrcIdType > r ( + SrcIdTraits::create (i, f, this)); + + if (!this->src_id_) + { + this->src_id_.set (::std::move (r)); + continue; + } + } + + // status + // + if (n.name () == "status" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< StatusType > r ( + StatusTraits::create (i, f, this)); + + if (!this->status_) + { + this->status_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:conference-info")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "id" && n.namespace_ ().empty ()) + { + this->id_.set (IdTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!id_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "id", + ""); + } + } + + MediaType* MediaType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class MediaType (*this, f, c); + } + + MediaType& MediaType:: + operator= (const MediaType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_text_ = x.display_text_; + this->type_ = x.type_; + this->label_ = x.label_; + this->src_id_ = x.src_id_; + this->status_ = x.status_; + this->any_ = x.any_; + this->id_ = x.id_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + MediaType:: + ~MediaType () + { + } + + // MediaStatusType + // + + MediaStatusType:: + MediaStatusType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + _xsd_MediaStatusType_convert (); + } + + MediaStatusType:: + MediaStatusType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + _xsd_MediaStatusType_convert (); + } + + MediaStatusType:: + MediaStatusType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + _xsd_MediaStatusType_convert (); + } + + MediaStatusType* MediaStatusType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class MediaStatusType (*this, f, c); + } + + MediaStatusType::Value MediaStatusType:: + _xsd_MediaStatusType_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_MediaStatusType_literals_); + const Value* i (::std::lower_bound ( + _xsd_MediaStatusType_indexes_, + _xsd_MediaStatusType_indexes_ + 4, + *this, + c)); + + if (i == _xsd_MediaStatusType_indexes_ + 4 || _xsd_MediaStatusType_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const MediaStatusType:: + _xsd_MediaStatusType_literals_[4] = + { + "recvonly", + "sendonly", + "sendrecv", + "inactive" + }; + + const MediaStatusType::Value MediaStatusType:: + _xsd_MediaStatusType_indexes_[4] = + { + ::LinphonePrivate::Xsd::ConferenceInfo::MediaStatusType::inactive, + ::LinphonePrivate::Xsd::ConferenceInfo::MediaStatusType::recvonly, + ::LinphonePrivate::Xsd::ConferenceInfo::MediaStatusType::sendonly, + ::LinphonePrivate::Xsd::ConferenceInfo::MediaStatusType::sendrecv + }; + + // SidebarsByValType + // + + const SidebarsByValType::StateType SidebarsByValType::state_default_value_ ( + "full"); + + SidebarsByValType:: + SidebarsByValType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + state_ (getStateDefaultValue (), this), + any_attribute_ (this->getDomDocument ()) + { + } + + SidebarsByValType:: + SidebarsByValType (const SidebarsByValType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (x.entry_, f, this), + state_ (x.state_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + SidebarsByValType:: + SidebarsByValType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + entry_ (this), + state_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void SidebarsByValType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // entry + // + if (n.name () == "entry" && n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< EntryType > r ( + EntryTraits::create (i, f, this)); + + this->entry_.push_back (::std::move (r)); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "state" && n.namespace_ ().empty ()) + { + this->state_.set (StateTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:conference-info" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!state_.present ()) + { + this->state_.set (getStateDefaultValue ()); + } + } + + SidebarsByValType* SidebarsByValType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class SidebarsByValType (*this, f, c); + } + + SidebarsByValType& SidebarsByValType:: + operator= (const SidebarsByValType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->entry_ = x.entry_; + this->state_ = x.state_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + SidebarsByValType:: + ~SidebarsByValType () + { + } + } + } +} + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::std_ostream_plate< 0, char > + std_ostream_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + ::std::ostream& + operator<< (::std::ostream& o, const ConferenceType& i) + { + if (i.getConferenceDescription ()) + { + o << ::std::endl << "conference-description: " << *i.getConferenceDescription (); + } + + if (i.getHostInfo ()) + { + o << ::std::endl << "host-info: " << *i.getHostInfo (); + } + + if (i.getConferenceState ()) + { + o << ::std::endl << "conference-state: " << *i.getConferenceState (); + } + + if (i.getUsers ()) + { + o << ::std::endl << "users: " << *i.getUsers (); + } + + if (i.getSidebarsByRef ()) + { + o << ::std::endl << "sidebars-by-ref: " << *i.getSidebarsByRef (); + } + + if (i.getSidebarsByVal ()) + { + o << ::std::endl << "sidebars-by-val: " << *i.getSidebarsByVal (); + } + + o << ::std::endl << "entity: " << i.getEntity (); + o << ::std::endl << "state: " << i.getState (); + if (i.getVersion ()) + { + o << ::std::endl << "version: " << *i.getVersion (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, StateType::Value i) + { + return o << StateType::_xsd_StateType_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const StateType& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, const ConferenceDescriptionType& i) + { + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + if (i.getSubject ()) + { + o << ::std::endl << "subject: " << *i.getSubject (); + } + + if (i.getFreeText ()) + { + o << ::std::endl << "free-text: " << *i.getFreeText (); + } + + if (i.getKeywords ()) + { + o << ::std::endl << "keywords: " << *i.getKeywords (); + } + + if (i.getConfUris ()) + { + o << ::std::endl << "conf-uris: " << *i.getConfUris (); + } + + if (i.getServiceUris ()) + { + o << ::std::endl << "service-uris: " << *i.getServiceUris (); + } + + if (i.getMaximumUserCount ()) + { + o << ::std::endl << "maximum-user-count: " << *i.getMaximumUserCount (); + } + + if (i.getAvailableMedia ()) + { + o << ::std::endl << "available-media: " << *i.getAvailableMedia (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const HostType& i) + { + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + if (i.getWebPage ()) + { + o << ::std::endl << "web-page: " << *i.getWebPage (); + } + + if (i.getUris ()) + { + o << ::std::endl << "uris: " << *i.getUris (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const ConferenceStateType& i) + { + if (i.getUserCount ()) + { + o << ::std::endl << "user-count: " << *i.getUserCount (); + } + + if (i.getActive ()) + { + o << ::std::endl << "active: " << *i.getActive (); + } + + if (i.getLocked ()) + { + o << ::std::endl << "locked: " << *i.getLocked (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const ConferenceMediaType& i) + { + for (ConferenceMediaType::EntryConstIterator + b (i.getEntry ().begin ()), e (i.getEntry ().end ()); + b != e; ++b) + { + o << ::std::endl << "entry: " << *b; + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const ConferenceMediumType& i) + { + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + o << ::std::endl << "type: " << i.getType (); + if (i.getStatus ()) + { + o << ::std::endl << "status: " << *i.getStatus (); + } + + o << ::std::endl << "label: " << i.getLabel (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const UrisType& i) + { + for (UrisType::EntryConstIterator + b (i.getEntry ().begin ()), e (i.getEntry ().end ()); + b != e; ++b) + { + o << ::std::endl << "entry: " << *b; + } + + o << ::std::endl << "state: " << i.getState (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const UriType& i) + { + o << ::std::endl << "uri: " << i.getUri (); + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + if (i.getPurpose ()) + { + o << ::std::endl << "purpose: " << *i.getPurpose (); + } + + if (i.getModified ()) + { + o << ::std::endl << "modified: " << *i.getModified (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const KeywordsType& i) + { + return o << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char >& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, const UsersType& i) + { + for (UsersType::UserConstIterator + b (i.getUser ().begin ()), e (i.getUser ().end ()); + b != e; ++b) + { + o << ::std::endl << "user: " << *b; + } + + o << ::std::endl << "state: " << i.getState (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const UserType& i) + { + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + if (i.getAssociatedAors ()) + { + o << ::std::endl << "associated-aors: " << *i.getAssociatedAors (); + } + + if (i.getRoles ()) + { + o << ::std::endl << "roles: " << *i.getRoles (); + } + + if (i.getLanguages ()) + { + o << ::std::endl << "languages: " << *i.getLanguages (); + } + + if (i.getCascadedFocus ()) + { + o << ::std::endl << "cascaded-focus: " << *i.getCascadedFocus (); + } + + for (UserType::EndpointConstIterator + b (i.getEndpoint ().begin ()), e (i.getEndpoint ().end ()); + b != e; ++b) + { + o << ::std::endl << "endpoint: " << *b; + } + + if (i.getEntity ()) + { + o << ::std::endl << "entity: " << *i.getEntity (); + } + + o << ::std::endl << "state: " << i.getState (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const UserRolesType& i) + { + for (UserRolesType::EntryConstIterator + b (i.getEntry ().begin ()), e (i.getEntry ().end ()); + b != e; ++b) + { + o << ::std::endl << "entry: " << *b; + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const UserLanguagesType& i) + { + return o << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char >& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, const EndpointType& i) + { + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + if (i.getReferred ()) + { + o << ::std::endl << "referred: " << *i.getReferred (); + } + + if (i.getStatus ()) + { + o << ::std::endl << "status: " << *i.getStatus (); + } + + if (i.getJoiningMethod ()) + { + o << ::std::endl << "joining-method: " << *i.getJoiningMethod (); + } + + if (i.getJoiningInfo ()) + { + o << ::std::endl << "joining-info: " << *i.getJoiningInfo (); + } + + if (i.getDisconnectionMethod ()) + { + o << ::std::endl << "disconnection-method: " << *i.getDisconnectionMethod (); + } + + if (i.getDisconnectionInfo ()) + { + o << ::std::endl << "disconnection-info: " << *i.getDisconnectionInfo (); + } + + for (EndpointType::MediaConstIterator + b (i.getMedia ().begin ()), e (i.getMedia ().end ()); + b != e; ++b) + { + o << ::std::endl << "media: " << *b; + } + + if (i.getCallInfo ()) + { + o << ::std::endl << "call-info: " << *i.getCallInfo (); + } + + if (i.getEntity ()) + { + o << ::std::endl << "entity: " << *i.getEntity (); + } + + o << ::std::endl << "state: " << i.getState (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, EndpointStatusType::Value i) + { + return o << EndpointStatusType::_xsd_EndpointStatusType_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const EndpointStatusType& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, JoiningType::Value i) + { + return o << JoiningType::_xsd_JoiningType_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const JoiningType& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, DisconnectionType::Value i) + { + return o << DisconnectionType::_xsd_DisconnectionType_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const DisconnectionType& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, const ExecutionType& i) + { + if (i.getWhen ()) + { + o << ::std::endl << "when: " << *i.getWhen (); + } + + if (i.getReason ()) + { + o << ::std::endl << "reason: " << *i.getReason (); + } + + if (i.getBy ()) + { + o << ::std::endl << "by: " << *i.getBy (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const CallType& i) + { + if (i.getSip ()) + { + o << ::std::endl << "sip: " << *i.getSip (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const SipDialogIdType& i) + { + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + o << ::std::endl << "call-id: " << i.getCallId (); + o << ::std::endl << "from-tag: " << i.getFromTag (); + o << ::std::endl << "to-tag: " << i.getToTag (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const MediaType& i) + { + if (i.getDisplayText ()) + { + o << ::std::endl << "display-text: " << *i.getDisplayText (); + } + + if (i.getType ()) + { + o << ::std::endl << "type: " << *i.getType (); + } + + if (i.getLabel ()) + { + o << ::std::endl << "label: " << *i.getLabel (); + } + + if (i.getSrcId ()) + { + o << ::std::endl << "src-id: " << *i.getSrcId (); + } + + if (i.getStatus ()) + { + o << ::std::endl << "status: " << *i.getStatus (); + } + + o << ::std::endl << "id: " << i.getId (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, MediaStatusType::Value i) + { + return o << MediaStatusType::_xsd_MediaStatusType_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const MediaStatusType& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, const SidebarsByValType& i) + { + for (SidebarsByValType::EntryConstIterator + b (i.getEntry ().begin ()), e (i.getEntry ().end ()); + b != e; ++b) + { + o << ::std::endl << "entry: " << *b; + } + + o << ::std::endl << "state: " << i.getState (); + return o; + } + } + } +} + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > ( + ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > ( + ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::std::string& u, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > ( + ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + const ::std::string& sid, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > ( + ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > ( + ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::xercesc::InputSource& i, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > ( + ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::xercesc::DOMDocument& doc, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + static_cast< ::xercesc::DOMDocument* > (doc.cloneNode (true))); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > ( + ::LinphonePrivate::Xsd::ConferenceInfo::parseConferenceInfo ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "conference-info" && + n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "conference-info", + "urn:ietf:params:xml:ns:conference-info"); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties&) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > c ( + ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) && + !(f & ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom)) + ? static_cast< ::xercesc::DOMDocument* > (d->cloneNode (true)) + : 0); + + ::xercesc::DOMDocument& doc (c.get () ? *c : *d); + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + doc.setUserData (::LinphonePrivate::Xsd::XmlSchema::dom::treeNodeKey, + (c.get () ? &c : &d), + 0); + + if (n.name () == "conference-info" && + n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "conference-info", + "urn:ietf:params:xml:ns:conference-info"); + } + } + } +} + +#include +#include +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_serializer_plate< 0, char > + type_serializer_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + void + serializeConferenceInfo (::std::ostream& o, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ConferenceInfo::serializeConferenceInfo (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeConferenceInfo (::std::ostream& o, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ConferenceInfo::serializeConferenceInfo (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeConferenceInfo (::std::ostream& o, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ConferenceInfo::serializeConferenceInfo (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeConferenceInfo (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ConferenceInfo::serializeConferenceInfo (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeConferenceInfo (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ConferenceInfo::serializeConferenceInfo (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeConferenceInfo (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ConferenceInfo::serializeConferenceInfo (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeConferenceInfo (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + ::LinphonePrivate::Xsd::XmlSchema::Flags) + { + ::xercesc::DOMElement& e (*d.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "conference-info" && + n.namespace_ () == "urn:ietf:params:xml:ns:conference-info") + { + e << s; + } + else + { + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "conference-info", + "urn:ietf:params:xml:ns:conference-info"); + } + } + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeConferenceInfo (const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::serialize< char > ( + "conference-info", + "urn:ietf:params:xml:ns:conference-info", + m, f)); + + ::LinphonePrivate::Xsd::ConferenceInfo::serializeConferenceInfo (*d, s, f); + return d; + } + + void + operator<< (::xercesc::DOMElement& e, const ConferenceType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ConferenceType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // conference-description + // + if (i.getConferenceDescription ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "conference-description", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getConferenceDescription (); + } + + // host-info + // + if (i.getHostInfo ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "host-info", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getHostInfo (); + } + + // conference-state + // + if (i.getConferenceState ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "conference-state", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getConferenceState (); + } + + // users + // + if (i.getUsers ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "users", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getUsers (); + } + + // sidebars-by-ref + // + if (i.getSidebarsByRef ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "sidebars-by-ref", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getSidebarsByRef (); + } + + // sidebars-by-val + // + if (i.getSidebarsByVal ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "sidebars-by-val", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getSidebarsByVal (); + } + + // any + // + for (ConferenceType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // entity + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "entity", + e)); + + a << i.getEntity (); + } + + // state + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "state", + e)); + + a << i.getState (); + } + + // version + // + if (i.getVersion ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "version", + e)); + + a << *i.getVersion (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const StateType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const StateType& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const StateType& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const ConferenceDescriptionType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ConferenceDescriptionType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // subject + // + if (i.getSubject ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "subject", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getSubject (); + } + + // free-text + // + if (i.getFreeText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "free-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getFreeText (); + } + + // keywords + // + if (i.getKeywords ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "keywords", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getKeywords (); + } + + // conf-uris + // + if (i.getConfUris ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "conf-uris", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getConfUris (); + } + + // service-uris + // + if (i.getServiceUris ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "service-uris", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getServiceUris (); + } + + // maximum-user-count + // + if (i.getMaximumUserCount ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "maximum-user-count", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getMaximumUserCount (); + } + + // available-media + // + if (i.getAvailableMedia ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "available-media", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getAvailableMedia (); + } + + // any + // + for (ConferenceDescriptionType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const HostType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (HostType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // web-page + // + if (i.getWebPage ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "web-page", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getWebPage (); + } + + // uris + // + if (i.getUris ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "uris", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getUris (); + } + + // any + // + for (HostType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const ConferenceStateType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ConferenceStateType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // user-count + // + if (i.getUserCount ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "user-count", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getUserCount (); + } + + // active + // + if (i.getActive ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "active", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getActive (); + } + + // locked + // + if (i.getLocked ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "locked", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getLocked (); + } + + // any + // + for (ConferenceStateType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const ConferenceMediaType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ConferenceMediaType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // entry + // + for (ConferenceMediaType::EntryConstIterator + b (i.getEntry ().begin ()), n (i.getEntry ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "entry", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *b; + } + } + + void + operator<< (::xercesc::DOMElement& e, const ConferenceMediumType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ConferenceMediumType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // type + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "type", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << i.getType (); + } + + // status + // + if (i.getStatus ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "status", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getStatus (); + } + + // any + // + for (ConferenceMediumType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // label + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "label", + e)); + + a << i.getLabel (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const UrisType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (UrisType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // entry + // + for (UrisType::EntryConstIterator + b (i.getEntry ().begin ()), n (i.getEntry ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "entry", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *b; + } + + // state + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "state", + e)); + + a << i.getState (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const UriType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (UriType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // uri + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "uri", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << i.getUri (); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // purpose + // + if (i.getPurpose ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "purpose", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getPurpose (); + } + + // modified + // + if (i.getModified ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "modified", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getModified (); + } + + // any + // + for (UriType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const KeywordsType& i) + { + e << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char >& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const KeywordsType& i) + { + a << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char >& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const KeywordsType& i) + { + l << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char >& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const UsersType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (UsersType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // user + // + for (UsersType::UserConstIterator + b (i.getUser ().begin ()), n (i.getUser ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "user", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *b; + } + + // any + // + for (UsersType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // state + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "state", + e)); + + a << i.getState (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const UserType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (UserType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // associated-aors + // + if (i.getAssociatedAors ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "associated-aors", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getAssociatedAors (); + } + + // roles + // + if (i.getRoles ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "roles", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getRoles (); + } + + // languages + // + if (i.getLanguages ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "languages", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getLanguages (); + } + + // cascaded-focus + // + if (i.getCascadedFocus ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "cascaded-focus", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getCascadedFocus (); + } + + // endpoint + // + for (UserType::EndpointConstIterator + b (i.getEndpoint ().begin ()), n (i.getEndpoint ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "endpoint", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *b; + } + + // any + // + for (UserType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // entity + // + if (i.getEntity ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "entity", + e)); + + a << *i.getEntity (); + } + + // state + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "state", + e)); + + a << i.getState (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const UserRolesType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (UserRolesType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // entry + // + for (UserRolesType::EntryConstIterator + b (i.getEntry ().begin ()), n (i.getEntry ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "entry", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *b; + } + } + + void + operator<< (::xercesc::DOMElement& e, const UserLanguagesType& i) + { + e << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char >& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const UserLanguagesType& i) + { + a << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char >& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const UserLanguagesType& i) + { + l << static_cast< const ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char >& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const EndpointType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (EndpointType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // referred + // + if (i.getReferred ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "referred", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getReferred (); + } + + // status + // + if (i.getStatus ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "status", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getStatus (); + } + + // joining-method + // + if (i.getJoiningMethod ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "joining-method", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getJoiningMethod (); + } + + // joining-info + // + if (i.getJoiningInfo ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "joining-info", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getJoiningInfo (); + } + + // disconnection-method + // + if (i.getDisconnectionMethod ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "disconnection-method", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisconnectionMethod (); + } + + // disconnection-info + // + if (i.getDisconnectionInfo ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "disconnection-info", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisconnectionInfo (); + } + + // media + // + for (EndpointType::MediaConstIterator + b (i.getMedia ().begin ()), n (i.getMedia ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "media", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *b; + } + + // call-info + // + if (i.getCallInfo ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "call-info", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getCallInfo (); + } + + // any + // + for (EndpointType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // entity + // + if (i.getEntity ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "entity", + e)); + + a << *i.getEntity (); + } + + // state + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "state", + e)); + + a << i.getState (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const EndpointStatusType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const EndpointStatusType& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const EndpointStatusType& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const JoiningType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const JoiningType& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const JoiningType& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const DisconnectionType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const DisconnectionType& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const DisconnectionType& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const ExecutionType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ExecutionType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // when + // + if (i.getWhen ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "when", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getWhen (); + } + + // reason + // + if (i.getReason ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "reason", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getReason (); + } + + // by + // + if (i.getBy ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "by", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getBy (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const CallType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (CallType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // sip + // + if (i.getSip ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "sip", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getSip (); + } + + // any + // + for (CallType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const SipDialogIdType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (SipDialogIdType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // call-id + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "call-id", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << i.getCallId (); + } + + // from-tag + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "from-tag", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << i.getFromTag (); + } + + // to-tag + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "to-tag", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << i.getToTag (); + } + + // any + // + for (SipDialogIdType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const MediaType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (MediaType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-text + // + if (i.getDisplayText ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-text", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getDisplayText (); + } + + // type + // + if (i.getType ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "type", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getType (); + } + + // label + // + if (i.getLabel ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "label", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getLabel (); + } + + // src-id + // + if (i.getSrcId ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "src-id", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getSrcId (); + } + + // status + // + if (i.getStatus ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "status", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *i.getStatus (); + } + + // any + // + for (MediaType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // id + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "id", + e)); + + a << i.getId (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const MediaStatusType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const MediaStatusType& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const MediaStatusType& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const SidebarsByValType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (SidebarsByValType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // entry + // + for (SidebarsByValType::EntryConstIterator + b (i.getEntry ().begin ()), n (i.getEntry ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "entry", + "urn:ietf:params:xml:ns:conference-info", + e)); + + s << *b; + } + + // state + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "state", + e)); + + a << i.getState (); + } + } + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + diff --git a/src/xml/conference-info.h b/src/xml/conference-info.h new file mode 100644 index 000000000..e9c315fd5 --- /dev/null +++ b/src/xml/conference-info.h @@ -0,0 +1,3923 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +#ifndef XML_CONFERENCE_INFO_H +#define XML_CONFERENCE_INFO_H + +#ifndef XSD_CXX11 +#define XSD_CXX11 +#endif + +#ifndef XSD_USE_CHAR +#define XSD_USE_CHAR +#endif + +#ifndef XSD_CXX_TREE_USE_CHAR +#define XSD_CXX_TREE_USE_CHAR +#endif + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#if (XSD_INT_VERSION != 4000000L) +#error XSD runtime version mismatch +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace XmlSchema + { + // anyType and anySimpleType. + // + typedef ::xsd::cxx::tree::type Type; + typedef ::xsd::cxx::tree::simple_type< char, Type > SimpleType; + typedef ::xsd::cxx::tree::type Container; + + // 8-bit + // + typedef signed char Byte; + typedef unsigned char UnsignedByte; + + // 16-bit + // + typedef short Short; + typedef unsigned short UnsignedShort; + + // 32-bit + // + typedef int Int; + typedef unsigned int UnsignedInt; + + // 64-bit + // + typedef long long Long; + typedef unsigned long long UnsignedLong; + + // Supposed to be arbitrary-length integral types. + // + typedef long long Integer; + typedef long long NonPositiveInteger; + typedef unsigned long long NonNegativeInteger; + typedef unsigned long long PositiveInteger; + typedef long long NegativeInteger; + + // Boolean. + // + typedef bool Boolean; + + // Floating-point types. + // + typedef float Float; + typedef double Double; + typedef double Decimal; + + // String types. + // + typedef ::xsd::cxx::tree::string< char, SimpleType > String; + typedef ::xsd::cxx::tree::normalized_string< char, String > NormalizedString; + typedef ::xsd::cxx::tree::token< char, NormalizedString > Token; + typedef ::xsd::cxx::tree::name< char, Token > Name; + typedef ::xsd::cxx::tree::nmtoken< char, Token > Nmtoken; + typedef ::xsd::cxx::tree::nmtokens< char, SimpleType, Nmtoken > Nmtokens; + typedef ::xsd::cxx::tree::ncname< char, Name > Ncname; + typedef ::xsd::cxx::tree::language< char, Token > Language; + + // ID/IDREF. + // + typedef ::xsd::cxx::tree::id< char, Ncname > Id; + typedef ::xsd::cxx::tree::idref< char, Ncname, Type > Idref; + typedef ::xsd::cxx::tree::idrefs< char, SimpleType, Idref > Idrefs; + + // URI. + // + typedef ::xsd::cxx::tree::uri< char, SimpleType > Uri; + + // Qualified name. + // + typedef ::xsd::cxx::tree::qname< char, SimpleType, Uri, Ncname > Qname; + + // Binary. + // + typedef ::xsd::cxx::tree::buffer< char > Buffer; + typedef ::xsd::cxx::tree::base64_binary< char, SimpleType > Base64Binary; + typedef ::xsd::cxx::tree::hex_binary< char, SimpleType > HexBinary; + + // Date/time. + // + typedef ::xsd::cxx::tree::time_zone TimeZone; + typedef ::xsd::cxx::tree::date< char, SimpleType > Date; + typedef ::xsd::cxx::tree::date_time< char, SimpleType > DateTime; + typedef ::xsd::cxx::tree::duration< char, SimpleType > Duration; + typedef ::xsd::cxx::tree::gday< char, SimpleType > Gday; + typedef ::xsd::cxx::tree::gmonth< char, SimpleType > Gmonth; + typedef ::xsd::cxx::tree::gmonth_day< char, SimpleType > GmonthDay; + typedef ::xsd::cxx::tree::gyear< char, SimpleType > Gyear; + typedef ::xsd::cxx::tree::gyear_month< char, SimpleType > GyearMonth; + typedef ::xsd::cxx::tree::time< char, SimpleType > Time; + + // Entity. + // + typedef ::xsd::cxx::tree::entity< char, Ncname > Entity; + typedef ::xsd::cxx::tree::entities< char, SimpleType, Entity > Entities; + + typedef ::xsd::cxx::tree::content_order ContentOrder; + // Namespace information and list stream. Used in + // serialization functions. + // + typedef ::xsd::cxx::xml::dom::namespace_info< char > NamespaceInfo; + typedef ::xsd::cxx::xml::dom::namespace_infomap< char > NamespaceInfomap; + typedef ::xsd::cxx::tree::list_stream< char > ListStream; + typedef ::xsd::cxx::tree::as_double< Double > AsDouble; + typedef ::xsd::cxx::tree::as_decimal< Decimal > AsDecimal; + typedef ::xsd::cxx::tree::facet Facet; + + // Flags and properties. + // + typedef ::xsd::cxx::tree::flags Flags; + typedef ::xsd::cxx::tree::properties< char > Properties; + + // Parsing/serialization diagnostics. + // + typedef ::xsd::cxx::tree::severity Severity; + typedef ::xsd::cxx::tree::error< char > Error; + typedef ::xsd::cxx::tree::diagnostics< char > Diagnostics; + + // Exceptions. + // + typedef ::xsd::cxx::tree::exception< char > Exception; + typedef ::xsd::cxx::tree::bounds< char > Bounds; + typedef ::xsd::cxx::tree::duplicate_id< char > DuplicateId; + typedef ::xsd::cxx::tree::parsing< char > Parsing; + typedef ::xsd::cxx::tree::expected_element< char > ExpectedElement; + typedef ::xsd::cxx::tree::unexpected_element< char > UnexpectedElement; + typedef ::xsd::cxx::tree::expected_attribute< char > ExpectedAttribute; + typedef ::xsd::cxx::tree::unexpected_enumerator< char > UnexpectedEnumerator; + typedef ::xsd::cxx::tree::expected_text_content< char > ExpectedTextContent; + typedef ::xsd::cxx::tree::no_prefix_mapping< char > NoPrefixMapping; + typedef ::xsd::cxx::tree::no_type_info< char > NoTypeInfo; + typedef ::xsd::cxx::tree::not_derived< char > NotDerived; + typedef ::xsd::cxx::tree::serialization< char > Serialization; + + // Error handler callback interface. + // + typedef ::xsd::cxx::xml::error_handler< char > ErrorHandler; + + // DOM interaction. + // + namespace dom + { + // Automatic pointer for DOMDocument. + // + using ::xsd::cxx::xml::dom::unique_ptr; + +#ifndef XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA +#define XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA + // DOM user data key for back pointers to tree nodes. + // + const XMLCh* const treeNodeKey = ::xsd::cxx::tree::user_data_keys::node; +#endif + } + } + } +} + +// Forward declarations. +// +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + class ConferenceType; + class StateType; + class ConferenceDescriptionType; + class HostType; + class ConferenceStateType; + class ConferenceMediaType; + class ConferenceMediumType; + class UrisType; + class UriType; + class KeywordsType; + class UsersType; + class UserType; + class UserRolesType; + class UserLanguagesType; + class EndpointType; + class EndpointStatusType; + class JoiningType; + class DisconnectionType; + class ExecutionType; + class CallType; + class SipDialogIdType; + class MediaType; + class MediaStatusType; + class SidebarsByValType; + } + } +} + + +#include // ::std::unique_ptr +#include // std::numeric_limits +#include // std::binary_search +#include // std::move + +#include + +#include +#include +#include +#include + +#include + +#include + +#include "xml.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + class ConferenceType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // conference-description + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceDescriptionType ConferenceDescriptionType; + typedef ::xsd::cxx::tree::optional< ConferenceDescriptionType > ConferenceDescriptionOptional; + typedef ::xsd::cxx::tree::traits< ConferenceDescriptionType, char > ConferenceDescriptionTraits; + + const ConferenceDescriptionOptional& + getConferenceDescription () const; + + ConferenceDescriptionOptional& + getConferenceDescription (); + + void + setConferenceDescription (const ConferenceDescriptionType& x); + + void + setConferenceDescription (const ConferenceDescriptionOptional& x); + + void + setConferenceDescription (::std::unique_ptr< ConferenceDescriptionType > p); + + // host-info + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::HostType HostInfoType; + typedef ::xsd::cxx::tree::optional< HostInfoType > HostInfoOptional; + typedef ::xsd::cxx::tree::traits< HostInfoType, char > HostInfoTraits; + + const HostInfoOptional& + getHostInfo () const; + + HostInfoOptional& + getHostInfo (); + + void + setHostInfo (const HostInfoType& x); + + void + setHostInfo (const HostInfoOptional& x); + + void + setHostInfo (::std::unique_ptr< HostInfoType > p); + + // conference-state + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceStateType ConferenceStateType; + typedef ::xsd::cxx::tree::optional< ConferenceStateType > ConferenceStateOptional; + typedef ::xsd::cxx::tree::traits< ConferenceStateType, char > ConferenceStateTraits; + + const ConferenceStateOptional& + getConferenceState () const; + + ConferenceStateOptional& + getConferenceState (); + + void + setConferenceState (const ConferenceStateType& x); + + void + setConferenceState (const ConferenceStateOptional& x); + + void + setConferenceState (::std::unique_ptr< ConferenceStateType > p); + + // users + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UsersType UsersType; + typedef ::xsd::cxx::tree::optional< UsersType > UsersOptional; + typedef ::xsd::cxx::tree::traits< UsersType, char > UsersTraits; + + const UsersOptional& + getUsers () const; + + UsersOptional& + getUsers (); + + void + setUsers (const UsersType& x); + + void + setUsers (const UsersOptional& x); + + void + setUsers (::std::unique_ptr< UsersType > p); + + // sidebars-by-ref + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UrisType SidebarsByRefType; + typedef ::xsd::cxx::tree::optional< SidebarsByRefType > SidebarsByRefOptional; + typedef ::xsd::cxx::tree::traits< SidebarsByRefType, char > SidebarsByRefTraits; + + const SidebarsByRefOptional& + getSidebarsByRef () const; + + SidebarsByRefOptional& + getSidebarsByRef (); + + void + setSidebarsByRef (const SidebarsByRefType& x); + + void + setSidebarsByRef (const SidebarsByRefOptional& x); + + void + setSidebarsByRef (::std::unique_ptr< SidebarsByRefType > p); + + // sidebars-by-val + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::SidebarsByValType SidebarsByValType; + typedef ::xsd::cxx::tree::optional< SidebarsByValType > SidebarsByValOptional; + typedef ::xsd::cxx::tree::traits< SidebarsByValType, char > SidebarsByValTraits; + + const SidebarsByValOptional& + getSidebarsByVal () const; + + SidebarsByValOptional& + getSidebarsByVal (); + + void + setSidebarsByVal (const SidebarsByValType& x); + + void + setSidebarsByVal (const SidebarsByValOptional& x); + + void + setSidebarsByVal (::std::unique_ptr< SidebarsByValType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // entity + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri EntityType; + typedef ::xsd::cxx::tree::traits< EntityType, char > EntityTraits; + + const EntityType& + getEntity () const; + + EntityType& + getEntity (); + + void + setEntity (const EntityType& x); + + void + setEntity (::std::unique_ptr< EntityType > p); + + ::std::unique_ptr< EntityType > + setDetachEntity (); + + // state + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::StateType StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + static const StateType& + getStateDefaultValue (); + + // version + // + typedef ::LinphonePrivate::Xsd::XmlSchema::UnsignedInt VersionType; + typedef ::xsd::cxx::tree::optional< VersionType > VersionOptional; + typedef ::xsd::cxx::tree::traits< VersionType, char > VersionTraits; + + const VersionOptional& + getVersion () const; + + VersionOptional& + getVersion (); + + void + setVersion (const VersionType& x); + + void + setVersion (const VersionOptional& x); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ConferenceType (const EntityType&); + + ConferenceType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ConferenceType (const ConferenceType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ConferenceType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ConferenceType& + operator= (const ConferenceType& x); + + virtual + ~ConferenceType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + ConferenceDescriptionOptional conference_description_; + HostInfoOptional host_info_; + ConferenceStateOptional conference_state_; + UsersOptional users_; + SidebarsByRefOptional sidebars_by_ref_; + SidebarsByValOptional sidebars_by_val_; + AnySequence any_; + ::xsd::cxx::tree::one< EntityType > entity_; + ::xsd::cxx::tree::one< StateType > state_; + static const StateType state_default_value_; + VersionOptional version_; + AnyAttributeSet any_attribute_; + }; + + class StateType: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + enum Value + { + full, + partial, + deleted + }; + + StateType (Value v); + + StateType (const char* v); + + StateType (const ::std::string& v); + + StateType (const ::LinphonePrivate::Xsd::XmlSchema::String& v); + + StateType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + StateType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + StateType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + StateType (const StateType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual StateType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + StateType& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_StateType_convert (); + } + + protected: + Value + _xsd_StateType_convert () const; + + public: + static const char* const _xsd_StateType_literals_[3]; + static const Value _xsd_StateType_indexes_[3]; + }; + + class ConferenceDescriptionType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // subject + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String SubjectType; + typedef ::xsd::cxx::tree::optional< SubjectType > SubjectOptional; + typedef ::xsd::cxx::tree::traits< SubjectType, char > SubjectTraits; + + const SubjectOptional& + getSubject () const; + + SubjectOptional& + getSubject (); + + void + setSubject (const SubjectType& x); + + void + setSubject (const SubjectOptional& x); + + void + setSubject (::std::unique_ptr< SubjectType > p); + + // free-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String FreeTextType; + typedef ::xsd::cxx::tree::optional< FreeTextType > FreeTextOptional; + typedef ::xsd::cxx::tree::traits< FreeTextType, char > FreeTextTraits; + + const FreeTextOptional& + getFreeText () const; + + FreeTextOptional& + getFreeText (); + + void + setFreeText (const FreeTextType& x); + + void + setFreeText (const FreeTextOptional& x); + + void + setFreeText (::std::unique_ptr< FreeTextType > p); + + // keywords + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::KeywordsType KeywordsType; + typedef ::xsd::cxx::tree::optional< KeywordsType > KeywordsOptional; + typedef ::xsd::cxx::tree::traits< KeywordsType, char > KeywordsTraits; + + const KeywordsOptional& + getKeywords () const; + + KeywordsOptional& + getKeywords (); + + void + setKeywords (const KeywordsType& x); + + void + setKeywords (const KeywordsOptional& x); + + void + setKeywords (::std::unique_ptr< KeywordsType > p); + + // conf-uris + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UrisType ConfUrisType; + typedef ::xsd::cxx::tree::optional< ConfUrisType > ConfUrisOptional; + typedef ::xsd::cxx::tree::traits< ConfUrisType, char > ConfUrisTraits; + + const ConfUrisOptional& + getConfUris () const; + + ConfUrisOptional& + getConfUris (); + + void + setConfUris (const ConfUrisType& x); + + void + setConfUris (const ConfUrisOptional& x); + + void + setConfUris (::std::unique_ptr< ConfUrisType > p); + + // service-uris + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UrisType ServiceUrisType; + typedef ::xsd::cxx::tree::optional< ServiceUrisType > ServiceUrisOptional; + typedef ::xsd::cxx::tree::traits< ServiceUrisType, char > ServiceUrisTraits; + + const ServiceUrisOptional& + getServiceUris () const; + + ServiceUrisOptional& + getServiceUris (); + + void + setServiceUris (const ServiceUrisType& x); + + void + setServiceUris (const ServiceUrisOptional& x); + + void + setServiceUris (::std::unique_ptr< ServiceUrisType > p); + + // maximum-user-count + // + typedef ::LinphonePrivate::Xsd::XmlSchema::UnsignedInt MaximumUserCountType; + typedef ::xsd::cxx::tree::optional< MaximumUserCountType > MaximumUserCountOptional; + typedef ::xsd::cxx::tree::traits< MaximumUserCountType, char > MaximumUserCountTraits; + + const MaximumUserCountOptional& + getMaximumUserCount () const; + + MaximumUserCountOptional& + getMaximumUserCount (); + + void + setMaximumUserCount (const MaximumUserCountType& x); + + void + setMaximumUserCount (const MaximumUserCountOptional& x); + + // available-media + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceMediaType AvailableMediaType; + typedef ::xsd::cxx::tree::optional< AvailableMediaType > AvailableMediaOptional; + typedef ::xsd::cxx::tree::traits< AvailableMediaType, char > AvailableMediaTraits; + + const AvailableMediaOptional& + getAvailableMedia () const; + + AvailableMediaOptional& + getAvailableMedia (); + + void + setAvailableMedia (const AvailableMediaType& x); + + void + setAvailableMedia (const AvailableMediaOptional& x); + + void + setAvailableMedia (::std::unique_ptr< AvailableMediaType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ConferenceDescriptionType (); + + ConferenceDescriptionType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ConferenceDescriptionType (const ConferenceDescriptionType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ConferenceDescriptionType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ConferenceDescriptionType& + operator= (const ConferenceDescriptionType& x); + + virtual + ~ConferenceDescriptionType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayTextOptional display_text_; + SubjectOptional subject_; + FreeTextOptional free_text_; + KeywordsOptional keywords_; + ConfUrisOptional conf_uris_; + ServiceUrisOptional service_uris_; + MaximumUserCountOptional maximum_user_count_; + AvailableMediaOptional available_media_; + AnySequence any_; + AnyAttributeSet any_attribute_; + }; + + class HostType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // web-page + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri WebPageType; + typedef ::xsd::cxx::tree::optional< WebPageType > WebPageOptional; + typedef ::xsd::cxx::tree::traits< WebPageType, char > WebPageTraits; + + const WebPageOptional& + getWebPage () const; + + WebPageOptional& + getWebPage (); + + void + setWebPage (const WebPageType& x); + + void + setWebPage (const WebPageOptional& x); + + void + setWebPage (::std::unique_ptr< WebPageType > p); + + // uris + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UrisType UrisType; + typedef ::xsd::cxx::tree::optional< UrisType > UrisOptional; + typedef ::xsd::cxx::tree::traits< UrisType, char > UrisTraits; + + const UrisOptional& + getUris () const; + + UrisOptional& + getUris (); + + void + setUris (const UrisType& x); + + void + setUris (const UrisOptional& x); + + void + setUris (::std::unique_ptr< UrisType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + HostType (); + + HostType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + HostType (const HostType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual HostType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + HostType& + operator= (const HostType& x); + + virtual + ~HostType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayTextOptional display_text_; + WebPageOptional web_page_; + UrisOptional uris_; + AnySequence any_; + AnyAttributeSet any_attribute_; + }; + + class ConferenceStateType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // user-count + // + typedef ::LinphonePrivate::Xsd::XmlSchema::UnsignedInt UserCountType; + typedef ::xsd::cxx::tree::optional< UserCountType > UserCountOptional; + typedef ::xsd::cxx::tree::traits< UserCountType, char > UserCountTraits; + + const UserCountOptional& + getUserCount () const; + + UserCountOptional& + getUserCount (); + + void + setUserCount (const UserCountType& x); + + void + setUserCount (const UserCountOptional& x); + + // active + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Boolean ActiveType; + typedef ::xsd::cxx::tree::optional< ActiveType > ActiveOptional; + typedef ::xsd::cxx::tree::traits< ActiveType, char > ActiveTraits; + + const ActiveOptional& + getActive () const; + + ActiveOptional& + getActive (); + + void + setActive (const ActiveType& x); + + void + setActive (const ActiveOptional& x); + + // locked + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Boolean LockedType; + typedef ::xsd::cxx::tree::optional< LockedType > LockedOptional; + typedef ::xsd::cxx::tree::traits< LockedType, char > LockedTraits; + + const LockedOptional& + getLocked () const; + + LockedOptional& + getLocked (); + + void + setLocked (const LockedType& x); + + void + setLocked (const LockedOptional& x); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ConferenceStateType (); + + ConferenceStateType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ConferenceStateType (const ConferenceStateType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ConferenceStateType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ConferenceStateType& + operator= (const ConferenceStateType& x); + + virtual + ~ConferenceStateType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + UserCountOptional user_count_; + ActiveOptional active_; + LockedOptional locked_; + AnySequence any_; + AnyAttributeSet any_attribute_; + }; + + class ConferenceMediaType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // entry + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceMediumType EntryType; + typedef ::xsd::cxx::tree::sequence< EntryType > EntrySequence; + typedef EntrySequence::iterator EntryIterator; + typedef EntrySequence::const_iterator EntryConstIterator; + typedef ::xsd::cxx::tree::traits< EntryType, char > EntryTraits; + + const EntrySequence& + getEntry () const; + + EntrySequence& + getEntry (); + + void + setEntry (const EntrySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ConferenceMediaType (); + + ConferenceMediaType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ConferenceMediaType (const ConferenceMediaType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ConferenceMediaType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ConferenceMediaType& + operator= (const ConferenceMediaType& x); + + virtual + ~ConferenceMediaType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + EntrySequence entry_; + AnyAttributeSet any_attribute_; + }; + + class ConferenceMediumType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // type + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String TypeType; + typedef ::xsd::cxx::tree::traits< TypeType, char > TypeTraits; + + const TypeType& + getType () const; + + TypeType& + getType (); + + void + setType (const TypeType& x); + + void + setType (::std::unique_ptr< TypeType > p); + + ::std::unique_ptr< TypeType > + setDetachType (); + + // status + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::MediaStatusType StatusType; + typedef ::xsd::cxx::tree::optional< StatusType > StatusOptional; + typedef ::xsd::cxx::tree::traits< StatusType, char > StatusTraits; + + const StatusOptional& + getStatus () const; + + StatusOptional& + getStatus (); + + void + setStatus (const StatusType& x); + + void + setStatus (const StatusOptional& x); + + void + setStatus (::std::unique_ptr< StatusType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // label + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String LabelType; + typedef ::xsd::cxx::tree::traits< LabelType, char > LabelTraits; + + const LabelType& + getLabel () const; + + LabelType& + getLabel (); + + void + setLabel (const LabelType& x); + + void + setLabel (::std::unique_ptr< LabelType > p); + + ::std::unique_ptr< LabelType > + setDetachLabel (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ConferenceMediumType (const TypeType&, + const LabelType&); + + ConferenceMediumType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ConferenceMediumType (const ConferenceMediumType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ConferenceMediumType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ConferenceMediumType& + operator= (const ConferenceMediumType& x); + + virtual + ~ConferenceMediumType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayTextOptional display_text_; + ::xsd::cxx::tree::one< TypeType > type_; + StatusOptional status_; + AnySequence any_; + ::xsd::cxx::tree::one< LabelType > label_; + AnyAttributeSet any_attribute_; + }; + + class UrisType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // entry + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UriType EntryType; + typedef ::xsd::cxx::tree::sequence< EntryType > EntrySequence; + typedef EntrySequence::iterator EntryIterator; + typedef EntrySequence::const_iterator EntryConstIterator; + typedef ::xsd::cxx::tree::traits< EntryType, char > EntryTraits; + + const EntrySequence& + getEntry () const; + + EntrySequence& + getEntry (); + + void + setEntry (const EntrySequence& s); + + // state + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::StateType StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + static const StateType& + getStateDefaultValue (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + UrisType (); + + UrisType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UrisType (const UrisType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual UrisType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + UrisType& + operator= (const UrisType& x); + + virtual + ~UrisType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + EntrySequence entry_; + ::xsd::cxx::tree::one< StateType > state_; + static const StateType state_default_value_; + AnyAttributeSet any_attribute_; + }; + + class UriType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // uri + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri UriType1; + typedef ::xsd::cxx::tree::traits< UriType1, char > UriTraits; + + const UriType1& + getUri () const; + + UriType1& + getUri (); + + void + setUri (const UriType1& x); + + void + setUri (::std::unique_ptr< UriType1 > p); + + ::std::unique_ptr< UriType1 > + setDetachUri (); + + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // purpose + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String PurposeType; + typedef ::xsd::cxx::tree::optional< PurposeType > PurposeOptional; + typedef ::xsd::cxx::tree::traits< PurposeType, char > PurposeTraits; + + const PurposeOptional& + getPurpose () const; + + PurposeOptional& + getPurpose (); + + void + setPurpose (const PurposeType& x); + + void + setPurpose (const PurposeOptional& x); + + void + setPurpose (::std::unique_ptr< PurposeType > p); + + // modified + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ExecutionType ModifiedType; + typedef ::xsd::cxx::tree::optional< ModifiedType > ModifiedOptional; + typedef ::xsd::cxx::tree::traits< ModifiedType, char > ModifiedTraits; + + const ModifiedOptional& + getModified () const; + + ModifiedOptional& + getModified (); + + void + setModified (const ModifiedType& x); + + void + setModified (const ModifiedOptional& x); + + void + setModified (::std::unique_ptr< ModifiedType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + UriType (const UriType1&); + + UriType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UriType (const UriType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual UriType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + UriType& + operator= (const UriType& x); + + virtual + ~UriType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + ::xsd::cxx::tree::one< UriType1 > uri_; + DisplayTextOptional display_text_; + PurposeOptional purpose_; + ModifiedOptional modified_; + AnySequence any_; + AnyAttributeSet any_attribute_; + }; + + class KeywordsType: public ::LinphonePrivate::Xsd::XmlSchema::SimpleType, + public ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > + { + public: + KeywordsType (); + + KeywordsType (size_type n, const ::LinphonePrivate::Xsd::XmlSchema::String& x); + + template < typename I > + KeywordsType (const I& begin, const I& end) + : ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::String, char > (begin, end, this) + { + } + + KeywordsType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + KeywordsType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + KeywordsType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + KeywordsType (const KeywordsType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual KeywordsType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~KeywordsType (); + }; + + class UsersType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // user + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UserType UserType; + typedef ::xsd::cxx::tree::sequence< UserType > UserSequence; + typedef UserSequence::iterator UserIterator; + typedef UserSequence::const_iterator UserConstIterator; + typedef ::xsd::cxx::tree::traits< UserType, char > UserTraits; + + const UserSequence& + getUser () const; + + UserSequence& + getUser (); + + void + setUser (const UserSequence& s); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // state + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::StateType StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + static const StateType& + getStateDefaultValue (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + UsersType (); + + UsersType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UsersType (const UsersType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual UsersType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + UsersType& + operator= (const UsersType& x); + + virtual + ~UsersType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + UserSequence user_; + AnySequence any_; + ::xsd::cxx::tree::one< StateType > state_; + static const StateType state_default_value_; + AnyAttributeSet any_attribute_; + }; + + class UserType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // associated-aors + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UrisType AssociatedAorsType; + typedef ::xsd::cxx::tree::optional< AssociatedAorsType > AssociatedAorsOptional; + typedef ::xsd::cxx::tree::traits< AssociatedAorsType, char > AssociatedAorsTraits; + + const AssociatedAorsOptional& + getAssociatedAors () const; + + AssociatedAorsOptional& + getAssociatedAors (); + + void + setAssociatedAors (const AssociatedAorsType& x); + + void + setAssociatedAors (const AssociatedAorsOptional& x); + + void + setAssociatedAors (::std::unique_ptr< AssociatedAorsType > p); + + // roles + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UserRolesType RolesType; + typedef ::xsd::cxx::tree::optional< RolesType > RolesOptional; + typedef ::xsd::cxx::tree::traits< RolesType, char > RolesTraits; + + const RolesOptional& + getRoles () const; + + RolesOptional& + getRoles (); + + void + setRoles (const RolesType& x); + + void + setRoles (const RolesOptional& x); + + void + setRoles (::std::unique_ptr< RolesType > p); + + // languages + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::UserLanguagesType LanguagesType; + typedef ::xsd::cxx::tree::optional< LanguagesType > LanguagesOptional; + typedef ::xsd::cxx::tree::traits< LanguagesType, char > LanguagesTraits; + + const LanguagesOptional& + getLanguages () const; + + LanguagesOptional& + getLanguages (); + + void + setLanguages (const LanguagesType& x); + + void + setLanguages (const LanguagesOptional& x); + + void + setLanguages (::std::unique_ptr< LanguagesType > p); + + // cascaded-focus + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri CascadedFocusType; + typedef ::xsd::cxx::tree::optional< CascadedFocusType > CascadedFocusOptional; + typedef ::xsd::cxx::tree::traits< CascadedFocusType, char > CascadedFocusTraits; + + const CascadedFocusOptional& + getCascadedFocus () const; + + CascadedFocusOptional& + getCascadedFocus (); + + void + setCascadedFocus (const CascadedFocusType& x); + + void + setCascadedFocus (const CascadedFocusOptional& x); + + void + setCascadedFocus (::std::unique_ptr< CascadedFocusType > p); + + // endpoint + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::EndpointType EndpointType; + typedef ::xsd::cxx::tree::sequence< EndpointType > EndpointSequence; + typedef EndpointSequence::iterator EndpointIterator; + typedef EndpointSequence::const_iterator EndpointConstIterator; + typedef ::xsd::cxx::tree::traits< EndpointType, char > EndpointTraits; + + const EndpointSequence& + getEndpoint () const; + + EndpointSequence& + getEndpoint (); + + void + setEndpoint (const EndpointSequence& s); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // entity + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri EntityType; + typedef ::xsd::cxx::tree::optional< EntityType > EntityOptional; + typedef ::xsd::cxx::tree::traits< EntityType, char > EntityTraits; + + const EntityOptional& + getEntity () const; + + EntityOptional& + getEntity (); + + void + setEntity (const EntityType& x); + + void + setEntity (const EntityOptional& x); + + void + setEntity (::std::unique_ptr< EntityType > p); + + // state + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::StateType StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + static const StateType& + getStateDefaultValue (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + UserType (); + + UserType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UserType (const UserType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual UserType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + UserType& + operator= (const UserType& x); + + virtual + ~UserType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayTextOptional display_text_; + AssociatedAorsOptional associated_aors_; + RolesOptional roles_; + LanguagesOptional languages_; + CascadedFocusOptional cascaded_focus_; + EndpointSequence endpoint_; + AnySequence any_; + EntityOptional entity_; + ::xsd::cxx::tree::one< StateType > state_; + static const StateType state_default_value_; + AnyAttributeSet any_attribute_; + }; + + class UserRolesType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // entry + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String EntryType; + typedef ::xsd::cxx::tree::sequence< EntryType > EntrySequence; + typedef EntrySequence::iterator EntryIterator; + typedef EntrySequence::const_iterator EntryConstIterator; + typedef ::xsd::cxx::tree::traits< EntryType, char > EntryTraits; + + const EntrySequence& + getEntry () const; + + EntrySequence& + getEntry (); + + void + setEntry (const EntrySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + UserRolesType (); + + UserRolesType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UserRolesType (const UserRolesType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual UserRolesType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + UserRolesType& + operator= (const UserRolesType& x); + + virtual + ~UserRolesType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + EntrySequence entry_; + AnyAttributeSet any_attribute_; + }; + + class UserLanguagesType: public ::LinphonePrivate::Xsd::XmlSchema::SimpleType, + public ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > + { + public: + UserLanguagesType (); + + UserLanguagesType (size_type n, const ::LinphonePrivate::Xsd::XmlSchema::Language& x); + + template < typename I > + UserLanguagesType (const I& begin, const I& end) + : ::xsd::cxx::tree::list< ::LinphonePrivate::Xsd::XmlSchema::Language, char > (begin, end, this) + { + } + + UserLanguagesType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UserLanguagesType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UserLanguagesType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + UserLanguagesType (const UserLanguagesType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual UserLanguagesType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~UserLanguagesType (); + }; + + class EndpointType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // referred + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ExecutionType ReferredType; + typedef ::xsd::cxx::tree::optional< ReferredType > ReferredOptional; + typedef ::xsd::cxx::tree::traits< ReferredType, char > ReferredTraits; + + const ReferredOptional& + getReferred () const; + + ReferredOptional& + getReferred (); + + void + setReferred (const ReferredType& x); + + void + setReferred (const ReferredOptional& x); + + void + setReferred (::std::unique_ptr< ReferredType > p); + + // status + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::EndpointStatusType StatusType; + typedef ::xsd::cxx::tree::optional< StatusType > StatusOptional; + typedef ::xsd::cxx::tree::traits< StatusType, char > StatusTraits; + + const StatusOptional& + getStatus () const; + + StatusOptional& + getStatus (); + + void + setStatus (const StatusType& x); + + void + setStatus (const StatusOptional& x); + + void + setStatus (::std::unique_ptr< StatusType > p); + + // joining-method + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::JoiningType JoiningMethodType; + typedef ::xsd::cxx::tree::optional< JoiningMethodType > JoiningMethodOptional; + typedef ::xsd::cxx::tree::traits< JoiningMethodType, char > JoiningMethodTraits; + + const JoiningMethodOptional& + getJoiningMethod () const; + + JoiningMethodOptional& + getJoiningMethod (); + + void + setJoiningMethod (const JoiningMethodType& x); + + void + setJoiningMethod (const JoiningMethodOptional& x); + + void + setJoiningMethod (::std::unique_ptr< JoiningMethodType > p); + + // joining-info + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ExecutionType JoiningInfoType; + typedef ::xsd::cxx::tree::optional< JoiningInfoType > JoiningInfoOptional; + typedef ::xsd::cxx::tree::traits< JoiningInfoType, char > JoiningInfoTraits; + + const JoiningInfoOptional& + getJoiningInfo () const; + + JoiningInfoOptional& + getJoiningInfo (); + + void + setJoiningInfo (const JoiningInfoType& x); + + void + setJoiningInfo (const JoiningInfoOptional& x); + + void + setJoiningInfo (::std::unique_ptr< JoiningInfoType > p); + + // disconnection-method + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::DisconnectionType DisconnectionMethodType; + typedef ::xsd::cxx::tree::optional< DisconnectionMethodType > DisconnectionMethodOptional; + typedef ::xsd::cxx::tree::traits< DisconnectionMethodType, char > DisconnectionMethodTraits; + + const DisconnectionMethodOptional& + getDisconnectionMethod () const; + + DisconnectionMethodOptional& + getDisconnectionMethod (); + + void + setDisconnectionMethod (const DisconnectionMethodType& x); + + void + setDisconnectionMethod (const DisconnectionMethodOptional& x); + + void + setDisconnectionMethod (::std::unique_ptr< DisconnectionMethodType > p); + + // disconnection-info + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ExecutionType DisconnectionInfoType; + typedef ::xsd::cxx::tree::optional< DisconnectionInfoType > DisconnectionInfoOptional; + typedef ::xsd::cxx::tree::traits< DisconnectionInfoType, char > DisconnectionInfoTraits; + + const DisconnectionInfoOptional& + getDisconnectionInfo () const; + + DisconnectionInfoOptional& + getDisconnectionInfo (); + + void + setDisconnectionInfo (const DisconnectionInfoType& x); + + void + setDisconnectionInfo (const DisconnectionInfoOptional& x); + + void + setDisconnectionInfo (::std::unique_ptr< DisconnectionInfoType > p); + + // media + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::MediaType MediaType; + typedef ::xsd::cxx::tree::sequence< MediaType > MediaSequence; + typedef MediaSequence::iterator MediaIterator; + typedef MediaSequence::const_iterator MediaConstIterator; + typedef ::xsd::cxx::tree::traits< MediaType, char > MediaTraits; + + const MediaSequence& + getMedia () const; + + MediaSequence& + getMedia (); + + void + setMedia (const MediaSequence& s); + + // call-info + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::CallType CallInfoType; + typedef ::xsd::cxx::tree::optional< CallInfoType > CallInfoOptional; + typedef ::xsd::cxx::tree::traits< CallInfoType, char > CallInfoTraits; + + const CallInfoOptional& + getCallInfo () const; + + CallInfoOptional& + getCallInfo (); + + void + setCallInfo (const CallInfoType& x); + + void + setCallInfo (const CallInfoOptional& x); + + void + setCallInfo (::std::unique_ptr< CallInfoType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // entity + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String EntityType; + typedef ::xsd::cxx::tree::optional< EntityType > EntityOptional; + typedef ::xsd::cxx::tree::traits< EntityType, char > EntityTraits; + + const EntityOptional& + getEntity () const; + + EntityOptional& + getEntity (); + + void + setEntity (const EntityType& x); + + void + setEntity (const EntityOptional& x); + + void + setEntity (::std::unique_ptr< EntityType > p); + + // state + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::StateType StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + static const StateType& + getStateDefaultValue (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + EndpointType (); + + EndpointType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + EndpointType (const EndpointType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual EndpointType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + EndpointType& + operator= (const EndpointType& x); + + virtual + ~EndpointType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayTextOptional display_text_; + ReferredOptional referred_; + StatusOptional status_; + JoiningMethodOptional joining_method_; + JoiningInfoOptional joining_info_; + DisconnectionMethodOptional disconnection_method_; + DisconnectionInfoOptional disconnection_info_; + MediaSequence media_; + CallInfoOptional call_info_; + AnySequence any_; + EntityOptional entity_; + ::xsd::cxx::tree::one< StateType > state_; + static const StateType state_default_value_; + AnyAttributeSet any_attribute_; + }; + + class EndpointStatusType: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + enum Value + { + pending, + dialing_out, + dialing_in, + alerting, + on_hold, + connected, + muted_via_focus, + disconnecting, + disconnected + }; + + EndpointStatusType (Value v); + + EndpointStatusType (const char* v); + + EndpointStatusType (const ::std::string& v); + + EndpointStatusType (const ::LinphonePrivate::Xsd::XmlSchema::String& v); + + EndpointStatusType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + EndpointStatusType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + EndpointStatusType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + EndpointStatusType (const EndpointStatusType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual EndpointStatusType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + EndpointStatusType& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_EndpointStatusType_convert (); + } + + protected: + Value + _xsd_EndpointStatusType_convert () const; + + public: + static const char* const _xsd_EndpointStatusType_literals_[9]; + static const Value _xsd_EndpointStatusType_indexes_[9]; + }; + + class JoiningType: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + enum Value + { + dialed_in, + dialed_out, + focus_owner + }; + + JoiningType (Value v); + + JoiningType (const char* v); + + JoiningType (const ::std::string& v); + + JoiningType (const ::LinphonePrivate::Xsd::XmlSchema::String& v); + + JoiningType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + JoiningType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + JoiningType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + JoiningType (const JoiningType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual JoiningType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + JoiningType& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_JoiningType_convert (); + } + + protected: + Value + _xsd_JoiningType_convert () const; + + public: + static const char* const _xsd_JoiningType_literals_[3]; + static const Value _xsd_JoiningType_indexes_[3]; + }; + + class DisconnectionType: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + enum Value + { + departed, + booted, + failed, + busy + }; + + DisconnectionType (Value v); + + DisconnectionType (const char* v); + + DisconnectionType (const ::std::string& v); + + DisconnectionType (const ::LinphonePrivate::Xsd::XmlSchema::String& v); + + DisconnectionType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + DisconnectionType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + DisconnectionType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + DisconnectionType (const DisconnectionType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual DisconnectionType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + DisconnectionType& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_DisconnectionType_convert (); + } + + protected: + Value + _xsd_DisconnectionType_convert () const; + + public: + static const char* const _xsd_DisconnectionType_literals_[4]; + static const Value _xsd_DisconnectionType_indexes_[4]; + }; + + class ExecutionType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // when + // + typedef ::LinphonePrivate::Xsd::XmlSchema::DateTime WhenType; + typedef ::xsd::cxx::tree::optional< WhenType > WhenOptional; + typedef ::xsd::cxx::tree::traits< WhenType, char > WhenTraits; + + const WhenOptional& + getWhen () const; + + WhenOptional& + getWhen (); + + void + setWhen (const WhenType& x); + + void + setWhen (const WhenOptional& x); + + void + setWhen (::std::unique_ptr< WhenType > p); + + // reason + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String ReasonType; + typedef ::xsd::cxx::tree::optional< ReasonType > ReasonOptional; + typedef ::xsd::cxx::tree::traits< ReasonType, char > ReasonTraits; + + const ReasonOptional& + getReason () const; + + ReasonOptional& + getReason (); + + void + setReason (const ReasonType& x); + + void + setReason (const ReasonOptional& x); + + void + setReason (::std::unique_ptr< ReasonType > p); + + // by + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri ByType; + typedef ::xsd::cxx::tree::optional< ByType > ByOptional; + typedef ::xsd::cxx::tree::traits< ByType, char > ByTraits; + + const ByOptional& + getBy () const; + + ByOptional& + getBy (); + + void + setBy (const ByType& x); + + void + setBy (const ByOptional& x); + + void + setBy (::std::unique_ptr< ByType > p); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ExecutionType (); + + ExecutionType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ExecutionType (const ExecutionType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ExecutionType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ExecutionType& + operator= (const ExecutionType& x); + + virtual + ~ExecutionType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + WhenOptional when_; + ReasonOptional reason_; + ByOptional by_; + AnyAttributeSet any_attribute_; + }; + + class CallType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // sip + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::SipDialogIdType SipType; + typedef ::xsd::cxx::tree::optional< SipType > SipOptional; + typedef ::xsd::cxx::tree::traits< SipType, char > SipTraits; + + const SipOptional& + getSip () const; + + SipOptional& + getSip (); + + void + setSip (const SipType& x); + + void + setSip (const SipOptional& x); + + void + setSip (::std::unique_ptr< SipType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + CallType (); + + CallType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + CallType (const CallType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual CallType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + CallType& + operator= (const CallType& x); + + virtual + ~CallType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + SipOptional sip_; + AnySequence any_; + AnyAttributeSet any_attribute_; + }; + + class SipDialogIdType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // call-id + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String CallIdType; + typedef ::xsd::cxx::tree::traits< CallIdType, char > CallIdTraits; + + const CallIdType& + getCallId () const; + + CallIdType& + getCallId (); + + void + setCallId (const CallIdType& x); + + void + setCallId (::std::unique_ptr< CallIdType > p); + + ::std::unique_ptr< CallIdType > + setDetachCall_id (); + + // from-tag + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String FromTagType; + typedef ::xsd::cxx::tree::traits< FromTagType, char > FromTagTraits; + + const FromTagType& + getFromTag () const; + + FromTagType& + getFromTag (); + + void + setFromTag (const FromTagType& x); + + void + setFromTag (::std::unique_ptr< FromTagType > p); + + ::std::unique_ptr< FromTagType > + setDetachFrom_tag (); + + // to-tag + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String ToTagType; + typedef ::xsd::cxx::tree::traits< ToTagType, char > ToTagTraits; + + const ToTagType& + getToTag () const; + + ToTagType& + getToTag (); + + void + setToTag (const ToTagType& x); + + void + setToTag (::std::unique_ptr< ToTagType > p); + + ::std::unique_ptr< ToTagType > + setDetachTo_tag (); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + SipDialogIdType (const CallIdType&, + const FromTagType&, + const ToTagType&); + + SipDialogIdType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + SipDialogIdType (const SipDialogIdType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual SipDialogIdType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + SipDialogIdType& + operator= (const SipDialogIdType& x); + + virtual + ~SipDialogIdType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayTextOptional display_text_; + ::xsd::cxx::tree::one< CallIdType > call_id_; + ::xsd::cxx::tree::one< FromTagType > from_tag_; + ::xsd::cxx::tree::one< ToTagType > to_tag_; + AnySequence any_; + AnyAttributeSet any_attribute_; + }; + + class MediaType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-text + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DisplayTextType; + typedef ::xsd::cxx::tree::optional< DisplayTextType > DisplayTextOptional; + typedef ::xsd::cxx::tree::traits< DisplayTextType, char > DisplayTextTraits; + + const DisplayTextOptional& + getDisplayText () const; + + DisplayTextOptional& + getDisplayText (); + + void + setDisplayText (const DisplayTextType& x); + + void + setDisplayText (const DisplayTextOptional& x); + + void + setDisplayText (::std::unique_ptr< DisplayTextType > p); + + // type + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String TypeType; + typedef ::xsd::cxx::tree::optional< TypeType > TypeOptional; + typedef ::xsd::cxx::tree::traits< TypeType, char > TypeTraits; + + const TypeOptional& + getType () const; + + TypeOptional& + getType (); + + void + setType (const TypeType& x); + + void + setType (const TypeOptional& x); + + void + setType (::std::unique_ptr< TypeType > p); + + // label + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String LabelType; + typedef ::xsd::cxx::tree::optional< LabelType > LabelOptional; + typedef ::xsd::cxx::tree::traits< LabelType, char > LabelTraits; + + const LabelOptional& + getLabel () const; + + LabelOptional& + getLabel (); + + void + setLabel (const LabelType& x); + + void + setLabel (const LabelOptional& x); + + void + setLabel (::std::unique_ptr< LabelType > p); + + // src-id + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String SrcIdType; + typedef ::xsd::cxx::tree::optional< SrcIdType > SrcIdOptional; + typedef ::xsd::cxx::tree::traits< SrcIdType, char > SrcIdTraits; + + const SrcIdOptional& + getSrcId () const; + + SrcIdOptional& + getSrcId (); + + void + setSrcId (const SrcIdType& x); + + void + setSrcId (const SrcIdOptional& x); + + void + setSrcId (::std::unique_ptr< SrcIdType > p); + + // status + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::MediaStatusType StatusType; + typedef ::xsd::cxx::tree::optional< StatusType > StatusOptional; + typedef ::xsd::cxx::tree::traits< StatusType, char > StatusTraits; + + const StatusOptional& + getStatus () const; + + StatusOptional& + getStatus (); + + void + setStatus (const StatusType& x); + + void + setStatus (const StatusOptional& x); + + void + setStatus (::std::unique_ptr< StatusType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // id + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String IdType; + typedef ::xsd::cxx::tree::traits< IdType, char > IdTraits; + + const IdType& + getId () const; + + IdType& + getId (); + + void + setId (const IdType& x); + + void + setId (::std::unique_ptr< IdType > p); + + ::std::unique_ptr< IdType > + setDetachId (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + MediaType (const IdType&); + + MediaType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + MediaType (const MediaType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual MediaType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + MediaType& + operator= (const MediaType& x); + + virtual + ~MediaType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayTextOptional display_text_; + TypeOptional type_; + LabelOptional label_; + SrcIdOptional src_id_; + StatusOptional status_; + AnySequence any_; + ::xsd::cxx::tree::one< IdType > id_; + AnyAttributeSet any_attribute_; + }; + + class MediaStatusType: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + enum Value + { + recvonly, + sendonly, + sendrecv, + inactive + }; + + MediaStatusType (Value v); + + MediaStatusType (const char* v); + + MediaStatusType (const ::std::string& v); + + MediaStatusType (const ::LinphonePrivate::Xsd::XmlSchema::String& v); + + MediaStatusType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + MediaStatusType (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + MediaStatusType (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + MediaStatusType (const MediaStatusType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual MediaStatusType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + MediaStatusType& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_MediaStatusType_convert (); + } + + protected: + Value + _xsd_MediaStatusType_convert () const; + + public: + static const char* const _xsd_MediaStatusType_literals_[4]; + static const Value _xsd_MediaStatusType_indexes_[4]; + }; + + class SidebarsByValType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // entry + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType EntryType; + typedef ::xsd::cxx::tree::sequence< EntryType > EntrySequence; + typedef EntrySequence::iterator EntryIterator; + typedef EntrySequence::const_iterator EntryConstIterator; + typedef ::xsd::cxx::tree::traits< EntryType, char > EntryTraits; + + const EntrySequence& + getEntry () const; + + EntrySequence& + getEntry (); + + void + setEntry (const EntrySequence& s); + + // state + // + typedef ::LinphonePrivate::Xsd::ConferenceInfo::StateType StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + static const StateType& + getStateDefaultValue (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + SidebarsByValType (); + + SidebarsByValType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + SidebarsByValType (const SidebarsByValType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual SidebarsByValType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + SidebarsByValType& + operator= (const SidebarsByValType& x); + + virtual + ~SidebarsByValType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + EntrySequence entry_; + ::xsd::cxx::tree::one< StateType > state_; + static const StateType state_default_value_; + AnyAttributeSet any_attribute_; + }; + } + } +} + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + ::std::ostream& + operator<< (::std::ostream&, const ConferenceType&); + + ::std::ostream& + operator<< (::std::ostream&, StateType::Value); + + ::std::ostream& + operator<< (::std::ostream&, const StateType&); + + ::std::ostream& + operator<< (::std::ostream&, const ConferenceDescriptionType&); + + ::std::ostream& + operator<< (::std::ostream&, const HostType&); + + ::std::ostream& + operator<< (::std::ostream&, const ConferenceStateType&); + + ::std::ostream& + operator<< (::std::ostream&, const ConferenceMediaType&); + + ::std::ostream& + operator<< (::std::ostream&, const ConferenceMediumType&); + + ::std::ostream& + operator<< (::std::ostream&, const UrisType&); + + ::std::ostream& + operator<< (::std::ostream&, const UriType&); + + ::std::ostream& + operator<< (::std::ostream&, const KeywordsType&); + + ::std::ostream& + operator<< (::std::ostream&, const UsersType&); + + ::std::ostream& + operator<< (::std::ostream&, const UserType&); + + ::std::ostream& + operator<< (::std::ostream&, const UserRolesType&); + + ::std::ostream& + operator<< (::std::ostream&, const UserLanguagesType&); + + ::std::ostream& + operator<< (::std::ostream&, const EndpointType&); + + ::std::ostream& + operator<< (::std::ostream&, EndpointStatusType::Value); + + ::std::ostream& + operator<< (::std::ostream&, const EndpointStatusType&); + + ::std::ostream& + operator<< (::std::ostream&, JoiningType::Value); + + ::std::ostream& + operator<< (::std::ostream&, const JoiningType&); + + ::std::ostream& + operator<< (::std::ostream&, DisconnectionType::Value); + + ::std::ostream& + operator<< (::std::ostream&, const DisconnectionType&); + + ::std::ostream& + operator<< (::std::ostream&, const ExecutionType&); + + ::std::ostream& + operator<< (::std::ostream&, const CallType&); + + ::std::ostream& + operator<< (::std::ostream&, const SipDialogIdType&); + + ::std::ostream& + operator<< (::std::ostream&, const MediaType&); + + ::std::ostream& + operator<< (::std::ostream&, MediaStatusType::Value); + + ::std::ostream& + operator<< (::std::ostream&, const MediaStatusType&); + + ::std::ostream& + operator<< (::std::ostream&, const SidebarsByValType&); + } + } +} + +#include + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + // Parse a URI or a local file. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::std::string& uri, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse std::istream. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::std::istream& is, + const ::std::string& id, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::InputSource. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::xercesc::InputSource& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::DOMDocument. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (const ::xercesc::DOMDocument& d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType > + parseConferenceInfo (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + } + } +} + +#include + +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ConferenceInfo + { + // Serialize to std::ostream. + // + + void + serializeConferenceInfo (::std::ostream& os, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeConferenceInfo (::std::ostream& os, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeConferenceInfo (::std::ostream& os, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to xercesc::XMLFormatTarget. + // + + void + serializeConferenceInfo (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeConferenceInfo (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeConferenceInfo (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to an existing xercesc::DOMDocument. + // + + void + serializeConferenceInfo (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to a new xercesc::DOMDocument. + // + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeConferenceInfo (const ::LinphonePrivate::Xsd::ConferenceInfo::ConferenceType& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + operator<< (::xercesc::DOMElement&, const ConferenceType&); + + void + operator<< (::xercesc::DOMElement&, const StateType&); + + void + operator<< (::xercesc::DOMAttr&, const StateType&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const StateType&); + + void + operator<< (::xercesc::DOMElement&, const ConferenceDescriptionType&); + + void + operator<< (::xercesc::DOMElement&, const HostType&); + + void + operator<< (::xercesc::DOMElement&, const ConferenceStateType&); + + void + operator<< (::xercesc::DOMElement&, const ConferenceMediaType&); + + void + operator<< (::xercesc::DOMElement&, const ConferenceMediumType&); + + void + operator<< (::xercesc::DOMElement&, const UrisType&); + + void + operator<< (::xercesc::DOMElement&, const UriType&); + + void + operator<< (::xercesc::DOMElement&, const KeywordsType&); + + void + operator<< (::xercesc::DOMAttr&, const KeywordsType&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const KeywordsType&); + + void + operator<< (::xercesc::DOMElement&, const UsersType&); + + void + operator<< (::xercesc::DOMElement&, const UserType&); + + void + operator<< (::xercesc::DOMElement&, const UserRolesType&); + + void + operator<< (::xercesc::DOMElement&, const UserLanguagesType&); + + void + operator<< (::xercesc::DOMAttr&, const UserLanguagesType&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const UserLanguagesType&); + + void + operator<< (::xercesc::DOMElement&, const EndpointType&); + + void + operator<< (::xercesc::DOMElement&, const EndpointStatusType&); + + void + operator<< (::xercesc::DOMAttr&, const EndpointStatusType&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const EndpointStatusType&); + + void + operator<< (::xercesc::DOMElement&, const JoiningType&); + + void + operator<< (::xercesc::DOMAttr&, const JoiningType&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const JoiningType&); + + void + operator<< (::xercesc::DOMElement&, const DisconnectionType&); + + void + operator<< (::xercesc::DOMAttr&, const DisconnectionType&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const DisconnectionType&); + + void + operator<< (::xercesc::DOMElement&, const ExecutionType&); + + void + operator<< (::xercesc::DOMElement&, const CallType&); + + void + operator<< (::xercesc::DOMElement&, const SipDialogIdType&); + + void + operator<< (::xercesc::DOMElement&, const MediaType&); + + void + operator<< (::xercesc::DOMElement&, const MediaStatusType&); + + void + operator<< (::xercesc::DOMAttr&, const MediaStatusType&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const MediaStatusType&); + + void + operator<< (::xercesc::DOMElement&, const SidebarsByValType&); + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + +#endif // XML_CONFERENCE_INFO_H diff --git a/src/xml/conference-info.xsd b/src/xml/conference-info.xsd new file mode 100644 index 000000000..8f7b332ac --- /dev/null +++ b/src/xml/conference-info.xsd @@ -0,0 +1,387 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/xml/epilogue.txt b/src/xml/epilogue.txt new file mode 100644 index 000000000..faa93c2e5 --- /dev/null +++ b/src/xml/epilogue.txt @@ -0,0 +1,9 @@ +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif diff --git a/src/xml/generate.py b/src/xml/generate.py new file mode 100755 index 000000000..e1214dbf9 --- /dev/null +++ b/src/xml/generate.py @@ -0,0 +1,116 @@ +#!/usr/bin/python + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +from distutils.spawn import find_executable +import os +import sys +from subprocess import Popen, PIPE + + +def find_xsdcxx(): + xsdcxx = find_executable("xsdcxx") + if xsdcxx is not None: + return xsdcxx + xsdcxx = find_executable("xsd") + return xsdcxx + +def generate(name): + xsdcxx = find_xsdcxx() + if xsdcxx is None: + print("Cannot find xsdcxx (or xsd) program in the PATH") + return -1 + print("Using " + xsdcxx) + cwd = os.getcwd() + script_dir = os.path.dirname(os.path.realpath(__file__)) + source_file = name + ".xsd" + print("Generating code from " + source_file) + source_file = os.path.join("xml", source_file) + prologue_file = os.path.join("xml", "prologue.txt") + epilogue_file = os.path.join("xml", "epilogue.txt") + work_dir = os.path.join(script_dir, "..") + os.chdir(work_dir) + p = Popen([xsdcxx, + "cxx-tree", + "--generate-wildcard", + "--generate-serialization", + "--generate-ostream", + "--generate-detach", + "--generate-polymorphic", + "--std", "c++11", + "--type-naming", "java", + "--function-naming", "java", + "--hxx-suffix", ".h", + "--ixx-suffix", ".h", + "--cxx-suffix", ".cpp", + "--location-regex", "%http://.+/(.+)%$1%", + "--output-dir", "xml", + "--show-sloc", + "--prologue-file", prologue_file, + "--epilogue-file", epilogue_file, + "--root-element-first", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-([^,-]+)-?([^,-]*)%\\u$1\\u$2\\u$3\\u$4%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-?([^,-]*)%\\u$1\\u$2\\u$3%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-?([^,-]*)%\\u$1\\u$2%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-([^,-]+)-?([^,-]*),([^,]+)%\\u$1\\u$2\\u$3\\u$4\\l\\u$5%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-?([^,-]*),([^,]+)%\\u$1\\u$2\\u$3\\l\\u$4%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-?([^,-]*),([^,]+)%\\u$1\\u$2\\l\\u$3%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-([^,-]+)-?([^,-]*),([^,]+),([^,]+)%\\u$1\\u$2\\u$3\\u$4\\l\\u$5\\u$6%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-?([^,-]*),([^,]+),([^,]+)%\\u$1\\u$2\\u$3\\l\\u$4\\u$5%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-?([^,-]*),([^,]+),([^,]+)%\\u$1\\u$2\\l\\u$3\\u$4%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-([^,-]+)-?([^,-]*),([^,]+),([^,]+),([^,]+)%\\u$1\\u$2\\u$3\\u$4\\l\\u$5\\u$6\\u$7%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-([^,-]+)-?([^,-]*),([^,]+),([^,]+),([^,]+)%\\u$1\\u$2\\u$3\\l\\u$4\\u$5\\u$6%", + "--type-regex", "%(?:[^ ]* )?([^,-]+)-?([^,-]*),([^,]+),([^,]+),([^,]+)%\\u$1\\u$2\\l\\u$3\\u$4\\u$5%", + "--accessor-regex", "%([^,-]+)-([^,-]+)-?([^,-]*)%get\\u$1\\u$2\\u$3%", + "--accessor-regex", "%([^,-]+)-?([^,-]*)%get\\u$1\\u$2%", + "--accessor-regex", "%([^,-]+)-([^,-]+)-?([^,-]*),([^,]+)%get\\u$1\\u$2\\u$3\\l\\u$4%", + "--accessor-regex", "%([^,-]+)-?([^,-]*),([^,]+)%get\\u$1\\u$2\\l\\u$3%", + "--accessor-regex", "%([^,-]+)-([^,-]+)-?([^,-]*),([^,]+),([^,]+)%get\\u$1\\u$2\\u$3\\l\\u$4\\u$5%", + "--accessor-regex", "%([^,-]+)-?([^,-]*),([^,]+),([^,]+)%get\\u$1\\u$2\\l\\u$3\\u$4%", + "--modifier-regex", "%([^,-]+)-([^,-]+)-?([^,-]*)%set\\u$1\\u$2\\u$3%", + "--modifier-regex", "%([^,-]+)-?([^,-]*)%set\\u$1\\u$2%", + "--modifier-regex", "%([^,-]+)-([^,-]+)-?([^,-]*),([^,]+)%set\\u$1\\u$2\\u$3\\l\\u$4%", + "--modifier-regex", "%([^,-]+)-?([^,-]*),([^,]+)%set\\u$1\\u$2\\l\\u$3%", + "--modifier-regex", "%([^,-]+)-([^,-]+)-?([^,-]*),([^,]+),([^,]+)%set\\u$1\\u$2\\u$3\\l\\u$4\\u$5%", + "--modifier-regex", "%([^,-]+)-?([^,-]*),([^,]+),([^,]+)%set\\u$1\\u$2\\l\\u$3\\u$4%", + "--parser-regex", "%([^-]+)-?([^-]*)%parse\\u$1\\u$2%", + "--serializer-regex", "%([^-]+)-?([^-]*)%serialize\\u$1\\u$2%", + "--namespace-map", "http://www.w3.org/2001/XMLSchema=LinphonePrivate::Xsd::XmlSchema", + "--namespace-map", "urn:ietf:params:xml:ns:conference-info=LinphonePrivate::Xsd::ConferenceInfo", + "--namespace-map", "urn:ietf:params:xml:ns:imdn=LinphonePrivate::Xsd::Imdn", + "--namespace-map", "urn:ietf:params:xml:ns:im-iscomposing=LinphonePrivate::Xsd::IsComposing", + "--namespace-map", "http://www.linphone.org/xsds/imdn.xsd=LinphonePrivate::Xsd::LinphoneImdn", + "--namespace-map", "urn:ietf:params:xml:ns:resource-lists=LinphonePrivate::Xsd::ResourceLists", + "--namespace-map", "urn:ietf:params:xml:ns:rlmi=LinphonePrivate::Xsd::Rlmi", + source_file + ], shell=False) + p.communicate() + os.chdir(cwd) + return 0 + +def main(argv = None): + generate("xml") + generate("conference-info") + generate("imdn") + generate("is-composing") + generate("linphone-imdn") + generate("resource-lists") + generate("rlmi") + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/xml/imdn.cpp b/src/xml/imdn.cpp new file mode 100644 index 000000000..653fa2604 --- /dev/null +++ b/src/xml/imdn.cpp @@ -0,0 +1,3449 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#include "imdn.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + // Imdn + // + + const Imdn::MessageIdType& Imdn:: + getMessageId () const + { + return this->message_id_.get (); + } + + Imdn::MessageIdType& Imdn:: + getMessageId () + { + return this->message_id_.get (); + } + + void Imdn:: + setMessageId (const MessageIdType& x) + { + this->message_id_.set (x); + } + + void Imdn:: + setMessageId (::std::unique_ptr< MessageIdType > x) + { + this->message_id_.set (std::move (x)); + } + + ::std::unique_ptr< Imdn::MessageIdType > Imdn:: + setDetachMessage_id () + { + return this->message_id_.detach (); + } + + const Imdn::DatetimeType& Imdn:: + getDatetime () const + { + return this->datetime_.get (); + } + + Imdn::DatetimeType& Imdn:: + getDatetime () + { + return this->datetime_.get (); + } + + void Imdn:: + setDatetime (const DatetimeType& x) + { + this->datetime_.set (x); + } + + void Imdn:: + setDatetime (::std::unique_ptr< DatetimeType > x) + { + this->datetime_.set (std::move (x)); + } + + ::std::unique_ptr< Imdn::DatetimeType > Imdn:: + setDetachDatetime () + { + return this->datetime_.detach (); + } + + const Imdn::RecipientUriOptional& Imdn:: + getRecipientUri () const + { + return this->recipient_uri_; + } + + Imdn::RecipientUriOptional& Imdn:: + getRecipientUri () + { + return this->recipient_uri_; + } + + void Imdn:: + setRecipientUri (const RecipientUriType& x) + { + this->recipient_uri_.set (x); + } + + void Imdn:: + setRecipientUri (const RecipientUriOptional& x) + { + this->recipient_uri_ = x; + } + + void Imdn:: + setRecipientUri (::std::unique_ptr< RecipientUriType > x) + { + this->recipient_uri_.set (std::move (x)); + } + + const Imdn::OriginalRecipientUriOptional& Imdn:: + getOriginalRecipientUri () const + { + return this->original_recipient_uri_; + } + + Imdn::OriginalRecipientUriOptional& Imdn:: + getOriginalRecipientUri () + { + return this->original_recipient_uri_; + } + + void Imdn:: + setOriginalRecipientUri (const OriginalRecipientUriType& x) + { + this->original_recipient_uri_.set (x); + } + + void Imdn:: + setOriginalRecipientUri (const OriginalRecipientUriOptional& x) + { + this->original_recipient_uri_ = x; + } + + void Imdn:: + setOriginalRecipientUri (::std::unique_ptr< OriginalRecipientUriType > x) + { + this->original_recipient_uri_.set (std::move (x)); + } + + const Imdn::SubjectOptional& Imdn:: + getSubject () const + { + return this->subject_; + } + + Imdn::SubjectOptional& Imdn:: + getSubject () + { + return this->subject_; + } + + void Imdn:: + setSubject (const SubjectType& x) + { + this->subject_.set (x); + } + + void Imdn:: + setSubject (const SubjectOptional& x) + { + this->subject_ = x; + } + + void Imdn:: + setSubject (::std::unique_ptr< SubjectType > x) + { + this->subject_.set (std::move (x)); + } + + const Imdn::DeliveryNotificationOptional& Imdn:: + getDeliveryNotification () const + { + return this->delivery_notification_; + } + + Imdn::DeliveryNotificationOptional& Imdn:: + getDeliveryNotification () + { + return this->delivery_notification_; + } + + void Imdn:: + setDeliveryNotification (const DeliveryNotificationType& x) + { + this->delivery_notification_.set (x); + } + + void Imdn:: + setDeliveryNotification (const DeliveryNotificationOptional& x) + { + this->delivery_notification_ = x; + } + + void Imdn:: + setDeliveryNotification (::std::unique_ptr< DeliveryNotificationType > x) + { + this->delivery_notification_.set (std::move (x)); + } + + const Imdn::DisplayNotificationOptional& Imdn:: + getDisplayNotification () const + { + return this->display_notification_; + } + + Imdn::DisplayNotificationOptional& Imdn:: + getDisplayNotification () + { + return this->display_notification_; + } + + void Imdn:: + setDisplayNotification (const DisplayNotificationType& x) + { + this->display_notification_.set (x); + } + + void Imdn:: + setDisplayNotification (const DisplayNotificationOptional& x) + { + this->display_notification_ = x; + } + + void Imdn:: + setDisplayNotification (::std::unique_ptr< DisplayNotificationType > x) + { + this->display_notification_.set (std::move (x)); + } + + const Imdn::ProcessingNotificationOptional& Imdn:: + getProcessingNotification () const + { + return this->processing_notification_; + } + + Imdn::ProcessingNotificationOptional& Imdn:: + getProcessingNotification () + { + return this->processing_notification_; + } + + void Imdn:: + setProcessingNotification (const ProcessingNotificationType& x) + { + this->processing_notification_.set (x); + } + + void Imdn:: + setProcessingNotification (const ProcessingNotificationOptional& x) + { + this->processing_notification_ = x; + } + + void Imdn:: + setProcessingNotification (::std::unique_ptr< ProcessingNotificationType > x) + { + this->processing_notification_.set (std::move (x)); + } + + const Imdn::AnySequence& Imdn:: + getAny () const + { + return this->any_; + } + + Imdn::AnySequence& Imdn:: + getAny () + { + return this->any_; + } + + void Imdn:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ::xercesc::DOMDocument& Imdn:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& Imdn:: + getDomDocument () + { + return *this->dom_document_; + } + + + // DeliveryNotification + // + + const DeliveryNotification::StatusType& DeliveryNotification:: + getStatus () const + { + return this->status_.get (); + } + + DeliveryNotification::StatusType& DeliveryNotification:: + getStatus () + { + return this->status_.get (); + } + + void DeliveryNotification:: + setStatus (const StatusType& x) + { + this->status_.set (x); + } + + void DeliveryNotification:: + setStatus (::std::unique_ptr< StatusType > x) + { + this->status_.set (std::move (x)); + } + + ::std::unique_ptr< DeliveryNotification::StatusType > DeliveryNotification:: + setDetachStatus () + { + return this->status_.detach (); + } + + + // Delivered + // + + + // Failed + // + + + // DisplayNotification + // + + const DisplayNotification::StatusType& DisplayNotification:: + getStatus () const + { + return this->status_.get (); + } + + DisplayNotification::StatusType& DisplayNotification:: + getStatus () + { + return this->status_.get (); + } + + void DisplayNotification:: + setStatus (const StatusType& x) + { + this->status_.set (x); + } + + void DisplayNotification:: + setStatus (::std::unique_ptr< StatusType > x) + { + this->status_.set (std::move (x)); + } + + ::std::unique_ptr< DisplayNotification::StatusType > DisplayNotification:: + setDetachStatus () + { + return this->status_.detach (); + } + + + // Displayed + // + + + // ProcessingNotification + // + + const ProcessingNotification::StatusType& ProcessingNotification:: + getStatus () const + { + return this->status_.get (); + } + + ProcessingNotification::StatusType& ProcessingNotification:: + getStatus () + { + return this->status_.get (); + } + + void ProcessingNotification:: + setStatus (const StatusType& x) + { + this->status_.set (x); + } + + void ProcessingNotification:: + setStatus (::std::unique_ptr< StatusType > x) + { + this->status_.set (std::move (x)); + } + + ::std::unique_ptr< ProcessingNotification::StatusType > ProcessingNotification:: + setDetachStatus () + { + return this->status_.detach (); + } + + + // Processed + // + + + // Stored + // + + + // Forbidden + // + + + // Error + // + + + // Status + // + + const Status::DeliveredOptional& Status:: + getDelivered () const + { + return this->delivered_; + } + + Status::DeliveredOptional& Status:: + getDelivered () + { + return this->delivered_; + } + + void Status:: + setDelivered (const DeliveredType& x) + { + this->delivered_.set (x); + } + + void Status:: + setDelivered (const DeliveredOptional& x) + { + this->delivered_ = x; + } + + void Status:: + setDelivered (::std::unique_ptr< DeliveredType > x) + { + this->delivered_.set (std::move (x)); + } + + const Status::FailedOptional& Status:: + getFailed () const + { + return this->failed_; + } + + Status::FailedOptional& Status:: + getFailed () + { + return this->failed_; + } + + void Status:: + setFailed (const FailedType& x) + { + this->failed_.set (x); + } + + void Status:: + setFailed (const FailedOptional& x) + { + this->failed_ = x; + } + + void Status:: + setFailed (::std::unique_ptr< FailedType > x) + { + this->failed_.set (std::move (x)); + } + + const Status::ForbiddenOptional& Status:: + getForbidden () const + { + return this->forbidden_; + } + + Status::ForbiddenOptional& Status:: + getForbidden () + { + return this->forbidden_; + } + + void Status:: + setForbidden (const ForbiddenType& x) + { + this->forbidden_.set (x); + } + + void Status:: + setForbidden (const ForbiddenOptional& x) + { + this->forbidden_ = x; + } + + void Status:: + setForbidden (::std::unique_ptr< ForbiddenType > x) + { + this->forbidden_.set (std::move (x)); + } + + const Status::ErrorOptional& Status:: + getError () const + { + return this->error_; + } + + Status::ErrorOptional& Status:: + getError () + { + return this->error_; + } + + void Status:: + setError (const ErrorType& x) + { + this->error_.set (x); + } + + void Status:: + setError (const ErrorOptional& x) + { + this->error_ = x; + } + + void Status:: + setError (::std::unique_ptr< ErrorType > x) + { + this->error_.set (std::move (x)); + } + + const Status::ReasonOptional& Status:: + getReason () const + { + return this->reason_; + } + + Status::ReasonOptional& Status:: + getReason () + { + return this->reason_; + } + + void Status:: + setReason (const ReasonType& x) + { + this->reason_.set (x); + } + + void Status:: + setReason (const ReasonOptional& x) + { + this->reason_ = x; + } + + void Status:: + setReason (::std::unique_ptr< ReasonType > x) + { + this->reason_.set (std::move (x)); + } + + + // Status1 + // + + const Status1::DisplayedOptional& Status1:: + getDisplayed () const + { + return this->displayed_; + } + + Status1::DisplayedOptional& Status1:: + getDisplayed () + { + return this->displayed_; + } + + void Status1:: + setDisplayed (const DisplayedType& x) + { + this->displayed_.set (x); + } + + void Status1:: + setDisplayed (const DisplayedOptional& x) + { + this->displayed_ = x; + } + + void Status1:: + setDisplayed (::std::unique_ptr< DisplayedType > x) + { + this->displayed_.set (std::move (x)); + } + + const Status1::ForbiddenOptional& Status1:: + getForbidden () const + { + return this->forbidden_; + } + + Status1::ForbiddenOptional& Status1:: + getForbidden () + { + return this->forbidden_; + } + + void Status1:: + setForbidden (const ForbiddenType& x) + { + this->forbidden_.set (x); + } + + void Status1:: + setForbidden (const ForbiddenOptional& x) + { + this->forbidden_ = x; + } + + void Status1:: + setForbidden (::std::unique_ptr< ForbiddenType > x) + { + this->forbidden_.set (std::move (x)); + } + + const Status1::ErrorOptional& Status1:: + getError () const + { + return this->error_; + } + + Status1::ErrorOptional& Status1:: + getError () + { + return this->error_; + } + + void Status1:: + setError (const ErrorType& x) + { + this->error_.set (x); + } + + void Status1:: + setError (const ErrorOptional& x) + { + this->error_ = x; + } + + void Status1:: + setError (::std::unique_ptr< ErrorType > x) + { + this->error_.set (std::move (x)); + } + + const Status1::AnySequence& Status1:: + getAny () const + { + return this->any_; + } + + Status1::AnySequence& Status1:: + getAny () + { + return this->any_; + } + + void Status1:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ::xercesc::DOMDocument& Status1:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& Status1:: + getDomDocument () + { + return *this->dom_document_; + } + + + // Status2 + // + + const Status2::ProcessedOptional& Status2:: + getProcessed () const + { + return this->processed_; + } + + Status2::ProcessedOptional& Status2:: + getProcessed () + { + return this->processed_; + } + + void Status2:: + setProcessed (const ProcessedType& x) + { + this->processed_.set (x); + } + + void Status2:: + setProcessed (const ProcessedOptional& x) + { + this->processed_ = x; + } + + void Status2:: + setProcessed (::std::unique_ptr< ProcessedType > x) + { + this->processed_.set (std::move (x)); + } + + const Status2::StoredOptional& Status2:: + getStored () const + { + return this->stored_; + } + + Status2::StoredOptional& Status2:: + getStored () + { + return this->stored_; + } + + void Status2:: + setStored (const StoredType& x) + { + this->stored_.set (x); + } + + void Status2:: + setStored (const StoredOptional& x) + { + this->stored_ = x; + } + + void Status2:: + setStored (::std::unique_ptr< StoredType > x) + { + this->stored_.set (std::move (x)); + } + + const Status2::ForbiddenOptional& Status2:: + getForbidden () const + { + return this->forbidden_; + } + + Status2::ForbiddenOptional& Status2:: + getForbidden () + { + return this->forbidden_; + } + + void Status2:: + setForbidden (const ForbiddenType& x) + { + this->forbidden_.set (x); + } + + void Status2:: + setForbidden (const ForbiddenOptional& x) + { + this->forbidden_ = x; + } + + void Status2:: + setForbidden (::std::unique_ptr< ForbiddenType > x) + { + this->forbidden_.set (std::move (x)); + } + + const Status2::ErrorOptional& Status2:: + getError () const + { + return this->error_; + } + + Status2::ErrorOptional& Status2:: + getError () + { + return this->error_; + } + + void Status2:: + setError (const ErrorType& x) + { + this->error_.set (x); + } + + void Status2:: + setError (const ErrorOptional& x) + { + this->error_ = x; + } + + void Status2:: + setError (::std::unique_ptr< ErrorType > x) + { + this->error_.set (std::move (x)); + } + + const Status2::AnySequence& Status2:: + getAny () const + { + return this->any_; + } + + Status2::AnySequence& Status2:: + getAny () + { + return this->any_; + } + + void Status2:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ::xercesc::DOMDocument& Status2:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& Status2:: + getDomDocument () + { + return *this->dom_document_; + } + } + } +} + +#include + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_factory_plate< 0, char > + type_factory_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + // Imdn + // + + Imdn:: + Imdn (const MessageIdType& message_id, + const DatetimeType& datetime) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + message_id_ (message_id, this), + datetime_ (datetime, this), + recipient_uri_ (this), + original_recipient_uri_ (this), + subject_ (this), + delivery_notification_ (this), + display_notification_ (this), + processing_notification_ (this), + any_ (this->getDomDocument ()) + { + } + + Imdn:: + Imdn (const Imdn& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + message_id_ (x.message_id_, f, this), + datetime_ (x.datetime_, f, this), + recipient_uri_ (x.recipient_uri_, f, this), + original_recipient_uri_ (x.original_recipient_uri_, f, this), + subject_ (x.subject_, f, this), + delivery_notification_ (x.delivery_notification_, f, this), + display_notification_ (x.display_notification_, f, this), + processing_notification_ (x.processing_notification_, f, this), + any_ (x.any_, this->getDomDocument ()) + { + } + + Imdn:: + Imdn (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + message_id_ (this), + datetime_ (this), + recipient_uri_ (this), + original_recipient_uri_ (this), + subject_ (this), + delivery_notification_ (this), + display_notification_ (this), + processing_notification_ (this), + any_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void Imdn:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // message-id + // + if (n.name () == "message-id" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< MessageIdType > r ( + MessageIdTraits::create (i, f, this)); + + if (!message_id_.present ()) + { + this->message_id_.set (::std::move (r)); + continue; + } + } + + // datetime + // + if (n.name () == "datetime" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< DatetimeType > r ( + DatetimeTraits::create (i, f, this)); + + if (!datetime_.present ()) + { + this->datetime_.set (::std::move (r)); + continue; + } + } + + // recipient-uri + // + if (n.name () == "recipient-uri" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< RecipientUriType > r ( + RecipientUriTraits::create (i, f, this)); + + if (!this->recipient_uri_) + { + this->recipient_uri_.set (::std::move (r)); + continue; + } + } + + // original-recipient-uri + // + if (n.name () == "original-recipient-uri" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< OriginalRecipientUriType > r ( + OriginalRecipientUriTraits::create (i, f, this)); + + if (!this->original_recipient_uri_) + { + this->original_recipient_uri_.set (::std::move (r)); + continue; + } + } + + // subject + // + if (n.name () == "subject" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< SubjectType > r ( + SubjectTraits::create (i, f, this)); + + if (!this->subject_) + { + this->subject_.set (::std::move (r)); + continue; + } + } + + // delivery-notification + // + if (n.name () == "delivery-notification" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< DeliveryNotificationType > r ( + DeliveryNotificationTraits::create (i, f, this)); + + if (!this->delivery_notification_) + { + this->delivery_notification_.set (::std::move (r)); + continue; + } + } + + // display-notification + // + if (n.name () == "display-notification" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< DisplayNotificationType > r ( + DisplayNotificationTraits::create (i, f, this)); + + if (!this->display_notification_) + { + this->display_notification_.set (::std::move (r)); + continue; + } + } + + // processing-notification + // + if (n.name () == "processing-notification" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ProcessingNotificationType > r ( + ProcessingNotificationTraits::create (i, f, this)); + + if (!this->processing_notification_) + { + this->processing_notification_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:imdn")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + if (!message_id_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "message-id", + "urn:ietf:params:xml:ns:imdn"); + } + + if (!datetime_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "datetime", + "urn:ietf:params:xml:ns:imdn"); + } + } + + Imdn* Imdn:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Imdn (*this, f, c); + } + + Imdn& Imdn:: + operator= (const Imdn& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->message_id_ = x.message_id_; + this->datetime_ = x.datetime_; + this->recipient_uri_ = x.recipient_uri_; + this->original_recipient_uri_ = x.original_recipient_uri_; + this->subject_ = x.subject_; + this->delivery_notification_ = x.delivery_notification_; + this->display_notification_ = x.display_notification_; + this->processing_notification_ = x.processing_notification_; + this->any_ = x.any_; + } + + return *this; + } + + Imdn:: + ~Imdn () + { + } + + // DeliveryNotification + // + + DeliveryNotification:: + DeliveryNotification (const StatusType& status) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + status_ (status, this) + { + } + + DeliveryNotification:: + DeliveryNotification (::std::unique_ptr< StatusType > status) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + status_ (std::move (status), this) + { + } + + DeliveryNotification:: + DeliveryNotification (const DeliveryNotification& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + status_ (x.status_, f, this) + { + } + + DeliveryNotification:: + DeliveryNotification (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + status_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void DeliveryNotification:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // status + // + if (n.name () == "status" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< StatusType > r ( + StatusTraits::create (i, f, this)); + + if (!status_.present ()) + { + this->status_.set (::std::move (r)); + continue; + } + } + + break; + } + + if (!status_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "status", + "urn:ietf:params:xml:ns:imdn"); + } + } + + DeliveryNotification* DeliveryNotification:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class DeliveryNotification (*this, f, c); + } + + DeliveryNotification& DeliveryNotification:: + operator= (const DeliveryNotification& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->status_ = x.status_; + } + + return *this; + } + + DeliveryNotification:: + ~DeliveryNotification () + { + } + + // Delivered + // + + Delivered:: + Delivered () + : ::LinphonePrivate::Xsd::XmlSchema::Type () + { + } + + Delivered:: + Delivered (const Delivered& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c) + { + } + + Delivered:: + Delivered (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f, c) + { + } + + Delivered:: + Delivered (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (a, f, c) + { + } + + Delivered:: + Delivered (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (s, e, f, c) + { + } + + Delivered* Delivered:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Delivered (*this, f, c); + } + + Delivered:: + ~Delivered () + { + } + + // Failed + // + + Failed:: + Failed () + : ::LinphonePrivate::Xsd::XmlSchema::Type () + { + } + + Failed:: + Failed (const Failed& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c) + { + } + + Failed:: + Failed (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f, c) + { + } + + Failed:: + Failed (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (a, f, c) + { + } + + Failed:: + Failed (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (s, e, f, c) + { + } + + Failed* Failed:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Failed (*this, f, c); + } + + Failed:: + ~Failed () + { + } + + // DisplayNotification + // + + DisplayNotification:: + DisplayNotification (const StatusType& status) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + status_ (status, this) + { + } + + DisplayNotification:: + DisplayNotification (::std::unique_ptr< StatusType > status) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + status_ (std::move (status), this) + { + } + + DisplayNotification:: + DisplayNotification (const DisplayNotification& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + status_ (x.status_, f, this) + { + } + + DisplayNotification:: + DisplayNotification (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + status_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void DisplayNotification:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // status + // + if (n.name () == "status" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< StatusType > r ( + StatusTraits::create (i, f, this)); + + if (!status_.present ()) + { + this->status_.set (::std::move (r)); + continue; + } + } + + break; + } + + if (!status_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "status", + "urn:ietf:params:xml:ns:imdn"); + } + } + + DisplayNotification* DisplayNotification:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class DisplayNotification (*this, f, c); + } + + DisplayNotification& DisplayNotification:: + operator= (const DisplayNotification& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->status_ = x.status_; + } + + return *this; + } + + DisplayNotification:: + ~DisplayNotification () + { + } + + // Displayed + // + + Displayed:: + Displayed () + : ::LinphonePrivate::Xsd::XmlSchema::Type () + { + } + + Displayed:: + Displayed (const Displayed& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c) + { + } + + Displayed:: + Displayed (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f, c) + { + } + + Displayed:: + Displayed (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (a, f, c) + { + } + + Displayed:: + Displayed (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (s, e, f, c) + { + } + + Displayed* Displayed:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Displayed (*this, f, c); + } + + Displayed:: + ~Displayed () + { + } + + // ProcessingNotification + // + + ProcessingNotification:: + ProcessingNotification (const StatusType& status) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + status_ (status, this) + { + } + + ProcessingNotification:: + ProcessingNotification (::std::unique_ptr< StatusType > status) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + status_ (std::move (status), this) + { + } + + ProcessingNotification:: + ProcessingNotification (const ProcessingNotification& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + status_ (x.status_, f, this) + { + } + + ProcessingNotification:: + ProcessingNotification (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + status_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void ProcessingNotification:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // status + // + if (n.name () == "status" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< StatusType > r ( + StatusTraits::create (i, f, this)); + + if (!status_.present ()) + { + this->status_.set (::std::move (r)); + continue; + } + } + + break; + } + + if (!status_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "status", + "urn:ietf:params:xml:ns:imdn"); + } + } + + ProcessingNotification* ProcessingNotification:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ProcessingNotification (*this, f, c); + } + + ProcessingNotification& ProcessingNotification:: + operator= (const ProcessingNotification& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->status_ = x.status_; + } + + return *this; + } + + ProcessingNotification:: + ~ProcessingNotification () + { + } + + // Processed + // + + Processed:: + Processed () + : ::LinphonePrivate::Xsd::XmlSchema::Type () + { + } + + Processed:: + Processed (const Processed& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c) + { + } + + Processed:: + Processed (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f, c) + { + } + + Processed:: + Processed (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (a, f, c) + { + } + + Processed:: + Processed (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (s, e, f, c) + { + } + + Processed* Processed:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Processed (*this, f, c); + } + + Processed:: + ~Processed () + { + } + + // Stored + // + + Stored:: + Stored () + : ::LinphonePrivate::Xsd::XmlSchema::Type () + { + } + + Stored:: + Stored (const Stored& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c) + { + } + + Stored:: + Stored (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f, c) + { + } + + Stored:: + Stored (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (a, f, c) + { + } + + Stored:: + Stored (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (s, e, f, c) + { + } + + Stored* Stored:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Stored (*this, f, c); + } + + Stored:: + ~Stored () + { + } + + // Forbidden + // + + Forbidden:: + Forbidden () + : ::LinphonePrivate::Xsd::XmlSchema::Type () + { + } + + Forbidden:: + Forbidden (const Forbidden& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c) + { + } + + Forbidden:: + Forbidden (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f, c) + { + } + + Forbidden:: + Forbidden (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (a, f, c) + { + } + + Forbidden:: + Forbidden (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (s, e, f, c) + { + } + + Forbidden* Forbidden:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Forbidden (*this, f, c); + } + + Forbidden:: + ~Forbidden () + { + } + + // Error + // + + Error:: + Error () + : ::LinphonePrivate::Xsd::XmlSchema::Type () + { + } + + Error:: + Error (const Error& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c) + { + } + + Error:: + Error (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f, c) + { + } + + Error:: + Error (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (a, f, c) + { + } + + Error:: + Error (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (s, e, f, c) + { + } + + Error* Error:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Error (*this, f, c); + } + + Error:: + ~Error () + { + } + + // Status + // + + Status:: + Status () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + delivered_ (this), + failed_ (this), + forbidden_ (this), + error_ (this), + reason_ (this) + { + } + + Status:: + Status (const Status& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + delivered_ (x.delivered_, f, this), + failed_ (x.failed_, f, this), + forbidden_ (x.forbidden_, f, this), + error_ (x.error_, f, this), + reason_ (x.reason_, f, this) + { + } + + Status:: + Status (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + delivered_ (this), + failed_ (this), + forbidden_ (this), + error_ (this), + reason_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void Status:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // delivered + // + if (n.name () == "delivered" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< DeliveredType > r ( + DeliveredTraits::create (i, f, this)); + + if (!this->delivered_) + { + this->delivered_.set (::std::move (r)); + continue; + } + } + + // failed + // + if (n.name () == "failed" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< FailedType > r ( + FailedTraits::create (i, f, this)); + + if (!this->failed_) + { + this->failed_.set (::std::move (r)); + continue; + } + } + + // forbidden + // + if (n.name () == "forbidden" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ForbiddenType > r ( + ForbiddenTraits::create (i, f, this)); + + if (!this->forbidden_) + { + this->forbidden_.set (::std::move (r)); + continue; + } + } + + // error + // + if (n.name () == "error" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ErrorType > r ( + ErrorTraits::create (i, f, this)); + + if (!this->error_) + { + this->error_.set (::std::move (r)); + continue; + } + } + + // reason + // + if (n.name () == "reason" && n.namespace_ () == "http://www.linphone.org/xsds/imdn.xsd") + { + ::std::unique_ptr< ReasonType > r ( + ReasonTraits::create (i, f, this)); + + if (!this->reason_) + { + this->reason_.set (::std::move (r)); + continue; + } + } + + break; + } + } + + Status* Status:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Status (*this, f, c); + } + + Status& Status:: + operator= (const Status& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->delivered_ = x.delivered_; + this->failed_ = x.failed_; + this->forbidden_ = x.forbidden_; + this->error_ = x.error_; + this->reason_ = x.reason_; + } + + return *this; + } + + Status:: + ~Status () + { + } + + // Status1 + // + + Status1:: + Status1 () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + displayed_ (this), + forbidden_ (this), + error_ (this), + any_ (this->getDomDocument ()) + { + } + + Status1:: + Status1 (const Status1& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + displayed_ (x.displayed_, f, this), + forbidden_ (x.forbidden_, f, this), + error_ (x.error_, f, this), + any_ (x.any_, this->getDomDocument ()) + { + } + + Status1:: + Status1 (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + displayed_ (this), + forbidden_ (this), + error_ (this), + any_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void Status1:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // displayed + // + if (n.name () == "displayed" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< DisplayedType > r ( + DisplayedTraits::create (i, f, this)); + + if (!this->displayed_) + { + this->displayed_.set (::std::move (r)); + continue; + } + } + + // forbidden + // + if (n.name () == "forbidden" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ForbiddenType > r ( + ForbiddenTraits::create (i, f, this)); + + if (!this->forbidden_) + { + this->forbidden_.set (::std::move (r)); + continue; + } + } + + // error + // + if (n.name () == "error" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ErrorType > r ( + ErrorTraits::create (i, f, this)); + + if (!this->error_) + { + this->error_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:imdn")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + } + + Status1* Status1:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Status1 (*this, f, c); + } + + Status1& Status1:: + operator= (const Status1& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->displayed_ = x.displayed_; + this->forbidden_ = x.forbidden_; + this->error_ = x.error_; + this->any_ = x.any_; + } + + return *this; + } + + Status1:: + ~Status1 () + { + } + + // Status2 + // + + Status2:: + Status2 () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + processed_ (this), + stored_ (this), + forbidden_ (this), + error_ (this), + any_ (this->getDomDocument ()) + { + } + + Status2:: + Status2 (const Status2& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + processed_ (x.processed_, f, this), + stored_ (x.stored_, f, this), + forbidden_ (x.forbidden_, f, this), + error_ (x.error_, f, this), + any_ (x.any_, this->getDomDocument ()) + { + } + + Status2:: + Status2 (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + processed_ (this), + stored_ (this), + forbidden_ (this), + error_ (this), + any_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void Status2:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // processed + // + if (n.name () == "processed" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ProcessedType > r ( + ProcessedTraits::create (i, f, this)); + + if (!this->processed_) + { + this->processed_.set (::std::move (r)); + continue; + } + } + + // stored + // + if (n.name () == "stored" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< StoredType > r ( + StoredTraits::create (i, f, this)); + + if (!this->stored_) + { + this->stored_.set (::std::move (r)); + continue; + } + } + + // forbidden + // + if (n.name () == "forbidden" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ForbiddenType > r ( + ForbiddenTraits::create (i, f, this)); + + if (!this->forbidden_) + { + this->forbidden_.set (::std::move (r)); + continue; + } + } + + // error + // + if (n.name () == "error" && n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ErrorType > r ( + ErrorTraits::create (i, f, this)); + + if (!this->error_) + { + this->error_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:imdn")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + } + + Status2* Status2:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Status2 (*this, f, c); + } + + Status2& Status2:: + operator= (const Status2& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->processed_ = x.processed_; + this->stored_ = x.stored_; + this->forbidden_ = x.forbidden_; + this->error_ = x.error_; + this->any_ = x.any_; + } + + return *this; + } + + Status2:: + ~Status2 () + { + } + } + } +} + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::std_ostream_plate< 0, char > + std_ostream_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + ::std::ostream& + operator<< (::std::ostream& o, const Imdn& i) + { + o << ::std::endl << "message-id: " << i.getMessageId (); + o << ::std::endl << "datetime: " << i.getDatetime (); + if (i.getRecipientUri ()) + { + o << ::std::endl << "recipient-uri: " << *i.getRecipientUri (); + } + + if (i.getOriginalRecipientUri ()) + { + o << ::std::endl << "original-recipient-uri: " << *i.getOriginalRecipientUri (); + } + + if (i.getSubject ()) + { + o << ::std::endl << "subject: " << *i.getSubject (); + } + + if (i.getDeliveryNotification ()) + { + o << ::std::endl << "delivery-notification: " << *i.getDeliveryNotification (); + } + + if (i.getDisplayNotification ()) + { + o << ::std::endl << "display-notification: " << *i.getDisplayNotification (); + } + + if (i.getProcessingNotification ()) + { + o << ::std::endl << "processing-notification: " << *i.getProcessingNotification (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const DeliveryNotification& i) + { + o << ::std::endl << "status: " << i.getStatus (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Delivered&) + { + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Failed&) + { + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const DisplayNotification& i) + { + o << ::std::endl << "status: " << i.getStatus (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Displayed&) + { + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const ProcessingNotification& i) + { + o << ::std::endl << "status: " << i.getStatus (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Processed&) + { + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Stored&) + { + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Forbidden&) + { + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Error&) + { + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Status& i) + { + if (i.getDelivered ()) + { + o << ::std::endl << "delivered: " << *i.getDelivered (); + } + + if (i.getFailed ()) + { + o << ::std::endl << "failed: " << *i.getFailed (); + } + + if (i.getForbidden ()) + { + o << ::std::endl << "forbidden: " << *i.getForbidden (); + } + + if (i.getError ()) + { + o << ::std::endl << "error: " << *i.getError (); + } + + if (i.getReason ()) + { + o << ::std::endl << "reason: " << *i.getReason (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Status1& i) + { + if (i.getDisplayed ()) + { + o << ::std::endl << "displayed: " << *i.getDisplayed (); + } + + if (i.getForbidden ()) + { + o << ::std::endl << "forbidden: " << *i.getForbidden (); + } + + if (i.getError ()) + { + o << ::std::endl << "error: " << *i.getError (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Status2& i) + { + if (i.getProcessed ()) + { + o << ::std::endl << "processed: " << *i.getProcessed (); + } + + if (i.getStored ()) + { + o << ::std::endl << "stored: " << *i.getStored (); + } + + if (i.getForbidden ()) + { + o << ::std::endl << "forbidden: " << *i.getForbidden (); + } + + if (i.getError ()) + { + o << ::std::endl << "error: " << *i.getError (); + } + + return o; + } + } + } +} + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > ( + ::LinphonePrivate::Xsd::Imdn::parseImdn ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > ( + ::LinphonePrivate::Xsd::Imdn::parseImdn ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::std::string& u, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > ( + ::LinphonePrivate::Xsd::Imdn::parseImdn ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::Imdn::parseImdn (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::Imdn::parseImdn (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::Imdn::parseImdn (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::Imdn::parseImdn (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::Imdn::parseImdn (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + const ::std::string& sid, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::Imdn::parseImdn (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > ( + ::LinphonePrivate::Xsd::Imdn::parseImdn ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > ( + ::LinphonePrivate::Xsd::Imdn::parseImdn ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::xercesc::InputSource& i, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > ( + ::LinphonePrivate::Xsd::Imdn::parseImdn ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::xercesc::DOMDocument& doc, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + static_cast< ::xercesc::DOMDocument* > (doc.cloneNode (true))); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > ( + ::LinphonePrivate::Xsd::Imdn::parseImdn ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "imdn" && + n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::Imdn::Imdn, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "imdn", + "urn:ietf:params:xml:ns:imdn"); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties&) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > c ( + ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) && + !(f & ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom)) + ? static_cast< ::xercesc::DOMDocument* > (d->cloneNode (true)) + : 0); + + ::xercesc::DOMDocument& doc (c.get () ? *c : *d); + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + doc.setUserData (::LinphonePrivate::Xsd::XmlSchema::dom::treeNodeKey, + (c.get () ? &c : &d), + 0); + + if (n.name () == "imdn" && + n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::Imdn::Imdn, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "imdn", + "urn:ietf:params:xml:ns:imdn"); + } + } + } +} + +#include +#include +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_serializer_plate< 0, char > + type_serializer_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + void + serializeImdn (::std::ostream& o, + const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Imdn::serializeImdn (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeImdn (::std::ostream& o, + const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Imdn::serializeImdn (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeImdn (::std::ostream& o, + const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Imdn::serializeImdn (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeImdn (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Imdn::serializeImdn (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeImdn (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Imdn::serializeImdn (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeImdn (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Imdn::serializeImdn (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeImdn (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + ::LinphonePrivate::Xsd::XmlSchema::Flags) + { + ::xercesc::DOMElement& e (*d.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "imdn" && + n.namespace_ () == "urn:ietf:params:xml:ns:imdn") + { + e << s; + } + else + { + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "imdn", + "urn:ietf:params:xml:ns:imdn"); + } + } + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeImdn (const ::LinphonePrivate::Xsd::Imdn::Imdn& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::serialize< char > ( + "imdn", + "urn:ietf:params:xml:ns:imdn", + m, f)); + + ::LinphonePrivate::Xsd::Imdn::serializeImdn (*d, s, f); + return d; + } + + void + operator<< (::xercesc::DOMElement& e, const Imdn& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // message-id + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "message-id", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << i.getMessageId (); + } + + // datetime + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "datetime", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << i.getDatetime (); + } + + // recipient-uri + // + if (i.getRecipientUri ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "recipient-uri", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getRecipientUri (); + } + + // original-recipient-uri + // + if (i.getOriginalRecipientUri ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "original-recipient-uri", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getOriginalRecipientUri (); + } + + // subject + // + if (i.getSubject ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "subject", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getSubject (); + } + + // delivery-notification + // + if (i.getDeliveryNotification ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "delivery-notification", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getDeliveryNotification (); + } + + // display-notification + // + if (i.getDisplayNotification ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-notification", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getDisplayNotification (); + } + + // processing-notification + // + if (i.getProcessingNotification ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "processing-notification", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getProcessingNotification (); + } + + // any + // + for (Imdn::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const DeliveryNotification& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // status + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "status", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << i.getStatus (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Delivered& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + } + + void + operator<< (::xercesc::DOMAttr&, const Delivered&) + { + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Delivered&) + { + } + + void + operator<< (::xercesc::DOMElement& e, const Failed& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + } + + void + operator<< (::xercesc::DOMAttr&, const Failed&) + { + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Failed&) + { + } + + void + operator<< (::xercesc::DOMElement& e, const DisplayNotification& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // status + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "status", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << i.getStatus (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Displayed& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + } + + void + operator<< (::xercesc::DOMAttr&, const Displayed&) + { + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Displayed&) + { + } + + void + operator<< (::xercesc::DOMElement& e, const ProcessingNotification& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // status + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "status", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << i.getStatus (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Processed& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + } + + void + operator<< (::xercesc::DOMAttr&, const Processed&) + { + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Processed&) + { + } + + void + operator<< (::xercesc::DOMElement& e, const Stored& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + } + + void + operator<< (::xercesc::DOMAttr&, const Stored&) + { + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Stored&) + { + } + + void + operator<< (::xercesc::DOMElement& e, const Forbidden& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + } + + void + operator<< (::xercesc::DOMAttr&, const Forbidden&) + { + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Forbidden&) + { + } + + void + operator<< (::xercesc::DOMElement& e, const Error& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + } + + void + operator<< (::xercesc::DOMAttr&, const Error&) + { + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Error&) + { + } + + void + operator<< (::xercesc::DOMElement& e, const Status& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // delivered + // + if (i.getDelivered ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "delivered", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getDelivered (); + } + + // failed + // + if (i.getFailed ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "failed", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getFailed (); + } + + // forbidden + // + if (i.getForbidden ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "forbidden", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getForbidden (); + } + + // error + // + if (i.getError ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "error", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getError (); + } + + // reason + // + if (i.getReason ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "reason", + "http://www.linphone.org/xsds/imdn.xsd", + e)); + + s << *i.getReason (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Status1& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // displayed + // + if (i.getDisplayed ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "displayed", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getDisplayed (); + } + + // forbidden + // + if (i.getForbidden ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "forbidden", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getForbidden (); + } + + // error + // + if (i.getError ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "error", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getError (); + } + + // any + // + for (Status1::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Status2& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // processed + // + if (i.getProcessed ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "processed", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getProcessed (); + } + + // stored + // + if (i.getStored ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "stored", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getStored (); + } + + // forbidden + // + if (i.getForbidden ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "forbidden", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getForbidden (); + } + + // error + // + if (i.getError ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "error", + "urn:ietf:params:xml:ns:imdn", + e)); + + s << *i.getError (); + } + + // any + // + for (Status2::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + diff --git a/src/xml/imdn.h b/src/xml/imdn.h new file mode 100644 index 000000000..ca544a67c --- /dev/null +++ b/src/xml/imdn.h @@ -0,0 +1,1739 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +#ifndef XML_IMDN_H +#define XML_IMDN_H + +#ifndef XSD_CXX11 +#define XSD_CXX11 +#endif + +#ifndef XSD_USE_CHAR +#define XSD_USE_CHAR +#endif + +#ifndef XSD_CXX_TREE_USE_CHAR +#define XSD_CXX_TREE_USE_CHAR +#endif + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#if (XSD_INT_VERSION != 4000000L) +#error XSD runtime version mismatch +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace XmlSchema + { + // anyType and anySimpleType. + // + typedef ::xsd::cxx::tree::type Type; + typedef ::xsd::cxx::tree::simple_type< char, Type > SimpleType; + typedef ::xsd::cxx::tree::type Container; + + // 8-bit + // + typedef signed char Byte; + typedef unsigned char UnsignedByte; + + // 16-bit + // + typedef short Short; + typedef unsigned short UnsignedShort; + + // 32-bit + // + typedef int Int; + typedef unsigned int UnsignedInt; + + // 64-bit + // + typedef long long Long; + typedef unsigned long long UnsignedLong; + + // Supposed to be arbitrary-length integral types. + // + typedef long long Integer; + typedef long long NonPositiveInteger; + typedef unsigned long long NonNegativeInteger; + typedef unsigned long long PositiveInteger; + typedef long long NegativeInteger; + + // Boolean. + // + typedef bool Boolean; + + // Floating-point types. + // + typedef float Float; + typedef double Double; + typedef double Decimal; + + // String types. + // + typedef ::xsd::cxx::tree::string< char, SimpleType > String; + typedef ::xsd::cxx::tree::normalized_string< char, String > NormalizedString; + typedef ::xsd::cxx::tree::token< char, NormalizedString > Token; + typedef ::xsd::cxx::tree::name< char, Token > Name; + typedef ::xsd::cxx::tree::nmtoken< char, Token > Nmtoken; + typedef ::xsd::cxx::tree::nmtokens< char, SimpleType, Nmtoken > Nmtokens; + typedef ::xsd::cxx::tree::ncname< char, Name > Ncname; + typedef ::xsd::cxx::tree::language< char, Token > Language; + + // ID/IDREF. + // + typedef ::xsd::cxx::tree::id< char, Ncname > Id; + typedef ::xsd::cxx::tree::idref< char, Ncname, Type > Idref; + typedef ::xsd::cxx::tree::idrefs< char, SimpleType, Idref > Idrefs; + + // URI. + // + typedef ::xsd::cxx::tree::uri< char, SimpleType > Uri; + + // Qualified name. + // + typedef ::xsd::cxx::tree::qname< char, SimpleType, Uri, Ncname > Qname; + + // Binary. + // + typedef ::xsd::cxx::tree::buffer< char > Buffer; + typedef ::xsd::cxx::tree::base64_binary< char, SimpleType > Base64Binary; + typedef ::xsd::cxx::tree::hex_binary< char, SimpleType > HexBinary; + + // Date/time. + // + typedef ::xsd::cxx::tree::time_zone TimeZone; + typedef ::xsd::cxx::tree::date< char, SimpleType > Date; + typedef ::xsd::cxx::tree::date_time< char, SimpleType > DateTime; + typedef ::xsd::cxx::tree::duration< char, SimpleType > Duration; + typedef ::xsd::cxx::tree::gday< char, SimpleType > Gday; + typedef ::xsd::cxx::tree::gmonth< char, SimpleType > Gmonth; + typedef ::xsd::cxx::tree::gmonth_day< char, SimpleType > GmonthDay; + typedef ::xsd::cxx::tree::gyear< char, SimpleType > Gyear; + typedef ::xsd::cxx::tree::gyear_month< char, SimpleType > GyearMonth; + typedef ::xsd::cxx::tree::time< char, SimpleType > Time; + + // Entity. + // + typedef ::xsd::cxx::tree::entity< char, Ncname > Entity; + typedef ::xsd::cxx::tree::entities< char, SimpleType, Entity > Entities; + + typedef ::xsd::cxx::tree::content_order ContentOrder; + // Namespace information and list stream. Used in + // serialization functions. + // + typedef ::xsd::cxx::xml::dom::namespace_info< char > NamespaceInfo; + typedef ::xsd::cxx::xml::dom::namespace_infomap< char > NamespaceInfomap; + typedef ::xsd::cxx::tree::list_stream< char > ListStream; + typedef ::xsd::cxx::tree::as_double< Double > AsDouble; + typedef ::xsd::cxx::tree::as_decimal< Decimal > AsDecimal; + typedef ::xsd::cxx::tree::facet Facet; + + // Flags and properties. + // + typedef ::xsd::cxx::tree::flags Flags; + typedef ::xsd::cxx::tree::properties< char > Properties; + + // Parsing/serialization diagnostics. + // + typedef ::xsd::cxx::tree::severity Severity; + typedef ::xsd::cxx::tree::error< char > Error; + typedef ::xsd::cxx::tree::diagnostics< char > Diagnostics; + + // Exceptions. + // + typedef ::xsd::cxx::tree::exception< char > Exception; + typedef ::xsd::cxx::tree::bounds< char > Bounds; + typedef ::xsd::cxx::tree::duplicate_id< char > DuplicateId; + typedef ::xsd::cxx::tree::parsing< char > Parsing; + typedef ::xsd::cxx::tree::expected_element< char > ExpectedElement; + typedef ::xsd::cxx::tree::unexpected_element< char > UnexpectedElement; + typedef ::xsd::cxx::tree::expected_attribute< char > ExpectedAttribute; + typedef ::xsd::cxx::tree::unexpected_enumerator< char > UnexpectedEnumerator; + typedef ::xsd::cxx::tree::expected_text_content< char > ExpectedTextContent; + typedef ::xsd::cxx::tree::no_prefix_mapping< char > NoPrefixMapping; + typedef ::xsd::cxx::tree::no_type_info< char > NoTypeInfo; + typedef ::xsd::cxx::tree::not_derived< char > NotDerived; + typedef ::xsd::cxx::tree::serialization< char > Serialization; + + // Error handler callback interface. + // + typedef ::xsd::cxx::xml::error_handler< char > ErrorHandler; + + // DOM interaction. + // + namespace dom + { + // Automatic pointer for DOMDocument. + // + using ::xsd::cxx::xml::dom::unique_ptr; + +#ifndef XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA +#define XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA + // DOM user data key for back pointers to tree nodes. + // + const XMLCh* const treeNodeKey = ::xsd::cxx::tree::user_data_keys::node; +#endif + } + } + } +} + +// Forward declarations. +// +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + class Imdn; + class DeliveryNotification; + class Delivered; + class Failed; + class DisplayNotification; + class Displayed; + class ProcessingNotification; + class Processed; + class Stored; + class Forbidden; + class Error; + class Status; + class Status1; + class Status2; + } + } +} + + +#include // ::std::unique_ptr +#include // std::numeric_limits +#include // std::binary_search +#include // std::move + +#include + +#include +#include +#include +#include + +#include + +#include + +#include "linphone-imdn.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + class Imdn: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // message-id + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Token MessageIdType; + typedef ::xsd::cxx::tree::traits< MessageIdType, char > MessageIdTraits; + + const MessageIdType& + getMessageId () const; + + MessageIdType& + getMessageId (); + + void + setMessageId (const MessageIdType& x); + + void + setMessageId (::std::unique_ptr< MessageIdType > p); + + ::std::unique_ptr< MessageIdType > + setDetachMessage_id (); + + // datetime + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String DatetimeType; + typedef ::xsd::cxx::tree::traits< DatetimeType, char > DatetimeTraits; + + const DatetimeType& + getDatetime () const; + + DatetimeType& + getDatetime (); + + void + setDatetime (const DatetimeType& x); + + void + setDatetime (::std::unique_ptr< DatetimeType > p); + + ::std::unique_ptr< DatetimeType > + setDetachDatetime (); + + // recipient-uri + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri RecipientUriType; + typedef ::xsd::cxx::tree::optional< RecipientUriType > RecipientUriOptional; + typedef ::xsd::cxx::tree::traits< RecipientUriType, char > RecipientUriTraits; + + const RecipientUriOptional& + getRecipientUri () const; + + RecipientUriOptional& + getRecipientUri (); + + void + setRecipientUri (const RecipientUriType& x); + + void + setRecipientUri (const RecipientUriOptional& x); + + void + setRecipientUri (::std::unique_ptr< RecipientUriType > p); + + // original-recipient-uri + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri OriginalRecipientUriType; + typedef ::xsd::cxx::tree::optional< OriginalRecipientUriType > OriginalRecipientUriOptional; + typedef ::xsd::cxx::tree::traits< OriginalRecipientUriType, char > OriginalRecipientUriTraits; + + const OriginalRecipientUriOptional& + getOriginalRecipientUri () const; + + OriginalRecipientUriOptional& + getOriginalRecipientUri (); + + void + setOriginalRecipientUri (const OriginalRecipientUriType& x); + + void + setOriginalRecipientUri (const OriginalRecipientUriOptional& x); + + void + setOriginalRecipientUri (::std::unique_ptr< OriginalRecipientUriType > p); + + // subject + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String SubjectType; + typedef ::xsd::cxx::tree::optional< SubjectType > SubjectOptional; + typedef ::xsd::cxx::tree::traits< SubjectType, char > SubjectTraits; + + const SubjectOptional& + getSubject () const; + + SubjectOptional& + getSubject (); + + void + setSubject (const SubjectType& x); + + void + setSubject (const SubjectOptional& x); + + void + setSubject (::std::unique_ptr< SubjectType > p); + + // delivery-notification + // + typedef ::LinphonePrivate::Xsd::Imdn::DeliveryNotification DeliveryNotificationType; + typedef ::xsd::cxx::tree::optional< DeliveryNotificationType > DeliveryNotificationOptional; + typedef ::xsd::cxx::tree::traits< DeliveryNotificationType, char > DeliveryNotificationTraits; + + const DeliveryNotificationOptional& + getDeliveryNotification () const; + + DeliveryNotificationOptional& + getDeliveryNotification (); + + void + setDeliveryNotification (const DeliveryNotificationType& x); + + void + setDeliveryNotification (const DeliveryNotificationOptional& x); + + void + setDeliveryNotification (::std::unique_ptr< DeliveryNotificationType > p); + + // display-notification + // + typedef ::LinphonePrivate::Xsd::Imdn::DisplayNotification DisplayNotificationType; + typedef ::xsd::cxx::tree::optional< DisplayNotificationType > DisplayNotificationOptional; + typedef ::xsd::cxx::tree::traits< DisplayNotificationType, char > DisplayNotificationTraits; + + const DisplayNotificationOptional& + getDisplayNotification () const; + + DisplayNotificationOptional& + getDisplayNotification (); + + void + setDisplayNotification (const DisplayNotificationType& x); + + void + setDisplayNotification (const DisplayNotificationOptional& x); + + void + setDisplayNotification (::std::unique_ptr< DisplayNotificationType > p); + + // processing-notification + // + typedef ::LinphonePrivate::Xsd::Imdn::ProcessingNotification ProcessingNotificationType; + typedef ::xsd::cxx::tree::optional< ProcessingNotificationType > ProcessingNotificationOptional; + typedef ::xsd::cxx::tree::traits< ProcessingNotificationType, char > ProcessingNotificationTraits; + + const ProcessingNotificationOptional& + getProcessingNotification () const; + + ProcessingNotificationOptional& + getProcessingNotification (); + + void + setProcessingNotification (const ProcessingNotificationType& x); + + void + setProcessingNotification (const ProcessingNotificationOptional& x); + + void + setProcessingNotification (::std::unique_ptr< ProcessingNotificationType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + Imdn (const MessageIdType&, + const DatetimeType&); + + Imdn (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Imdn (const Imdn& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Imdn* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Imdn& + operator= (const Imdn& x); + + virtual + ~Imdn (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + ::xsd::cxx::tree::one< MessageIdType > message_id_; + ::xsd::cxx::tree::one< DatetimeType > datetime_; + RecipientUriOptional recipient_uri_; + OriginalRecipientUriOptional original_recipient_uri_; + SubjectOptional subject_; + DeliveryNotificationOptional delivery_notification_; + DisplayNotificationOptional display_notification_; + ProcessingNotificationOptional processing_notification_; + AnySequence any_; + }; + + class DeliveryNotification: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // status + // + typedef ::LinphonePrivate::Xsd::Imdn::Status StatusType; + typedef ::xsd::cxx::tree::traits< StatusType, char > StatusTraits; + + const StatusType& + getStatus () const; + + StatusType& + getStatus (); + + void + setStatus (const StatusType& x); + + void + setStatus (::std::unique_ptr< StatusType > p); + + ::std::unique_ptr< StatusType > + setDetachStatus (); + + // Constructors. + // + DeliveryNotification (const StatusType&); + + DeliveryNotification (::std::unique_ptr< StatusType >); + + DeliveryNotification (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + DeliveryNotification (const DeliveryNotification& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual DeliveryNotification* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + DeliveryNotification& + operator= (const DeliveryNotification& x); + + virtual + ~DeliveryNotification (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::xsd::cxx::tree::one< StatusType > status_; + }; + + class Delivered: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // Constructors. + // + Delivered (); + + Delivered (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Delivered (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Delivered (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Delivered (const Delivered& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Delivered* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~Delivered (); + }; + + class Failed: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // Constructors. + // + Failed (); + + Failed (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Failed (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Failed (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Failed (const Failed& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Failed* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~Failed (); + }; + + class DisplayNotification: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // status + // + typedef ::LinphonePrivate::Xsd::Imdn::Status1 StatusType; + typedef ::xsd::cxx::tree::traits< StatusType, char > StatusTraits; + + const StatusType& + getStatus () const; + + StatusType& + getStatus (); + + void + setStatus (const StatusType& x); + + void + setStatus (::std::unique_ptr< StatusType > p); + + ::std::unique_ptr< StatusType > + setDetachStatus (); + + // Constructors. + // + DisplayNotification (const StatusType&); + + DisplayNotification (::std::unique_ptr< StatusType >); + + DisplayNotification (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + DisplayNotification (const DisplayNotification& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual DisplayNotification* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + DisplayNotification& + operator= (const DisplayNotification& x); + + virtual + ~DisplayNotification (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::xsd::cxx::tree::one< StatusType > status_; + }; + + class Displayed: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // Constructors. + // + Displayed (); + + Displayed (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Displayed (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Displayed (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Displayed (const Displayed& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Displayed* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~Displayed (); + }; + + class ProcessingNotification: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // status + // + typedef ::LinphonePrivate::Xsd::Imdn::Status2 StatusType; + typedef ::xsd::cxx::tree::traits< StatusType, char > StatusTraits; + + const StatusType& + getStatus () const; + + StatusType& + getStatus (); + + void + setStatus (const StatusType& x); + + void + setStatus (::std::unique_ptr< StatusType > p); + + ::std::unique_ptr< StatusType > + setDetachStatus (); + + // Constructors. + // + ProcessingNotification (const StatusType&); + + ProcessingNotification (::std::unique_ptr< StatusType >); + + ProcessingNotification (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ProcessingNotification (const ProcessingNotification& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ProcessingNotification* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ProcessingNotification& + operator= (const ProcessingNotification& x); + + virtual + ~ProcessingNotification (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::xsd::cxx::tree::one< StatusType > status_; + }; + + class Processed: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // Constructors. + // + Processed (); + + Processed (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Processed (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Processed (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Processed (const Processed& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Processed* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~Processed (); + }; + + class Stored: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // Constructors. + // + Stored (); + + Stored (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Stored (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Stored (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Stored (const Stored& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Stored* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~Stored (); + }; + + class Forbidden: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // Constructors. + // + Forbidden (); + + Forbidden (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Forbidden (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Forbidden (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Forbidden (const Forbidden& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Forbidden* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~Forbidden (); + }; + + class Error: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // Constructors. + // + Error (); + + Error (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Error (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Error (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Error (const Error& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Error* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~Error (); + }; + + class Status: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // delivered + // + typedef ::LinphonePrivate::Xsd::Imdn::Delivered DeliveredType; + typedef ::xsd::cxx::tree::optional< DeliveredType > DeliveredOptional; + typedef ::xsd::cxx::tree::traits< DeliveredType, char > DeliveredTraits; + + const DeliveredOptional& + getDelivered () const; + + DeliveredOptional& + getDelivered (); + + void + setDelivered (const DeliveredType& x); + + void + setDelivered (const DeliveredOptional& x); + + void + setDelivered (::std::unique_ptr< DeliveredType > p); + + // failed + // + typedef ::LinphonePrivate::Xsd::Imdn::Failed FailedType; + typedef ::xsd::cxx::tree::optional< FailedType > FailedOptional; + typedef ::xsd::cxx::tree::traits< FailedType, char > FailedTraits; + + const FailedOptional& + getFailed () const; + + FailedOptional& + getFailed (); + + void + setFailed (const FailedType& x); + + void + setFailed (const FailedOptional& x); + + void + setFailed (::std::unique_ptr< FailedType > p); + + // forbidden + // + typedef ::LinphonePrivate::Xsd::Imdn::Forbidden ForbiddenType; + typedef ::xsd::cxx::tree::optional< ForbiddenType > ForbiddenOptional; + typedef ::xsd::cxx::tree::traits< ForbiddenType, char > ForbiddenTraits; + + const ForbiddenOptional& + getForbidden () const; + + ForbiddenOptional& + getForbidden (); + + void + setForbidden (const ForbiddenType& x); + + void + setForbidden (const ForbiddenOptional& x); + + void + setForbidden (::std::unique_ptr< ForbiddenType > p); + + // error + // + typedef ::LinphonePrivate::Xsd::Imdn::Error ErrorType; + typedef ::xsd::cxx::tree::optional< ErrorType > ErrorOptional; + typedef ::xsd::cxx::tree::traits< ErrorType, char > ErrorTraits; + + const ErrorOptional& + getError () const; + + ErrorOptional& + getError (); + + void + setError (const ErrorType& x); + + void + setError (const ErrorOptional& x); + + void + setError (::std::unique_ptr< ErrorType > p); + + // reason + // + typedef ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason ReasonType; + typedef ::xsd::cxx::tree::optional< ReasonType > ReasonOptional; + typedef ::xsd::cxx::tree::traits< ReasonType, char > ReasonTraits; + + const ReasonOptional& + getReason () const; + + ReasonOptional& + getReason (); + + void + setReason (const ReasonType& x); + + void + setReason (const ReasonOptional& x); + + void + setReason (::std::unique_ptr< ReasonType > p); + + // Constructors. + // + Status (); + + Status (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Status (const Status& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Status* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Status& + operator= (const Status& x); + + virtual + ~Status (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + DeliveredOptional delivered_; + FailedOptional failed_; + ForbiddenOptional forbidden_; + ErrorOptional error_; + ReasonOptional reason_; + }; + + class Status1: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // displayed + // + typedef ::LinphonePrivate::Xsd::Imdn::Displayed DisplayedType; + typedef ::xsd::cxx::tree::optional< DisplayedType > DisplayedOptional; + typedef ::xsd::cxx::tree::traits< DisplayedType, char > DisplayedTraits; + + const DisplayedOptional& + getDisplayed () const; + + DisplayedOptional& + getDisplayed (); + + void + setDisplayed (const DisplayedType& x); + + void + setDisplayed (const DisplayedOptional& x); + + void + setDisplayed (::std::unique_ptr< DisplayedType > p); + + // forbidden + // + typedef ::LinphonePrivate::Xsd::Imdn::Forbidden ForbiddenType; + typedef ::xsd::cxx::tree::optional< ForbiddenType > ForbiddenOptional; + typedef ::xsd::cxx::tree::traits< ForbiddenType, char > ForbiddenTraits; + + const ForbiddenOptional& + getForbidden () const; + + ForbiddenOptional& + getForbidden (); + + void + setForbidden (const ForbiddenType& x); + + void + setForbidden (const ForbiddenOptional& x); + + void + setForbidden (::std::unique_ptr< ForbiddenType > p); + + // error + // + typedef ::LinphonePrivate::Xsd::Imdn::Error ErrorType; + typedef ::xsd::cxx::tree::optional< ErrorType > ErrorOptional; + typedef ::xsd::cxx::tree::traits< ErrorType, char > ErrorTraits; + + const ErrorOptional& + getError () const; + + ErrorOptional& + getError (); + + void + setError (const ErrorType& x); + + void + setError (const ErrorOptional& x); + + void + setError (::std::unique_ptr< ErrorType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + Status1 (); + + Status1 (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Status1 (const Status1& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Status1* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Status1& + operator= (const Status1& x); + + virtual + ~Status1 (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayedOptional displayed_; + ForbiddenOptional forbidden_; + ErrorOptional error_; + AnySequence any_; + }; + + class Status2: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // processed + // + typedef ::LinphonePrivate::Xsd::Imdn::Processed ProcessedType; + typedef ::xsd::cxx::tree::optional< ProcessedType > ProcessedOptional; + typedef ::xsd::cxx::tree::traits< ProcessedType, char > ProcessedTraits; + + const ProcessedOptional& + getProcessed () const; + + ProcessedOptional& + getProcessed (); + + void + setProcessed (const ProcessedType& x); + + void + setProcessed (const ProcessedOptional& x); + + void + setProcessed (::std::unique_ptr< ProcessedType > p); + + // stored + // + typedef ::LinphonePrivate::Xsd::Imdn::Stored StoredType; + typedef ::xsd::cxx::tree::optional< StoredType > StoredOptional; + typedef ::xsd::cxx::tree::traits< StoredType, char > StoredTraits; + + const StoredOptional& + getStored () const; + + StoredOptional& + getStored (); + + void + setStored (const StoredType& x); + + void + setStored (const StoredOptional& x); + + void + setStored (::std::unique_ptr< StoredType > p); + + // forbidden + // + typedef ::LinphonePrivate::Xsd::Imdn::Forbidden ForbiddenType; + typedef ::xsd::cxx::tree::optional< ForbiddenType > ForbiddenOptional; + typedef ::xsd::cxx::tree::traits< ForbiddenType, char > ForbiddenTraits; + + const ForbiddenOptional& + getForbidden () const; + + ForbiddenOptional& + getForbidden (); + + void + setForbidden (const ForbiddenType& x); + + void + setForbidden (const ForbiddenOptional& x); + + void + setForbidden (::std::unique_ptr< ForbiddenType > p); + + // error + // + typedef ::LinphonePrivate::Xsd::Imdn::Error ErrorType; + typedef ::xsd::cxx::tree::optional< ErrorType > ErrorOptional; + typedef ::xsd::cxx::tree::traits< ErrorType, char > ErrorTraits; + + const ErrorOptional& + getError () const; + + ErrorOptional& + getError (); + + void + setError (const ErrorType& x); + + void + setError (const ErrorOptional& x); + + void + setError (::std::unique_ptr< ErrorType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + Status2 (); + + Status2 (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Status2 (const Status2& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Status2* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Status2& + operator= (const Status2& x); + + virtual + ~Status2 (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + ProcessedOptional processed_; + StoredOptional stored_; + ForbiddenOptional forbidden_; + ErrorOptional error_; + AnySequence any_; + }; + } + } +} + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + ::std::ostream& + operator<< (::std::ostream&, const Imdn&); + + ::std::ostream& + operator<< (::std::ostream&, const DeliveryNotification&); + + ::std::ostream& + operator<< (::std::ostream&, const Delivered&); + + ::std::ostream& + operator<< (::std::ostream&, const Failed&); + + ::std::ostream& + operator<< (::std::ostream&, const DisplayNotification&); + + ::std::ostream& + operator<< (::std::ostream&, const Displayed&); + + ::std::ostream& + operator<< (::std::ostream&, const ProcessingNotification&); + + ::std::ostream& + operator<< (::std::ostream&, const Processed&); + + ::std::ostream& + operator<< (::std::ostream&, const Stored&); + + ::std::ostream& + operator<< (::std::ostream&, const Forbidden&); + + ::std::ostream& + operator<< (::std::ostream&, const Error&); + + ::std::ostream& + operator<< (::std::ostream&, const Status&); + + ::std::ostream& + operator<< (::std::ostream&, const Status1&); + + ::std::ostream& + operator<< (::std::ostream&, const Status2&); + } + } +} + +#include + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + // Parse a URI or a local file. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::std::string& uri, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse std::istream. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::std::istream& is, + const ::std::string& id, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::InputSource. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::xercesc::InputSource& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::DOMDocument. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (const ::xercesc::DOMDocument& d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Imdn::Imdn > + parseImdn (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + } + } +} + +#include + +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Imdn + { + // Serialize to std::ostream. + // + + void + serializeImdn (::std::ostream& os, + const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeImdn (::std::ostream& os, + const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeImdn (::std::ostream& os, + const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to xercesc::XMLFormatTarget. + // + + void + serializeImdn (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeImdn (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeImdn (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to an existing xercesc::DOMDocument. + // + + void + serializeImdn (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to a new xercesc::DOMDocument. + // + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeImdn (const ::LinphonePrivate::Xsd::Imdn::Imdn& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + operator<< (::xercesc::DOMElement&, const Imdn&); + + void + operator<< (::xercesc::DOMElement&, const DeliveryNotification&); + + void + operator<< (::xercesc::DOMElement&, const Delivered&); + + void + operator<< (::xercesc::DOMAttr&, const Delivered&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Delivered&); + + void + operator<< (::xercesc::DOMElement&, const Failed&); + + void + operator<< (::xercesc::DOMAttr&, const Failed&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Failed&); + + void + operator<< (::xercesc::DOMElement&, const DisplayNotification&); + + void + operator<< (::xercesc::DOMElement&, const Displayed&); + + void + operator<< (::xercesc::DOMAttr&, const Displayed&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Displayed&); + + void + operator<< (::xercesc::DOMElement&, const ProcessingNotification&); + + void + operator<< (::xercesc::DOMElement&, const Processed&); + + void + operator<< (::xercesc::DOMAttr&, const Processed&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Processed&); + + void + operator<< (::xercesc::DOMElement&, const Stored&); + + void + operator<< (::xercesc::DOMAttr&, const Stored&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Stored&); + + void + operator<< (::xercesc::DOMElement&, const Forbidden&); + + void + operator<< (::xercesc::DOMAttr&, const Forbidden&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Forbidden&); + + void + operator<< (::xercesc::DOMElement&, const Error&); + + void + operator<< (::xercesc::DOMAttr&, const Error&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Error&); + + void + operator<< (::xercesc::DOMElement&, const Status&); + + void + operator<< (::xercesc::DOMElement&, const Status1&); + + void + operator<< (::xercesc::DOMElement&, const Status2&); + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + +#endif // XML_IMDN_H diff --git a/src/xml/imdn.xsd b/src/xml/imdn.xsd new file mode 100644 index 000000000..f69675f60 --- /dev/null +++ b/src/xml/imdn.xsd @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/xml/is-composing.cpp b/src/xml/is-composing.cpp new file mode 100644 index 000000000..ced754a84 --- /dev/null +++ b/src/xml/is-composing.cpp @@ -0,0 +1,971 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#include "is-composing.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + // IsComposing + // + + const IsComposing::StateType& IsComposing:: + getState () const + { + return this->state_.get (); + } + + IsComposing::StateType& IsComposing:: + getState () + { + return this->state_.get (); + } + + void IsComposing:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void IsComposing:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< IsComposing::StateType > IsComposing:: + setDetachState () + { + return this->state_.detach (); + } + + const IsComposing::LastactiveOptional& IsComposing:: + getLastactive () const + { + return this->lastactive_; + } + + IsComposing::LastactiveOptional& IsComposing:: + getLastactive () + { + return this->lastactive_; + } + + void IsComposing:: + setLastactive (const LastactiveType& x) + { + this->lastactive_.set (x); + } + + void IsComposing:: + setLastactive (const LastactiveOptional& x) + { + this->lastactive_ = x; + } + + void IsComposing:: + setLastactive (::std::unique_ptr< LastactiveType > x) + { + this->lastactive_.set (std::move (x)); + } + + const IsComposing::ContenttypeOptional& IsComposing:: + getContenttype () const + { + return this->contenttype_; + } + + IsComposing::ContenttypeOptional& IsComposing:: + getContenttype () + { + return this->contenttype_; + } + + void IsComposing:: + setContenttype (const ContenttypeType& x) + { + this->contenttype_.set (x); + } + + void IsComposing:: + setContenttype (const ContenttypeOptional& x) + { + this->contenttype_ = x; + } + + void IsComposing:: + setContenttype (::std::unique_ptr< ContenttypeType > x) + { + this->contenttype_.set (std::move (x)); + } + + const IsComposing::RefreshOptional& IsComposing:: + getRefresh () const + { + return this->refresh_; + } + + IsComposing::RefreshOptional& IsComposing:: + getRefresh () + { + return this->refresh_; + } + + void IsComposing:: + setRefresh (const RefreshType& x) + { + this->refresh_.set (x); + } + + void IsComposing:: + setRefresh (const RefreshOptional& x) + { + this->refresh_ = x; + } + + const IsComposing::AnySequence& IsComposing:: + getAny () const + { + return this->any_; + } + + IsComposing::AnySequence& IsComposing:: + getAny () + { + return this->any_; + } + + void IsComposing:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ::xercesc::DOMDocument& IsComposing:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& IsComposing:: + getDomDocument () + { + return *this->dom_document_; + } + } + } +} + +#include + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_factory_plate< 0, char > + type_factory_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + // IsComposing + // + + IsComposing:: + IsComposing (const StateType& state) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + state_ (state, this), + lastactive_ (this), + contenttype_ (this), + refresh_ (this), + any_ (this->getDomDocument ()) + { + } + + IsComposing:: + IsComposing (const IsComposing& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + state_ (x.state_, f, this), + lastactive_ (x.lastactive_, f, this), + contenttype_ (x.contenttype_, f, this), + refresh_ (x.refresh_, f, this), + any_ (x.any_, this->getDomDocument ()) + { + } + + IsComposing:: + IsComposing (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + state_ (this), + lastactive_ (this), + contenttype_ (this), + refresh_ (this), + any_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void IsComposing:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // state + // + if (n.name () == "state" && n.namespace_ () == "urn:ietf:params:xml:ns:im-iscomposing") + { + ::std::unique_ptr< StateType > r ( + StateTraits::create (i, f, this)); + + if (!state_.present ()) + { + this->state_.set (::std::move (r)); + continue; + } + } + + // lastactive + // + if (n.name () == "lastactive" && n.namespace_ () == "urn:ietf:params:xml:ns:im-iscomposing") + { + ::std::unique_ptr< LastactiveType > r ( + LastactiveTraits::create (i, f, this)); + + if (!this->lastactive_) + { + this->lastactive_.set (::std::move (r)); + continue; + } + } + + // contenttype + // + if (n.name () == "contenttype" && n.namespace_ () == "urn:ietf:params:xml:ns:im-iscomposing") + { + ::std::unique_ptr< ContenttypeType > r ( + ContenttypeTraits::create (i, f, this)); + + if (!this->contenttype_) + { + this->contenttype_.set (::std::move (r)); + continue; + } + } + + // refresh + // + if (n.name () == "refresh" && n.namespace_ () == "urn:ietf:params:xml:ns:im-iscomposing") + { + if (!this->refresh_) + { + this->refresh_.set (RefreshTraits::create (i, f, this)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:im-iscomposing")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + if (!state_.present ()) + { + throw ::xsd::cxx::tree::expected_element< char > ( + "state", + "urn:ietf:params:xml:ns:im-iscomposing"); + } + } + + IsComposing* IsComposing:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class IsComposing (*this, f, c); + } + + IsComposing& IsComposing:: + operator= (const IsComposing& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->state_ = x.state_; + this->lastactive_ = x.lastactive_; + this->contenttype_ = x.contenttype_; + this->refresh_ = x.refresh_; + this->any_ = x.any_; + } + + return *this; + } + + IsComposing:: + ~IsComposing () + { + } + } + } +} + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::std_ostream_plate< 0, char > + std_ostream_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + ::std::ostream& + operator<< (::std::ostream& o, const IsComposing& i) + { + o << ::std::endl << "state: " << i.getState (); + if (i.getLastactive ()) + { + o << ::std::endl << "lastactive: " << *i.getLastactive (); + } + + if (i.getContenttype ()) + { + o << ::std::endl << "contenttype: " << *i.getContenttype (); + } + + if (i.getRefresh ()) + { + o << ::std::endl << "refresh: " << *i.getRefresh (); + } + + return o; + } + } + } +} + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > ( + ::LinphonePrivate::Xsd::IsComposing::parseIsComposing ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > ( + ::LinphonePrivate::Xsd::IsComposing::parseIsComposing ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::std::string& u, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > ( + ::LinphonePrivate::Xsd::IsComposing::parseIsComposing ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::IsComposing::parseIsComposing (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::IsComposing::parseIsComposing (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::IsComposing::parseIsComposing (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::IsComposing::parseIsComposing (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::IsComposing::parseIsComposing (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + const ::std::string& sid, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::IsComposing::parseIsComposing (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > ( + ::LinphonePrivate::Xsd::IsComposing::parseIsComposing ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > ( + ::LinphonePrivate::Xsd::IsComposing::parseIsComposing ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::xercesc::InputSource& i, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > ( + ::LinphonePrivate::Xsd::IsComposing::parseIsComposing ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::xercesc::DOMDocument& doc, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + static_cast< ::xercesc::DOMDocument* > (doc.cloneNode (true))); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > ( + ::LinphonePrivate::Xsd::IsComposing::parseIsComposing ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "isComposing" && + n.namespace_ () == "urn:ietf:params:xml:ns:im-iscomposing") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::IsComposing::IsComposing, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "isComposing", + "urn:ietf:params:xml:ns:im-iscomposing"); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties&) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > c ( + ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) && + !(f & ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom)) + ? static_cast< ::xercesc::DOMDocument* > (d->cloneNode (true)) + : 0); + + ::xercesc::DOMDocument& doc (c.get () ? *c : *d); + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + doc.setUserData (::LinphonePrivate::Xsd::XmlSchema::dom::treeNodeKey, + (c.get () ? &c : &d), + 0); + + if (n.name () == "isComposing" && + n.namespace_ () == "urn:ietf:params:xml:ns:im-iscomposing") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::IsComposing::IsComposing, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "isComposing", + "urn:ietf:params:xml:ns:im-iscomposing"); + } + } + } +} + +#include +#include +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_serializer_plate< 0, char > + type_serializer_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + void + serializeIsComposing (::std::ostream& o, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::IsComposing::serializeIsComposing (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeIsComposing (::std::ostream& o, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::IsComposing::serializeIsComposing (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeIsComposing (::std::ostream& o, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::IsComposing::serializeIsComposing (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeIsComposing (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::IsComposing::serializeIsComposing (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeIsComposing (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::IsComposing::serializeIsComposing (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeIsComposing (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::IsComposing::serializeIsComposing (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeIsComposing (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + ::LinphonePrivate::Xsd::XmlSchema::Flags) + { + ::xercesc::DOMElement& e (*d.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "isComposing" && + n.namespace_ () == "urn:ietf:params:xml:ns:im-iscomposing") + { + e << s; + } + else + { + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "isComposing", + "urn:ietf:params:xml:ns:im-iscomposing"); + } + } + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeIsComposing (const ::LinphonePrivate::Xsd::IsComposing::IsComposing& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::serialize< char > ( + "isComposing", + "urn:ietf:params:xml:ns:im-iscomposing", + m, f)); + + ::LinphonePrivate::Xsd::IsComposing::serializeIsComposing (*d, s, f); + return d; + } + + void + operator<< (::xercesc::DOMElement& e, const IsComposing& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // state + // + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "state", + "urn:ietf:params:xml:ns:im-iscomposing", + e)); + + s << i.getState (); + } + + // lastactive + // + if (i.getLastactive ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "lastactive", + "urn:ietf:params:xml:ns:im-iscomposing", + e)); + + s << *i.getLastactive (); + } + + // contenttype + // + if (i.getContenttype ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "contenttype", + "urn:ietf:params:xml:ns:im-iscomposing", + e)); + + s << *i.getContenttype (); + } + + // refresh + // + if (i.getRefresh ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "refresh", + "urn:ietf:params:xml:ns:im-iscomposing", + e)); + + s << *i.getRefresh (); + } + + // any + // + for (IsComposing::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + } + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + diff --git a/src/xml/is-composing.h b/src/xml/is-composing.h new file mode 100644 index 000000000..a19585c91 --- /dev/null +++ b/src/xml/is-composing.h @@ -0,0 +1,687 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +#ifndef XML_IS_COMPOSING_H +#define XML_IS_COMPOSING_H + +#ifndef XSD_CXX11 +#define XSD_CXX11 +#endif + +#ifndef XSD_USE_CHAR +#define XSD_USE_CHAR +#endif + +#ifndef XSD_CXX_TREE_USE_CHAR +#define XSD_CXX_TREE_USE_CHAR +#endif + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#if (XSD_INT_VERSION != 4000000L) +#error XSD runtime version mismatch +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace XmlSchema + { + // anyType and anySimpleType. + // + typedef ::xsd::cxx::tree::type Type; + typedef ::xsd::cxx::tree::simple_type< char, Type > SimpleType; + typedef ::xsd::cxx::tree::type Container; + + // 8-bit + // + typedef signed char Byte; + typedef unsigned char UnsignedByte; + + // 16-bit + // + typedef short Short; + typedef unsigned short UnsignedShort; + + // 32-bit + // + typedef int Int; + typedef unsigned int UnsignedInt; + + // 64-bit + // + typedef long long Long; + typedef unsigned long long UnsignedLong; + + // Supposed to be arbitrary-length integral types. + // + typedef long long Integer; + typedef long long NonPositiveInteger; + typedef unsigned long long NonNegativeInteger; + typedef unsigned long long PositiveInteger; + typedef long long NegativeInteger; + + // Boolean. + // + typedef bool Boolean; + + // Floating-point types. + // + typedef float Float; + typedef double Double; + typedef double Decimal; + + // String types. + // + typedef ::xsd::cxx::tree::string< char, SimpleType > String; + typedef ::xsd::cxx::tree::normalized_string< char, String > NormalizedString; + typedef ::xsd::cxx::tree::token< char, NormalizedString > Token; + typedef ::xsd::cxx::tree::name< char, Token > Name; + typedef ::xsd::cxx::tree::nmtoken< char, Token > Nmtoken; + typedef ::xsd::cxx::tree::nmtokens< char, SimpleType, Nmtoken > Nmtokens; + typedef ::xsd::cxx::tree::ncname< char, Name > Ncname; + typedef ::xsd::cxx::tree::language< char, Token > Language; + + // ID/IDREF. + // + typedef ::xsd::cxx::tree::id< char, Ncname > Id; + typedef ::xsd::cxx::tree::idref< char, Ncname, Type > Idref; + typedef ::xsd::cxx::tree::idrefs< char, SimpleType, Idref > Idrefs; + + // URI. + // + typedef ::xsd::cxx::tree::uri< char, SimpleType > Uri; + + // Qualified name. + // + typedef ::xsd::cxx::tree::qname< char, SimpleType, Uri, Ncname > Qname; + + // Binary. + // + typedef ::xsd::cxx::tree::buffer< char > Buffer; + typedef ::xsd::cxx::tree::base64_binary< char, SimpleType > Base64Binary; + typedef ::xsd::cxx::tree::hex_binary< char, SimpleType > HexBinary; + + // Date/time. + // + typedef ::xsd::cxx::tree::time_zone TimeZone; + typedef ::xsd::cxx::tree::date< char, SimpleType > Date; + typedef ::xsd::cxx::tree::date_time< char, SimpleType > DateTime; + typedef ::xsd::cxx::tree::duration< char, SimpleType > Duration; + typedef ::xsd::cxx::tree::gday< char, SimpleType > Gday; + typedef ::xsd::cxx::tree::gmonth< char, SimpleType > Gmonth; + typedef ::xsd::cxx::tree::gmonth_day< char, SimpleType > GmonthDay; + typedef ::xsd::cxx::tree::gyear< char, SimpleType > Gyear; + typedef ::xsd::cxx::tree::gyear_month< char, SimpleType > GyearMonth; + typedef ::xsd::cxx::tree::time< char, SimpleType > Time; + + // Entity. + // + typedef ::xsd::cxx::tree::entity< char, Ncname > Entity; + typedef ::xsd::cxx::tree::entities< char, SimpleType, Entity > Entities; + + typedef ::xsd::cxx::tree::content_order ContentOrder; + // Namespace information and list stream. Used in + // serialization functions. + // + typedef ::xsd::cxx::xml::dom::namespace_info< char > NamespaceInfo; + typedef ::xsd::cxx::xml::dom::namespace_infomap< char > NamespaceInfomap; + typedef ::xsd::cxx::tree::list_stream< char > ListStream; + typedef ::xsd::cxx::tree::as_double< Double > AsDouble; + typedef ::xsd::cxx::tree::as_decimal< Decimal > AsDecimal; + typedef ::xsd::cxx::tree::facet Facet; + + // Flags and properties. + // + typedef ::xsd::cxx::tree::flags Flags; + typedef ::xsd::cxx::tree::properties< char > Properties; + + // Parsing/serialization diagnostics. + // + typedef ::xsd::cxx::tree::severity Severity; + typedef ::xsd::cxx::tree::error< char > Error; + typedef ::xsd::cxx::tree::diagnostics< char > Diagnostics; + + // Exceptions. + // + typedef ::xsd::cxx::tree::exception< char > Exception; + typedef ::xsd::cxx::tree::bounds< char > Bounds; + typedef ::xsd::cxx::tree::duplicate_id< char > DuplicateId; + typedef ::xsd::cxx::tree::parsing< char > Parsing; + typedef ::xsd::cxx::tree::expected_element< char > ExpectedElement; + typedef ::xsd::cxx::tree::unexpected_element< char > UnexpectedElement; + typedef ::xsd::cxx::tree::expected_attribute< char > ExpectedAttribute; + typedef ::xsd::cxx::tree::unexpected_enumerator< char > UnexpectedEnumerator; + typedef ::xsd::cxx::tree::expected_text_content< char > ExpectedTextContent; + typedef ::xsd::cxx::tree::no_prefix_mapping< char > NoPrefixMapping; + typedef ::xsd::cxx::tree::no_type_info< char > NoTypeInfo; + typedef ::xsd::cxx::tree::not_derived< char > NotDerived; + typedef ::xsd::cxx::tree::serialization< char > Serialization; + + // Error handler callback interface. + // + typedef ::xsd::cxx::xml::error_handler< char > ErrorHandler; + + // DOM interaction. + // + namespace dom + { + // Automatic pointer for DOMDocument. + // + using ::xsd::cxx::xml::dom::unique_ptr; + +#ifndef XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA +#define XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA + // DOM user data key for back pointers to tree nodes. + // + const XMLCh* const treeNodeKey = ::xsd::cxx::tree::user_data_keys::node; +#endif + } + } + } +} + +// Forward declarations. +// +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + class IsComposing; + } + } +} + + +#include // ::std::unique_ptr +#include // std::numeric_limits +#include // std::binary_search +#include // std::move + +#include + +#include +#include +#include +#include + +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + class IsComposing: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // state + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + // lastactive + // + typedef ::LinphonePrivate::Xsd::XmlSchema::DateTime LastactiveType; + typedef ::xsd::cxx::tree::optional< LastactiveType > LastactiveOptional; + typedef ::xsd::cxx::tree::traits< LastactiveType, char > LastactiveTraits; + + const LastactiveOptional& + getLastactive () const; + + LastactiveOptional& + getLastactive (); + + void + setLastactive (const LastactiveType& x); + + void + setLastactive (const LastactiveOptional& x); + + void + setLastactive (::std::unique_ptr< LastactiveType > p); + + // contenttype + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String ContenttypeType; + typedef ::xsd::cxx::tree::optional< ContenttypeType > ContenttypeOptional; + typedef ::xsd::cxx::tree::traits< ContenttypeType, char > ContenttypeTraits; + + const ContenttypeOptional& + getContenttype () const; + + ContenttypeOptional& + getContenttype (); + + void + setContenttype (const ContenttypeType& x); + + void + setContenttype (const ContenttypeOptional& x); + + void + setContenttype (::std::unique_ptr< ContenttypeType > p); + + // refresh + // + typedef ::LinphonePrivate::Xsd::XmlSchema::PositiveInteger RefreshType; + typedef ::xsd::cxx::tree::optional< RefreshType > RefreshOptional; + typedef ::xsd::cxx::tree::traits< RefreshType, char > RefreshTraits; + + const RefreshOptional& + getRefresh () const; + + RefreshOptional& + getRefresh (); + + void + setRefresh (const RefreshType& x); + + void + setRefresh (const RefreshOptional& x); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + IsComposing (const StateType&); + + IsComposing (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + IsComposing (const IsComposing& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual IsComposing* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + IsComposing& + operator= (const IsComposing& x); + + virtual + ~IsComposing (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + ::xsd::cxx::tree::one< StateType > state_; + LastactiveOptional lastactive_; + ContenttypeOptional contenttype_; + RefreshOptional refresh_; + AnySequence any_; + }; + } + } +} + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + ::std::ostream& + operator<< (::std::ostream&, const IsComposing&); + } + } +} + +#include + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + // Parse a URI or a local file. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::std::string& uri, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse std::istream. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::std::istream& is, + const ::std::string& id, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::InputSource. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::xercesc::InputSource& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::DOMDocument. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (const ::xercesc::DOMDocument& d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::IsComposing::IsComposing > + parseIsComposing (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + } + } +} + +#include + +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace IsComposing + { + // Serialize to std::ostream. + // + + void + serializeIsComposing (::std::ostream& os, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeIsComposing (::std::ostream& os, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeIsComposing (::std::ostream& os, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to xercesc::XMLFormatTarget. + // + + void + serializeIsComposing (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeIsComposing (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeIsComposing (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to an existing xercesc::DOMDocument. + // + + void + serializeIsComposing (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to a new xercesc::DOMDocument. + // + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeIsComposing (const ::LinphonePrivate::Xsd::IsComposing::IsComposing& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + operator<< (::xercesc::DOMElement&, const IsComposing&); + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + +#endif // XML_IS_COMPOSING_H diff --git a/src/xml/is-composing.xsd b/src/xml/is-composing.xsd new file mode 100644 index 000000000..7cf4a8b70 --- /dev/null +++ b/src/xml/is-composing.xsd @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/src/xml/linphone-imdn.cpp b/src/xml/linphone-imdn.cpp new file mode 100644 index 000000000..5f064f1a5 --- /dev/null +++ b/src/xml/linphone-imdn.cpp @@ -0,0 +1,726 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#include "linphone-imdn.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + // ImdnReason + // + + const ImdnReason::CodeType& ImdnReason:: + getCode () const + { + return this->code_.get (); + } + + ImdnReason::CodeType& ImdnReason:: + getCode () + { + return this->code_.get (); + } + + void ImdnReason:: + setCode (const CodeType& x) + { + this->code_.set (x); + } + + ImdnReason::CodeType ImdnReason:: + getCodeDefaultValue () + { + return CodeType (200); + } + } + } +} + +#include + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_factory_plate< 0, char > + type_factory_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + // ImdnReason + // + + ImdnReason:: + ImdnReason () + : ::LinphonePrivate::Xsd::XmlSchema::String (), + code_ (getCodeDefaultValue (), this) + { + } + + ImdnReason:: + ImdnReason (const char* _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + code_ (getCodeDefaultValue (), this) + { + } + + ImdnReason:: + ImdnReason (const ::std::string& _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + code_ (getCodeDefaultValue (), this) + { + } + + ImdnReason:: + ImdnReason (const ::LinphonePrivate::Xsd::XmlSchema::String& _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + code_ (getCodeDefaultValue (), this) + { + } + + ImdnReason:: + ImdnReason (const ImdnReason& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (x, f, c), + code_ (x.code_, f, this) + { + } + + ImdnReason:: + ImdnReason (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + code_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, false, false, true); + this->parse (p, f); + } + } + + void ImdnReason:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "code" && n.namespace_ ().empty ()) + { + this->code_.set (CodeTraits::create (i, f, this)); + continue; + } + } + + if (!code_.present ()) + { + this->code_.set (getCodeDefaultValue ()); + } + } + + ImdnReason* ImdnReason:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ImdnReason (*this, f, c); + } + + ImdnReason& ImdnReason:: + operator= (const ImdnReason& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = x; + this->code_ = x.code_; + } + + return *this; + } + + ImdnReason:: + ~ImdnReason () + { + } + } + } +} + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::std_ostream_plate< 0, char > + std_ostream_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + ::std::ostream& + operator<< (::std::ostream& o, const ImdnReason& i) + { + o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + + o << ::std::endl << "code: " << i.getCode (); + return o; + } + } + } +} + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > ( + ::LinphonePrivate::Xsd::LinphoneImdn::parseReason ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > ( + ::LinphonePrivate::Xsd::LinphoneImdn::parseReason ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::std::string& u, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > ( + ::LinphonePrivate::Xsd::LinphoneImdn::parseReason ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::LinphoneImdn::parseReason (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::LinphoneImdn::parseReason (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::LinphoneImdn::parseReason (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::LinphoneImdn::parseReason (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::LinphoneImdn::parseReason (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + const ::std::string& sid, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::LinphoneImdn::parseReason (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > ( + ::LinphonePrivate::Xsd::LinphoneImdn::parseReason ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > ( + ::LinphonePrivate::Xsd::LinphoneImdn::parseReason ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::xercesc::InputSource& i, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > ( + ::LinphonePrivate::Xsd::LinphoneImdn::parseReason ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::xercesc::DOMDocument& doc, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + static_cast< ::xercesc::DOMDocument* > (doc.cloneNode (true))); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > ( + ::LinphonePrivate::Xsd::LinphoneImdn::parseReason ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "reason" && + n.namespace_ () == "http://www.linphone.org/xsds/imdn.xsd") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "reason", + "http://www.linphone.org/xsds/imdn.xsd"); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties&) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > c ( + ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) && + !(f & ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom)) + ? static_cast< ::xercesc::DOMDocument* > (d->cloneNode (true)) + : 0); + + ::xercesc::DOMDocument& doc (c.get () ? *c : *d); + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + doc.setUserData (::LinphonePrivate::Xsd::XmlSchema::dom::treeNodeKey, + (c.get () ? &c : &d), + 0); + + if (n.name () == "reason" && + n.namespace_ () == "http://www.linphone.org/xsds/imdn.xsd") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "reason", + "http://www.linphone.org/xsds/imdn.xsd"); + } + } + } +} + +#include +#include +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_serializer_plate< 0, char > + type_serializer_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + void + serializeReason (::std::ostream& o, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::LinphoneImdn::serializeReason (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeReason (::std::ostream& o, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::LinphoneImdn::serializeReason (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeReason (::std::ostream& o, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::LinphoneImdn::serializeReason (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeReason (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::LinphoneImdn::serializeReason (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeReason (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::LinphoneImdn::serializeReason (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeReason (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::LinphoneImdn::serializeReason (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeReason (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + ::LinphonePrivate::Xsd::XmlSchema::Flags) + { + ::xercesc::DOMElement& e (*d.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "reason" && + n.namespace_ () == "http://www.linphone.org/xsds/imdn.xsd") + { + e << s; + } + else + { + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "reason", + "http://www.linphone.org/xsds/imdn.xsd"); + } + } + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeReason (const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::serialize< char > ( + "reason", + "http://www.linphone.org/xsds/imdn.xsd", + m, f)); + + ::LinphonePrivate::Xsd::LinphoneImdn::serializeReason (*d, s, f); + return d; + } + + void + operator<< (::xercesc::DOMElement& e, const ImdnReason& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + + // code + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "code", + e)); + + a << i.getCode (); + } + } + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + diff --git a/src/xml/linphone-imdn.h b/src/xml/linphone-imdn.h new file mode 100644 index 000000000..ea7478f60 --- /dev/null +++ b/src/xml/linphone-imdn.h @@ -0,0 +1,601 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +#ifndef XML_LINPHONE_IMDN_H +#define XML_LINPHONE_IMDN_H + +#ifndef XSD_CXX11 +#define XSD_CXX11 +#endif + +#ifndef XSD_USE_CHAR +#define XSD_USE_CHAR +#endif + +#ifndef XSD_CXX_TREE_USE_CHAR +#define XSD_CXX_TREE_USE_CHAR +#endif + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#if (XSD_INT_VERSION != 4000000L) +#error XSD runtime version mismatch +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace XmlSchema + { + // anyType and anySimpleType. + // + typedef ::xsd::cxx::tree::type Type; + typedef ::xsd::cxx::tree::simple_type< char, Type > SimpleType; + typedef ::xsd::cxx::tree::type Container; + + // 8-bit + // + typedef signed char Byte; + typedef unsigned char UnsignedByte; + + // 16-bit + // + typedef short Short; + typedef unsigned short UnsignedShort; + + // 32-bit + // + typedef int Int; + typedef unsigned int UnsignedInt; + + // 64-bit + // + typedef long long Long; + typedef unsigned long long UnsignedLong; + + // Supposed to be arbitrary-length integral types. + // + typedef long long Integer; + typedef long long NonPositiveInteger; + typedef unsigned long long NonNegativeInteger; + typedef unsigned long long PositiveInteger; + typedef long long NegativeInteger; + + // Boolean. + // + typedef bool Boolean; + + // Floating-point types. + // + typedef float Float; + typedef double Double; + typedef double Decimal; + + // String types. + // + typedef ::xsd::cxx::tree::string< char, SimpleType > String; + typedef ::xsd::cxx::tree::normalized_string< char, String > NormalizedString; + typedef ::xsd::cxx::tree::token< char, NormalizedString > Token; + typedef ::xsd::cxx::tree::name< char, Token > Name; + typedef ::xsd::cxx::tree::nmtoken< char, Token > Nmtoken; + typedef ::xsd::cxx::tree::nmtokens< char, SimpleType, Nmtoken > Nmtokens; + typedef ::xsd::cxx::tree::ncname< char, Name > Ncname; + typedef ::xsd::cxx::tree::language< char, Token > Language; + + // ID/IDREF. + // + typedef ::xsd::cxx::tree::id< char, Ncname > Id; + typedef ::xsd::cxx::tree::idref< char, Ncname, Type > Idref; + typedef ::xsd::cxx::tree::idrefs< char, SimpleType, Idref > Idrefs; + + // URI. + // + typedef ::xsd::cxx::tree::uri< char, SimpleType > Uri; + + // Qualified name. + // + typedef ::xsd::cxx::tree::qname< char, SimpleType, Uri, Ncname > Qname; + + // Binary. + // + typedef ::xsd::cxx::tree::buffer< char > Buffer; + typedef ::xsd::cxx::tree::base64_binary< char, SimpleType > Base64Binary; + typedef ::xsd::cxx::tree::hex_binary< char, SimpleType > HexBinary; + + // Date/time. + // + typedef ::xsd::cxx::tree::time_zone TimeZone; + typedef ::xsd::cxx::tree::date< char, SimpleType > Date; + typedef ::xsd::cxx::tree::date_time< char, SimpleType > DateTime; + typedef ::xsd::cxx::tree::duration< char, SimpleType > Duration; + typedef ::xsd::cxx::tree::gday< char, SimpleType > Gday; + typedef ::xsd::cxx::tree::gmonth< char, SimpleType > Gmonth; + typedef ::xsd::cxx::tree::gmonth_day< char, SimpleType > GmonthDay; + typedef ::xsd::cxx::tree::gyear< char, SimpleType > Gyear; + typedef ::xsd::cxx::tree::gyear_month< char, SimpleType > GyearMonth; + typedef ::xsd::cxx::tree::time< char, SimpleType > Time; + + // Entity. + // + typedef ::xsd::cxx::tree::entity< char, Ncname > Entity; + typedef ::xsd::cxx::tree::entities< char, SimpleType, Entity > Entities; + + typedef ::xsd::cxx::tree::content_order ContentOrder; + // Namespace information and list stream. Used in + // serialization functions. + // + typedef ::xsd::cxx::xml::dom::namespace_info< char > NamespaceInfo; + typedef ::xsd::cxx::xml::dom::namespace_infomap< char > NamespaceInfomap; + typedef ::xsd::cxx::tree::list_stream< char > ListStream; + typedef ::xsd::cxx::tree::as_double< Double > AsDouble; + typedef ::xsd::cxx::tree::as_decimal< Decimal > AsDecimal; + typedef ::xsd::cxx::tree::facet Facet; + + // Flags and properties. + // + typedef ::xsd::cxx::tree::flags Flags; + typedef ::xsd::cxx::tree::properties< char > Properties; + + // Parsing/serialization diagnostics. + // + typedef ::xsd::cxx::tree::severity Severity; + typedef ::xsd::cxx::tree::error< char > Error; + typedef ::xsd::cxx::tree::diagnostics< char > Diagnostics; + + // Exceptions. + // + typedef ::xsd::cxx::tree::exception< char > Exception; + typedef ::xsd::cxx::tree::bounds< char > Bounds; + typedef ::xsd::cxx::tree::duplicate_id< char > DuplicateId; + typedef ::xsd::cxx::tree::parsing< char > Parsing; + typedef ::xsd::cxx::tree::expected_element< char > ExpectedElement; + typedef ::xsd::cxx::tree::unexpected_element< char > UnexpectedElement; + typedef ::xsd::cxx::tree::expected_attribute< char > ExpectedAttribute; + typedef ::xsd::cxx::tree::unexpected_enumerator< char > UnexpectedEnumerator; + typedef ::xsd::cxx::tree::expected_text_content< char > ExpectedTextContent; + typedef ::xsd::cxx::tree::no_prefix_mapping< char > NoPrefixMapping; + typedef ::xsd::cxx::tree::no_type_info< char > NoTypeInfo; + typedef ::xsd::cxx::tree::not_derived< char > NotDerived; + typedef ::xsd::cxx::tree::serialization< char > Serialization; + + // Error handler callback interface. + // + typedef ::xsd::cxx::xml::error_handler< char > ErrorHandler; + + // DOM interaction. + // + namespace dom + { + // Automatic pointer for DOMDocument. + // + using ::xsd::cxx::xml::dom::unique_ptr; + +#ifndef XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA +#define XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA + // DOM user data key for back pointers to tree nodes. + // + const XMLCh* const treeNodeKey = ::xsd::cxx::tree::user_data_keys::node; +#endif + } + } + } +} + +// Forward declarations. +// +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + class ImdnReason; + } + } +} + + +#include // ::std::unique_ptr +#include // std::numeric_limits +#include // std::binary_search +#include // std::move + +#include + +#include +#include +#include +#include + +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + class ImdnReason: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + // code + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Int CodeType; + typedef ::xsd::cxx::tree::traits< CodeType, char > CodeTraits; + + const CodeType& + getCode () const; + + CodeType& + getCode (); + + void + setCode (const CodeType& x); + + static CodeType + getCodeDefaultValue (); + + // Constructors. + // + ImdnReason (); + + ImdnReason (const char*); + + ImdnReason (const ::std::string&); + + ImdnReason (const ::LinphonePrivate::Xsd::XmlSchema::String&); + + ImdnReason (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ImdnReason (const ImdnReason& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ImdnReason* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ImdnReason& + operator= (const ImdnReason& x); + + virtual + ~ImdnReason (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::xsd::cxx::tree::one< CodeType > code_; + }; + } + } +} + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + ::std::ostream& + operator<< (::std::ostream&, const ImdnReason&); + } + } +} + +#include + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + // Parse a URI or a local file. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::std::string& uri, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse std::istream. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::std::istream& is, + const ::std::string& id, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::InputSource. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::xercesc::InputSource& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::DOMDocument. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (const ::xercesc::DOMDocument& d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason > + parseReason (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + } + } +} + +#include + +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace LinphoneImdn + { + // Serialize to std::ostream. + // + + void + serializeReason (::std::ostream& os, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeReason (::std::ostream& os, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeReason (::std::ostream& os, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to xercesc::XMLFormatTarget. + // + + void + serializeReason (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeReason (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeReason (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to an existing xercesc::DOMDocument. + // + + void + serializeReason (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to a new xercesc::DOMDocument. + // + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeReason (const ::LinphonePrivate::Xsd::LinphoneImdn::ImdnReason& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + operator<< (::xercesc::DOMElement&, const ImdnReason&); + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + +#endif // XML_LINPHONE_IMDN_H diff --git a/src/xml/linphone-imdn.xsd b/src/xml/linphone-imdn.xsd new file mode 100644 index 000000000..6a6136a0d --- /dev/null +++ b/src/xml/linphone-imdn.xsd @@ -0,0 +1,15 @@ + + + + + + + + + + + + diff --git a/src/xml/prologue.txt b/src/xml/prologue.txt new file mode 100644 index 000000000..2349b5d94 --- /dev/null +++ b/src/xml/prologue.txt @@ -0,0 +1,14 @@ +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif diff --git a/src/xml/resource-lists.cpp b/src/xml/resource-lists.cpp new file mode 100644 index 000000000..d74589fde --- /dev/null +++ b/src/xml/resource-lists.cpp @@ -0,0 +1,2531 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#include "resource-lists.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + // ListType + // + + const ListType::DisplayNameOptional& ListType:: + getDisplayName () const + { + return this->display_name_; + } + + ListType::DisplayNameOptional& ListType:: + getDisplayName () + { + return this->display_name_; + } + + void ListType:: + setDisplayName (const DisplayNameType& x) + { + this->display_name_.set (x); + } + + void ListType:: + setDisplayName (const DisplayNameOptional& x) + { + this->display_name_ = x; + } + + void ListType:: + setDisplayName (::std::unique_ptr< DisplayNameType > x) + { + this->display_name_.set (std::move (x)); + } + + const ListType::ListSequence& ListType:: + getList () const + { + return this->list_; + } + + ListType::ListSequence& ListType:: + getList () + { + return this->list_; + } + + void ListType:: + setList (const ListSequence& s) + { + this->list_ = s; + } + + const ListType::ExternalSequence& ListType:: + getExternal () const + { + return this->external_; + } + + ListType::ExternalSequence& ListType:: + getExternal () + { + return this->external_; + } + + void ListType:: + setExternal (const ExternalSequence& s) + { + this->external_ = s; + } + + const ListType::EntrySequence& ListType:: + getEntry () const + { + return this->entry_; + } + + ListType::EntrySequence& ListType:: + getEntry () + { + return this->entry_; + } + + void ListType:: + setEntry (const EntrySequence& s) + { + this->entry_ = s; + } + + const ListType::EntryRefSequence& ListType:: + getEntryRef () const + { + return this->entry_ref_; + } + + ListType::EntryRefSequence& ListType:: + getEntryRef () + { + return this->entry_ref_; + } + + void ListType:: + setEntryRef (const EntryRefSequence& s) + { + this->entry_ref_ = s; + } + + const ListType::AnySequence& ListType:: + getAny () const + { + return this->any_; + } + + ListType::AnySequence& ListType:: + getAny () + { + return this->any_; + } + + void ListType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ListType::NameOptional& ListType:: + getName () const + { + return this->name_; + } + + ListType::NameOptional& ListType:: + getName () + { + return this->name_; + } + + void ListType:: + setName (const NameType& x) + { + this->name_.set (x); + } + + void ListType:: + setName (const NameOptional& x) + { + this->name_ = x; + } + + void ListType:: + setName (::std::unique_ptr< NameType > x) + { + this->name_.set (std::move (x)); + } + + const ListType::AnyAttributeSet& ListType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ListType::AnyAttributeSet& ListType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ListType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ListType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ListType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // EntryType + // + + const EntryType::DisplayNameOptional& EntryType:: + getDisplayName () const + { + return this->display_name_; + } + + EntryType::DisplayNameOptional& EntryType:: + getDisplayName () + { + return this->display_name_; + } + + void EntryType:: + setDisplayName (const DisplayNameType& x) + { + this->display_name_.set (x); + } + + void EntryType:: + setDisplayName (const DisplayNameOptional& x) + { + this->display_name_ = x; + } + + void EntryType:: + setDisplayName (::std::unique_ptr< DisplayNameType > x) + { + this->display_name_.set (std::move (x)); + } + + const EntryType::AnySequence& EntryType:: + getAny () const + { + return this->any_; + } + + EntryType::AnySequence& EntryType:: + getAny () + { + return this->any_; + } + + void EntryType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const EntryType::UriType& EntryType:: + getUri () const + { + return this->uri_.get (); + } + + EntryType::UriType& EntryType:: + getUri () + { + return this->uri_.get (); + } + + void EntryType:: + setUri (const UriType& x) + { + this->uri_.set (x); + } + + void EntryType:: + setUri (::std::unique_ptr< UriType > x) + { + this->uri_.set (std::move (x)); + } + + ::std::unique_ptr< EntryType::UriType > EntryType:: + setDetachUri () + { + return this->uri_.detach (); + } + + const EntryType::AnyAttributeSet& EntryType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + EntryType::AnyAttributeSet& EntryType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void EntryType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& EntryType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& EntryType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // EntryRefType + // + + const EntryRefType::DisplayNameOptional& EntryRefType:: + getDisplayName () const + { + return this->display_name_; + } + + EntryRefType::DisplayNameOptional& EntryRefType:: + getDisplayName () + { + return this->display_name_; + } + + void EntryRefType:: + setDisplayName (const DisplayNameType& x) + { + this->display_name_.set (x); + } + + void EntryRefType:: + setDisplayName (const DisplayNameOptional& x) + { + this->display_name_ = x; + } + + void EntryRefType:: + setDisplayName (::std::unique_ptr< DisplayNameType > x) + { + this->display_name_.set (std::move (x)); + } + + const EntryRefType::AnySequence& EntryRefType:: + getAny () const + { + return this->any_; + } + + EntryRefType::AnySequence& EntryRefType:: + getAny () + { + return this->any_; + } + + void EntryRefType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const EntryRefType::RefType& EntryRefType:: + getRef () const + { + return this->ref_.get (); + } + + EntryRefType::RefType& EntryRefType:: + getRef () + { + return this->ref_.get (); + } + + void EntryRefType:: + setRef (const RefType& x) + { + this->ref_.set (x); + } + + void EntryRefType:: + setRef (::std::unique_ptr< RefType > x) + { + this->ref_.set (std::move (x)); + } + + ::std::unique_ptr< EntryRefType::RefType > EntryRefType:: + setDetachRef () + { + return this->ref_.detach (); + } + + const EntryRefType::AnyAttributeSet& EntryRefType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + EntryRefType::AnyAttributeSet& EntryRefType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void EntryRefType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& EntryRefType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& EntryRefType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // ExternalType + // + + const ExternalType::DisplayNameOptional& ExternalType:: + getDisplayName () const + { + return this->display_name_; + } + + ExternalType::DisplayNameOptional& ExternalType:: + getDisplayName () + { + return this->display_name_; + } + + void ExternalType:: + setDisplayName (const DisplayNameType& x) + { + this->display_name_.set (x); + } + + void ExternalType:: + setDisplayName (const DisplayNameOptional& x) + { + this->display_name_ = x; + } + + void ExternalType:: + setDisplayName (::std::unique_ptr< DisplayNameType > x) + { + this->display_name_.set (std::move (x)); + } + + const ExternalType::AnySequence& ExternalType:: + getAny () const + { + return this->any_; + } + + ExternalType::AnySequence& ExternalType:: + getAny () + { + return this->any_; + } + + void ExternalType:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const ExternalType::AnchorOptional& ExternalType:: + getAnchor () const + { + return this->anchor_; + } + + ExternalType::AnchorOptional& ExternalType:: + getAnchor () + { + return this->anchor_; + } + + void ExternalType:: + setAnchor (const AnchorType& x) + { + this->anchor_.set (x); + } + + void ExternalType:: + setAnchor (const AnchorOptional& x) + { + this->anchor_ = x; + } + + void ExternalType:: + setAnchor (::std::unique_ptr< AnchorType > x) + { + this->anchor_.set (std::move (x)); + } + + const ExternalType::AnyAttributeSet& ExternalType:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + ExternalType::AnyAttributeSet& ExternalType:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void ExternalType:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& ExternalType:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& ExternalType:: + getDomDocument () + { + return *this->dom_document_; + } + + + // DisplayNameType + // + + const DisplayNameType::LangOptional& DisplayNameType:: + getLang () const + { + return this->lang_; + } + + DisplayNameType::LangOptional& DisplayNameType:: + getLang () + { + return this->lang_; + } + + void DisplayNameType:: + setLang (const LangType& x) + { + this->lang_.set (x); + } + + void DisplayNameType:: + setLang (const LangOptional& x) + { + this->lang_ = x; + } + + void DisplayNameType:: + setLang (::std::unique_ptr< LangType > x) + { + this->lang_.set (std::move (x)); + } + + + // List + // + + + // DisplayName + // + + + // ResourceLists + // + + const ResourceLists::ListSequence& ResourceLists:: + getList () const + { + return this->list_; + } + + ResourceLists::ListSequence& ResourceLists:: + getList () + { + return this->list_; + } + + void ResourceLists:: + setList (const ListSequence& s) + { + this->list_ = s; + } + } + } +} + +#include + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_factory_plate< 0, char > + type_factory_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + // ListType + // + + ListType:: + ListType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + list_ (this), + external_ (this), + entry_ (this), + entry_ref_ (this), + any_ (this->getDomDocument ()), + name_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + ListType:: + ListType (const ListType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (x.display_name_, f, this), + list_ (x.list_, f, this), + external_ (x.external_, f, this), + entry_ (x.entry_, f, this), + entry_ref_ (x.entry_ref_, f, this), + any_ (x.any_, this->getDomDocument ()), + name_ (x.name_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ListType:: + ListType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + list_ (this), + external_ (this), + entry_ (this), + entry_ref_ (this), + any_ (this->getDomDocument ()), + name_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ListType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-name + // + if (n.name () == "display-name" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< DisplayNameType > r ( + DisplayNameTraits::create (i, f, this)); + + if (!this->display_name_) + { + this->display_name_.set (::std::move (r)); + continue; + } + } + + // list + // + if (n.name () == "list" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< ListType1 > r ( + ListTraits::create (i, f, this)); + + this->list_.push_back (::std::move (r)); + continue; + } + + // external + // + if (n.name () == "external" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< ExternalType > r ( + ExternalTraits::create (i, f, this)); + + this->external_.push_back (::std::move (r)); + continue; + } + + // entry + // + if (n.name () == "entry" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< EntryType > r ( + EntryTraits::create (i, f, this)); + + this->entry_.push_back (::std::move (r)); + continue; + } + + // entry-ref + // + if (n.name () == "entry-ref" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< EntryRefType > r ( + EntryRefTraits::create (i, f, this)); + + this->entry_ref_.push_back (::std::move (r)); + continue; + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "name" && n.namespace_ ().empty ()) + { + this->name_.set (NameTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + ListType* ListType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ListType (*this, f, c); + } + + ListType& ListType:: + operator= (const ListType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_name_ = x.display_name_; + this->list_ = x.list_; + this->external_ = x.external_; + this->entry_ = x.entry_; + this->entry_ref_ = x.entry_ref_; + this->any_ = x.any_; + this->name_ = x.name_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ListType:: + ~ListType () + { + } + + // EntryType + // + + EntryType:: + EntryType (const UriType& uri) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + any_ (this->getDomDocument ()), + uri_ (uri, this), + any_attribute_ (this->getDomDocument ()) + { + } + + EntryType:: + EntryType (const EntryType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (x.display_name_, f, this), + any_ (x.any_, this->getDomDocument ()), + uri_ (x.uri_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + EntryType:: + EntryType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + any_ (this->getDomDocument ()), + uri_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void EntryType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-name + // + if (n.name () == "display-name" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< DisplayNameType > r ( + DisplayNameTraits::create (i, f, this)); + + if (!this->display_name_) + { + this->display_name_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "uri" && n.namespace_ ().empty ()) + { + this->uri_.set (UriTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!uri_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "uri", + ""); + } + } + + EntryType* EntryType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class EntryType (*this, f, c); + } + + EntryType& EntryType:: + operator= (const EntryType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_name_ = x.display_name_; + this->any_ = x.any_; + this->uri_ = x.uri_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + EntryType:: + ~EntryType () + { + } + + // EntryRefType + // + + EntryRefType:: + EntryRefType (const RefType& ref) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + any_ (this->getDomDocument ()), + ref_ (ref, this), + any_attribute_ (this->getDomDocument ()) + { + } + + EntryRefType:: + EntryRefType (const EntryRefType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (x.display_name_, f, this), + any_ (x.any_, this->getDomDocument ()), + ref_ (x.ref_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + EntryRefType:: + EntryRefType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + any_ (this->getDomDocument ()), + ref_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void EntryRefType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-name + // + if (n.name () == "display-name" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< DisplayNameType > r ( + DisplayNameTraits::create (i, f, this)); + + if (!this->display_name_) + { + this->display_name_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "ref" && n.namespace_ ().empty ()) + { + this->ref_.set (RefTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!ref_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "ref", + ""); + } + } + + EntryRefType* EntryRefType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class EntryRefType (*this, f, c); + } + + EntryRefType& EntryRefType:: + operator= (const EntryRefType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_name_ = x.display_name_; + this->any_ = x.any_; + this->ref_ = x.ref_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + EntryRefType:: + ~EntryRefType () + { + } + + // ExternalType + // + + ExternalType:: + ExternalType () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + any_ (this->getDomDocument ()), + anchor_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + ExternalType:: + ExternalType (const ExternalType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (x.display_name_, f, this), + any_ (x.any_, this->getDomDocument ()), + anchor_ (x.anchor_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + ExternalType:: + ExternalType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + display_name_ (this), + any_ (this->getDomDocument ()), + anchor_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void ExternalType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // display-name + // + if (n.name () == "display-name" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< DisplayNameType > r ( + DisplayNameTraits::create (i, f, this)); + + if (!this->display_name_) + { + this->display_name_.set (::std::move (r)); + continue; + } + } + + // any + // + if ((!n.namespace_ ().empty () && n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists")) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "anchor" && n.namespace_ ().empty ()) + { + this->anchor_.set (AnchorTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((!n.namespace_ ().empty () && + n.namespace_ () != "urn:ietf:params:xml:ns:resource-lists" && + n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + } + + ExternalType* ExternalType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ExternalType (*this, f, c); + } + + ExternalType& ExternalType:: + operator= (const ExternalType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->display_name_ = x.display_name_; + this->any_ = x.any_; + this->anchor_ = x.anchor_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + ExternalType:: + ~ExternalType () + { + } + + // DisplayNameType + // + + DisplayNameType:: + DisplayNameType () + : ::LinphonePrivate::Xsd::XmlSchema::String (), + lang_ (this) + { + } + + DisplayNameType:: + DisplayNameType (const char* _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + lang_ (this) + { + } + + DisplayNameType:: + DisplayNameType (const ::std::string& _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + lang_ (this) + { + } + + DisplayNameType:: + DisplayNameType (const ::LinphonePrivate::Xsd::XmlSchema::String& _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + lang_ (this) + { + } + + DisplayNameType:: + DisplayNameType (const DisplayNameType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (x, f, c), + lang_ (x.lang_, f, this) + { + } + + DisplayNameType:: + DisplayNameType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + lang_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, false, false, true); + this->parse (p, f); + } + } + + void DisplayNameType:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "lang" && n.namespace_ () == "http://www.w3.org/XML/1998/namespace") + { + this->lang_.set (LangTraits::create (i, f, this)); + continue; + } + } + } + + DisplayNameType* DisplayNameType:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class DisplayNameType (*this, f, c); + } + + DisplayNameType& DisplayNameType:: + operator= (const DisplayNameType& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = x; + this->lang_ = x.lang_; + } + + return *this; + } + + DisplayNameType:: + ~DisplayNameType () + { + } + + // List + // + + List:: + List () + : ::LinphonePrivate::Xsd::ResourceLists::ListType () + { + } + + List:: + List (const List& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::ResourceLists::ListType (x, f, c) + { + } + + List:: + List (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::ResourceLists::ListType (e, f, c) + { + } + + List* List:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class List (*this, f, c); + } + + List:: + ~List () + { + } + + // DisplayName + // + + DisplayName:: + DisplayName () + : ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType () + { + } + + DisplayName:: + DisplayName (const char* _xsd_String_base) + : ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType (_xsd_String_base) + { + } + + DisplayName:: + DisplayName (const ::std::string& _xsd_String_base) + : ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType (_xsd_String_base) + { + } + + DisplayName:: + DisplayName (const ::LinphonePrivate::Xsd::XmlSchema::String& _xsd_String_base) + : ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType (_xsd_String_base) + { + } + + DisplayName:: + DisplayName (const DisplayName& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType (x, f, c) + { + } + + DisplayName:: + DisplayName (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType (e, f, c) + { + } + + DisplayName* DisplayName:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class DisplayName (*this, f, c); + } + + DisplayName:: + ~DisplayName () + { + } + + // ResourceLists + // + + ResourceLists:: + ResourceLists () + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + list_ (this) + { + } + + ResourceLists:: + ResourceLists (const ResourceLists& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + list_ (x.list_, f, this) + { + } + + ResourceLists:: + ResourceLists (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + list_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, false); + this->parse (p, f); + } + } + + void ResourceLists:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // list + // + if (n.name () == "list" && n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< ListType > r ( + ListTraits::create (i, f, this)); + + this->list_.push_back (::std::move (r)); + continue; + } + + break; + } + } + + ResourceLists* ResourceLists:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class ResourceLists (*this, f, c); + } + + ResourceLists& ResourceLists:: + operator= (const ResourceLists& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->list_ = x.list_; + } + + return *this; + } + + ResourceLists:: + ~ResourceLists () + { + } + } + } +} + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::std_ostream_plate< 0, char > + std_ostream_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + ::std::ostream& + operator<< (::std::ostream& o, const ListType& i) + { + if (i.getDisplayName ()) + { + o << ::std::endl << "display-name: " << *i.getDisplayName (); + } + + for (ListType::ListConstIterator + b (i.getList ().begin ()), e (i.getList ().end ()); + b != e; ++b) + { + o << ::std::endl << "list: " << *b; + } + + for (ListType::ExternalConstIterator + b (i.getExternal ().begin ()), e (i.getExternal ().end ()); + b != e; ++b) + { + o << ::std::endl << "external: " << *b; + } + + for (ListType::EntryConstIterator + b (i.getEntry ().begin ()), e (i.getEntry ().end ()); + b != e; ++b) + { + o << ::std::endl << "entry: " << *b; + } + + for (ListType::EntryRefConstIterator + b (i.getEntryRef ().begin ()), e (i.getEntryRef ().end ()); + b != e; ++b) + { + o << ::std::endl << "entry-ref: " << *b; + } + + if (i.getName ()) + { + o << ::std::endl << "name: " << *i.getName (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const EntryType& i) + { + if (i.getDisplayName ()) + { + o << ::std::endl << "display-name: " << *i.getDisplayName (); + } + + o << ::std::endl << "uri: " << i.getUri (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const EntryRefType& i) + { + if (i.getDisplayName ()) + { + o << ::std::endl << "display-name: " << *i.getDisplayName (); + } + + o << ::std::endl << "ref: " << i.getRef (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const ExternalType& i) + { + if (i.getDisplayName ()) + { + o << ::std::endl << "display-name: " << *i.getDisplayName (); + } + + if (i.getAnchor ()) + { + o << ::std::endl << "anchor: " << *i.getAnchor (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const DisplayNameType& i) + { + o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + + if (i.getLang ()) + { + o << ::std::endl << "lang: " << *i.getLang (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const List& i) + { + o << static_cast< const ::LinphonePrivate::Xsd::ResourceLists::ListType& > (i); + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const DisplayName& i) + { + o << static_cast< const ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType& > (i); + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const ResourceLists& i) + { + for (ResourceLists::ListConstIterator + b (i.getList ().begin ()), e (i.getList ().end ()); + b != e; ++b) + { + o << ::std::endl << "list: " << *b; + } + + return o; + } + } + } +} + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > ( + ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > ( + ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::std::string& u, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > ( + ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + const ::std::string& sid, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > ( + ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > ( + ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::xercesc::InputSource& i, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > ( + ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::xercesc::DOMDocument& doc, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + static_cast< ::xercesc::DOMDocument* > (doc.cloneNode (true))); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > ( + ::LinphonePrivate::Xsd::ResourceLists::parseResourceLists ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "resource-lists" && + n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "resource-lists", + "urn:ietf:params:xml:ns:resource-lists"); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties&) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > c ( + ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) && + !(f & ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom)) + ? static_cast< ::xercesc::DOMDocument* > (d->cloneNode (true)) + : 0); + + ::xercesc::DOMDocument& doc (c.get () ? *c : *d); + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + doc.setUserData (::LinphonePrivate::Xsd::XmlSchema::dom::treeNodeKey, + (c.get () ? &c : &d), + 0); + + if (n.name () == "resource-lists" && + n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "resource-lists", + "urn:ietf:params:xml:ns:resource-lists"); + } + } + } +} + +#include +#include +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_serializer_plate< 0, char > + type_serializer_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + void + operator<< (::xercesc::DOMElement& e, const ListType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ListType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-name + // + if (i.getDisplayName ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-name", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *i.getDisplayName (); + } + + // list + // + for (ListType::ListConstIterator + b (i.getList ().begin ()), n (i.getList ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "list", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *b; + } + + // external + // + for (ListType::ExternalConstIterator + b (i.getExternal ().begin ()), n (i.getExternal ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "external", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *b; + } + + // entry + // + for (ListType::EntryConstIterator + b (i.getEntry ().begin ()), n (i.getEntry ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "entry", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *b; + } + + // entry-ref + // + for (ListType::EntryRefConstIterator + b (i.getEntryRef ().begin ()), n (i.getEntryRef ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "entry-ref", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *b; + } + + // any + // + for (ListType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // name + // + if (i.getName ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "name", + e)); + + a << *i.getName (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const EntryType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (EntryType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-name + // + if (i.getDisplayName ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-name", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *i.getDisplayName (); + } + + // any + // + for (EntryType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // uri + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "uri", + e)); + + a << i.getUri (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const EntryRefType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (EntryRefType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-name + // + if (i.getDisplayName ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-name", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *i.getDisplayName (); + } + + // any + // + for (EntryRefType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // ref + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "ref", + e)); + + a << i.getRef (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const ExternalType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (ExternalType::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // display-name + // + if (i.getDisplayName ()) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "display-name", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *i.getDisplayName (); + } + + // any + // + for (ExternalType::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // anchor + // + if (i.getAnchor ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "anchor", + e)); + + a << *i.getAnchor (); + } + } + + void + serializeResourceLists (::std::ostream& o, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ResourceLists::serializeResourceLists (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeResourceLists (::std::ostream& o, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ResourceLists::serializeResourceLists (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeResourceLists (::std::ostream& o, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ResourceLists::serializeResourceLists (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeResourceLists (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ResourceLists::serializeResourceLists (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeResourceLists (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ResourceLists::serializeResourceLists (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeResourceLists (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::ResourceLists::serializeResourceLists (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeResourceLists (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + ::LinphonePrivate::Xsd::XmlSchema::Flags) + { + ::xercesc::DOMElement& e (*d.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "resource-lists" && + n.namespace_ () == "urn:ietf:params:xml:ns:resource-lists") + { + e << s; + } + else + { + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "resource-lists", + "urn:ietf:params:xml:ns:resource-lists"); + } + } + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeResourceLists (const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::serialize< char > ( + "resource-lists", + "urn:ietf:params:xml:ns:resource-lists", + m, f)); + + ::LinphonePrivate::Xsd::ResourceLists::serializeResourceLists (*d, s, f); + return d; + } + + void + operator<< (::xercesc::DOMElement& e, const DisplayNameType& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + + // lang + // + if (i.getLang ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "lang", + "http://www.w3.org/XML/1998/namespace", + e)); + + a << *i.getLang (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const List& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::ResourceLists::ListType& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const DisplayName& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const ResourceLists& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // list + // + for (ResourceLists::ListConstIterator + b (i.getList ().begin ()), n (i.getList ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "list", + "urn:ietf:params:xml:ns:resource-lists", + e)); + + s << *b; + } + } + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + diff --git a/src/xml/resource-lists.h b/src/xml/resource-lists.h new file mode 100644 index 000000000..b2384df98 --- /dev/null +++ b/src/xml/resource-lists.h @@ -0,0 +1,1315 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +#ifndef XML_RESOURCE_LISTS_H +#define XML_RESOURCE_LISTS_H + +#ifndef XSD_CXX11 +#define XSD_CXX11 +#endif + +#ifndef XSD_USE_CHAR +#define XSD_USE_CHAR +#endif + +#ifndef XSD_CXX_TREE_USE_CHAR +#define XSD_CXX_TREE_USE_CHAR +#endif + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#if (XSD_INT_VERSION != 4000000L) +#error XSD runtime version mismatch +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace XmlSchema + { + // anyType and anySimpleType. + // + typedef ::xsd::cxx::tree::type Type; + typedef ::xsd::cxx::tree::simple_type< char, Type > SimpleType; + typedef ::xsd::cxx::tree::type Container; + + // 8-bit + // + typedef signed char Byte; + typedef unsigned char UnsignedByte; + + // 16-bit + // + typedef short Short; + typedef unsigned short UnsignedShort; + + // 32-bit + // + typedef int Int; + typedef unsigned int UnsignedInt; + + // 64-bit + // + typedef long long Long; + typedef unsigned long long UnsignedLong; + + // Supposed to be arbitrary-length integral types. + // + typedef long long Integer; + typedef long long NonPositiveInteger; + typedef unsigned long long NonNegativeInteger; + typedef unsigned long long PositiveInteger; + typedef long long NegativeInteger; + + // Boolean. + // + typedef bool Boolean; + + // Floating-point types. + // + typedef float Float; + typedef double Double; + typedef double Decimal; + + // String types. + // + typedef ::xsd::cxx::tree::string< char, SimpleType > String; + typedef ::xsd::cxx::tree::normalized_string< char, String > NormalizedString; + typedef ::xsd::cxx::tree::token< char, NormalizedString > Token; + typedef ::xsd::cxx::tree::name< char, Token > Name; + typedef ::xsd::cxx::tree::nmtoken< char, Token > Nmtoken; + typedef ::xsd::cxx::tree::nmtokens< char, SimpleType, Nmtoken > Nmtokens; + typedef ::xsd::cxx::tree::ncname< char, Name > Ncname; + typedef ::xsd::cxx::tree::language< char, Token > Language; + + // ID/IDREF. + // + typedef ::xsd::cxx::tree::id< char, Ncname > Id; + typedef ::xsd::cxx::tree::idref< char, Ncname, Type > Idref; + typedef ::xsd::cxx::tree::idrefs< char, SimpleType, Idref > Idrefs; + + // URI. + // + typedef ::xsd::cxx::tree::uri< char, SimpleType > Uri; + + // Qualified name. + // + typedef ::xsd::cxx::tree::qname< char, SimpleType, Uri, Ncname > Qname; + + // Binary. + // + typedef ::xsd::cxx::tree::buffer< char > Buffer; + typedef ::xsd::cxx::tree::base64_binary< char, SimpleType > Base64Binary; + typedef ::xsd::cxx::tree::hex_binary< char, SimpleType > HexBinary; + + // Date/time. + // + typedef ::xsd::cxx::tree::time_zone TimeZone; + typedef ::xsd::cxx::tree::date< char, SimpleType > Date; + typedef ::xsd::cxx::tree::date_time< char, SimpleType > DateTime; + typedef ::xsd::cxx::tree::duration< char, SimpleType > Duration; + typedef ::xsd::cxx::tree::gday< char, SimpleType > Gday; + typedef ::xsd::cxx::tree::gmonth< char, SimpleType > Gmonth; + typedef ::xsd::cxx::tree::gmonth_day< char, SimpleType > GmonthDay; + typedef ::xsd::cxx::tree::gyear< char, SimpleType > Gyear; + typedef ::xsd::cxx::tree::gyear_month< char, SimpleType > GyearMonth; + typedef ::xsd::cxx::tree::time< char, SimpleType > Time; + + // Entity. + // + typedef ::xsd::cxx::tree::entity< char, Ncname > Entity; + typedef ::xsd::cxx::tree::entities< char, SimpleType, Entity > Entities; + + typedef ::xsd::cxx::tree::content_order ContentOrder; + // Namespace information and list stream. Used in + // serialization functions. + // + typedef ::xsd::cxx::xml::dom::namespace_info< char > NamespaceInfo; + typedef ::xsd::cxx::xml::dom::namespace_infomap< char > NamespaceInfomap; + typedef ::xsd::cxx::tree::list_stream< char > ListStream; + typedef ::xsd::cxx::tree::as_double< Double > AsDouble; + typedef ::xsd::cxx::tree::as_decimal< Decimal > AsDecimal; + typedef ::xsd::cxx::tree::facet Facet; + + // Flags and properties. + // + typedef ::xsd::cxx::tree::flags Flags; + typedef ::xsd::cxx::tree::properties< char > Properties; + + // Parsing/serialization diagnostics. + // + typedef ::xsd::cxx::tree::severity Severity; + typedef ::xsd::cxx::tree::error< char > Error; + typedef ::xsd::cxx::tree::diagnostics< char > Diagnostics; + + // Exceptions. + // + typedef ::xsd::cxx::tree::exception< char > Exception; + typedef ::xsd::cxx::tree::bounds< char > Bounds; + typedef ::xsd::cxx::tree::duplicate_id< char > DuplicateId; + typedef ::xsd::cxx::tree::parsing< char > Parsing; + typedef ::xsd::cxx::tree::expected_element< char > ExpectedElement; + typedef ::xsd::cxx::tree::unexpected_element< char > UnexpectedElement; + typedef ::xsd::cxx::tree::expected_attribute< char > ExpectedAttribute; + typedef ::xsd::cxx::tree::unexpected_enumerator< char > UnexpectedEnumerator; + typedef ::xsd::cxx::tree::expected_text_content< char > ExpectedTextContent; + typedef ::xsd::cxx::tree::no_prefix_mapping< char > NoPrefixMapping; + typedef ::xsd::cxx::tree::no_type_info< char > NoTypeInfo; + typedef ::xsd::cxx::tree::not_derived< char > NotDerived; + typedef ::xsd::cxx::tree::serialization< char > Serialization; + + // Error handler callback interface. + // + typedef ::xsd::cxx::xml::error_handler< char > ErrorHandler; + + // DOM interaction. + // + namespace dom + { + // Automatic pointer for DOMDocument. + // + using ::xsd::cxx::xml::dom::unique_ptr; + +#ifndef XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA +#define XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA + // DOM user data key for back pointers to tree nodes. + // + const XMLCh* const treeNodeKey = ::xsd::cxx::tree::user_data_keys::node; +#endif + } + } + } +} + +// Forward declarations. +// +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + class ListType; + class EntryType; + class EntryRefType; + class ExternalType; + class DisplayNameType; + class List; + class DisplayName; + class ResourceLists; + } + } +} + + +#include // ::std::unique_ptr +#include // std::numeric_limits +#include // std::binary_search +#include // std::move + +#include + +#include +#include +#include +#include + +#include + +#include + +#include "xml.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + class ListType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-name + // + typedef ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType DisplayNameType; + typedef ::xsd::cxx::tree::optional< DisplayNameType > DisplayNameOptional; + typedef ::xsd::cxx::tree::traits< DisplayNameType, char > DisplayNameTraits; + + const DisplayNameOptional& + getDisplayName () const; + + DisplayNameOptional& + getDisplayName (); + + void + setDisplayName (const DisplayNameType& x); + + void + setDisplayName (const DisplayNameOptional& x); + + void + setDisplayName (::std::unique_ptr< DisplayNameType > p); + + // list + // + typedef ::LinphonePrivate::Xsd::ResourceLists::List ListType1; + typedef ::xsd::cxx::tree::sequence< ListType1 > ListSequence; + typedef ListSequence::iterator ListIterator; + typedef ListSequence::const_iterator ListConstIterator; + typedef ::xsd::cxx::tree::traits< ListType1, char > ListTraits; + + const ListSequence& + getList () const; + + ListSequence& + getList (); + + void + setList (const ListSequence& s); + + // external + // + typedef ::LinphonePrivate::Xsd::ResourceLists::ExternalType ExternalType; + typedef ::xsd::cxx::tree::sequence< ExternalType > ExternalSequence; + typedef ExternalSequence::iterator ExternalIterator; + typedef ExternalSequence::const_iterator ExternalConstIterator; + typedef ::xsd::cxx::tree::traits< ExternalType, char > ExternalTraits; + + const ExternalSequence& + getExternal () const; + + ExternalSequence& + getExternal (); + + void + setExternal (const ExternalSequence& s); + + // entry + // + typedef ::LinphonePrivate::Xsd::ResourceLists::EntryType EntryType; + typedef ::xsd::cxx::tree::sequence< EntryType > EntrySequence; + typedef EntrySequence::iterator EntryIterator; + typedef EntrySequence::const_iterator EntryConstIterator; + typedef ::xsd::cxx::tree::traits< EntryType, char > EntryTraits; + + const EntrySequence& + getEntry () const; + + EntrySequence& + getEntry (); + + void + setEntry (const EntrySequence& s); + + // entry-ref + // + typedef ::LinphonePrivate::Xsd::ResourceLists::EntryRefType EntryRefType; + typedef ::xsd::cxx::tree::sequence< EntryRefType > EntryRefSequence; + typedef EntryRefSequence::iterator EntryRefIterator; + typedef EntryRefSequence::const_iterator EntryRefConstIterator; + typedef ::xsd::cxx::tree::traits< EntryRefType, char > EntryRefTraits; + + const EntryRefSequence& + getEntryRef () const; + + EntryRefSequence& + getEntryRef (); + + void + setEntryRef (const EntryRefSequence& s); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // name + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String NameType; + typedef ::xsd::cxx::tree::optional< NameType > NameOptional; + typedef ::xsd::cxx::tree::traits< NameType, char > NameTraits; + + const NameOptional& + getName () const; + + NameOptional& + getName (); + + void + setName (const NameType& x); + + void + setName (const NameOptional& x); + + void + setName (::std::unique_ptr< NameType > p); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ListType (); + + ListType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ListType (const ListType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ListType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ListType& + operator= (const ListType& x); + + virtual + ~ListType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayNameOptional display_name_; + ListSequence list_; + ExternalSequence external_; + EntrySequence entry_; + EntryRefSequence entry_ref_; + AnySequence any_; + NameOptional name_; + AnyAttributeSet any_attribute_; + }; + + class EntryType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-name + // + typedef ::LinphonePrivate::Xsd::ResourceLists::DisplayName DisplayNameType; + typedef ::xsd::cxx::tree::optional< DisplayNameType > DisplayNameOptional; + typedef ::xsd::cxx::tree::traits< DisplayNameType, char > DisplayNameTraits; + + const DisplayNameOptional& + getDisplayName () const; + + DisplayNameOptional& + getDisplayName (); + + void + setDisplayName (const DisplayNameType& x); + + void + setDisplayName (const DisplayNameOptional& x); + + void + setDisplayName (::std::unique_ptr< DisplayNameType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // uri + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri UriType; + typedef ::xsd::cxx::tree::traits< UriType, char > UriTraits; + + const UriType& + getUri () const; + + UriType& + getUri (); + + void + setUri (const UriType& x); + + void + setUri (::std::unique_ptr< UriType > p); + + ::std::unique_ptr< UriType > + setDetachUri (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + EntryType (const UriType&); + + EntryType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + EntryType (const EntryType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual EntryType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + EntryType& + operator= (const EntryType& x); + + virtual + ~EntryType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayNameOptional display_name_; + AnySequence any_; + ::xsd::cxx::tree::one< UriType > uri_; + AnyAttributeSet any_attribute_; + }; + + class EntryRefType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-name + // + typedef ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType DisplayNameType; + typedef ::xsd::cxx::tree::optional< DisplayNameType > DisplayNameOptional; + typedef ::xsd::cxx::tree::traits< DisplayNameType, char > DisplayNameTraits; + + const DisplayNameOptional& + getDisplayName () const; + + DisplayNameOptional& + getDisplayName (); + + void + setDisplayName (const DisplayNameType& x); + + void + setDisplayName (const DisplayNameOptional& x); + + void + setDisplayName (::std::unique_ptr< DisplayNameType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // ref + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri RefType; + typedef ::xsd::cxx::tree::traits< RefType, char > RefTraits; + + const RefType& + getRef () const; + + RefType& + getRef (); + + void + setRef (const RefType& x); + + void + setRef (::std::unique_ptr< RefType > p); + + ::std::unique_ptr< RefType > + setDetachRef (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + EntryRefType (const RefType&); + + EntryRefType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + EntryRefType (const EntryRefType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual EntryRefType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + EntryRefType& + operator= (const EntryRefType& x); + + virtual + ~EntryRefType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayNameOptional display_name_; + AnySequence any_; + ::xsd::cxx::tree::one< RefType > ref_; + AnyAttributeSet any_attribute_; + }; + + class ExternalType: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // display-name + // + typedef ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType DisplayNameType; + typedef ::xsd::cxx::tree::optional< DisplayNameType > DisplayNameOptional; + typedef ::xsd::cxx::tree::traits< DisplayNameType, char > DisplayNameTraits; + + const DisplayNameOptional& + getDisplayName () const; + + DisplayNameOptional& + getDisplayName (); + + void + setDisplayName (const DisplayNameType& x); + + void + setDisplayName (const DisplayNameOptional& x); + + void + setDisplayName (::std::unique_ptr< DisplayNameType > p); + + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // anchor + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri AnchorType; + typedef ::xsd::cxx::tree::optional< AnchorType > AnchorOptional; + typedef ::xsd::cxx::tree::traits< AnchorType, char > AnchorTraits; + + const AnchorOptional& + getAnchor () const; + + AnchorOptional& + getAnchor (); + + void + setAnchor (const AnchorType& x); + + void + setAnchor (const AnchorOptional& x); + + void + setAnchor (::std::unique_ptr< AnchorType > p); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + ExternalType (); + + ExternalType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ExternalType (const ExternalType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ExternalType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ExternalType& + operator= (const ExternalType& x); + + virtual + ~ExternalType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + DisplayNameOptional display_name_; + AnySequence any_; + AnchorOptional anchor_; + AnyAttributeSet any_attribute_; + }; + + class DisplayNameType: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + // lang + // + typedef ::namespace_::Lang LangType; + typedef ::xsd::cxx::tree::optional< LangType > LangOptional; + typedef ::xsd::cxx::tree::traits< LangType, char > LangTraits; + + const LangOptional& + getLang () const; + + LangOptional& + getLang (); + + void + setLang (const LangType& x); + + void + setLang (const LangOptional& x); + + void + setLang (::std::unique_ptr< LangType > p); + + // Constructors. + // + DisplayNameType (); + + DisplayNameType (const char*); + + DisplayNameType (const ::std::string&); + + DisplayNameType (const ::LinphonePrivate::Xsd::XmlSchema::String&); + + DisplayNameType (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + DisplayNameType (const DisplayNameType& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual DisplayNameType* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + DisplayNameType& + operator= (const DisplayNameType& x); + + virtual + ~DisplayNameType (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + LangOptional lang_; + }; + + class List: public ::LinphonePrivate::Xsd::ResourceLists::ListType + { + public: + // Constructors. + // + List (); + + List (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + List (const List& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual List* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~List (); + }; + + class DisplayName: public ::LinphonePrivate::Xsd::ResourceLists::DisplayNameType + { + public: + // Constructors. + // + DisplayName (); + + DisplayName (const char*); + + DisplayName (const ::std::string&); + + DisplayName (const ::LinphonePrivate::Xsd::XmlSchema::String&); + + DisplayName (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + DisplayName (const DisplayName& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual DisplayName* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + virtual + ~DisplayName (); + }; + + class ResourceLists: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // list + // + typedef ::LinphonePrivate::Xsd::ResourceLists::ListType ListType; + typedef ::xsd::cxx::tree::sequence< ListType > ListSequence; + typedef ListSequence::iterator ListIterator; + typedef ListSequence::const_iterator ListConstIterator; + typedef ::xsd::cxx::tree::traits< ListType, char > ListTraits; + + const ListSequence& + getList () const; + + ListSequence& + getList (); + + void + setList (const ListSequence& s); + + // Constructors. + // + ResourceLists (); + + ResourceLists (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + ResourceLists (const ResourceLists& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual ResourceLists* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + ResourceLists& + operator= (const ResourceLists& x); + + virtual + ~ResourceLists (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ListSequence list_; + }; + } + } +} + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + ::std::ostream& + operator<< (::std::ostream&, const ListType&); + + ::std::ostream& + operator<< (::std::ostream&, const EntryType&); + + ::std::ostream& + operator<< (::std::ostream&, const EntryRefType&); + + ::std::ostream& + operator<< (::std::ostream&, const ExternalType&); + + ::std::ostream& + operator<< (::std::ostream&, const DisplayNameType&); + + ::std::ostream& + operator<< (::std::ostream&, const List&); + + ::std::ostream& + operator<< (::std::ostream&, const DisplayName&); + + ::std::ostream& + operator<< (::std::ostream&, const ResourceLists&); + } + } +} + +#include + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + // Parse a URI or a local file. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::std::string& uri, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse std::istream. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::std::istream& is, + const ::std::string& id, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::InputSource. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::xercesc::InputSource& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::DOMDocument. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (const ::xercesc::DOMDocument& d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::ResourceLists::ResourceLists > + parseResourceLists (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + } + } +} + +#include + +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace ResourceLists + { + void + operator<< (::xercesc::DOMElement&, const ListType&); + + void + operator<< (::xercesc::DOMElement&, const EntryType&); + + void + operator<< (::xercesc::DOMElement&, const EntryRefType&); + + void + operator<< (::xercesc::DOMElement&, const ExternalType&); + + // Serialize to std::ostream. + // + + void + serializeResourceLists (::std::ostream& os, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeResourceLists (::std::ostream& os, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeResourceLists (::std::ostream& os, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to xercesc::XMLFormatTarget. + // + + void + serializeResourceLists (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeResourceLists (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeResourceLists (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to an existing xercesc::DOMDocument. + // + + void + serializeResourceLists (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to a new xercesc::DOMDocument. + // + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeResourceLists (const ::LinphonePrivate::Xsd::ResourceLists::ResourceLists& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + operator<< (::xercesc::DOMElement&, const DisplayNameType&); + + void + operator<< (::xercesc::DOMElement&, const List&); + + void + operator<< (::xercesc::DOMElement&, const DisplayName&); + + void + operator<< (::xercesc::DOMElement&, const ResourceLists&); + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + +#endif // XML_RESOURCE_LISTS_H diff --git a/src/xml/resource-lists.xsd b/src/xml/resource-lists.xsd new file mode 100644 index 000000000..c4884db55 --- /dev/null +++ b/src/xml/resource-lists.xsd @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/xml/rlmi.cpp b/src/xml/rlmi.cpp new file mode 100644 index 000000000..eb0541331 --- /dev/null +++ b/src/xml/rlmi.cpp @@ -0,0 +1,2121 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#include "rlmi.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + // List + // + + const List::NameSequence& List:: + getName () const + { + return this->name_; + } + + List::NameSequence& List:: + getName () + { + return this->name_; + } + + void List:: + setName (const NameSequence& s) + { + this->name_ = s; + } + + const List::ResourceSequence& List:: + getResource () const + { + return this->resource_; + } + + List::ResourceSequence& List:: + getResource () + { + return this->resource_; + } + + void List:: + setResource (const ResourceSequence& s) + { + this->resource_ = s; + } + + const List::UriType& List:: + getUri () const + { + return this->uri_.get (); + } + + List::UriType& List:: + getUri () + { + return this->uri_.get (); + } + + void List:: + setUri (const UriType& x) + { + this->uri_.set (x); + } + + void List:: + setUri (::std::unique_ptr< UriType > x) + { + this->uri_.set (std::move (x)); + } + + ::std::unique_ptr< List::UriType > List:: + setDetachUri () + { + return this->uri_.detach (); + } + + const List::VersionType& List:: + getVersion () const + { + return this->version_.get (); + } + + List::VersionType& List:: + getVersion () + { + return this->version_.get (); + } + + void List:: + setVersion (const VersionType& x) + { + this->version_.set (x); + } + + const List::FullStateType& List:: + getFullState () const + { + return this->fullState_.get (); + } + + List::FullStateType& List:: + getFullState () + { + return this->fullState_.get (); + } + + void List:: + setFullState (const FullStateType& x) + { + this->fullState_.set (x); + } + + const List::CidOptional& List:: + getCid () const + { + return this->cid_; + } + + List::CidOptional& List:: + getCid () + { + return this->cid_; + } + + void List:: + setCid (const CidType& x) + { + this->cid_.set (x); + } + + void List:: + setCid (const CidOptional& x) + { + this->cid_ = x; + } + + void List:: + setCid (::std::unique_ptr< CidType > x) + { + this->cid_.set (std::move (x)); + } + + const List::AnyAttributeSet& List:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + List::AnyAttributeSet& List:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void List:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& List:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& List:: + getDomDocument () + { + return *this->dom_document_; + } + + + // Resource + // + + const Resource::NameSequence& Resource:: + getName () const + { + return this->name_; + } + + Resource::NameSequence& Resource:: + getName () + { + return this->name_; + } + + void Resource:: + setName (const NameSequence& s) + { + this->name_ = s; + } + + const Resource::InstanceSequence& Resource:: + getInstance () const + { + return this->instance_; + } + + Resource::InstanceSequence& Resource:: + getInstance () + { + return this->instance_; + } + + void Resource:: + setInstance (const InstanceSequence& s) + { + this->instance_ = s; + } + + const Resource::UriType& Resource:: + getUri () const + { + return this->uri_.get (); + } + + Resource::UriType& Resource:: + getUri () + { + return this->uri_.get (); + } + + void Resource:: + setUri (const UriType& x) + { + this->uri_.set (x); + } + + void Resource:: + setUri (::std::unique_ptr< UriType > x) + { + this->uri_.set (std::move (x)); + } + + ::std::unique_ptr< Resource::UriType > Resource:: + setDetachUri () + { + return this->uri_.detach (); + } + + const Resource::AnyAttributeSet& Resource:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + Resource::AnyAttributeSet& Resource:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void Resource:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& Resource:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& Resource:: + getDomDocument () + { + return *this->dom_document_; + } + + + // Instance + // + + const Instance::AnySequence& Instance:: + getAny () const + { + return this->any_; + } + + Instance::AnySequence& Instance:: + getAny () + { + return this->any_; + } + + void Instance:: + setAny (const AnySequence& s) + { + this->any_ = s; + } + + const Instance::IdType& Instance:: + getId () const + { + return this->id_.get (); + } + + Instance::IdType& Instance:: + getId () + { + return this->id_.get (); + } + + void Instance:: + setId (const IdType& x) + { + this->id_.set (x); + } + + void Instance:: + setId (::std::unique_ptr< IdType > x) + { + this->id_.set (std::move (x)); + } + + ::std::unique_ptr< Instance::IdType > Instance:: + setDetachId () + { + return this->id_.detach (); + } + + const Instance::StateType& Instance:: + getState () const + { + return this->state_.get (); + } + + Instance::StateType& Instance:: + getState () + { + return this->state_.get (); + } + + void Instance:: + setState (const StateType& x) + { + this->state_.set (x); + } + + void Instance:: + setState (::std::unique_ptr< StateType > x) + { + this->state_.set (std::move (x)); + } + + ::std::unique_ptr< Instance::StateType > Instance:: + setDetachState () + { + return this->state_.detach (); + } + + const Instance::ReasonOptional& Instance:: + getReason () const + { + return this->reason_; + } + + Instance::ReasonOptional& Instance:: + getReason () + { + return this->reason_; + } + + void Instance:: + setReason (const ReasonType& x) + { + this->reason_.set (x); + } + + void Instance:: + setReason (const ReasonOptional& x) + { + this->reason_ = x; + } + + void Instance:: + setReason (::std::unique_ptr< ReasonType > x) + { + this->reason_.set (std::move (x)); + } + + const Instance::CidOptional& Instance:: + getCid () const + { + return this->cid_; + } + + Instance::CidOptional& Instance:: + getCid () + { + return this->cid_; + } + + void Instance:: + setCid (const CidType& x) + { + this->cid_.set (x); + } + + void Instance:: + setCid (const CidOptional& x) + { + this->cid_ = x; + } + + void Instance:: + setCid (::std::unique_ptr< CidType > x) + { + this->cid_.set (std::move (x)); + } + + const Instance::AnyAttributeSet& Instance:: + getAnyAttribute () const + { + return this->any_attribute_; + } + + Instance::AnyAttributeSet& Instance:: + getAnyAttribute () + { + return this->any_attribute_; + } + + void Instance:: + setAnyAttribute (const AnyAttributeSet& s) + { + this->any_attribute_ = s; + } + + const ::xercesc::DOMDocument& Instance:: + getDomDocument () const + { + return *this->dom_document_; + } + + ::xercesc::DOMDocument& Instance:: + getDomDocument () + { + return *this->dom_document_; + } + + + // Name + // + + const Name::LangOptional& Name:: + getLang () const + { + return this->lang_; + } + + Name::LangOptional& Name:: + getLang () + { + return this->lang_; + } + + void Name:: + setLang (const LangType& x) + { + this->lang_.set (x); + } + + void Name:: + setLang (const LangOptional& x) + { + this->lang_ = x; + } + + void Name:: + setLang (::std::unique_ptr< LangType > x) + { + this->lang_.set (std::move (x)); + } + + + // State + // + + State:: + State (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_State_literals_[v]) + { + } + + State:: + State (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + State:: + State (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + State:: + State (const ::LinphonePrivate::Xsd::XmlSchema::String& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + State:: + State (const State& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (v, f, c) + { + } + + State& State:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_State_literals_[v]); + + return *this; + } + } + } +} + +#include + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_factory_plate< 0, char > + type_factory_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + // List + // + + List:: + List (const UriType& uri, + const VersionType& version, + const FullStateType& fullState) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + name_ (this), + resource_ (this), + uri_ (uri, this), + version_ (version, this), + fullState_ (fullState, this), + cid_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + List:: + List (const List& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + name_ (x.name_, f, this), + resource_ (x.resource_, f, this), + uri_ (x.uri_, f, this), + version_ (x.version_, f, this), + fullState_ (x.fullState_, f, this), + cid_ (x.cid_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + List:: + List (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + name_ (this), + resource_ (this), + uri_ (this), + version_ (this), + fullState_ (this), + cid_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void List:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // name + // + if (n.name () == "name" && n.namespace_ () == "urn:ietf:params:xml:ns:rlmi") + { + ::std::unique_ptr< NameType > r ( + NameTraits::create (i, f, this)); + + this->name_.push_back (::std::move (r)); + continue; + } + + // resource + // + if (n.name () == "resource" && n.namespace_ () == "urn:ietf:params:xml:ns:rlmi") + { + ::std::unique_ptr< ResourceType > r ( + ResourceTraits::create (i, f, this)); + + this->resource_.push_back (::std::move (r)); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "uri" && n.namespace_ ().empty ()) + { + this->uri_.set (UriTraits::create (i, f, this)); + continue; + } + + if (n.name () == "version" && n.namespace_ ().empty ()) + { + this->version_.set (VersionTraits::create (i, f, this)); + continue; + } + + if (n.name () == "fullState" && n.namespace_ ().empty ()) + { + this->fullState_.set (FullStateTraits::create (i, f, this)); + continue; + } + + if (n.name () == "cid" && n.namespace_ ().empty ()) + { + this->cid_.set (CidTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!uri_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "uri", + ""); + } + + if (!version_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "version", + ""); + } + + if (!fullState_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "fullState", + ""); + } + } + + List* List:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class List (*this, f, c); + } + + List& List:: + operator= (const List& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->name_ = x.name_; + this->resource_ = x.resource_; + this->uri_ = x.uri_; + this->version_ = x.version_; + this->fullState_ = x.fullState_; + this->cid_ = x.cid_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + List:: + ~List () + { + } + + // Resource + // + + Resource:: + Resource (const UriType& uri) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + name_ (this), + instance_ (this), + uri_ (uri, this), + any_attribute_ (this->getDomDocument ()) + { + } + + Resource:: + Resource (const Resource& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + name_ (x.name_, f, this), + instance_ (x.instance_, f, this), + uri_ (x.uri_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + Resource:: + Resource (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + name_ (this), + instance_ (this), + uri_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void Resource:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // name + // + if (n.name () == "name" && n.namespace_ () == "urn:ietf:params:xml:ns:rlmi") + { + ::std::unique_ptr< NameType > r ( + NameTraits::create (i, f, this)); + + this->name_.push_back (::std::move (r)); + continue; + } + + // instance + // + if (n.name () == "instance" && n.namespace_ () == "urn:ietf:params:xml:ns:rlmi") + { + ::std::unique_ptr< InstanceType > r ( + InstanceTraits::create (i, f, this)); + + this->instance_.push_back (::std::move (r)); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "uri" && n.namespace_ ().empty ()) + { + this->uri_.set (UriTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!uri_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "uri", + ""); + } + } + + Resource* Resource:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Resource (*this, f, c); + } + + Resource& Resource:: + operator= (const Resource& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->name_ = x.name_; + this->instance_ = x.instance_; + this->uri_ = x.uri_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + Resource:: + ~Resource () + { + } + + // Instance + // + + Instance:: + Instance (const IdType& id, + const StateType& state) + : ::LinphonePrivate::Xsd::XmlSchema::Type (), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + any_ (this->getDomDocument ()), + id_ (id, this), + state_ (state, this), + reason_ (this), + cid_ (this), + any_attribute_ (this->getDomDocument ()) + { + } + + Instance:: + Instance (const Instance& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (x, f, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + any_ (x.any_, this->getDomDocument ()), + id_ (x.id_, f, this), + state_ (x.state_, f, this), + reason_ (x.reason_, f, this), + cid_ (x.cid_, f, this), + any_attribute_ (x.any_attribute_, this->getDomDocument ()) + { + } + + Instance:: + Instance (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Type (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + dom_document_ (::xsd::cxx::xml::dom::create_document< char > ()), + any_ (this->getDomDocument ()), + id_ (this), + state_ (this), + reason_ (this), + cid_ (this), + any_attribute_ (this->getDomDocument ()) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, true, false, true); + this->parse (p, f); + } + } + + void Instance:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + for (; p.more_content (); p.next_content (false)) + { + const ::xercesc::DOMElement& i (p.cur_element ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + // any + // + if (true) + { + ::xercesc::DOMElement* r ( + static_cast< ::xercesc::DOMElement* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMElement* > (&i), true))); + this->any_.push_back (r); + continue; + } + + break; + } + + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "id" && n.namespace_ ().empty ()) + { + this->id_.set (IdTraits::create (i, f, this)); + continue; + } + + if (n.name () == "state" && n.namespace_ ().empty ()) + { + this->state_.set (StateTraits::create (i, f, this)); + continue; + } + + if (n.name () == "reason" && n.namespace_ ().empty ()) + { + this->reason_.set (ReasonTraits::create (i, f, this)); + continue; + } + + if (n.name () == "cid" && n.namespace_ ().empty ()) + { + this->cid_.set (CidTraits::create (i, f, this)); + continue; + } + + // any_attribute + // + if ((n.namespace_ () != ::xsd::cxx::xml::bits::xmlns_namespace< char > () && + n.namespace_ () != ::xsd::cxx::xml::bits::xsi_namespace< char > ())) + { + ::xercesc::DOMAttr* r ( + static_cast< ::xercesc::DOMAttr* > ( + this->getDomDocument ().importNode ( + const_cast< ::xercesc::DOMAttr* > (&i), true))); + this->any_attribute_ .insert (r); + continue; + } + } + + if (!id_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "id", + ""); + } + + if (!state_.present ()) + { + throw ::xsd::cxx::tree::expected_attribute< char > ( + "state", + ""); + } + } + + Instance* Instance:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Instance (*this, f, c); + } + + Instance& Instance:: + operator= (const Instance& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Type& > (*this) = x; + this->any_ = x.any_; + this->id_ = x.id_; + this->state_ = x.state_; + this->reason_ = x.reason_; + this->cid_ = x.cid_; + this->any_attribute_ = x.any_attribute_; + } + + return *this; + } + + Instance:: + ~Instance () + { + } + + // Name + // + + Name:: + Name () + : ::LinphonePrivate::Xsd::XmlSchema::String (), + lang_ (this) + { + } + + Name:: + Name (const char* _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + lang_ (this) + { + } + + Name:: + Name (const ::std::string& _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + lang_ (this) + { + } + + Name:: + Name (const ::LinphonePrivate::Xsd::XmlSchema::String& _xsd_String_base) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_String_base), + lang_ (this) + { + } + + Name:: + Name (const Name& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (x, f, c), + lang_ (x.lang_, f, this) + { + } + + Name:: + Name (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f | ::LinphonePrivate::Xsd::XmlSchema::Flags::base, c), + lang_ (this) + { + if ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::base) == 0) + { + ::xsd::cxx::xml::dom::parser< char > p (e, false, false, true); + this->parse (p, f); + } + } + + void Name:: + parse (::xsd::cxx::xml::dom::parser< char >& p, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + while (p.more_attributes ()) + { + const ::xercesc::DOMAttr& i (p.next_attribute ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (i)); + + if (n.name () == "lang" && n.namespace_ () == "http://www.w3.org/XML/1998/namespace") + { + this->lang_.set (LangTraits::create (i, f, this)); + continue; + } + } + } + + Name* Name:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Name (*this, f, c); + } + + Name& Name:: + operator= (const Name& x) + { + if (this != &x) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = x; + this->lang_ = x.lang_; + } + + return *this; + } + + Name:: + ~Name () + { + } + + // State + // + + State:: + State (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + _xsd_State_convert (); + } + + State:: + State (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + _xsd_State_convert (); + } + + State:: + State (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + _xsd_State_convert (); + } + + State* State:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class State (*this, f, c); + } + + State::Value State:: + _xsd_State_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_State_literals_); + const Value* i (::std::lower_bound ( + _xsd_State_indexes_, + _xsd_State_indexes_ + 3, + *this, + c)); + + if (i == _xsd_State_indexes_ + 3 || _xsd_State_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const State:: + _xsd_State_literals_[3] = + { + "active", + "pending", + "terminated" + }; + + const State::Value State:: + _xsd_State_indexes_[3] = + { + ::LinphonePrivate::Xsd::Rlmi::State::active, + ::LinphonePrivate::Xsd::Rlmi::State::pending, + ::LinphonePrivate::Xsd::Rlmi::State::terminated + }; + } + } +} + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::std_ostream_plate< 0, char > + std_ostream_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + ::std::ostream& + operator<< (::std::ostream& o, const List& i) + { + for (List::NameConstIterator + b (i.getName ().begin ()), e (i.getName ().end ()); + b != e; ++b) + { + o << ::std::endl << "name: " << *b; + } + + for (List::ResourceConstIterator + b (i.getResource ().begin ()), e (i.getResource ().end ()); + b != e; ++b) + { + o << ::std::endl << "resource: " << *b; + } + + o << ::std::endl << "uri: " << i.getUri (); + o << ::std::endl << "version: " << i.getVersion (); + o << ::std::endl << "fullState: " << i.getFullState (); + if (i.getCid ()) + { + o << ::std::endl << "cid: " << *i.getCid (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Resource& i) + { + for (Resource::NameConstIterator + b (i.getName ().begin ()), e (i.getName ().end ()); + b != e; ++b) + { + o << ::std::endl << "name: " << *b; + } + + for (Resource::InstanceConstIterator + b (i.getInstance ().begin ()), e (i.getInstance ().end ()); + b != e; ++b) + { + o << ::std::endl << "instance: " << *b; + } + + o << ::std::endl << "uri: " << i.getUri (); + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Instance& i) + { + o << ::std::endl << "id: " << i.getId (); + o << ::std::endl << "state: " << i.getState (); + if (i.getReason ()) + { + o << ::std::endl << "reason: " << *i.getReason (); + } + + if (i.getCid ()) + { + o << ::std::endl << "cid: " << *i.getCid (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Name& i) + { + o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + + if (i.getLang ()) + { + o << ::std::endl << "lang: " << *i.getLang (); + } + + return o; + } + + ::std::ostream& + operator<< (::std::ostream& o, State::Value i) + { + return o << State::_xsd_State_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const State& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + } + } +} + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > ( + ::LinphonePrivate::Xsd::Rlmi::parseList ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::std::string& u, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > ( + ::LinphonePrivate::Xsd::Rlmi::parseList ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::std::string& u, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + u, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > ( + ::LinphonePrivate::Xsd::Rlmi::parseList ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::Rlmi::parseList (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::Rlmi::parseList (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is); + return ::LinphonePrivate::Xsd::Rlmi::parseList (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::Rlmi::parseList (isrc, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + const ::std::string& sid, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0, + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) == 0); + + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::Rlmi::parseList (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + const ::std::string& sid, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::xml::sax::std_input_source isrc (is, sid); + return ::LinphonePrivate::Xsd::Rlmi::parseList (isrc, h, f, p); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::xsd::cxx::tree::error_handler< char > h; + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + h.throw_if_failed< ::xsd::cxx::tree::parsing< char > > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > ( + ::LinphonePrivate::Xsd::Rlmi::parseList ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::xercesc::InputSource& i, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > ( + ::LinphonePrivate::Xsd::Rlmi::parseList ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::xercesc::InputSource& i, + ::xercesc::DOMErrorHandler& h, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::parse< char > ( + i, h, p, f)); + + if (!d.get ()) + throw ::xsd::cxx::tree::parsing< char > (); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > ( + ::LinphonePrivate::Xsd::Rlmi::parseList ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::xercesc::DOMDocument& doc, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p) + { + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + static_cast< ::xercesc::DOMDocument* > (doc.cloneNode (true))); + + return ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > ( + ::LinphonePrivate::Xsd::Rlmi::parseList ( + std::move (d), f | ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom, p)); + } + + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "list" && + n.namespace_ () == "urn:ietf:params:xml:ns:rlmi") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::Rlmi::List, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "list", + "urn:ietf:params:xml:ns:rlmi"); + } + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + const ::LinphonePrivate::Xsd::XmlSchema::Properties&) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > c ( + ((f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) && + !(f & ::LinphonePrivate::Xsd::XmlSchema::Flags::own_dom)) + ? static_cast< ::xercesc::DOMDocument* > (d->cloneNode (true)) + : 0); + + ::xercesc::DOMDocument& doc (c.get () ? *c : *d); + const ::xercesc::DOMElement& e (*doc.getDocumentElement ()); + + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::keep_dom) + doc.setUserData (::LinphonePrivate::Xsd::XmlSchema::dom::treeNodeKey, + (c.get () ? &c : &d), + 0); + + if (n.name () == "list" && + n.namespace_ () == "urn:ietf:params:xml:ns:rlmi") + { + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > r ( + ::xsd::cxx::tree::traits< ::LinphonePrivate::Xsd::Rlmi::List, char >::create ( + e, f, 0)); + return r; + } + + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "list", + "urn:ietf:params:xml:ns:rlmi"); + } + } + } +} + +#include +#include +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_serializer_plate< 0, char > + type_serializer_plate_init; +} + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + void + serializeList (::std::ostream& o, + const ::LinphonePrivate::Xsd::Rlmi::List& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Rlmi::serializeList (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeList (::std::ostream& o, + const ::LinphonePrivate::Xsd::Rlmi::List& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::xsd::cxx::xml::auto_initializer i ( + (f & ::LinphonePrivate::Xsd::XmlSchema::Flags::dont_initialize) == 0); + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Rlmi::serializeList (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeList (::std::ostream& o, + const ::LinphonePrivate::Xsd::Rlmi::List& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Rlmi::serializeList (s, m, f)); + ::xsd::cxx::xml::dom::ostream_format_target t (o); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeList (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::Rlmi::List& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Rlmi::serializeList (s, m, f)); + + ::xsd::cxx::tree::error_handler< char > h; + + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + h.throw_if_failed< ::xsd::cxx::tree::serialization< char > > (); + } + } + + void + serializeList (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::Rlmi::List& s, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Rlmi::serializeList (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeList (::xercesc::XMLFormatTarget& t, + const ::LinphonePrivate::Xsd::Rlmi::List& s, + ::xercesc::DOMErrorHandler& h, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + const ::std::string& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::LinphonePrivate::Xsd::Rlmi::serializeList (s, m, f)); + if (!::xsd::cxx::xml::dom::serialize (t, *d, e, h, f)) + { + throw ::xsd::cxx::tree::serialization< char > (); + } + } + + void + serializeList (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::Rlmi::List& s, + ::LinphonePrivate::Xsd::XmlSchema::Flags) + { + ::xercesc::DOMElement& e (*d.getDocumentElement ()); + const ::xsd::cxx::xml::qualified_name< char > n ( + ::xsd::cxx::xml::dom::name< char > (e)); + + if (n.name () == "list" && + n.namespace_ () == "urn:ietf:params:xml:ns:rlmi") + { + e << s; + } + else + { + throw ::xsd::cxx::tree::unexpected_element < char > ( + n.name (), + n.namespace_ (), + "list", + "urn:ietf:params:xml:ns:rlmi"); + } + } + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeList (const ::LinphonePrivate::Xsd::Rlmi::List& s, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m, + ::LinphonePrivate::Xsd::XmlSchema::Flags f) + { + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d ( + ::xsd::cxx::xml::dom::serialize< char > ( + "list", + "urn:ietf:params:xml:ns:rlmi", + m, f)); + + ::LinphonePrivate::Xsd::Rlmi::serializeList (*d, s, f); + return d; + } + + void + operator<< (::xercesc::DOMElement& e, const List& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (List::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // name + // + for (List::NameConstIterator + b (i.getName ().begin ()), n (i.getName ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "name", + "urn:ietf:params:xml:ns:rlmi", + e)); + + s << *b; + } + + // resource + // + for (List::ResourceConstIterator + b (i.getResource ().begin ()), n (i.getResource ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "resource", + "urn:ietf:params:xml:ns:rlmi", + e)); + + s << *b; + } + + // uri + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "uri", + e)); + + a << i.getUri (); + } + + // version + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "version", + e)); + + a << i.getVersion (); + } + + // fullState + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "fullState", + e)); + + a << i.getFullState (); + } + + // cid + // + if (i.getCid ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "cid", + e)); + + a << *i.getCid (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Resource& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (Resource::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // name + // + for (Resource::NameConstIterator + b (i.getName ().begin ()), n (i.getName ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "name", + "urn:ietf:params:xml:ns:rlmi", + e)); + + s << *b; + } + + // instance + // + for (Resource::InstanceConstIterator + b (i.getInstance ().begin ()), n (i.getInstance ().end ()); + b != n; ++b) + { + ::xercesc::DOMElement& s ( + ::xsd::cxx::xml::dom::create_element ( + "instance", + "urn:ietf:params:xml:ns:rlmi", + e)); + + s << *b; + } + + // uri + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "uri", + e)); + + a << i.getUri (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Instance& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Type& > (i); + + // any_attribute + // + for (Instance::AnyAttributeConstIterator + b (i.getAnyAttribute ().begin ()), n (i.getAnyAttribute ().end ()); + b != n; ++b) + { + ::xercesc::DOMAttr* a ( + static_cast< ::xercesc::DOMAttr* > ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMAttr* > (&(*b)), true))); + + if (a->getLocalName () == 0) + e.setAttributeNode (a); + else + e.setAttributeNodeNS (a); + } + + // any + // + for (Instance::AnyConstIterator + b (i.getAny ().begin ()), n (i.getAny ().end ()); + b != n; ++b) + { + e.appendChild ( + e.getOwnerDocument ()->importNode ( + const_cast< ::xercesc::DOMElement* > (&(*b)), true)); + } + + // id + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "id", + e)); + + a << i.getId (); + } + + // state + // + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "state", + e)); + + a << i.getState (); + } + + // reason + // + if (i.getReason ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "reason", + e)); + + a << *i.getReason (); + } + + // cid + // + if (i.getCid ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "cid", + e)); + + a << *i.getCid (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const Name& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + + // lang + // + if (i.getLang ()) + { + ::xercesc::DOMAttr& a ( + ::xsd::cxx::xml::dom::create_attribute ( + "lang", + "http://www.w3.org/XML/1998/namespace", + e)); + + a << *i.getLang (); + } + } + + void + operator<< (::xercesc::DOMElement& e, const State& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const State& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const State& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + diff --git a/src/xml/rlmi.h b/src/xml/rlmi.h new file mode 100644 index 000000000..68855f6cc --- /dev/null +++ b/src/xml/rlmi.h @@ -0,0 +1,1156 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +#ifndef XML_RLMI_H +#define XML_RLMI_H + +#ifndef XSD_CXX11 +#define XSD_CXX11 +#endif + +#ifndef XSD_USE_CHAR +#define XSD_USE_CHAR +#endif + +#ifndef XSD_CXX_TREE_USE_CHAR +#define XSD_CXX_TREE_USE_CHAR +#endif + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#if (XSD_INT_VERSION != 4000000L) +#error XSD runtime version mismatch +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace XmlSchema + { + // anyType and anySimpleType. + // + typedef ::xsd::cxx::tree::type Type; + typedef ::xsd::cxx::tree::simple_type< char, Type > SimpleType; + typedef ::xsd::cxx::tree::type Container; + + // 8-bit + // + typedef signed char Byte; + typedef unsigned char UnsignedByte; + + // 16-bit + // + typedef short Short; + typedef unsigned short UnsignedShort; + + // 32-bit + // + typedef int Int; + typedef unsigned int UnsignedInt; + + // 64-bit + // + typedef long long Long; + typedef unsigned long long UnsignedLong; + + // Supposed to be arbitrary-length integral types. + // + typedef long long Integer; + typedef long long NonPositiveInteger; + typedef unsigned long long NonNegativeInteger; + typedef unsigned long long PositiveInteger; + typedef long long NegativeInteger; + + // Boolean. + // + typedef bool Boolean; + + // Floating-point types. + // + typedef float Float; + typedef double Double; + typedef double Decimal; + + // String types. + // + typedef ::xsd::cxx::tree::string< char, SimpleType > String; + typedef ::xsd::cxx::tree::normalized_string< char, String > NormalizedString; + typedef ::xsd::cxx::tree::token< char, NormalizedString > Token; + typedef ::xsd::cxx::tree::name< char, Token > Name; + typedef ::xsd::cxx::tree::nmtoken< char, Token > Nmtoken; + typedef ::xsd::cxx::tree::nmtokens< char, SimpleType, Nmtoken > Nmtokens; + typedef ::xsd::cxx::tree::ncname< char, Name > Ncname; + typedef ::xsd::cxx::tree::language< char, Token > Language; + + // ID/IDREF. + // + typedef ::xsd::cxx::tree::id< char, Ncname > Id; + typedef ::xsd::cxx::tree::idref< char, Ncname, Type > Idref; + typedef ::xsd::cxx::tree::idrefs< char, SimpleType, Idref > Idrefs; + + // URI. + // + typedef ::xsd::cxx::tree::uri< char, SimpleType > Uri; + + // Qualified name. + // + typedef ::xsd::cxx::tree::qname< char, SimpleType, Uri, Ncname > Qname; + + // Binary. + // + typedef ::xsd::cxx::tree::buffer< char > Buffer; + typedef ::xsd::cxx::tree::base64_binary< char, SimpleType > Base64Binary; + typedef ::xsd::cxx::tree::hex_binary< char, SimpleType > HexBinary; + + // Date/time. + // + typedef ::xsd::cxx::tree::time_zone TimeZone; + typedef ::xsd::cxx::tree::date< char, SimpleType > Date; + typedef ::xsd::cxx::tree::date_time< char, SimpleType > DateTime; + typedef ::xsd::cxx::tree::duration< char, SimpleType > Duration; + typedef ::xsd::cxx::tree::gday< char, SimpleType > Gday; + typedef ::xsd::cxx::tree::gmonth< char, SimpleType > Gmonth; + typedef ::xsd::cxx::tree::gmonth_day< char, SimpleType > GmonthDay; + typedef ::xsd::cxx::tree::gyear< char, SimpleType > Gyear; + typedef ::xsd::cxx::tree::gyear_month< char, SimpleType > GyearMonth; + typedef ::xsd::cxx::tree::time< char, SimpleType > Time; + + // Entity. + // + typedef ::xsd::cxx::tree::entity< char, Ncname > Entity; + typedef ::xsd::cxx::tree::entities< char, SimpleType, Entity > Entities; + + typedef ::xsd::cxx::tree::content_order ContentOrder; + // Namespace information and list stream. Used in + // serialization functions. + // + typedef ::xsd::cxx::xml::dom::namespace_info< char > NamespaceInfo; + typedef ::xsd::cxx::xml::dom::namespace_infomap< char > NamespaceInfomap; + typedef ::xsd::cxx::tree::list_stream< char > ListStream; + typedef ::xsd::cxx::tree::as_double< Double > AsDouble; + typedef ::xsd::cxx::tree::as_decimal< Decimal > AsDecimal; + typedef ::xsd::cxx::tree::facet Facet; + + // Flags and properties. + // + typedef ::xsd::cxx::tree::flags Flags; + typedef ::xsd::cxx::tree::properties< char > Properties; + + // Parsing/serialization diagnostics. + // + typedef ::xsd::cxx::tree::severity Severity; + typedef ::xsd::cxx::tree::error< char > Error; + typedef ::xsd::cxx::tree::diagnostics< char > Diagnostics; + + // Exceptions. + // + typedef ::xsd::cxx::tree::exception< char > Exception; + typedef ::xsd::cxx::tree::bounds< char > Bounds; + typedef ::xsd::cxx::tree::duplicate_id< char > DuplicateId; + typedef ::xsd::cxx::tree::parsing< char > Parsing; + typedef ::xsd::cxx::tree::expected_element< char > ExpectedElement; + typedef ::xsd::cxx::tree::unexpected_element< char > UnexpectedElement; + typedef ::xsd::cxx::tree::expected_attribute< char > ExpectedAttribute; + typedef ::xsd::cxx::tree::unexpected_enumerator< char > UnexpectedEnumerator; + typedef ::xsd::cxx::tree::expected_text_content< char > ExpectedTextContent; + typedef ::xsd::cxx::tree::no_prefix_mapping< char > NoPrefixMapping; + typedef ::xsd::cxx::tree::no_type_info< char > NoTypeInfo; + typedef ::xsd::cxx::tree::not_derived< char > NotDerived; + typedef ::xsd::cxx::tree::serialization< char > Serialization; + + // Error handler callback interface. + // + typedef ::xsd::cxx::xml::error_handler< char > ErrorHandler; + + // DOM interaction. + // + namespace dom + { + // Automatic pointer for DOMDocument. + // + using ::xsd::cxx::xml::dom::unique_ptr; + +#ifndef XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA +#define XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA + // DOM user data key for back pointers to tree nodes. + // + const XMLCh* const treeNodeKey = ::xsd::cxx::tree::user_data_keys::node; +#endif + } + } + } +} + +// Forward declarations. +// +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + class List; + class Resource; + class Instance; + class Name; + class State; + } + } +} + + +#include // ::std::unique_ptr +#include // std::numeric_limits +#include // std::binary_search +#include // std::move + +#include + +#include +#include +#include +#include + +#include + +#include + +#include "xml.h" + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + class List: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // name + // + typedef ::LinphonePrivate::Xsd::Rlmi::Name NameType; + typedef ::xsd::cxx::tree::sequence< NameType > NameSequence; + typedef NameSequence::iterator NameIterator; + typedef NameSequence::const_iterator NameConstIterator; + typedef ::xsd::cxx::tree::traits< NameType, char > NameTraits; + + const NameSequence& + getName () const; + + NameSequence& + getName (); + + void + setName (const NameSequence& s); + + // resource + // + typedef ::LinphonePrivate::Xsd::Rlmi::Resource ResourceType; + typedef ::xsd::cxx::tree::sequence< ResourceType > ResourceSequence; + typedef ResourceSequence::iterator ResourceIterator; + typedef ResourceSequence::const_iterator ResourceConstIterator; + typedef ::xsd::cxx::tree::traits< ResourceType, char > ResourceTraits; + + const ResourceSequence& + getResource () const; + + ResourceSequence& + getResource (); + + void + setResource (const ResourceSequence& s); + + // uri + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri UriType; + typedef ::xsd::cxx::tree::traits< UriType, char > UriTraits; + + const UriType& + getUri () const; + + UriType& + getUri (); + + void + setUri (const UriType& x); + + void + setUri (::std::unique_ptr< UriType > p); + + ::std::unique_ptr< UriType > + setDetachUri (); + + // version + // + typedef ::LinphonePrivate::Xsd::XmlSchema::UnsignedInt VersionType; + typedef ::xsd::cxx::tree::traits< VersionType, char > VersionTraits; + + const VersionType& + getVersion () const; + + VersionType& + getVersion (); + + void + setVersion (const VersionType& x); + + // fullState + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Boolean FullStateType; + typedef ::xsd::cxx::tree::traits< FullStateType, char > FullStateTraits; + + const FullStateType& + getFullState () const; + + FullStateType& + getFullState (); + + void + setFullState (const FullStateType& x); + + // cid + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String CidType; + typedef ::xsd::cxx::tree::optional< CidType > CidOptional; + typedef ::xsd::cxx::tree::traits< CidType, char > CidTraits; + + const CidOptional& + getCid () const; + + CidOptional& + getCid (); + + void + setCid (const CidType& x); + + void + setCid (const CidOptional& x); + + void + setCid (::std::unique_ptr< CidType > p); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + List (const UriType&, + const VersionType&, + const FullStateType&); + + List (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + List (const List& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual List* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + List& + operator= (const List& x); + + virtual + ~List (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + NameSequence name_; + ResourceSequence resource_; + ::xsd::cxx::tree::one< UriType > uri_; + ::xsd::cxx::tree::one< VersionType > version_; + ::xsd::cxx::tree::one< FullStateType > fullState_; + CidOptional cid_; + AnyAttributeSet any_attribute_; + }; + + class Resource: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // name + // + typedef ::LinphonePrivate::Xsd::Rlmi::Name NameType; + typedef ::xsd::cxx::tree::sequence< NameType > NameSequence; + typedef NameSequence::iterator NameIterator; + typedef NameSequence::const_iterator NameConstIterator; + typedef ::xsd::cxx::tree::traits< NameType, char > NameTraits; + + const NameSequence& + getName () const; + + NameSequence& + getName (); + + void + setName (const NameSequence& s); + + // instance + // + typedef ::LinphonePrivate::Xsd::Rlmi::Instance InstanceType; + typedef ::xsd::cxx::tree::sequence< InstanceType > InstanceSequence; + typedef InstanceSequence::iterator InstanceIterator; + typedef InstanceSequence::const_iterator InstanceConstIterator; + typedef ::xsd::cxx::tree::traits< InstanceType, char > InstanceTraits; + + const InstanceSequence& + getInstance () const; + + InstanceSequence& + getInstance (); + + void + setInstance (const InstanceSequence& s); + + // uri + // + typedef ::LinphonePrivate::Xsd::XmlSchema::Uri UriType; + typedef ::xsd::cxx::tree::traits< UriType, char > UriTraits; + + const UriType& + getUri () const; + + UriType& + getUri (); + + void + setUri (const UriType& x); + + void + setUri (::std::unique_ptr< UriType > p); + + ::std::unique_ptr< UriType > + setDetachUri (); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + Resource (const UriType&); + + Resource (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Resource (const Resource& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Resource* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Resource& + operator= (const Resource& x); + + virtual + ~Resource (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + NameSequence name_; + InstanceSequence instance_; + ::xsd::cxx::tree::one< UriType > uri_; + AnyAttributeSet any_attribute_; + }; + + class Instance: public ::LinphonePrivate::Xsd::XmlSchema::Type + { + public: + // any + // + typedef ::xsd::cxx::tree::element_sequence AnySequence; + typedef AnySequence::iterator AnyIterator; + typedef AnySequence::const_iterator AnyConstIterator; + + const AnySequence& + getAny () const; + + AnySequence& + getAny (); + + void + setAny (const AnySequence& s); + + // id + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String IdType; + typedef ::xsd::cxx::tree::traits< IdType, char > IdTraits; + + const IdType& + getId () const; + + IdType& + getId (); + + void + setId (const IdType& x); + + void + setId (::std::unique_ptr< IdType > p); + + ::std::unique_ptr< IdType > + setDetachId (); + + // state + // + typedef ::LinphonePrivate::Xsd::Rlmi::State StateType; + typedef ::xsd::cxx::tree::traits< StateType, char > StateTraits; + + const StateType& + getState () const; + + StateType& + getState (); + + void + setState (const StateType& x); + + void + setState (::std::unique_ptr< StateType > p); + + ::std::unique_ptr< StateType > + setDetachState (); + + // reason + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String ReasonType; + typedef ::xsd::cxx::tree::optional< ReasonType > ReasonOptional; + typedef ::xsd::cxx::tree::traits< ReasonType, char > ReasonTraits; + + const ReasonOptional& + getReason () const; + + ReasonOptional& + getReason (); + + void + setReason (const ReasonType& x); + + void + setReason (const ReasonOptional& x); + + void + setReason (::std::unique_ptr< ReasonType > p); + + // cid + // + typedef ::LinphonePrivate::Xsd::XmlSchema::String CidType; + typedef ::xsd::cxx::tree::optional< CidType > CidOptional; + typedef ::xsd::cxx::tree::traits< CidType, char > CidTraits; + + const CidOptional& + getCid () const; + + CidOptional& + getCid (); + + void + setCid (const CidType& x); + + void + setCid (const CidOptional& x); + + void + setCid (::std::unique_ptr< CidType > p); + + // any_attribute + // + typedef ::xsd::cxx::tree::attribute_set< char > AnyAttributeSet; + typedef AnyAttributeSet::iterator AnyAttributeIterator; + typedef AnyAttributeSet::const_iterator AnyAttributeConstIterator; + + const AnyAttributeSet& + getAnyAttribute () const; + + AnyAttributeSet& + getAnyAttribute (); + + void + setAnyAttribute (const AnyAttributeSet& s); + + // DOMDocument for wildcard content. + // + const ::xercesc::DOMDocument& + getDomDocument () const; + + ::xercesc::DOMDocument& + getDomDocument (); + + // Constructors. + // + Instance (const IdType&, + const StateType&); + + Instance (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Instance (const Instance& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Instance* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Instance& + operator= (const Instance& x); + + virtual + ~Instance (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > dom_document_; + + AnySequence any_; + ::xsd::cxx::tree::one< IdType > id_; + ::xsd::cxx::tree::one< StateType > state_; + ReasonOptional reason_; + CidOptional cid_; + AnyAttributeSet any_attribute_; + }; + + class Name: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + // lang + // + typedef ::namespace_::Lang LangType; + typedef ::xsd::cxx::tree::optional< LangType > LangOptional; + typedef ::xsd::cxx::tree::traits< LangType, char > LangTraits; + + const LangOptional& + getLang () const; + + LangOptional& + getLang (); + + void + setLang (const LangType& x); + + void + setLang (const LangOptional& x); + + void + setLang (::std::unique_ptr< LangType > p); + + // Constructors. + // + Name (); + + Name (const char*); + + Name (const ::std::string&); + + Name (const ::LinphonePrivate::Xsd::XmlSchema::String&); + + Name (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Name (const Name& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Name* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Name& + operator= (const Name& x); + + virtual + ~Name (); + + // Implementation. + // + protected: + void + parse (::xsd::cxx::xml::dom::parser< char >&, + ::LinphonePrivate::Xsd::XmlSchema::Flags); + + protected: + LangOptional lang_; + }; + + class State: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + enum Value + { + active, + pending, + terminated + }; + + State (Value v); + + State (const char* v); + + State (const ::std::string& v); + + State (const ::LinphonePrivate::Xsd::XmlSchema::String& v); + + State (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + State (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + State (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + State (const State& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual State* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + State& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_State_convert (); + } + + protected: + Value + _xsd_State_convert () const; + + public: + static const char* const _xsd_State_literals_[3]; + static const Value _xsd_State_indexes_[3]; + }; + } + } +} + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + ::std::ostream& + operator<< (::std::ostream&, const List&); + + ::std::ostream& + operator<< (::std::ostream&, const Resource&); + + ::std::ostream& + operator<< (::std::ostream&, const Instance&); + + ::std::ostream& + operator<< (::std::ostream&, const Name&); + + ::std::ostream& + operator<< (::std::ostream&, State::Value); + + ::std::ostream& + operator<< (::std::ostream&, const State&); + } + } +} + +#include + +#include +#include +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + // Parse a URI or a local file. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::std::string& uri, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::std::string& uri, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse std::istream. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + const ::std::string& id, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::std::istream& is, + const ::std::string& id, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::InputSource. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::xercesc::InputSource& is, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::xercesc::InputSource& is, + ::xercesc::DOMErrorHandler& eh, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + // Parse xercesc::DOMDocument. + // + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (const ::xercesc::DOMDocument& d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + + ::std::unique_ptr< ::LinphonePrivate::Xsd::Rlmi::List > + parseList (::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > d, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + const ::LinphonePrivate::Xsd::XmlSchema::Properties& p = ::LinphonePrivate::Xsd::XmlSchema::Properties ()); + } + } +} + +#include + +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace Rlmi + { + // Serialize to std::ostream. + // + + void + serializeList (::std::ostream& os, + const ::LinphonePrivate::Xsd::Rlmi::List& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeList (::std::ostream& os, + const ::LinphonePrivate::Xsd::Rlmi::List& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeList (::std::ostream& os, + const ::LinphonePrivate::Xsd::Rlmi::List& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to xercesc::XMLFormatTarget. + // + + void + serializeList (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::Rlmi::List& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeList (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::Rlmi::List& x, + ::LinphonePrivate::Xsd::XmlSchema::ErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + serializeList (::xercesc::XMLFormatTarget& ft, + const ::LinphonePrivate::Xsd::Rlmi::List& x, + ::xercesc::DOMErrorHandler& eh, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + const ::std::string& e = "UTF-8", + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to an existing xercesc::DOMDocument. + // + + void + serializeList (::xercesc::DOMDocument& d, + const ::LinphonePrivate::Xsd::Rlmi::List& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + // Serialize to a new xercesc::DOMDocument. + // + + ::LinphonePrivate::Xsd::XmlSchema::dom::unique_ptr< ::xercesc::DOMDocument > + serializeList (const ::LinphonePrivate::Xsd::Rlmi::List& x, + const ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap& m = ::LinphonePrivate::Xsd::XmlSchema::NamespaceInfomap (), + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0); + + void + operator<< (::xercesc::DOMElement&, const List&); + + void + operator<< (::xercesc::DOMElement&, const Resource&); + + void + operator<< (::xercesc::DOMElement&, const Instance&); + + void + operator<< (::xercesc::DOMElement&, const Name&); + + void + operator<< (::xercesc::DOMElement&, const State&); + + void + operator<< (::xercesc::DOMAttr&, const State&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const State&); + } + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + +#endif // XML_RLMI_H diff --git a/src/xml/rlmi.xsd b/src/xml/rlmi.xsd new file mode 100644 index 000000000..a903802fb --- /dev/null +++ b/src/xml/rlmi.xsd @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/xml/xml.cpp b/src/xml/xml.cpp new file mode 100644 index 000000000..7c5162e3d --- /dev/null +++ b/src/xml/xml.cpp @@ -0,0 +1,501 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#include "xml.h" + +namespace namespace_ +{ + // Lang + // + + Lang:: + Lang (const char* s) + : ::LinphonePrivate::Xsd::XmlSchema::String (s) + { + } + + Lang:: + Lang (const ::std::string& s) + : ::LinphonePrivate::Xsd::XmlSchema::String (s) + { + } + + Lang:: + Lang (const Lang& o, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (o, f, c) + { + } + + // Space + // + + Space:: + Space (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (_xsd_Space_literals_[v]) + { + } + + Space:: + Space (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (v) + { + } + + Space:: + Space (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (v) + { + } + + Space:: + Space (const ::LinphonePrivate::Xsd::XmlSchema::Ncname& v) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (v) + { + } + + Space:: + Space (const Space& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (v, f, c) + { + } + + Space& Space:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::Ncname& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::Ncname (_xsd_Space_literals_[v]); + + return *this; + } + + + // Lang_member + // + + Lang_member:: + Lang_member (Value v) + : ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_Lang_member_literals_[v]) + { + } + + Lang_member:: + Lang_member (const char* v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + Lang_member:: + Lang_member (const ::std::string& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + Lang_member:: + Lang_member (const ::LinphonePrivate::Xsd::XmlSchema::String& v) + : ::LinphonePrivate::Xsd::XmlSchema::String (v) + { + } + + Lang_member:: + Lang_member (const Lang_member& v, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (v, f, c) + { + } + + Lang_member& Lang_member:: + operator= (Value v) + { + static_cast< ::LinphonePrivate::Xsd::XmlSchema::String& > (*this) = + ::LinphonePrivate::Xsd::XmlSchema::String (_xsd_Lang_member_literals_[v]); + + return *this; + } +} + +#include + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_factory_plate< 0, char > + type_factory_plate_init; +} + +namespace namespace_ +{ + // Lang + // + + Lang:: + Lang (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + } + + Lang:: + Lang (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + } + + Lang:: + Lang (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + } + + Lang* Lang:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Lang (*this, f, c); + } + + // Space + // + + Space:: + Space (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (e, f, c) + { + _xsd_Space_convert (); + } + + Space:: + Space (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (a, f, c) + { + _xsd_Space_convert (); + } + + Space:: + Space (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::Ncname (s, e, f, c) + { + _xsd_Space_convert (); + } + + Space* Space:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Space (*this, f, c); + } + + Space::Value Space:: + _xsd_Space_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_Space_literals_); + const Value* i (::std::lower_bound ( + _xsd_Space_indexes_, + _xsd_Space_indexes_ + 2, + *this, + c)); + + if (i == _xsd_Space_indexes_ + 2 || _xsd_Space_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const Space:: + _xsd_Space_literals_[2] = + { + "default", + "preserve" + }; + + const Space::Value Space:: + _xsd_Space_indexes_[2] = + { + ::namespace_::Space::default_, + ::namespace_::Space::preserve + }; + + // Lang_member + // + + Lang_member:: + Lang_member (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (e, f, c) + { + _xsd_Lang_member_convert (); + } + + Lang_member:: + Lang_member (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (a, f, c) + { + _xsd_Lang_member_convert (); + } + + Lang_member:: + Lang_member (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) + : ::LinphonePrivate::Xsd::XmlSchema::String (s, e, f, c) + { + _xsd_Lang_member_convert (); + } + + Lang_member* Lang_member:: + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f, + ::LinphonePrivate::Xsd::XmlSchema::Container* c) const + { + return new class Lang_member (*this, f, c); + } + + Lang_member::Value Lang_member:: + _xsd_Lang_member_convert () const + { + ::xsd::cxx::tree::enum_comparator< char > c (_xsd_Lang_member_literals_); + const Value* i (::std::lower_bound ( + _xsd_Lang_member_indexes_, + _xsd_Lang_member_indexes_ + 1, + *this, + c)); + + if (i == _xsd_Lang_member_indexes_ + 1 || _xsd_Lang_member_literals_[*i] != *this) + { + throw ::xsd::cxx::tree::unexpected_enumerator < char > (*this); + } + + return *i; + } + + const char* const Lang_member:: + _xsd_Lang_member_literals_[1] = + { + "" + }; + + const Lang_member::Value Lang_member:: + _xsd_Lang_member_indexes_[1] = + { + ::namespace_::Lang_member::empty + }; +} + +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::std_ostream_plate< 0, char > + std_ostream_plate_init; +} + +namespace namespace_ +{ + ::std::ostream& + operator<< (::std::ostream& o, const Lang& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, Space::Value i) + { + return o << Space::_xsd_Space_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Space& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Ncname& > (i); + } + + ::std::ostream& + operator<< (::std::ostream& o, Lang_member::Value i) + { + return o << Lang_member::_xsd_Lang_member_literals_[i]; + } + + ::std::ostream& + operator<< (::std::ostream& o, const Lang_member& i) + { + return o << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } +} + +#include +#include +#include + +namespace namespace_ +{ +} + +#include +#include +#include + +#include + +namespace _xsd +{ + static + const ::xsd::cxx::tree::type_serializer_plate< 0, char > + type_serializer_plate_init; +} + +namespace namespace_ +{ + void + operator<< (::xercesc::DOMElement& e, const Lang& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const Lang& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const Lang& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const Space& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Ncname& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const Space& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Ncname& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const Space& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::Ncname& > (i); + } + + void + operator<< (::xercesc::DOMElement& e, const Lang_member& i) + { + e << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::xercesc::DOMAttr& a, const Lang_member& i) + { + a << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream& l, + const Lang_member& i) + { + l << static_cast< const ::LinphonePrivate::Xsd::XmlSchema::String& > (i); + } +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + diff --git a/src/xml/xml.h b/src/xml/xml.h new file mode 100644 index 000000000..c05ea2029 --- /dev/null +++ b/src/xml/xml.h @@ -0,0 +1,534 @@ +// Copyright (c) 2005-2014 Code Synthesis Tools CC +// +// This program was generated by CodeSynthesis XSD, an XML Schema to +// C++ data binding compiler. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2 as +// published by the Free Software Foundation. +// +// 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// +// In addition, as a special exception, Code Synthesis Tools CC gives +// permission to link this program with the Xerces-C++ library (or with +// modified versions of Xerces-C++ that use the same license as Xerces-C++), +// and distribute linked combinations including the two. You must obey +// the GNU General Public License version 2 in all respects for all of +// the code used other than Xerces-C++. If you modify this copy of the +// program, you may extend this exception to your version of the program, +// but you are not obligated to do so. If you do not wish to do so, delete +// this exception statement from your version. +// +// Furthermore, Code Synthesis Tools CC makes a special exception for +// the Free/Libre and Open Source Software (FLOSS) which is described +// in the accompanying FLOSSE file. +// + +#ifndef XML_XML_H +#define XML_XML_H + +#ifndef XSD_CXX11 +#define XSD_CXX11 +#endif + +#ifndef XSD_USE_CHAR +#define XSD_USE_CHAR +#endif + +#ifndef XSD_CXX_TREE_USE_CHAR +#define XSD_CXX_TREE_USE_CHAR +#endif + +// Begin prologue. +// +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" + #pragma GCC diagnostic ignored "-Wsign-conversion" + #pragma GCC diagnostic ignored "-Wconversion" +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wsuggest-override" +#endif +#if __GNUC__ >=7 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +// +// End prologue. + +#include + +#if (XSD_INT_VERSION != 4000000L) +#error XSD runtime version mismatch +#endif + +#include + +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace LinphonePrivate +{ + namespace Xsd + { + namespace XmlSchema + { + // anyType and anySimpleType. + // + typedef ::xsd::cxx::tree::type Type; + typedef ::xsd::cxx::tree::simple_type< char, Type > SimpleType; + typedef ::xsd::cxx::tree::type Container; + + // 8-bit + // + typedef signed char Byte; + typedef unsigned char UnsignedByte; + + // 16-bit + // + typedef short Short; + typedef unsigned short UnsignedShort; + + // 32-bit + // + typedef int Int; + typedef unsigned int UnsignedInt; + + // 64-bit + // + typedef long long Long; + typedef unsigned long long UnsignedLong; + + // Supposed to be arbitrary-length integral types. + // + typedef long long Integer; + typedef long long NonPositiveInteger; + typedef unsigned long long NonNegativeInteger; + typedef unsigned long long PositiveInteger; + typedef long long NegativeInteger; + + // Boolean. + // + typedef bool Boolean; + + // Floating-point types. + // + typedef float Float; + typedef double Double; + typedef double Decimal; + + // String types. + // + typedef ::xsd::cxx::tree::string< char, SimpleType > String; + typedef ::xsd::cxx::tree::normalized_string< char, String > NormalizedString; + typedef ::xsd::cxx::tree::token< char, NormalizedString > Token; + typedef ::xsd::cxx::tree::name< char, Token > Name; + typedef ::xsd::cxx::tree::nmtoken< char, Token > Nmtoken; + typedef ::xsd::cxx::tree::nmtokens< char, SimpleType, Nmtoken > Nmtokens; + typedef ::xsd::cxx::tree::ncname< char, Name > Ncname; + typedef ::xsd::cxx::tree::language< char, Token > Language; + + // ID/IDREF. + // + typedef ::xsd::cxx::tree::id< char, Ncname > Id; + typedef ::xsd::cxx::tree::idref< char, Ncname, Type > Idref; + typedef ::xsd::cxx::tree::idrefs< char, SimpleType, Idref > Idrefs; + + // URI. + // + typedef ::xsd::cxx::tree::uri< char, SimpleType > Uri; + + // Qualified name. + // + typedef ::xsd::cxx::tree::qname< char, SimpleType, Uri, Ncname > Qname; + + // Binary. + // + typedef ::xsd::cxx::tree::buffer< char > Buffer; + typedef ::xsd::cxx::tree::base64_binary< char, SimpleType > Base64Binary; + typedef ::xsd::cxx::tree::hex_binary< char, SimpleType > HexBinary; + + // Date/time. + // + typedef ::xsd::cxx::tree::time_zone TimeZone; + typedef ::xsd::cxx::tree::date< char, SimpleType > Date; + typedef ::xsd::cxx::tree::date_time< char, SimpleType > DateTime; + typedef ::xsd::cxx::tree::duration< char, SimpleType > Duration; + typedef ::xsd::cxx::tree::gday< char, SimpleType > Gday; + typedef ::xsd::cxx::tree::gmonth< char, SimpleType > Gmonth; + typedef ::xsd::cxx::tree::gmonth_day< char, SimpleType > GmonthDay; + typedef ::xsd::cxx::tree::gyear< char, SimpleType > Gyear; + typedef ::xsd::cxx::tree::gyear_month< char, SimpleType > GyearMonth; + typedef ::xsd::cxx::tree::time< char, SimpleType > Time; + + // Entity. + // + typedef ::xsd::cxx::tree::entity< char, Ncname > Entity; + typedef ::xsd::cxx::tree::entities< char, SimpleType, Entity > Entities; + + typedef ::xsd::cxx::tree::content_order ContentOrder; + // Namespace information and list stream. Used in + // serialization functions. + // + typedef ::xsd::cxx::xml::dom::namespace_info< char > NamespaceInfo; + typedef ::xsd::cxx::xml::dom::namespace_infomap< char > NamespaceInfomap; + typedef ::xsd::cxx::tree::list_stream< char > ListStream; + typedef ::xsd::cxx::tree::as_double< Double > AsDouble; + typedef ::xsd::cxx::tree::as_decimal< Decimal > AsDecimal; + typedef ::xsd::cxx::tree::facet Facet; + + // Flags and properties. + // + typedef ::xsd::cxx::tree::flags Flags; + typedef ::xsd::cxx::tree::properties< char > Properties; + + // Parsing/serialization diagnostics. + // + typedef ::xsd::cxx::tree::severity Severity; + typedef ::xsd::cxx::tree::error< char > Error; + typedef ::xsd::cxx::tree::diagnostics< char > Diagnostics; + + // Exceptions. + // + typedef ::xsd::cxx::tree::exception< char > Exception; + typedef ::xsd::cxx::tree::bounds< char > Bounds; + typedef ::xsd::cxx::tree::duplicate_id< char > DuplicateId; + typedef ::xsd::cxx::tree::parsing< char > Parsing; + typedef ::xsd::cxx::tree::expected_element< char > ExpectedElement; + typedef ::xsd::cxx::tree::unexpected_element< char > UnexpectedElement; + typedef ::xsd::cxx::tree::expected_attribute< char > ExpectedAttribute; + typedef ::xsd::cxx::tree::unexpected_enumerator< char > UnexpectedEnumerator; + typedef ::xsd::cxx::tree::expected_text_content< char > ExpectedTextContent; + typedef ::xsd::cxx::tree::no_prefix_mapping< char > NoPrefixMapping; + typedef ::xsd::cxx::tree::no_type_info< char > NoTypeInfo; + typedef ::xsd::cxx::tree::not_derived< char > NotDerived; + typedef ::xsd::cxx::tree::serialization< char > Serialization; + + // Error handler callback interface. + // + typedef ::xsd::cxx::xml::error_handler< char > ErrorHandler; + + // DOM interaction. + // + namespace dom + { + // Automatic pointer for DOMDocument. + // + using ::xsd::cxx::xml::dom::unique_ptr; + +#ifndef XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA +#define XSD_CXX_TREE_TREE_NODE_KEY__LINPHONEPRIVATE__XSD__XMLSCHEMA + // DOM user data key for back pointers to tree nodes. + // + const XMLCh* const treeNodeKey = ::xsd::cxx::tree::user_data_keys::node; +#endif + } + } + } +} + +// Forward declarations. +// +namespace namespace_ +{ + class Lang; + class Space; + class Lang_member; +} + + +#include // ::std::unique_ptr +#include // std::numeric_limits +#include // std::binary_search +#include // std::move + +#include + +#include +#include +#include +#include + +#include + +#include + +namespace namespace_ +{ + class Lang: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + + Lang (const char* v); + + Lang (const ::std::string& v); + + Lang (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Lang (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Lang (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Lang (const Lang& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Lang* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + }; + + class Space: public ::LinphonePrivate::Xsd::XmlSchema::Ncname + { + public: + enum Value + { + default_, + preserve + }; + + Space (Value v); + + Space (const char* v); + + Space (const ::std::string& v); + + Space (const ::LinphonePrivate::Xsd::XmlSchema::Ncname& v); + + Space (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Space (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Space (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Space (const Space& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Space* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Space& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_Space_convert (); + } + + protected: + Value + _xsd_Space_convert () const; + + public: + static const char* const _xsd_Space_literals_[2]; + static const Value _xsd_Space_indexes_[2]; + }; + + class Lang_member: public ::LinphonePrivate::Xsd::XmlSchema::String + { + public: + enum Value + { + empty + }; + + Lang_member (Value v); + + Lang_member (const char* v); + + Lang_member (const ::std::string& v); + + Lang_member (const ::LinphonePrivate::Xsd::XmlSchema::String& v); + + Lang_member (const ::xercesc::DOMElement& e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Lang_member (const ::xercesc::DOMAttr& a, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Lang_member (const ::std::string& s, + const ::xercesc::DOMElement* e, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + Lang_member (const Lang_member& x, + ::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0); + + virtual Lang_member* + _clone (::LinphonePrivate::Xsd::XmlSchema::Flags f = 0, + ::LinphonePrivate::Xsd::XmlSchema::Container* c = 0) const; + + Lang_member& + operator= (Value v); + + virtual + operator Value () const + { + return _xsd_Lang_member_convert (); + } + + protected: + Value + _xsd_Lang_member_convert () const; + + public: + static const char* const _xsd_Lang_member_literals_[1]; + static const Value _xsd_Lang_member_indexes_[1]; + }; +} + +#include + +namespace namespace_ +{ + ::std::ostream& + operator<< (::std::ostream&, const Lang&); + + ::std::ostream& + operator<< (::std::ostream&, Space::Value); + + ::std::ostream& + operator<< (::std::ostream&, const Space&); + + ::std::ostream& + operator<< (::std::ostream&, Lang_member::Value); + + ::std::ostream& + operator<< (::std::ostream&, const Lang_member&); +} + +#include + +#include +#include +#include + +namespace namespace_ +{ +} + +#include + +#include +#include +#include + +#include + +namespace namespace_ +{ + void + operator<< (::xercesc::DOMElement&, const Lang&); + + void + operator<< (::xercesc::DOMAttr&, const Lang&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Lang&); + + void + operator<< (::xercesc::DOMElement&, const Space&); + + void + operator<< (::xercesc::DOMAttr&, const Space&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Space&); + + void + operator<< (::xercesc::DOMElement&, const Lang_member&); + + void + operator<< (::xercesc::DOMAttr&, const Lang_member&); + + void + operator<< (::LinphonePrivate::Xsd::XmlSchema::ListStream&, + const Lang_member&); +} + +#include + +// Begin epilogue. +// +#if __GNUC__ >= 7 + #pragma GCC diagnostic pop +#endif +#if __GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1) + #pragma GCC diagnostic pop +#endif +#if __clang__ || __GNUC__ >= 4 + #pragma GCC diagnostic pop +#endif +// +// End epilogue. + +#endif // XML_XML_H diff --git a/src/xml/xml.xsd b/src/xml/xml.xsd new file mode 100644 index 000000000..aea7d0db0 --- /dev/null +++ b/src/xml/xml.xsd @@ -0,0 +1,287 @@ + + + + + + +
+

About the XML namespace

+ +
+

+ This schema document describes the XML namespace, in a form + suitable for import by other schema documents. +

+

+ See + http://www.w3.org/XML/1998/namespace.html and + + http://www.w3.org/TR/REC-xml for information + about this namespace. +

+

+ Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance. +

+

+ See further below in this document for more information about how to refer to this schema document from your own + XSD schema documents and about the + namespace-versioning policy governing this schema document. +

+
+
+
+
+ + + + +
+ +

lang (as an attribute name)

+

+ denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+ +
+
+

Notes

+

+ Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. +

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

+ The union allows for the 'un-declaration' of xml:lang with + the empty string. +

+
+
+
+ + + + + + + + + +
+ + + + +
+ +

space (as an attribute name)

+

+ denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+ +
+
+
+ + + + + + +
+ + + +
+ +

base (as an attribute name)

+

+ denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+ +

+ See http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
+
+
+ + + + +
+ +

id (as an attribute name)

+

+ denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+ +

+ See http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
+
+
+ + + + + + + + + + +
+ +

Father (in any context at all)

+ +
+

+ denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: +

+
+

+ In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father". +

+
+
+
+
+
+ + + +
+

About this schema document

+ +
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow xml:base, + xml:lang, xml:space or + xml:id attributes on elements they define. +

+

+ To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows: +

+
+          <schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+     
+

+ or +

+
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+     
+

+ Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g. +

+
+          <type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+     
+

+ will define a type which will schema-validate an instance element + with any of those attributes. +

+
+
+
+
+ + + +
+

Versioning policy for this schema document

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + + http://www.w3.org/2009/01/xml.xsd. +

+

+ At the date of issue it can also be found at + + http://www.w3.org/2001/xml.xsd. +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + + will change accordingly; the version at + + http://www.w3.org/2009/01/xml.xsd + + will not change. +

+

+ Previous dated (and unchanging) versions of this schema + document are at: +

+ +
+
+
+
+ +
+ diff --git a/tester/CMakeLists.txt b/tester/CMakeLists.txt index 193a7add0..f9538b403 100644 --- a/tester/CMakeLists.txt +++ b/tester/CMakeLists.txt @@ -20,7 +20,7 @@ # ############################################################################ -set(OTHER_LIBS_FOR_TESTER ${BCTOOLBOX_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${BELLESIP_LIBRARIES} ${XML2_LIBRARIES}) +set(OTHER_LIBS_FOR_TESTER ${BCTOOLBOX_LIBRARIES} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${BELLESIP_LIBRARIES} ${XML2_LIBRARIES} ${XSD_LIBRARIES} ${BELR_LIBRARIES}) if(INTL_FOUND) list(APPEND OTHER_LIBS_FOR_TESTER ${INTL_LIBRARIES}) endif() @@ -78,10 +78,17 @@ set(CERTIFICATE_CLIENT_FILES set(CERTIFICATE_FILES ${CERTIFICATE_ALT_FILES} ${CERTIFICATE_CN_FILES} ${CERTIFICATE_CLIENT_FILES}) +set(DB_FILES + db/friends.db + db/linphone.db + db/messages.db +) + set(RC_FILES rcfiles/account_creator_rc rcfiles/assistant_create.rc rcfiles/carddav_rc + rcfiles/chloe_rc rcfiles/conference_focus_rc rcfiles/empty_rc rcfiles/friends_rc @@ -134,12 +141,13 @@ set(RC_FILES rcfiles/pauline_zrtp_ecdh448_rc rcfiles/remote_zero_length_params_rc rcfiles/stun_rc - rcfiles/upnp_rc rcfiles/zero_length_params_rc ) set(IMAGE_FILES images/linphone.svg + images/linphonesiteqr.jpg + images/linphonesiteqr_captured.jpg images/nowebcamCIF.jpg images/nowebcamVGA.jpg ) @@ -152,11 +160,11 @@ set(VCARD_FILES set(OTHER_FILES tester_hosts local_tester_hosts - messages.db ) set(IOS_RESOURCES_FILES ${OTHER_FILES} + ${DB_FILES} certificates images rcfiles @@ -177,8 +185,8 @@ set(SOURCE_FILES_C dtmf_tester.c eventapi_tester.c flexisip_tester.c + group_chat_tester.c liblinphone_tester.c - liblinphone_tester.h log_collection_tester.c message_tester.c offeranswer_tester.c @@ -193,13 +201,24 @@ set(SOURCE_FILES_C stun_tester.c tester.c tunnel_tester.c - upnp_tester.c vcard_tester.c video_tester.c ) set(SOURCE_FILES_CXX - cpim_tester.cpp + clonable-object-tester.cpp + conference-event-tester.cpp + contents-tester.cpp + cpim-tester.cpp + main-db-tester.cpp + multipart-tester.cpp + property-container-tester.cpp +) + +set(HEADER_FILES + liblinphone_tester.h + tools/private-access.h + tools/tester.h ) set(SOURCE_FILES_OBJC ) @@ -209,10 +228,17 @@ if(APPLE) endif() endif() +# TODO: Remove me later! +list(REMOVE_ITEM STRICT_OPTIONS_CPP "-Wconversion" "-Werror=conversion" "-Wcast-align" "-Werror=cast-align") +if (ANDROID AND CMAKE_C_COMPILER_ID STREQUAL "GNU") #restrict to Android as it seems to break reguler linux + list (APPEND STRICT_OPTIONS_C "-std=c99") +endif() bc_apply_compile_flags(SOURCE_FILES_C STRICT_OPTIONS_CPP STRICT_OPTIONS_C) bc_apply_compile_flags(SOURCE_FILES_CXX STRICT_OPTIONS_CPP STRICT_OPTIONS_CXX) bc_apply_compile_flags(SOURCE_FILES_OBJC STRICT_OPTIONS_CPP STRICT_OPTIONS_OBJC) +add_definitions("-DLINPHONE_TESTER") + if(MSVC) get_source_file_property(MESSAGE_TESTER_C_COMPILE_FLAGS message_tester.c COMPILE_FLAGS) set(MESSAGE_TESTER_C_COMPILE_FLAGS "${MESSAGE_TESTER_C_COMPILE_FLAGS} /wd4996") # Disable "was declared deprecated" warnings @@ -233,13 +259,14 @@ endif() # on mobile platforms, we compile the tester as a library so that we can link with it directly from native applications if(ANDROID OR IOS) - add_library(linphonetester SHARED ${SOURCE_FILES_C} ${SOURCE_FILES_CXX}) + add_library(linphonetester SHARED ${HEADER_FILES} ${SOURCE_FILES_C} ${SOURCE_FILES_CXX}) target_include_directories(linphonetester PUBLIC ${BCTOOLBOX_TESTER_INCLUDE_DIRS}) target_link_libraries(linphonetester ${LINPHONE_LIBS_FOR_TOOLS} ${OTHER_LIBS_FOR_TESTER}) if(IOS) set_target_properties(linphonetester PROPERTIES FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER com.belledonne-communications.linphonetester + PUBLIC_HEADER "${HEADER_FILES}" ) endif() install(TARGETS linphonetester @@ -254,7 +281,7 @@ if(ANDROID OR IOS) PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ ) elseif(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") - add_library(linphone_tester_static STATIC ${SOURCE_FILES_C} ${SOURCE_FILES_CXX}) + add_library(linphone_tester_static STATIC ${HEADER_FILES} ${SOURCE_FILES_C} ${SOURCE_FILES_CXX}) target_include_directories(linphone_tester_static PUBLIC ${BCTOOLBOX_TESTER_INCLUDE_DIRS}) target_link_libraries(linphone_tester_static ${LINPHONE_LIBS_FOR_TOOLS} ${OTHER_LIBS_FOR_TESTER}) @@ -288,23 +315,15 @@ endif() if (NOT ANDROID AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") if(IOS) set_source_files_properties(${IOS_RESOURCES_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - add_executable(liblinphone_tester MACOSX_BUNDLE ${IOS_RESOURCES_FILES} ${SOURCE_FILES_C} ${SOURCE_FILES_CXX} ${SOURCE_FILES_OBJC}) + add_executable(liblinphone_tester MACOSX_BUNDLE ${IOS_RESOURCES_FILES} ${HEADER_FILES} ${SOURCE_FILES_C} ${SOURCE_FILES_CXX} ${SOURCE_FILES_OBJC}) else() - add_executable(liblinphone_tester ${SOURCE_FILES_C} ${SOURCE_FILES_CXX} ${SOURCE_FILES_OBJC}) + add_executable(liblinphone_tester ${HEADER_FILES} ${SOURCE_FILES_C} ${SOURCE_FILES_CXX} ${SOURCE_FILES_OBJC}) endif() set_target_properties(liblinphone_tester PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set_target_properties(liblinphone_tester PROPERTIES LINKER_LANGUAGE CXX) + set_target_properties(liblinphone_tester PROPERTIES C_STANDARD 99) target_include_directories(liblinphone_tester PUBLIC ${BCTOOLBOX_TESTER_INCLUDE_DIRS}) target_link_libraries(liblinphone_tester ${LINPHONE_LIBS_FOR_TOOLS} ${OTHER_LIBS_FOR_TESTER}) - if (GTK2_FOUND) - target_compile_definitions(liblinphone_tester PRIVATE HAVE_GTK) - target_include_directories(liblinphone_tester PUBLIC ${GTK2_INCLUDE_DIRS}) - target_link_libraries(liblinphone_tester ${GTK2_LIBRARIES}) - if(GTKMACINTEGRATION_FOUND) - target_include_directories(liblinphone_tester PUBLIC ${GTKMACINTEGRATION_INCLUDE_DIRS}) - target_link_libraries(liblinphone_tester ${GTKMACINTEGRATION_LIBRARIES}) - endif() - endif() if(NOT IOS) install(TARGETS liblinphone_tester @@ -313,14 +332,15 @@ if (NOT ANDROID AND NOT CMAKE_SYSTEM_NAME STREQUAL "WindowsStore") ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) - install(FILES ${OTHER_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester") - install(FILES ${SOUND_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sounds") - install(FILES ${SIPP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sipp") install(FILES ${CERTIFICATE_ALT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/altname") - install(FILES ${CERTIFICATE_CN_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/cn") install(FILES ${CERTIFICATE_CLIENT_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/client") - install(FILES ${RC_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/rcfiles") + install(FILES ${CERTIFICATE_CN_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/certificates/cn") + install(FILES ${DB_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/db") install(FILES ${IMAGE_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/images") + install(FILES ${OTHER_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester") + install(FILES ${RC_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/rcfiles") + install(FILES ${SIPP_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sipp") + install(FILES ${SOUND_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/sounds") install(FILES ${VCARD_FILES} DESTINATION "${CMAKE_INSTALL_DATADIR}/liblinphone_tester/vcards") endif() endif() diff --git a/tester/Makefile.am b/tester/Makefile.am index 98634b009..9ef8aafac 100644 --- a/tester/Makefile.am +++ b/tester/Makefile.am @@ -77,7 +77,6 @@ RCFILES = \ rcfiles/pauline_zrtp_srtpsuite_aes256_rc\ rcfiles/remote_zero_length_params_rc\ rcfiles/stun_rc\ - rcfiles/upnp_rc\ rcfiles/zero_length_params_rc @@ -149,7 +148,6 @@ liblinphonetester_la_SOURCES = \ stun_tester.c \ tester.c \ tunnel_tester.c \ - upnp_tester.c \ vcard_tester.c \ video_tester.c @@ -169,13 +167,6 @@ AM_CFLAGS = -DBC_CONFIG_FILE=\"config.h\" $(STRICT_OPTIONS) $(STRICT_OPTIONS_ $(ORTP_CFLAGS) $(MEDIASTREAMER_CFLAGS) $(BCTOOLBOXTESTER_CFLAGS) \ $(BELLESIP_CFLAGS) $(LIBXML2_CFLAGS) $(SQLITE3_CFLAGS) $(BELCARD_CFLAGS) -if BUILD_GTK_UI - -liblinphonetester_la_LIBADD += $(LIBGTK_LIBS) $(LIBGTKMAC_LIBS) -AM_CFLAGS += $(LIBGTK_CFLAGS) $(LIBGTKMAC_CFLAGS) -DHAVE_GTK - -endif - #AM_LDFLAGS=-Wl,-rpath -Wl,$(libdir) bin_PROGRAMS= diff --git a/tester/account_creator_tester.c b/tester/account_creator_tester.c index a19a9278b..cc5773f3a 100644 --- a/tester/account_creator_tester.c +++ b/tester/account_creator_tester.c @@ -17,7 +17,8 @@ */ #include "liblinphone_tester.h" -#include "private.h" +#include "tester_utils.h" +#include static const char XMLRPC_URL[] = "https://sip2.linphone.org:446/xmlrpc.php"; @@ -339,6 +340,20 @@ static void account_creator_cb(LinphoneAccountCreator *creator, LinphoneAccountC account_creator_set_cb_done(cbs); } +static void set_string(char **dest, const char *src, bool_t lowercase) { + if (*dest) { + ms_free(*dest); + *dest = NULL; + } + if (src) { + *dest = ms_strdup(src); + if (lowercase) { + char *cur = *dest; + for (; *cur; cur++) *cur = tolower(*cur); + } + } +} + static void _get_activation_code_cb(LinphoneXmlRpcRequest *request) { LinphoneAccountCreator *creator = (LinphoneAccountCreator *)linphone_xml_rpc_request_get_user_data(request); LinphoneAccountCreatorStatus status = LinphoneAccountCreatorStatusRequestFailed; diff --git a/tester/accountmanager.c b/tester/accountmanager.c index 26ebd3f75..51f8694f0 100644 --- a/tester/accountmanager.c +++ b/tester/accountmanager.c @@ -16,8 +16,9 @@ along with this program. If not, see . */ +#include #include "liblinphone_tester.h" -#include "private.h" +#include "tester_utils.h" struct _Account{ LinphoneAddress *identity; @@ -96,11 +97,25 @@ Account *account_manager_get_account(AccountManager *m, const LinphoneAddress *i return NULL; } +LinphoneAddress *account_manager_get_identity_with_modified_identity(const LinphoneAddress *modified_identity){ + AccountManager *m = account_manager_get(); + bctbx_list_t *it; + + for(it=m->accounts;it!=NULL;it=it->next){ + Account *a=(Account*)it->data; + if (linphone_address_weak_equal(a->modified_identity,modified_identity)){ + return a->identity; + } + } + return NULL; +} + + static void account_created_on_server_cb(LinphoneCore *lc, LinphoneProxyConfig *cfg, LinphoneRegistrationState state, const char *info){ Account *account=(Account*)linphone_core_get_user_data(lc); switch(state){ case LinphoneRegistrationOk: { - char * phrase = sal_op_get_error_info((SalOp*)cfg->op)->full_string; + char * phrase = sal_op_get_error_info(linphone_proxy_config_get_sal_op(cfg))->full_string; if (phrase && strcasecmp("Test account created", phrase) == 0) { account->created=1; } else { @@ -116,17 +131,7 @@ static void account_created_on_server_cb(LinphoneCore *lc, LinphoneProxyConfig * } } -// TEMPORARY CODE: remove function below when flexisip is updated, this is not needed anymore! -// The new flexisip now answer "200 Test account created" when creating a test account, and do not -// challenge authentication anymore! so this code is not used for newer version -static void account_created_auth_requested_cb(LinphoneCore *lc, const char *username, const char *realm, const char *domain){ - Account *account=(Account*)linphone_core_get_user_data(lc); - account->created=1; -} -// TEMPORARY CODE: remove line above when flexisip is updated, this is not needed anymore! - void account_create_on_server(Account *account, const LinphoneProxyConfig *refcfg, const char* phone_alias){ - LinphoneCoreVTable vtable={0}; LinphoneCore *lc; LinphoneAddress *tmp_identity=linphone_address_clone(account->modified_identity); LinphoneProxyConfig *cfg; @@ -134,13 +139,11 @@ void account_create_on_server(Account *account, const LinphoneProxyConfig *refcf char *tmp; LinphoneAddress *server_addr; LinphoneSipTransports tr; - char *chatdb; + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); - vtable.registration_state_changed=account_created_on_server_cb; - // TEMPORARY CODE: remove line below when flexisip is updated, this is not needed anymore! - vtable.auth_info_requested=account_created_auth_requested_cb; - lc=configure_lc_from(&vtable,bc_tester_get_resource_dir_prefix(),NULL,account); - chatdb = ms_strdup(linphone_core_get_chat_database_path(lc)); + linphone_core_cbs_set_registration_state_changed(cbs, account_created_on_server_cb); + lc = configure_lc_from(cbs, bc_tester_get_resource_dir_prefix(), NULL, account); + linphone_core_cbs_unref(cbs); tr.udp_port=LC_SIP_TRANSPORT_RANDOM; tr.tcp_port=LC_SIP_TRANSPORT_RANDOM; tr.tls_port=LC_SIP_TRANSPORT_RANDOM; @@ -196,8 +199,6 @@ void account_create_on_server(Account *account, const LinphoneProxyConfig *refcf ms_error("Account creation could not clean the registration context."); } linphone_core_unref(lc); - unlink(chatdb); - ms_free(chatdb); } static LinphoneAddress *account_manager_check_account(AccountManager *m, LinphoneProxyConfig *cfg, LinphoneCoreManager *cm){ @@ -236,10 +237,10 @@ static LinphoneAddress *account_manager_check_account(AccountManager *m, Linphon /* create and/or set uuid */ if (account->uuid == NULL) { char tmp[64]; - sal_create_uuid(cm->lc->sal, tmp, sizeof(tmp)); + sal_create_uuid(linphone_core_get_sal(cm->lc), tmp, sizeof(tmp)); account->uuid = bctbx_strdup(tmp); } - sal_set_uuid(cm->lc->sal, account->uuid); + sal_set_uuid(linphone_core_get_sal(cm->lc), account->uuid); } /*remove previous auth info to avoid mismatching*/ @@ -259,8 +260,8 @@ static LinphoneAddress *account_manager_check_account(AccountManager *m, Linphon void linphone_core_manager_check_accounts(LinphoneCoreManager *m){ const bctbx_list_t *it; AccountManager *am=account_manager_get(); - int logmask = linphone_core_get_log_level_mask(); - + unsigned int logmask = linphone_core_get_log_level_mask(); + if (!liblinphonetester_show_account_manager_logs) linphone_core_set_log_level_mask(ORTP_ERROR|ORTP_FATAL); for(it=linphone_core_get_proxy_config_list(m->lc);it!=NULL;it=it->next){ LinphoneProxyConfig *cfg=(LinphoneProxyConfig *)it->data; diff --git a/tester/audio_bypass_tester.c b/tester/audio_bypass_tester.c index c2315d813..c6d1f7e23 100644 --- a/tester/audio_bypass_tester.c +++ b/tester/audio_bypass_tester.c @@ -17,7 +17,7 @@ */ #include "liblinphone_tester.h" -#include "private.h" +#include "tester_utils.h" #include "audio_bypass_wav_header.h" // This is a copy of mediastreamer2/src/audiofilters/wav_header.h /********************************************************************** @@ -68,9 +68,7 @@ int audio_bypass_read_wav_header_from_fd(wave_header_t *header,int fd){ format_t *format_chunk=&header->format_chunk; data_t *data_chunk=&header->data_chunk; - unsigned long len=0; - - len = read(fd, (char*)riff_chunk, sizeof(riff_t)) ; + ssize_t len = read(fd, (char*)riff_chunk, sizeof(riff_t)) ; if (len != sizeof(riff_t)){ goto not_a_wav; } @@ -85,7 +83,7 @@ int audio_bypass_read_wav_header_from_fd(wave_header_t *header,int fd){ goto not_a_wav; } - if ((skip=le_uint32(format_chunk->len)-0x10)>0) + if ((skip=(int)le_uint32(format_chunk->len)-0x10)>0) { lseek(fd,skip,SEEK_CUR); } @@ -438,7 +436,7 @@ static void only_enable_payload(LinphoneCore *lc, const char *mime, int rate, in * This is important so that the audio comparison is succesful*/ static void set_jitter_buffer_params(LinphoneCore *lc){ int jitter_buffer_ms = 300; - lp_config_set_int(lc->config, "rtp", "jitter_buffer_min_size", jitter_buffer_ms); + lp_config_set_int(linphone_core_get_config(lc), "rtp", "jitter_buffer_min_size", jitter_buffer_ms); linphone_core_set_audio_jittcomp(lc, jitter_buffer_ms); } @@ -459,8 +457,8 @@ static void audio_bypass(void) { double similar=1; const double threshold = 0.85; - lp_config_set_string(marie_lc->config, "sound", "features", "None"); - lp_config_set_string(pauline_lc->config, "sound", "features", "None"); + lp_config_set_string(linphone_core_get_config(marie_lc), "sound", "features", "None"); + lp_config_set_string(linphone_core_get_config(pauline_lc), "sound", "features", "None"); /*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/ unlink(recordpath); @@ -491,7 +489,7 @@ static void audio_bypass(void) { call_ok = call(marie, pauline); BC_ASSERT_TRUE(call_ok); if (!call_ok) goto end; - + BC_ASSERT_STRING_EQUAL(linphone_call_params_get_used_audio_codec(linphone_call_get_current_params(linphone_core_get_current_call(marie_lc)))->mime_type, "L16"); diff --git a/tester/audio_bypass_wav_header.h b/tester/audio_bypass_wav_header.h index e82df007b..f1d75905c 100644 --- a/tester/audio_bypass_wav_header.h +++ b/tester/audio_bypass_wav_header.h @@ -26,54 +26,51 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #ifdef _WIN32 -# include -# ifndef R_OK -# define R_OK 0x2 -# endif -# ifndef W_OK -# define W_OK 0x6 -# endif -# ifndef F_OK -# define F_OK 0x0 -# endif + #include + #ifndef R_OK + #define R_OK 0x2 + #endif + #ifndef W_OK + #define W_OK 0x6 + #endif + #ifndef F_OK + #define F_OK 0x0 + #endif -# ifndef S_IRUSR -# define S_IRUSR S_IREAD -# endif + #ifndef S_IRUSR + #define S_IRUSR S_IREAD + #endif -# ifndef S_IWUSR -# define S_IWUSR S_IWRITE -# endif + #ifndef S_IWUSR + #define S_IWUSR S_IWRITE + #endif -# define open _open -# define read _read -# define write _write -# define close _close -# define access _access -# define lseek _lseek -#else /*_WIN32*/ - -# ifndef O_BINARY -# define O_BINARY 0 -# endif - -#endif /*!_WIN32*/ + #define open _open + #define read _read + #define write _write + #define close _close + #define access _access + #define lseek _lseek +#else + #ifndef O_BINARY + #define O_BINARY 0 + #endif +#endif #ifdef swap16 #else /* all integer in wav header must be read in least endian order */ -static MS2_INLINE uint16_t swap16(uint16_t a) -{ - return ((a & 0xFF) << 8) | ((a & 0xFF00) >> 8); +static MS2_INLINE uint16_t swap16(uint16_t a) { + return (uint16_t)(((a & 0xFF) << 8) | ((a & 0xFF00) >> 8)); } #endif #ifdef swap32 #else -static MS2_INLINE uint32_t swap32(uint32_t a) -{ - return ((a & 0xFF) << 24) | ((a & 0xFF00) << 8) | - ((a & 0xFF0000) >> 8) | ((a & 0xFF000000) >> 24); +static MS2_INLINE uint32_t swap32(uint32_t a) { + return (uint32_t)( + ((a & 0xFF) << 24) | ((a & 0xFF00) << 8) | ((a & 0xFF0000) >> 8) | ((a & 0xFF000000) >> 24) + ); } #endif @@ -82,9 +79,9 @@ static MS2_INLINE uint32_t swap32(uint32_t a) #define le_uint16(a) (swap16((a))) #define le_int16(a) ( (int16_t) swap16((uint16_t)((a))) ) #else -#define le_uint32(a) (a) -#define le_uint16(a) (a) -#define le_int16(a) (a) +#define le_uint32(a) ((uint32_t)(a)) +#define le_uint16(a) ((uint16_t)(a)) +#define le_int16(a) ((int16_t)(a)) #endif typedef struct _riff_t { diff --git a/tester/call_multi_tester.c b/tester/call_multi_tester.c index 273bf60c4..913eb43ec 100644 --- a/tester/call_multi_tester.c +++ b/tester/call_multi_tester.c @@ -21,8 +21,8 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" #include "mediastreamer2/msutils.h" #include "belle-sip/sipstack.h" @@ -42,13 +42,22 @@ static const char* get_laure_rc(void) { } } static void call_waiting_indication_with_param(bool_t enable_caller_privacy) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCoreManager* laure = linphone_core_manager_new( get_laure_rc()); bctbx_list_t *iterator; bctbx_list_t* lcs; LinphoneCall* pauline_called_by_marie; LinphoneCall* pauline_called_by_laure=NULL; + LinphoneCoreManager *marie = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(marie, "marie_rc", NULL); + linphone_core_remove_supported_tag(marie->lc,"gruu"); + linphone_core_manager_start(marie, TRUE); + LinphoneCoreManager *pauline = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(pauline, "pauline_tcp_rc", NULL); + linphone_core_remove_supported_tag(pauline->lc,"gruu"); + linphone_core_manager_start(pauline,TRUE); + LinphoneCoreManager *laure = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(laure, get_laure_rc(), NULL); + linphone_core_remove_supported_tag(laure->lc,"gruu"); + linphone_core_manager_start(laure, TRUE); LinphoneCallParams *laure_params=linphone_core_create_call_params(laure->lc, NULL); LinphoneCallParams *marie_params=linphone_core_create_call_params(marie->lc, NULL); @@ -82,14 +91,16 @@ static void call_waiting_indication_with_param(bool_t enable_caller_privacy) { ,&laure->stat.number_of_LinphoneCallOutgoingRinging ,1)); - for (iterator=(bctbx_list_t *)linphone_core_get_calls(pauline->lc);iterator!=NULL;iterator=iterator->next) { - LinphoneCall *call=(LinphoneCall *)iterator->data; + bctbx_list_t *calls = bctbx_list_copy(linphone_core_get_calls(pauline->lc)); + for (iterator = calls; iterator; iterator = bctbx_list_next(iterator)) { + LinphoneCall *call = (LinphoneCall *)bctbx_list_get_data(iterator); if (call != pauline_called_by_marie) { /*fine, this is the call waiting*/ pauline_called_by_laure=call; linphone_call_accept(pauline_called_by_laure); } } + bctbx_list_free(calls); BC_ASSERT_TRUE(wait_for(laure->lc ,pauline->lc @@ -269,7 +280,7 @@ static void simple_conference_base(LinphoneCoreManager* marie, LinphoneCoreManag lcs=bctbx_list_append(lcs,laure->lc); if (focus) lcs=bctbx_list_append(lcs,focus->lc); - is_remote_conf = (strcmp(lp_config_get_string(marie->lc->config, "misc", "conference_type", "local"), "remote") == 0); + is_remote_conf = (strcmp(lp_config_get_string(linphone_core_get_config(marie->lc), "misc", "conference_type", "local"), "remote") == 0); if(is_remote_conf) BC_ASSERT_PTR_NOT_NULL(focus); if (!BC_ASSERT_TRUE(call(marie,pauline))) goto end; @@ -534,6 +545,7 @@ static void simple_call_transfer(void) { linphone_call_transfer(pauline_called_by_marie,laure_identity); + bctbx_free(laure_identity); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallRefered,1,2000)); /*marie pausing pauline*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallPausing,1,2000)); @@ -846,7 +858,7 @@ static void eject_from_3_participants_conference(LinphoneCoreManager *marie, Lin lcs=bctbx_list_append(lcs,laure->lc); if(focus) lcs=bctbx_list_append(lcs,focus->lc); - is_remote_conf = (strcmp(lp_config_get_string(marie->lc->config, "misc", "conference_type", "local"), "remote") == 0); + is_remote_conf = (strcmp(lp_config_get_string(linphone_core_get_config(marie->lc), "misc", "conference_type", "local"), "remote") == 0); if(is_remote_conf) BC_ASSERT_PTR_NOT_NULL(focus); BC_ASSERT_TRUE(call(marie,pauline)); @@ -1141,10 +1153,9 @@ void do_not_stop_ringing_when_declining_one_of_two_incoming_calls(void) { BC_ASSERT_TRUE(wait_for(laure->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for(laure->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallReleased,1)); - BC_ASSERT_TRUE(linphone_ringtoneplayer_is_started(pauline->lc->ringtoneplayer)); + BC_ASSERT_TRUE(linphone_ringtoneplayer_is_started(linphone_core_get_ringtoneplayer(pauline->lc))); linphone_call_terminate(pauline_called_by_marie); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallEnd,2)); - BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallReleased,2)); linphone_core_manager_destroy(marie); @@ -1161,7 +1172,7 @@ test_t multi_call_tests[] = { TEST_NO_TAG("Incoming call accepted when outgoing call in outgoing ringing", incoming_call_accepted_when_outgoing_call_in_outgoing_ringing), TEST_NO_TAG("Incoming call accepted when outgoing call in outgoing ringing early media", incoming_call_accepted_when_outgoing_call_in_outgoing_ringing_early_media), TEST_NO_TAG("Simple conference", simple_conference), - TEST_NO_TAG("Simple conference established from scractch", simple_conference_from_scratch), + TEST_NO_TAG("Simple conference established from scratch", simple_conference_from_scratch), TEST_ONE_TAG("Simple conference with ICE", simple_conference_with_ice, "ICE"), TEST_ONE_TAG("Simple ZRTP conference with ICE", simple_zrtp_conference_with_ice, "ICE"), TEST_NO_TAG("Eject from 3 participants conference", eject_from_3_participants_local_conference), diff --git a/tester/call_multicast_tester.c b/tester/call_multicast_tester.c index 99116b5da..f6182aa18 100644 --- a/tester/call_multicast_tester.c +++ b/tester/call_multicast_tester.c @@ -18,6 +18,7 @@ #include "liblinphone_tester.h" +#include "tester_utils.h" #include "linphone/core.h" #include "belle-sip/belle-sip.h" @@ -54,7 +55,7 @@ static void call_multicast_base(bool_t video) { BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(marie),70,int,"%d"); if (video) { /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(linphone_core_get_current_call(marie->lc)); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_get_current_call(marie->lc)); linphone_call_send_vfu_request(linphone_core_get_current_call(marie->lc)); BC_ASSERT_TRUE( wait_for(marie->lc,pauline->lc,&marie->stat.number_of_IframeDecoded,1)); } @@ -148,7 +149,7 @@ static void early_media_with_multicast_base(bool_t video) { /* send a 183 to initiate the early media */ if (video) { /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(linphone_core_get_current_call(pauline->lc)); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_get_current_call(pauline->lc)); } linphone_call_accept_early_media(linphone_core_get_current_call(pauline->lc)); @@ -159,7 +160,7 @@ static void early_media_with_multicast_base(bool_t video) { /* send a 183 to initiate the early media */ if (video) { /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(linphone_core_get_current_call(pauline2->lc)); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_get_current_call(pauline2->lc)); } linphone_call_accept_early_media(linphone_core_get_current_call(pauline2->lc)); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index c6ede11e8..2408640ac 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -21,8 +21,8 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" #include "mediastreamer2/msutils.h" #include "belle-sip/sipstack.h" #include @@ -45,10 +45,11 @@ extern void libmsopenh264_init(MSFactory *factory); 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); - char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); + LinphoneCallLog *calllog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(calllog)); + char* from=linphone_address_as_string(linphone_call_log_get_from(calllog)); stats* counters; - ms_message(" %s call from [%s] to [%s], new state is [%s]" ,linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing" + ms_message(" %s call from [%s] to [%s], new state is [%s]" ,linphone_call_log_get_dir(calllog)==LinphoneCallIncoming?"Incoming":"Outgoing" ,from ,to ,linphone_call_state_to_string(cstate)); @@ -101,28 +102,28 @@ static void rtcp_received(stats* counters, mblk_t *packet) { void call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *lstats) { stats* counters = get_stats(lc); counters->number_of_LinphoneCallStatsUpdated++; - if (lstats->updated & LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { + if (_linphone_call_stats_get_updated(lstats) & LINPHONE_CALL_STATS_RECEIVED_RTCP_UPDATE) { counters->number_of_rtcp_received++; - if (lstats->rtcp_received_via_mux){ + if (_linphone_call_stats_rtcp_received_via_mux(lstats)){ counters->number_of_rtcp_received_via_mux++; } - rtcp_received(counters, lstats->received_rtcp); + rtcp_received(counters, _linphone_call_stats_get_received_rtcp(lstats)); } - if (lstats->updated & LINPHONE_CALL_STATS_SENT_RTCP_UPDATE ) { + if (_linphone_call_stats_get_updated(lstats) & LINPHONE_CALL_STATS_SENT_RTCP_UPDATE ) { counters->number_of_rtcp_sent++; } - if (lstats->updated & LINPHONE_CALL_STATS_PERIODICAL_UPDATE ) { + if (_linphone_call_stats_get_updated(lstats) & LINPHONE_CALL_STATS_PERIODICAL_UPDATE ) { int tab_size = sizeof (counters->audio_download_bandwidth)/sizeof(int); - int index = (counters->current_bandwidth_index[lstats->type]++) % tab_size; + int index = (counters->current_bandwidth_index[linphone_call_stats_get_type(lstats)]++) % tab_size; LinphoneCallStats *audio_stats, *video_stats; audio_stats = linphone_call_get_audio_stats(call); video_stats = linphone_call_get_video_stats(call); - if (lstats->type == LINPHONE_CALL_STATS_AUDIO) { - counters->audio_download_bandwidth[index] = (int)audio_stats->download_bandwidth; - counters->audio_upload_bandwidth[index] = (int)audio_stats->upload_bandwidth; + if (linphone_call_stats_get_type(lstats) == LINPHONE_CALL_STATS_AUDIO) { + counters->audio_download_bandwidth[index] = (int)linphone_call_stats_get_download_bandwidth(audio_stats); + counters->audio_upload_bandwidth[index] = (int)linphone_call_stats_get_upload_bandwidth(audio_stats); } else { - counters->video_download_bandwidth[index] = (int)video_stats->download_bandwidth; - counters->video_upload_bandwidth[index] = (int)video_stats->upload_bandwidth; + counters->video_download_bandwidth[index] = (int)linphone_call_stats_get_download_bandwidth(video_stats); + counters->video_upload_bandwidth[index] = (int)linphone_call_stats_get_upload_bandwidth(video_stats); } linphone_call_stats_unref(audio_stats); linphone_call_stats_unref(video_stats); @@ -131,10 +132,11 @@ void call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCall } void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token) { - char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); + LinphoneCallLog *calllog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(calllog)); + char* from=linphone_address_as_string(linphone_call_log_get_from(calllog)); stats* counters; - ms_message(" %s call from [%s] to [%s], is now [%s]",linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing" + ms_message(" %s call from [%s] to [%s], is now [%s]",linphone_call_log_get_dir(calllog)==LinphoneCallIncoming?"Incoming":"Outgoing" ,from ,to ,(on?"encrypted":"unencrypted")); @@ -148,8 +150,9 @@ void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool } void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state) { - char* to=linphone_address_as_string(linphone_call_get_call_log(transfered)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(transfered)->from); + LinphoneCallLog *clog = linphone_call_get_call_log(transfered); + char* to=linphone_address_as_string(linphone_call_log_get_to(clog)); + char* from=linphone_address_as_string(linphone_call_log_get_to(clog)); stats* counters; ms_message("Transferred call from [%s] to [%s], new state is [%s]",from,to,linphone_call_state_to_string(new_call_state)); ms_free(to); @@ -169,9 +172,11 @@ void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, } } + static void linphone_call_next_video_frame_decoded_cb(LinphoneCall *call) { - char* to = linphone_address_as_string(linphone_call_get_call_log(call)->to); - char* from = linphone_address_as_string(linphone_call_get_call_log(call)->from); + LinphoneCallLog *clog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(clog)); + char* from=linphone_address_as_string(linphone_call_log_get_to(clog)); stats* counters; LinphoneCore* lc = linphone_call_get_core(call); ms_message("call from [%s] to [%s] receive iFrame",from,to); @@ -181,18 +186,26 @@ static void linphone_call_next_video_frame_decoded_cb(LinphoneCall *call) { counters->number_of_IframeDecoded++; } -void linphone_call_set_first_video_frame_decoded_cb(LinphoneCall *call) { - LinphoneCallCbs *call_cbs = linphone_factory_create_call_cbs(linphone_factory_get()); - linphone_call_cbs_set_next_video_frame_decoded(call_cbs, linphone_call_next_video_frame_decoded_cb); - linphone_call_add_callbacks(call, call_cbs); - linphone_call_cbs_unref(call_cbs); +void liblinphone_tester_set_next_video_frame_decoded_cb(LinphoneCall *call) { + if (belle_sip_object_data_get(BELLE_SIP_OBJECT(call), "next_video_frame_decoded_set") == NULL){ + LinphoneCallCbs *call_cbs = linphone_factory_create_call_cbs(linphone_factory_get()); + linphone_call_cbs_set_next_video_frame_decoded(call_cbs, linphone_call_next_video_frame_decoded_cb); + linphone_call_add_callbacks(call, call_cbs); + linphone_call_cbs_unref(call_cbs); + belle_sip_object_data_set(BELLE_SIP_OBJECT(call), "next_video_frame_decoded_set", (void*)1, NULL); + } + linphone_call_request_notify_next_video_frame_decoded(call); } +#define reset_call_stats(var, value) \ + if (var) linphone_call_stats_unref(var); \ + var = value + void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreManager* callee) { LinphoneCall *c1,*c2; MSTimeSpec ts; int max_time_to_wait; - LinphoneCallStats *audio_stats1, *video_stats1, *audio_stats2, *video_stats2; + LinphoneCallStats *audio_stats1 = NULL, *video_stats1 = NULL, *audio_stats2 = NULL, *video_stats2 = NULL; c1=linphone_core_get_current_call(caller->lc); c2=linphone_core_get_current_call(callee->lc); @@ -209,71 +222,73 @@ void liblinphone_tester_check_rtcp(LinphoneCoreManager* caller, LinphoneCoreMana max_time_to_wait = 5000; do { - audio_stats1 = linphone_call_get_audio_stats(c1); - video_stats1 = linphone_call_get_video_stats(c1); - audio_stats2 = linphone_call_get_audio_stats(c2); - video_stats2 = linphone_call_get_video_stats(c2); - if (audio_stats1->round_trip_delay > 0.0 - && audio_stats2->round_trip_delay > 0.0 - && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || video_stats1->round_trip_delay>0.0) - && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c2)) || video_stats2->round_trip_delay>0.0)) { + reset_call_stats(audio_stats1, linphone_call_get_audio_stats(c1)); + reset_call_stats(video_stats1, linphone_call_get_video_stats(c1)); + reset_call_stats(audio_stats2, linphone_call_get_audio_stats(c2)); + reset_call_stats(video_stats2, linphone_call_get_video_stats(c2)); + if (linphone_call_stats_get_round_trip_delay(audio_stats1) > 0.0 + && linphone_call_stats_get_round_trip_delay(audio_stats2) > 0.0 + && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c1)) || linphone_call_stats_get_round_trip_delay(video_stats1)>0.0) + && (!linphone_call_log_video_enabled(linphone_call_get_call_log(c2)) || linphone_call_stats_get_round_trip_delay(video_stats2)>0.0)) { break; } - linphone_call_stats_unref(audio_stats1); - linphone_call_stats_unref(audio_stats2); - if (video_stats1) linphone_call_stats_unref(video_stats1); - if (video_stats2) linphone_call_stats_unref(video_stats2); wait_for_until(caller->lc,callee->lc,NULL,0,20); /*just to sleep while iterating*/ }while (!liblinphone_tester_clock_elapsed(&ts,max_time_to_wait)); - audio_stats1 = linphone_call_get_audio_stats(c1); - video_stats1 = linphone_call_get_video_stats(c1); - audio_stats2 = linphone_call_get_audio_stats(c2); - video_stats2 = linphone_call_get_video_stats(c2); + reset_call_stats(audio_stats1, linphone_call_get_audio_stats(c1)); + reset_call_stats(video_stats1, linphone_call_get_video_stats(c1)); + reset_call_stats(audio_stats2, linphone_call_get_audio_stats(c2)); + reset_call_stats(video_stats2, linphone_call_get_video_stats(c2)); if (linphone_core_rtcp_enabled(caller->lc) && linphone_core_rtcp_enabled(callee->lc)) { BC_ASSERT_GREATER(caller->stat.number_of_rtcp_received, 1, int, "%i"); BC_ASSERT_GREATER(callee->stat.number_of_rtcp_received, 1, int, "%i"); - BC_ASSERT_GREATER(audio_stats1->round_trip_delay,0.0,float,"%f"); - BC_ASSERT_GREATER(audio_stats2->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(audio_stats1),0.0,float,"%f"); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(audio_stats2),0.0,float,"%f"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_GREATER(video_stats1->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(video_stats1),0.0,float,"%f"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_GREATER(video_stats2->round_trip_delay,0.0,float,"%f"); + BC_ASSERT_GREATER(linphone_call_stats_get_round_trip_delay(video_stats2),0.0,float,"%f"); } } else { if (linphone_core_rtcp_enabled(caller->lc)) { - BC_ASSERT_EQUAL(audio_stats1->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); - BC_ASSERT_EQUAL(audio_stats2->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(audio_stats1)->sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(audio_stats2)->recv_rtcp_packets, 0, unsigned long long, "%llu"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_EQUAL(video_stats1->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(video_stats1)->sent_rtcp_packets, 0, unsigned long long, "%llu"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_EQUAL(video_stats2->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(video_stats2)->recv_rtcp_packets, 0, unsigned long long, "%llu"); } } if (linphone_core_rtcp_enabled(callee->lc)) { - BC_ASSERT_EQUAL(audio_stats2->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); - BC_ASSERT_EQUAL(audio_stats1->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(audio_stats2)->sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(audio_stats1)->recv_rtcp_packets, 0, unsigned long long, "%llu"); if (linphone_call_log_video_enabled(linphone_call_get_call_log(c1))) { - BC_ASSERT_EQUAL(video_stats1->rtp_stats.recv_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(video_stats1)->recv_rtcp_packets, 0, unsigned long long, "%llu"); } if (linphone_call_log_video_enabled(linphone_call_get_call_log(c2))) { - BC_ASSERT_EQUAL(video_stats2->rtp_stats.sent_rtcp_packets, 0, unsigned long long, "%llu"); + BC_ASSERT_EQUAL(linphone_call_stats_get_rtp_stats(video_stats2)->sent_rtcp_packets, 0, unsigned long long, "%llu"); } } } + + if (audio_stats1) linphone_call_stats_unref(audio_stats1); + if (audio_stats2) linphone_call_stats_unref(audio_stats2); + if (video_stats1) linphone_call_stats_unref(video_stats1); + if (video_stats2) linphone_call_stats_unref(video_stats2); + linphone_call_unref(c1); linphone_call_unref(c2); } static void setup_sdp_handling(const LinphoneCallTestParams* params, LinphoneCoreManager* mgr ){ if( params->sdp_removal ){ - sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateRemove); + sal_default_set_sdp_handling(linphone_core_get_sal(mgr->lc), SalOpSDPSimulateRemove); } else if( params->sdp_simulate_error ){ - sal_default_set_sdp_handling(mgr->lc->sal, SalOpSDPSimulateError); + sal_default_set_sdp_handling(linphone_core_get_sal(mgr->lc), SalOpSDPSimulateError); } } @@ -324,14 +339,14 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr ,initial_callee.number_of_LinphoneCallIncomingReceived+1); BC_ASSERT_EQUAL(did_receive_call, !callee_test_params->sdp_simulate_error, int, "%d"); - sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); - sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); if (!did_receive_call) return 0; if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) - BC_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc)); + BC_ASSERT_TRUE(linphone_core_is_incoming_invite_pending(callee_mgr->lc)); BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1, int, "%d"); @@ -360,7 +375,7 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr if (linphone_call_params_get_privacy(linphone_call_get_current_params(linphone_core_get_current_call(caller_mgr->lc))) == LinphonePrivacyNone) { /*don't check in case of p asserted id*/ - if (!lp_config_get_int(callee_mgr->lc->config,"sip","call_logs_use_asserted_id_instead_of_from",0)) + if (!lp_config_get_int(linphone_core_get_config(callee_mgr->lc),"sip","call_logs_use_asserted_id_instead_of_from",0)) BC_ASSERT_TRUE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(callee_call))); } else { BC_ASSERT_FALSE(linphone_address_weak_equal(callee_from,linphone_call_get_remote_address(linphone_core_get_current_call(callee_mgr->lc)))); @@ -422,8 +437,8 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr if (linphone_core_get_firewall_policy(caller_mgr->lc) == LinphonePolicyUseIce && linphone_core_get_firewall_policy(callee_mgr->lc) == LinphonePolicyUseIce && !linphone_core_sdp_200_ack_enabled(caller_mgr->lc) /*ice does not work with sdp less invite*/ - && lp_config_get_int(callee_mgr->lc->config, "sip", "update_call_when_ice_completed", TRUE) - && lp_config_get_int(caller_mgr->lc->config, "sip", "update_call_when_ice_completed", TRUE) + && lp_config_get_int(linphone_core_get_config(callee_mgr->lc), "sip", "update_call_when_ice_completed", TRUE) + && lp_config_get_int(linphone_core_get_config(callee_mgr->lc), "sip", "update_call_when_ice_completed", TRUE) && linphone_core_get_media_encryption(caller_mgr->lc) != LinphoneMediaEncryptionDTLS /*no ice-reinvite with DTLS*/) { BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+2)); BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+2)); @@ -435,11 +450,16 @@ bool_t call_with_params2(LinphoneCoreManager* caller_mgr } if (linphone_core_get_media_encryption(caller_mgr->lc) == LinphoneMediaEncryptionDTLS ) { - if (linphone_core_get_current_call(caller_mgr->lc)->audiostream) - BC_ASSERT_TRUE(ms_media_stream_sessions_get_encryption_mandatory(&linphone_core_get_current_call(caller_mgr->lc)->audiostream->ms.sessions)); + LinphoneCall *call = linphone_core_get_current_call(caller_mgr->lc); + AudioStream *astream = (AudioStream *)linphone_call_get_stream(call, LinphoneStreamTypeAudio); #ifdef VIDEO_ENABLED - if (linphone_core_get_current_call(caller_mgr->lc)->videostream && video_stream_started(linphone_core_get_current_call(caller_mgr->lc)->videostream)) - BC_ASSERT_TRUE(ms_media_stream_sessions_get_encryption_mandatory(&linphone_core_get_current_call(caller_mgr->lc)->videostream->ms.sessions)); + VideoStream *vstream = (VideoStream *)linphone_call_get_stream(call, LinphoneStreamTypeVideo); +#endif + if (astream) + BC_ASSERT_TRUE(ms_media_stream_sessions_get_encryption_mandatory(&astream->ms.sessions)); +#ifdef VIDEO_ENABLED + if (vstream && video_stream_started(vstream)) + BC_ASSERT_TRUE(ms_media_stream_sessions_get_encryption_mandatory(&vstream->ms.sessions)); #endif } @@ -656,19 +676,19 @@ static void call_with_timed_out_bye(void) { BC_ASSERT_TRUE(call(marie,pauline)); - sal_set_send_error(pauline->lc->sal,1500); /*to trash the message without generating error*/ + sal_set_send_error(linphone_core_get_sal(pauline->lc),1500); /*to trash the message without generating error*/ timer_config.T1=50; /*to have timer F = 3s*/ timer_config.T2=4000; timer_config.T3=0; timer_config.T4=5000; - belle_sip_stack_set_timer_config(sal_get_stack_impl(pauline->lc->sal),&timer_config); + belle_sip_stack_set_timer_config(sal_get_stack_impl(linphone_core_get_sal(pauline->lc)),&timer_config); linphone_core_terminate_all_calls(pauline->lc); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1,timer_config.T1*84)); - sal_set_send_error(pauline->lc->sal,0); + sal_set_send_error(linphone_core_get_sal(pauline->lc),0); linphone_core_terminate_all_calls(marie->lc); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1,5000)); @@ -745,7 +765,6 @@ static void call_outbound_with_multiple_proxy(void) { // calling marie should go through the second proxy config BC_ASSERT_TRUE(call(marie, pauline)); - wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); end_call(marie, pauline); linphone_core_manager_destroy(marie); @@ -802,9 +821,21 @@ static void multiple_answers_call_with_media_relay(void) { /* Scenario is this: pauline calls marie, which is registered 2 times. * Both linphones answer at the same time, and only one should get the * call running, the other should be terminated */ - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc" ); - LinphoneCoreManager* marie1 = linphone_core_manager_new( "marie_rc" ); - LinphoneCoreManager* marie2 = linphone_core_manager_new( "marie_rc" ); + LinphoneCoreManager* pauline = linphone_core_manager_new2( "pauline_tcp_rc", FALSE); + LinphoneCoreManager* marie1 = linphone_core_manager_new2( "marie_rc", FALSE); + LinphoneCoreManager* marie2 = linphone_core_manager_new2( "marie_rc", FALSE ); + + /* This tests a feature of the proxy (nta_msg_ackbye()) that doesn't work with gruu. + * Actually nta_msg_ackbye() is deprecated because it is not the task of the proxy to handle the race conditions of 200 Ok arriving at the same time. + * It is the job of the user-agent, see test multiple_answers_call() above. + */ + linphone_core_remove_supported_tag(pauline->lc,"gruu"); + linphone_core_remove_supported_tag(marie1->lc,"gruu"); + linphone_core_remove_supported_tag(marie2->lc,"gruu"); + + linphone_core_manager_start(pauline, TRUE); + linphone_core_manager_start(marie1, TRUE); + linphone_core_manager_start(marie2, TRUE); LinphoneCall* call1, *call2; @@ -857,7 +888,7 @@ static void call_with_specified_codec_bitrate(void) { int max_bw=50; #ifdef __arm__ - if (ms_factory_get_cpu_count(marie->lc->factory) <2) { /*2 opus codec channel + resampler is too much for a single core*/ + if (ms_factory_get_cpu_count(linphone_core_get_ms_factory(marie->lc)) <2) { /*2 opus codec channel + resampler is too much for a single core*/ #ifndef __ANDROID__ codec = "speex"; rate = 8000; @@ -1001,7 +1032,6 @@ static void simple_call_compatibility_mode(void) { BC_ASSERT_TRUE(wait_for(lc_pauline,lc_marie,&stat_marie->number_of_LinphoneCallStreamsRunning,1)); wait_for(lc_pauline,lc_marie,&stat_marie->number_of_LinphoneCallStreamsRunning,3); - wait_for_until(lc_pauline,lc_marie,NULL,0, 1000); end_call(pauline, marie); } linphone_core_manager_destroy(marie); @@ -1040,7 +1070,6 @@ static void terminate_call_with_error(void) { BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(ei), "Call refused for security reason"); BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(ei), "SIP"); } - wait_for_until(caller_mgr->lc, callee_mgr->lc, NULL, 0, 1000); linphone_call_terminate_with_error_info(out_call,ei); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallReleased,1)); @@ -1275,7 +1304,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); + sal_set_dns_timeout(linphone_core_get_sal(marie->lc),0); linphone_core_invite(marie->lc,"\"t\x8et\x8e\" "); /*just to use non ascii values*/ for(i=0;i<10;i++){ ms_usleep(200000); @@ -1447,26 +1476,29 @@ static void call_declined_with_error(void) { linphone_core_manager_destroy(caller_mgr); } -static void call_declined(void) { +static void call_declined_base(bool_t use_timeout) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall* in_call; LinphoneCall* out_call = linphone_core_invite_address(pauline->lc,marie->identity); + if (use_timeout) + linphone_core_set_inc_timeout(marie->lc, 1); linphone_call_ref(out_call); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1)); BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(marie->lc)); if (in_call) { linphone_call_ref(in_call); - linphone_call_terminate(in_call); + if (!use_timeout) + linphone_call_terminate(in_call); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallReleased,1)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1)); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallEnd,1, int, "%d"); - BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallEnd,1, int, "%d"); + BC_ASSERT_EQUAL(use_timeout ? pauline->stat.number_of_LinphoneCallError : pauline->stat.number_of_LinphoneCallEnd,1, int, "%d"); BC_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined, int, "%d"); - BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallDeclined, int, "%d"); - BC_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined, int, "%d"); - BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(out_call)),LinphoneCallDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)), use_timeout ? LinphoneCallMissed : LinphoneCallDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_get_reason(out_call), use_timeout ? LinphoneReasonBusy : LinphoneReasonDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(out_call)), use_timeout ? LinphoneCallAborted : LinphoneCallDeclined, int, "%d"); linphone_call_unref(in_call); } linphone_call_unref(out_call); @@ -1474,6 +1506,14 @@ static void call_declined(void) { linphone_core_manager_destroy(pauline); } +static void call_declined(void) { + call_declined_base(FALSE); +} + +static void call_declined_on_timeout(void) { + call_declined_base(TRUE); +} + static void call_terminated_by_caller(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -1510,7 +1550,7 @@ static void call_with_no_sdp_ack_without_sdp(void){ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallIncomingReceived,1)); call=linphone_core_get_current_call(pauline->lc); if (call){ - sal_call_set_sdp_handling(call->op, SalOpSDPSimulateError); /*this will have the effect that the SDP received in the ACK will be ignored*/ + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(call), SalOpSDPSimulateError); /*this will have the effect that the SDP received in the ACK will be ignored*/ linphone_call_accept(call); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallError,1)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); @@ -1528,12 +1568,12 @@ int check_nb_media_starts(LinphoneCoreManager *caller, LinphoneCoreManager *call if (!c1 || !c2) return FALSE; if (c1) { - c1_ret = c1->nb_media_starts == caller_nb_media_starts; - BC_ASSERT_EQUAL(c1->nb_media_starts, caller_nb_media_starts, unsigned int, "%u"); + c1_ret = (_linphone_call_get_nb_media_starts(c1) == caller_nb_media_starts) ? TRUE : FALSE; + BC_ASSERT_EQUAL(_linphone_call_get_nb_media_starts(c1), caller_nb_media_starts, unsigned int, "%u"); } if (c2) { - c2_ret = c2->nb_media_starts == callee_nb_media_starts; - BC_ASSERT_EQUAL(c2->nb_media_starts, callee_nb_media_starts, unsigned int, "%u"); + c2_ret = (_linphone_call_get_nb_media_starts(c2) == callee_nb_media_starts) ? TRUE : FALSE; + BC_ASSERT_EQUAL(_linphone_call_get_nb_media_starts(c2), callee_nb_media_starts, unsigned int, "%u"); } return c1_ret && c2_ret; } @@ -1823,7 +1863,7 @@ static void call_with_custom_sdp_attributes(void) { const LinphoneCallParams *marie_remote_params; const LinphoneCallParams *pauline_remote_params; const char *value; - LinphoneCoreVTable *vtable; + LinphoneCoreCbs *cbs; pauline_params = linphone_core_create_call_params(pauline->lc, NULL); linphone_call_params_add_custom_sdp_attribute(pauline_params, "weather", "bad"); @@ -1846,9 +1886,9 @@ static void call_with_custom_sdp_attributes(void) { BC_ASSERT_PTR_NOT_NULL(value); if (value) BC_ASSERT_STRING_EQUAL(value, "almost"); - vtable = linphone_core_v_table_new(); - vtable->call_state_changed = call_with_custom_sdp_attributes_cb; - linphone_core_add_listener(marie->lc, vtable); + cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_with_custom_sdp_attributes_cb); + linphone_core_add_callbacks(marie->lc, cbs); pauline_params = linphone_core_create_call_params(pauline->lc, call_pauline); linphone_call_params_clear_custom_sdp_attributes(pauline_params); linphone_call_params_clear_custom_sdp_media_attributes(pauline_params, LinphoneStreamTypeAudio); @@ -1865,6 +1905,7 @@ static void call_with_custom_sdp_attributes(void) { end_call(pauline, marie); + linphone_core_cbs_unref(cbs); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -1912,9 +1953,7 @@ static void call_caller_with_custom_header_or_sdp_attributes(void) { LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall *call_caller = NULL, *call_callee = NULL; LinphoneCallParams *caller_params; // *callee_params ; - - LinphoneCoreVTable *vtable; - + LinphoneCoreCbs *cbs; LinphoneCallTestParams caller_test_params = {0}; LinphoneCallTestParams callee_test_params = {0}; @@ -1938,11 +1977,11 @@ static void call_caller_with_custom_header_or_sdp_attributes(void) { setup_sdp_handling(&caller_test_params, caller_mgr); setup_sdp_handling(&callee_test_params, callee_mgr); - // Assign dedicated callback to vtable for caller and callee - vtable = linphone_core_v_table_new(); - vtable->call_state_changed = call_with_custom_header_or_sdp_cb; - linphone_core_add_listener(callee_mgr->lc, vtable); - linphone_core_add_listener(caller_mgr->lc, vtable); + // Assign dedicated callback for caller and callee + cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_with_custom_header_or_sdp_cb); + linphone_core_add_callbacks(callee_mgr->lc, cbs); + linphone_core_add_callbacks(caller_mgr->lc, cbs); //Caller initates the call with INVITE // caller params not null @@ -1959,8 +1998,8 @@ static void call_caller_with_custom_header_or_sdp_attributes(void) { linphone_call_params_unref(caller_params); - sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); - sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); // Wait for Outgoing Progress if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) @@ -1968,8 +2007,6 @@ static void call_caller_with_custom_header_or_sdp_attributes(void) { BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1, int, "%d"); - - LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,call_callee); ms_message("Created default call params with video=%i", linphone_call_params_video_enabled(default_params)); linphone_core_accept_call_with_params(callee_mgr->lc,call_callee,default_params); @@ -1995,6 +2032,7 @@ static void call_caller_with_custom_header_or_sdp_attributes(void) { end_call(caller_mgr, callee_mgr); + linphone_core_cbs_unref(cbs); linphone_core_manager_destroy(callee_mgr); linphone_core_manager_destroy(caller_mgr); } @@ -2034,20 +2072,16 @@ static void call_callee_with_custom_header_or_sdp_attributes(void) { LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall *call_caller = NULL, *call_callee = NULL; LinphoneCallParams *callee_params, *caller_params ; - - LinphoneCoreVTable *vtable; + LinphoneCoreCbs *cbs; const char *value; LinphoneCallTestParams caller_test_params = {0}; LinphoneCallTestParams callee_test_params = {0}; - stats initial_caller=caller_mgr->stat; stats initial_callee=callee_mgr->stat; bool_t did_receive_call; const LinphoneCallParams *caller_remote_params; caller_params = linphone_core_create_call_params(caller_mgr->lc, NULL); - - callee_test_params.base = NULL; caller_test_params.base = NULL; @@ -2058,11 +2092,11 @@ static void call_callee_with_custom_header_or_sdp_attributes(void) { setup_sdp_handling(&caller_test_params, caller_mgr); setup_sdp_handling(&callee_test_params, callee_mgr); - // Assign dedicated callback to vtable for caller and callee - vtable = linphone_core_v_table_new(); - vtable->call_state_changed = call_callee_with_custom_header_or_sdp_cb; - linphone_core_add_listener(callee_mgr->lc, vtable); - linphone_core_add_listener(caller_mgr->lc, vtable); + // Assign dedicated callback for caller and callee + cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_callee_with_custom_header_or_sdp_cb); + linphone_core_add_callbacks(callee_mgr->lc, cbs); + linphone_core_add_callbacks(caller_mgr->lc, cbs); //Caller initates the call with INVITE // caller params not null @@ -2079,8 +2113,8 @@ static void call_callee_with_custom_header_or_sdp_attributes(void) { - sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); - sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); + sal_default_set_sdp_handling(linphone_core_get_sal(caller_mgr->lc), SalOpSDPNormal); // Wait for Outgoing Progress if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) @@ -2121,6 +2155,7 @@ static void call_callee_with_custom_header_or_sdp_attributes(void) { linphone_call_params_unref(caller_params); end_call(caller_mgr, callee_mgr); + linphone_core_cbs_unref(cbs); linphone_core_manager_destroy(callee_mgr); linphone_core_manager_destroy(caller_mgr); } @@ -2129,6 +2164,7 @@ void call_paused_resumed_base(bool_t multicast, bool_t with_losses) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall* call_pauline; + RtpSession *rtp_session; const rtp_stats_t * stats; bool_t call_ok; @@ -2143,14 +2179,14 @@ void call_paused_resumed_base(bool_t multicast, bool_t with_losses) { wait_for_until(pauline->lc, marie->lc, NULL, 5, 3000); if (with_losses) { - sal_set_send_error(marie->lc->sal,1500); /*to trash 200ok without generating error*/ + sal_set_send_error(linphone_core_get_sal(marie->lc),1500); /*to trash 200ok without generating error*/ } linphone_call_pause(call_pauline); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausing,1)); if (with_losses) { BC_ASSERT_FALSE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,1,1000)); - sal_set_send_error(marie->lc->sal,0); /*to trash 200ok without generating error*/ + sal_set_send_error(linphone_core_get_sal(marie->lc),0); /*to trash 200ok without generating error*/ } @@ -2168,20 +2204,21 @@ void call_paused_resumed_base(bool_t multicast, bool_t with_losses) { wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000); /*since RTCP streams are reset when call is paused/resumed, there should be no loss at all*/ - if (BC_ASSERT_PTR_NOT_NULL(call_pauline->sessions->rtp_session)) { - stats = rtp_session_get_stats(call_pauline->sessions->rtp_session); + rtp_session = linphone_call_get_stream(call_pauline, LinphoneStreamTypeAudio)->sessions.rtp_session; + if (BC_ASSERT_PTR_NOT_NULL(rtp_session)) { + stats = rtp_session_get_stats(rtp_session); BC_ASSERT_EQUAL((int)stats->cum_packet_loss, 0, int, "%d"); } if (with_losses) { /* now we want to loose the ack*/ linphone_call_pause(call_pauline); - sal_set_send_error(pauline->lc->sal,1500); /*to trash ACK without generating error*/ + sal_set_send_error(linphone_core_get_sal(pauline->lc),1500); /*to trash ACK without generating error*/ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPausing,2)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallPausedByRemote,2)); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallPaused,2,1000)); /*now try to resume, it should be OK*/ - sal_set_send_error(pauline->lc->sal,0); + sal_set_send_error(linphone_core_get_sal(pauline->lc),0); linphone_call_resume(call_pauline); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,3,2000)); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,3,2000)); @@ -2257,7 +2294,7 @@ static void call_paused_by_both(void) { wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000); /*since RTCP streams are reset when call is paused/resumed, there should be no loss at all*/ - stats = rtp_session_get_stats(call_pauline->sessions->rtp_session); + stats = rtp_session_get_stats(linphone_call_get_stream(call_pauline, LinphoneStreamTypeAudio)->sessions.rtp_session); BC_ASSERT_EQUAL((int)stats->cum_packet_loss, 0, int, "%d"); end_call(marie, pauline); @@ -2272,7 +2309,7 @@ end: rtcp_count_current = pauline->stat.number_of_rtcp_sent; \ /*wait for an RTCP packet to have an accurate cumulative lost value*/ \ BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_rtcp_sent, rtcp_count_current+1, 10000)); \ - stats = rtp_session_get_stats(call_pauline->audiostream->ms.sessions.rtp_session); \ + stats = rtp_session_get_stats(rtp_session); \ loss_percentage = stats->cum_packet_loss * 100.f / (stats->packet_recv + stats->cum_packet_loss); \ BC_ASSERT_GREATER(loss_percentage, .75f * params.loss_rate, float, "%f"); \ BC_ASSERT_LOWER(loss_percentage , 1.25f * params.loss_rate, float, "%f") @@ -2292,7 +2329,8 @@ static void call_paused_resumed_with_loss(void) { BC_ASSERT_TRUE(call(pauline,marie)); call_pauline = linphone_core_get_current_call(pauline->lc); if (call_pauline){ - rtp_session_enable_network_simulation(call_pauline->audiostream->ms.sessions.rtp_session,¶ms); + RtpSession *rtp_session = linphone_call_get_stream(call_pauline, LinphoneStreamTypeAudio)->sessions.rtp_session; + rtp_session_enable_network_simulation(rtp_session, ¶ms); /*generate some traffic*/ wait_for_until(pauline->lc, marie->lc, NULL, 5, 10000); @@ -2405,7 +2443,7 @@ static void call_paused_resumed_from_callee(void) { wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000); /*since RTCP streams are reset when call is paused/resumed, there should be no loss at all*/ - stats = rtp_session_get_stats(call_marie->sessions->rtp_session); + stats = rtp_session_get_stats(linphone_call_get_stream(call_marie, LinphoneStreamTypeAudio)->sessions.rtp_session); BC_ASSERT_EQUAL((int)stats->cum_packet_loss, 0, int, "%d"); end_call(pauline, marie); @@ -2498,11 +2536,20 @@ static void call_with_media_relay_random_ports(void) { } static void call_with_privacy(void) { - LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall *c1,*c2; LinphoneCallParams *params; LinphoneProxyConfig* pauline_proxy; + + /* pub-gruu and privacy do not work well together. */ + LinphoneCoreManager *marie = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(marie, "marie_rc", NULL); + linphone_core_remove_supported_tag(marie->lc,"gruu"); + linphone_core_manager_start(marie, TRUE); + LinphoneCoreManager *pauline = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(pauline, transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", NULL); + linphone_core_remove_supported_tag(pauline->lc,"gruu"); + linphone_core_manager_start(pauline,TRUE); + params=linphone_core_create_call_params(pauline->lc, NULL); linphone_call_params_set_privacy(params,LinphonePrivacyId); @@ -2553,11 +2600,18 @@ static void call_with_privacy(void) { /*this ones makes call with privacy without previous registration*/ static void call_with_privacy2(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new2(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", FALSE); LinphoneCall *c1,*c2; LinphoneCallParams *params; LinphoneProxyConfig* pauline_proxy; + LinphoneCoreManager *marie = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(marie, "marie_rc", NULL); + linphone_core_remove_supported_tag(marie->lc,"gruu"); + linphone_core_manager_start(marie, TRUE); + LinphoneCoreManager *pauline = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(pauline, transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", NULL); + linphone_core_remove_supported_tag(pauline->lc,"gruu"); + linphone_core_manager_start(pauline,TRUE); + params=linphone_core_create_call_params(pauline->lc, NULL); linphone_call_params_set_privacy(params,LinphonePrivacyId); @@ -2583,7 +2637,7 @@ static void call_with_privacy2(void) { BC_ASSERT_EQUAL(linphone_call_params_get_privacy(linphone_call_get_current_params(c2)),LinphonePrivacyId, int, "%d"); } - liblinphone_tester_check_rtcp(pauline,marie); + end_call(pauline, marie); /*test proxy config privacy*/ @@ -2601,7 +2655,6 @@ static void call_with_privacy2(void) { BC_ASSERT_FALSE(linphone_address_weak_equal(linphone_call_get_remote_address(c2),pauline->identity)); BC_ASSERT_EQUAL(linphone_call_params_get_privacy(linphone_call_get_current_params(c2)),LinphonePrivacyId, int, "%d"); } - liblinphone_tester_check_rtcp(pauline,marie); end_call(marie, pauline); linphone_core_manager_destroy(marie); @@ -2816,7 +2869,7 @@ static void call_with_mkv_file_player(void) { linphone_player_cbs_set_user_data(cbs, marie); int res = linphone_player_open(player,hellomkv); //if(!ms_filter_codec_supported("opus")) { - if(!ms_factory_codec_supported(marie->lc->factory, "opus") && !ms_factory_codec_supported(pauline->lc->factory, "opus")){ + if(!ms_factory_codec_supported(linphone_core_get_ms_factory(marie->lc), "opus") && !ms_factory_codec_supported(linphone_core_get_ms_factory(pauline->lc), "opus")){ BC_ASSERT_EQUAL(res, -1, int, "%d"); end_call(marie, pauline); goto end; @@ -2907,13 +2960,13 @@ static void _call_base_with_configfile(LinphoneMediaEncryption mode, bool_t enab linphone_core_set_media_encryption(pauline->lc,mode); if (mode==LinphoneMediaEncryptionDTLS) { /* for DTLS we must access certificates or at least have a directory to store them */ char *path = bc_tester_file("certificates-marie"); - marie->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(marie->lc, path); bc_free(path); path = bc_tester_file("certificates-pauline"); - pauline->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(pauline->lc, path); bc_free(path); - belle_sip_mkdir(marie->lc->user_certificates_path); - belle_sip_mkdir(pauline->lc->user_certificates_path); + belle_sip_mkdir(linphone_core_get_user_certificates_path(marie->lc)); + belle_sip_mkdir(linphone_core_get_user_certificates_path(pauline->lc)); } linphone_core_set_firewall_policy(marie->lc,policy); @@ -3054,7 +3107,7 @@ static void early_media_call_with_ice(void) { BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallIncomingReceived,1,3000)); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallIncomingEarlyMedia,1,3000)); BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,1000)); - BC_ASSERT_TRUE(pauline_call->all_muted); + BC_ASSERT_TRUE(linphone_call_get_all_muted(pauline_call)); wait_for_until(pauline->lc,marie->lc,NULL,0,1000); @@ -3067,7 +3120,7 @@ static void early_media_call_with_ice(void) { BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected,1,3000)); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning,1,3000)); BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning,1,3000)); - BC_ASSERT_FALSE(pauline_call->all_muted); + BC_ASSERT_FALSE(linphone_call_get_all_muted(pauline_call)); end_call(marie, pauline); end: @@ -3104,34 +3157,34 @@ static void early_media_call_with_ringing_base(bool_t network_change){ BC_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000) ); BC_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000) ); - BC_ASSERT_TRUE(marie_call->all_muted); + BC_ASSERT_TRUE(linphone_call_get_all_muted(marie_call)); liblinphone_tester_check_rtcp(marie, pauline); /* this is a hack to simulate an incoming OK with a different IP address * in the 'c' SDP field. */ if (network_change) { - marie_call->localdesc_changed |= SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED; + _linphone_call_add_local_desc_changed_flag(marie_call, SAL_MEDIA_DESCRIPTION_NETWORK_CHANGED); } if (linphone_core_get_current_call(pauline->lc) && linphone_call_get_state(linphone_core_get_current_call(pauline->lc)) == LinphoneCallIncomingEarlyMedia) { linphone_call_accept(linphone_core_get_current_call(pauline->lc)); - + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000)); connected_time=ms_get_cur_time_ms(); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); - + BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); - BC_ASSERT_FALSE(marie_call->all_muted); - + BC_ASSERT_FALSE(linphone_call_get_all_muted(marie_call)); + liblinphone_tester_check_rtcp(marie, pauline); /*just to have a call duration !=0*/ wait_for_list(lcs,&dummy,1,2000); - + end_call(pauline, marie); ended_time=ms_get_cur_time_ms(); - BC_ASSERT_LOWER( labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1000, long, "%ld"); + BC_ASSERT_LOWER( labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1500, long, "%ld"); } bctbx_list_free(lcs); } @@ -3176,7 +3229,7 @@ static void early_media_call_with_update_base(bool_t media_change){ linphone_call_accept_early_media(pauline_call); BC_ASSERT_TRUE( wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,1000) ); BC_ASSERT_TRUE( wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,5000) ); - BC_ASSERT_TRUE(marie_call->all_muted); + BC_ASSERT_TRUE(linphone_call_get_all_muted(marie_call)); pauline_params = linphone_call_params_copy(linphone_call_get_current_params(pauline_call)); @@ -3193,7 +3246,7 @@ static void early_media_call_with_update_base(bool_t media_change){ BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallEarlyUpdatedByRemote,1,2000)); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia,1,2000)); BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia,1,2000)); - BC_ASSERT_TRUE(marie_call->all_muted); + BC_ASSERT_TRUE(linphone_call_get_all_muted(marie_call)); /*just to wait 2s*/ liblinphone_tester_check_rtcp(marie, pauline); @@ -3207,7 +3260,7 @@ static void early_media_call_with_update_base(bool_t media_change){ BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallConnected, 1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1,1000)); - BC_ASSERT_FALSE(marie_call->all_muted); + BC_ASSERT_FALSE(linphone_call_get_all_muted(marie_call)); liblinphone_tester_check_rtcp(marie, pauline); @@ -3246,14 +3299,14 @@ static void call_established_with_rejected_info(void) { BC_ASSERT_TRUE((call_ok=call(pauline,marie))); if (call_ok){ - sal_enable_unconditional_answer(marie->lc->sal,TRUE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),TRUE); im1 = linphone_core_create_info_message(pauline->lc); linphone_call_send_info_message(linphone_core_get_current_call(pauline->lc),im1); wait_for_until(marie->lc,pauline->lc,&dummy,1,1000); /*just to sleep while iterating 1s*/ linphone_info_message_unref(im1); - sal_enable_unconditional_answer(marie->lc->sal,FALSE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),FALSE); im2 = linphone_core_create_info_message(pauline->lc); linphone_call_send_info_message(linphone_core_get_current_call(pauline->lc),im2); @@ -3316,7 +3369,7 @@ static void call_established_with_complex_rejected_operation(void) { linphone_info_message_unref(info); params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc)); - sal_enable_pending_trans_checking(marie->lc->sal,FALSE); /*to allow // transactions*/ + sal_enable_pending_trans_checking(linphone_core_get_sal(marie->lc),FALSE); /*to allow // transactions*/ linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMU",8000,1),TRUE); linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMA",8000,1),FALSE); @@ -3512,7 +3565,7 @@ static void call_established_with_rejected_reinvite_with_error_base(bool_t trans linphone_info_message_unref(info); } else - sal_enable_unconditional_answer(marie->lc->sal,TRUE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),TRUE); result = linphone_call_update(linphone_core_get_current_call(pauline->lc),linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))); @@ -3530,7 +3583,7 @@ static void call_established_with_rejected_reinvite_with_error_base(bool_t trans check_call_state(marie,LinphoneCallStreamsRunning); if (!trans_pending) - sal_enable_unconditional_answer(marie->lc->sal,FALSE); + sal_enable_unconditional_answer(linphone_core_get_sal(marie->lc),FALSE); end_call(pauline, marie); } @@ -3560,7 +3613,8 @@ 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) { - ((VTableReference*)(marie->lc->vtable_refs->data))->cbs->vtable->auth_info_requested=NULL; + LinphoneCoreCbs *cbs = linphone_core_get_first_callbacks(marie->lc); + linphone_core_cbs_set_auth_info_requested(cbs, NULL); linphone_core_add_auth_info(marie->lc,wrong_auth_info); } @@ -3618,18 +3672,19 @@ void check_media_direction(LinphoneCoreManager* mgr, LinphoneCall *call, bctbx_l linphone_call_cbs_set_next_video_frame_decoded(call_cbs, linphone_call_next_video_frame_decoded_cb); linphone_call_add_callbacks(call, call_cbs); linphone_call_cbs_unref(call_cbs); + linphone_call_request_notify_next_video_frame_decoded(call); linphone_call_send_vfu_request(call); } switch (video_dir) { case LinphoneMediaDirectionInactive: - BC_ASSERT_LOWER((int)stats->upload_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)linphone_call_stats_get_upload_bandwidth(stats), 5, int, "%i"); break; case LinphoneMediaDirectionSendOnly: expected_recv_iframe = 0; - BC_ASSERT_LOWER((int)stats->download_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)linphone_call_stats_get_download_bandwidth(stats), 5, int, "%i"); break; case LinphoneMediaDirectionRecvOnly: - BC_ASSERT_LOWER((int)stats->upload_bandwidth, 5, int, "%i"); + BC_ASSERT_LOWER((int)linphone_call_stats_get_upload_bandwidth(stats), 5, int, "%i"); BCTBX_NO_BREAK; /*intentionally no break*/ case LinphoneMediaDirectionSendRecv: expected_recv_iframe = 1; @@ -3755,7 +3810,7 @@ static void call_with_in_dialog_update(void) { 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_call_params_set_no_user_consent(params, TRUE); linphone_call_update(linphone_core_get_current_call(marie->lc),params); linphone_call_params_unref(params); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallUpdating,1)); @@ -4018,7 +4073,7 @@ static void call_with_paused_no_sdp_on_resume(void) { wait_for_until(marie->lc, pauline->lc, &dummy, 1, 3000); BC_ASSERT_GREATER(linphone_core_manager_get_max_audio_down_bw(marie),70,int,"%i"); stats = linphone_call_get_audio_stats(linphone_core_get_current_call(pauline->lc)); - BC_ASSERT_TRUE(stats->download_bandwidth>70); + BC_ASSERT_TRUE(linphone_call_stats_get_download_bandwidth(stats)>70); linphone_call_stats_unref(stats); end_call(marie,pauline); end: @@ -4080,7 +4135,7 @@ void early_media_without_sdp_in_200_base( bool_t use_video, bool_t use_ice ){ liblinphone_tester_check_rtcp(marie, pauline); /* will send the 200OK _without_ SDP. We expect the early-media SDP to be used instead */ - sal_call_set_sdp_handling(pauline_call->op, SalOpSDPSimulateRemove); + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(pauline_call), SalOpSDPSimulateRemove); linphone_call_accept(pauline_call); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1,1000)); @@ -4095,7 +4150,7 @@ void early_media_without_sdp_in_200_base( bool_t use_video, bool_t use_ice ){ end_call(pauline, marie); ended_time=ms_get_cur_time_ms(); - BC_ASSERT_LOWER(labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1000, long, "%ld"); + BC_ASSERT_LOWER(labs((long)((linphone_call_log_get_duration(marie_call_log)*1000) - (int64_t)(ended_time - connected_time))), 1500, long, "%ld"); } bctbx_list_free(lcs); linphone_core_manager_destroy(marie); @@ -4134,9 +4189,11 @@ static void call_with_generic_cn(void) { BC_ASSERT_PTR_NOT_NULL(pauline_call); if (pauline_call){ const rtp_stats_t *rtps; + AudioStream *astream; wait_for_until(marie->lc, pauline->lc, NULL, 0, 8000); - rtps=rtp_session_get_stats(pauline_call->audiostream->ms.sessions.rtp_session); + astream = (AudioStream *)linphone_call_get_stream(pauline_call, LinphoneStreamTypeAudio); + rtps=rtp_session_get_stats(astream->ms.sessions.rtp_session); BC_ASSERT_TRUE(rtps->packet_recv<=300 && rtps->packet_recv>=200); } end_call(marie,pauline); @@ -4173,9 +4230,10 @@ static void call_state_changed_2(LinphoneCore *lc, LinphoneCall *call, LinphoneC static void call_state_changed_3(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg){ /*just to check multi listener in such situation*/ - char* to=linphone_address_as_string(linphone_call_get_call_log(call)->to); - char* from=linphone_address_as_string(linphone_call_get_call_log(call)->from); - ms_message("Third call listener reports: %s call from [%s] to [%s], new state is [%s]" ,linphone_call_get_call_log(call)->dir==LinphoneCallIncoming?"Incoming":"Outgoing" + LinphoneCallLog *clog = linphone_call_get_call_log(call); + char* to=linphone_address_as_string(linphone_call_log_get_to(clog)); + char* from=linphone_address_as_string(linphone_call_log_get_from(clog)); + ms_message("Third call listener reports: %s call from [%s] to [%s], new state is [%s]" ,linphone_call_log_get_dir(clog)==LinphoneCallIncoming?"Incoming":"Outgoing" ,from ,to ,linphone_call_state_to_string(cstate)); @@ -4187,15 +4245,16 @@ static void call_with_transport_change_base(bool_t succesfull_call) { LinphoneSipTransports sip_tr; LinphoneCoreManager* marie; LinphoneCoreManager* pauline; - LinphoneCoreVTable * v_table; - v_table = linphone_core_v_table_new(); - v_table->call_state_changed=call_state_changed_2; + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_state_changed_2); marie = linphone_core_manager_new("marie_rc"); pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); - linphone_core_add_listener(marie->lc,v_table); - v_table = linphone_core_v_table_new(); - v_table->call_state_changed=call_state_changed_3; - linphone_core_add_listener(marie->lc,v_table); + linphone_core_add_callbacks(marie->lc, cbs); + linphone_core_cbs_unref(cbs); + cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_state_changed_3); + linphone_core_add_callbacks(marie->lc, cbs); + linphone_core_cbs_unref(cbs); sip_tr.udp_port = 0; sip_tr.tcp_port = 45875; @@ -4266,8 +4325,8 @@ static void simple_stereo_call(const char *codec_name, int clock_rate, int bitra linphone_core_set_record_file(pauline->lc, recordpath); /*stereo is supported only without volume control, echo canceller...*/ - lp_config_set_string(marie->lc->config,"sound","features","REMOTE_PLAYING"); - lp_config_set_string(pauline->lc->config,"sound","features","REMOTE_PLAYING"); + lp_config_set_string(linphone_core_get_config(marie->lc),"sound","features","REMOTE_PLAYING"); + lp_config_set_string(linphone_core_get_config(pauline->lc),"sound","features","REMOTE_PLAYING"); if (!BC_ASSERT_TRUE(call(pauline,marie))) goto end; wait_for_until(marie->lc, pauline->lc, NULL, 0, 6000); @@ -4484,12 +4543,12 @@ static void call_with_rtp_io_mode(void) { /* The callee uses the RTP IO mode with the PCMU codec to send back audio to the caller. */ disable_all_audio_codecs_except_one(pauline->lc, "pcmu", -1); - lp_config_set_int(pauline->lc->config, "sound", "rtp_io", 1); - lp_config_set_string(pauline->lc->config, "sound", "rtp_local_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); - lp_config_set_string(pauline->lc->config, "sound", "rtp_remote_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); - lp_config_set_int(pauline->lc->config, "sound", "rtp_local_port", 17076); - lp_config_set_int(pauline->lc->config, "sound", "rtp_remote_port", 17076); - lp_config_set_string(pauline->lc->config, "sound", "rtp_map", "pcmu/8000/1"); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sound", "rtp_io", 1); + lp_config_set_string(linphone_core_get_config(pauline->lc), "sound", "rtp_local_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); + lp_config_set_string(linphone_core_get_config(pauline->lc), "sound", "rtp_remote_addr", linphone_core_ipv6_enabled(pauline->lc) ? "::1" : "127.0.0.1"); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sound", "rtp_local_port", 17076); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sound", "rtp_remote_port", 17076); + lp_config_set_string(linphone_core_get_config(pauline->lc), "sound", "rtp_map", "pcmu/8000/1"); BC_ASSERT_TRUE((call_ok = call(marie, pauline))); if (!call_ok) goto end; @@ -4561,8 +4620,9 @@ static void call_with_generic_nack_rtcp_feedback(void) { BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); call_marie = linphone_core_get_current_call(marie->lc); if (call_marie) { - rtp_session_enable_network_simulation(call_marie->audiostream->ms.sessions.rtp_session, ¶ms); - ortp_ev_dispatcher_connect(media_stream_get_event_dispatcher(&call_marie->audiostream->ms), + AudioStream *astream = (AudioStream *)linphone_call_get_stream(call_marie, LinphoneStreamTypeAudio); + rtp_session_enable_network_simulation(astream->ms.sessions.rtp_session, ¶ms); + ortp_ev_dispatcher_connect(media_stream_get_event_dispatcher(&astream->ms), ORTP_EVENT_RTCP_PACKET_RECEIVED, RTCP_RTPFB, (OrtpEvDispatcherCb)generic_nack_received, &marie->stat); } @@ -4704,7 +4764,7 @@ static void call_state_changed_4(LinphoneCore *lc, LinphoneCall *call, LinphoneC } } // We save the pointer to our RtpTransportModifier in the call user_data to be able to get to it later - call->user_data = rtptm; + linphone_call_set_user_data(call, rtptm); } } @@ -4716,7 +4776,7 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { LinphoneCall* call_marie = NULL; const rtp_stats_t * stats; bool_t call_ok; - LinphoneCoreVTable * v_table; + LinphoneCoreCbs *cbs; RtpTransportModifier *rtptm_marie = NULL; RtpTransportModifier *rtptm_pauline = NULL; RtpTransportModifierData *data_marie = NULL; @@ -4728,14 +4788,12 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { double similar = 1; // The factor of similarity between the played file and the one recorded const double threshold = 0.85; // Minimum similarity value to consider the record file equal to the one sent - // We create a new vtable to listen only to the call state changes, in order to plug our RTP Transport Modifier when the call will be established - v_table = linphone_core_v_table_new(); - v_table->call_state_changed = call_state_changed_4; - linphone_core_add_listener(pauline->lc,v_table); - v_table = linphone_core_v_table_new(); - v_table->call_state_changed = call_state_changed_4; - linphone_core_add_listener(marie->lc,v_table); - + // We create a new LinphoneCoreCbs to listen only to the call state changes, in order to plug our RTP Transport Modifier when the call will be established + cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_state_changed_4); + linphone_core_add_callbacks(pauline->lc, cbs); + linphone_core_add_callbacks(marie->lc, cbs); + linphone_core_cbs_unref(cbs); if (recordTest) { // When we do the record test, we need a file player to play the content of a sound file /*make sure the record file doesn't already exists, otherwise this test will append new samples to it*/ @@ -4782,7 +4840,7 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { wait_for_until(pauline->lc, marie->lc, NULL, 5, 5000); /*since RTCP streams are reset when call is paused/resumed, there should be no loss at all*/ - stats = rtp_session_get_stats(call_pauline->sessions->rtp_session); + stats = rtp_session_get_stats(linphone_call_get_stream(call_pauline, LinphoneStreamTypeAudio)->sessions.rtp_session); BC_ASSERT_EQUAL((int)stats->cum_packet_loss, 0, int, "%d"); end_call(pauline, marie); @@ -4822,8 +4880,8 @@ static void custom_rtp_modifier(bool_t pauseResumeTest, bool_t recordTest) { } // Now we can go fetch our custom structure and check the number of packets sent/received is the same on both sides - rtptm_marie = (RtpTransportModifier *)call_marie->user_data; - rtptm_pauline = (RtpTransportModifier *)call_pauline->user_data; + rtptm_marie = (RtpTransportModifier *)linphone_call_get_user_data(call_marie); + rtptm_pauline = (RtpTransportModifier *)linphone_call_get_user_data(call_pauline); data_marie = (RtpTransportModifierData *)rtptm_marie->data; data_pauline = (RtpTransportModifierData *)rtptm_pauline->data; @@ -5013,9 +5071,9 @@ static void recovered_call_on_network_switch_in_early_state_4(void) { BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1)); - BC_ASSERT_TRUE(sal_call_dialog_request_pending(incoming_call->op)); + BC_ASSERT_TRUE(sal_call_dialog_request_pending(linphone_call_get_op_as_sal_op(incoming_call))); wait_for_until(marie->lc, pauline->lc, NULL, 1, 2000); - BC_ASSERT_FALSE(sal_call_dialog_request_pending(incoming_call->op)); + BC_ASSERT_FALSE(sal_call_dialog_request_pending(linphone_call_get_op_as_sal_op(incoming_call))); linphone_call_terminate(incoming_call); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1)); @@ -5069,7 +5127,7 @@ static void configure_video_policies_for_network_switch(LinphoneCore *marie, Lin linphone_core_enable_video_display(pauline, TRUE); linphone_core_set_video_policy(marie, &policy); linphone_core_set_video_policy(pauline, &policy); - lp_config_set_int(pauline->config, "sip", "defer_update_default", TRUE); + lp_config_set_int(linphone_core_get_config(pauline), "sip", "defer_update_default", TRUE); } static void recovered_call_on_network_switch_during_reinvite_2(void) { @@ -5218,6 +5276,84 @@ end: linphone_core_manager_destroy(pauline); } +static void recovered_call_on_network_switch_in_early_media_base (bool_t callerLosesNetwork) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + bctbx_list_t *lcs = NULL; + LinphoneCall *marie_call; + LinphoneCallLog *marie_call_log; + uint64_t connected_time = 0; + uint64_t ended_time = 0; + + lcs = bctbx_list_append(lcs, marie->lc); + lcs = bctbx_list_append(lcs, pauline->lc); + + /* Marie calls Pauline, and after the call has rung, transitions to an early-media session */ + marie_call = linphone_core_invite_address(marie->lc, pauline->identity); + marie_call_log = linphone_call_get_call_log(marie_call); + BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1, 1000)); + + if (linphone_core_inc_invite_pending(pauline->lc)) { + /* Send a 183 to initiate the early media */ + linphone_call_accept_early_media(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia, 1, 2000) ); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia, 1, 2000) ); + BC_ASSERT_TRUE(linphone_call_get_all_muted(marie_call)); + + liblinphone_tester_check_rtcp(marie, pauline); + + if (callerLosesNetwork) { + /* Disconnect Marie's network and then reconnect it */ + linphone_core_set_network_reachable(marie->lc, FALSE); + BC_ASSERT_EQUAL(marie->stat.number_of_NetworkReachableFalse, 1, int, "%d"); + linphone_core_set_network_reachable(marie->lc, TRUE); + BC_ASSERT_EQUAL(marie->stat.number_of_NetworkReachableTrue, 2, int, "%d"); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 2)); + } else { + /* Disconnect Pauline's network and then reconnect it */ + linphone_core_set_network_reachable(pauline->lc, FALSE); + BC_ASSERT_EQUAL(pauline->stat.number_of_NetworkReachableFalse, 1, int, "%d"); + linphone_core_set_network_reachable(pauline->lc, TRUE); + BC_ASSERT_EQUAL(pauline->stat.number_of_NetworkReachableTrue, 2, int, "%d"); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 2)); + } + + wait_for_until(marie->lc, pauline->lc, NULL, 1, 2000); + liblinphone_tester_check_rtcp(marie, pauline); + + if (linphone_core_get_current_call(pauline->lc) + && (linphone_call_get_state(linphone_core_get_current_call(pauline->lc)) == LinphoneCallIncomingEarlyMedia) + ) { + linphone_call_accept(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallConnected, 1, 1000)); + connected_time = ms_get_cur_time_ms(); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallStreamsRunning, 1, 1000)); + BC_ASSERT_PTR_EQUAL(marie_call, linphone_core_get_current_call(marie->lc)); + BC_ASSERT_FALSE(linphone_call_get_all_muted(marie_call)); + + liblinphone_tester_check_rtcp(marie, pauline); + wait_for_list(lcs, 0, 1, 2000); /* Just to have a call duration != 0 */ + + end_call(pauline, marie); + ended_time = ms_get_cur_time_ms(); + BC_ASSERT_LOWER(labs((long)((linphone_call_log_get_duration(marie_call_log) * 1000) - (int64_t)(ended_time - connected_time))), 1500, long, "%ld"); + } + } + + bctbx_list_free(lcs); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void recovered_call_on_network_switch_in_early_media_1 (void) { + recovered_call_on_network_switch_in_early_media_base(TRUE); +} + +static void recovered_call_on_network_switch_in_early_media_2 (void) { + recovered_call_on_network_switch_in_early_media_base(FALSE); +} + static void _call_with_network_switch(bool_t use_ice, bool_t with_socket_refresh, bool_t enable_rtt, bool_t caller_pause, bool_t callee_pause) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -5261,11 +5397,13 @@ static void _call_with_network_switch(bool_t use_ice, bool_t with_socket_refresh linphone_call_pause(pauline_call); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallPausedByRemote, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallPaused, 1)); + wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); } else if (callee_pause) { marie_call = linphone_core_get_current_call(marie->lc); linphone_call_pause(marie_call); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallPausedByRemote, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallPaused, 1)); + wait_for_until(marie->lc, pauline->lc, NULL, 0, 1000); } /*marie looses the network and reconnects*/ @@ -5473,13 +5611,13 @@ end: static void call_logs_if_no_db_set(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* laure = linphone_core_manager_new("laure_call_logs_rc"); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 10); + BC_ASSERT_TRUE(bctbx_list_size(linphone_core_get_call_logs(laure->lc)) == 10); BC_ASSERT_TRUE(call(marie, laure)); wait_for_until(marie->lc, laure->lc, NULL, 5, 1000); end_call(marie, laure); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 11); + BC_ASSERT_TRUE(bctbx_list_size(linphone_core_get_call_logs(laure->lc)) == 11); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(laure); } @@ -5489,15 +5627,16 @@ static void call_logs_migrate(void) { char *logs_db = bc_tester_file("call_logs.db"); size_t i = 0; int incoming_count = 0, outgoing_count = 0, missed_count = 0, aborted_count = 0, decline_count = 0, video_enabled_count = 0; + bctbx_list_t **call_logs_attr = NULL; unlink(logs_db); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 10); + BC_ASSERT_TRUE(bctbx_list_size(linphone_core_get_call_logs(laure->lc)) == 10); linphone_core_set_call_logs_database_path(laure->lc, logs_db); BC_ASSERT_TRUE(linphone_core_get_call_history_size(laure->lc) == 10); - for (; i < bctbx_list_size(laure->lc->call_logs); i++) { - LinphoneCallLog *log = bctbx_list_nth_data(laure->lc->call_logs, (int)i); + for (; i < bctbx_list_size(linphone_core_get_call_logs(laure->lc)); i++) { + LinphoneCallLog *log = bctbx_list_nth_data(linphone_core_get_call_logs(laure->lc), (int)i); LinphoneCallStatus state = linphone_call_log_get_status(log); LinphoneCallDir direction = linphone_call_log_get_dir(log); @@ -5530,15 +5669,15 @@ static void call_logs_migrate(void) { LinphoneCallLog *log = linphone_core_get_last_outgoing_call_log(laure->lc); BC_ASSERT_PTR_NOT_NULL(log); if (log) { - BC_ASSERT_EQUAL((int)log->start_date_time, 1441738272, int, "%d"); + BC_ASSERT_EQUAL((int)linphone_call_log_get_start_date(log), 1441738272, int, "%d"); linphone_call_log_unref(log); log = NULL; } } - laure->lc->call_logs = bctbx_list_free_with_data(laure->lc->call_logs, (void (*)(void*))linphone_call_log_unref); - laure->lc->call_logs = call_logs_read_from_config_file(laure->lc); - BC_ASSERT_TRUE(bctbx_list_size(laure->lc->call_logs) == 0); + call_logs_attr = linphone_core_get_call_logs_attribute(laure->lc); + *call_logs_attr = bctbx_list_free_with_data(*call_logs_attr, (void (*)(void*))linphone_call_log_unref); + *call_logs_attr = linphone_core_read_call_logs_from_config_file(laure->lc); unlink(logs_db); ms_free(logs_db); @@ -5770,18 +5909,23 @@ static void call_with_ice_and_rtcp_mux_without_reinvite(void){ static void call_with_zrtp_configured_calling_base(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) { if (ms_zrtp_available()) { - bool_t call_ok; linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionZRTP); - BC_ASSERT_TRUE((call_ok=call(pauline,marie))); + if (BC_ASSERT_TRUE(call(pauline,marie))){ - liblinphone_tester_check_rtcp(marie,pauline); + liblinphone_tester_check_rtcp(marie,pauline); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - end_call(pauline, marie); + LinphoneCall *call = linphone_core_get_current_call(marie->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + + call = linphone_core_get_current_call(pauline->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + end_call(pauline, marie); + } } else { ms_warning("Test skipped, ZRTP not available"); } @@ -5790,23 +5934,32 @@ static void call_with_zrtp_configured_calling_base(LinphoneCoreManager *marie, L static void call_with_zrtp_configured_callee_base(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) { if (ms_zrtp_available()) { - bool_t call_ok; linphone_core_set_media_encryption(marie->lc, LinphoneMediaEncryptionZRTP); - BC_ASSERT_TRUE((call_ok=call(pauline,marie))); + if (BC_ASSERT_TRUE(call(pauline,marie))){ - liblinphone_tester_check_rtcp(marie,pauline); + liblinphone_tester_check_rtcp(marie,pauline); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(marie->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc))) - , LinphoneMediaEncryptionZRTP, int, "%i"); - end_call(pauline, marie); + LinphoneCall *call = linphone_core_get_current_call(marie->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + + call = linphone_core_get_current_call(pauline->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) return; + BC_ASSERT_EQUAL(linphone_call_params_get_media_encryption(linphone_call_get_current_params(call)) + , LinphoneMediaEncryptionZRTP, int, "%i"); + end_call(pauline, marie); + } } else { ms_warning("Test skipped, ZRTP not available"); } } +static bool_t is_matching_local_v4_or_v6(const char *ip, const char *localv4, const char *localv6){ + if (strlen(ip)==0) return FALSE; + return strcmp(ip, localv4) == 0 || strcmp(ip, localv6) == 0; +} /* * this test checks the 'dont_default_to_stun_candidates' mode, where the c= line is left to host @@ -5814,20 +5967,24 @@ static void call_with_zrtp_configured_callee_base(LinphoneCoreManager *marie, Li static void call_with_ice_with_default_candidate_not_stun(void){ LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); - char localip[LINPHONE_IPADDR_SIZE]; + char localip[LINPHONE_IPADDR_SIZE]={0}; + char localip6[LINPHONE_IPADDR_SIZE]={0}; bool_t call_ok; - lp_config_set_int(marie->lc->config, "net", "dont_default_to_stun_candidates", 1); + lp_config_set_int(linphone_core_get_config(marie->lc), "net", "dont_default_to_stun_candidates", 1); linphone_core_set_firewall_policy(marie->lc, LinphonePolicyUseIce); linphone_core_set_firewall_policy(pauline->lc, LinphonePolicyUseIce); linphone_core_get_local_ip(marie->lc, AF_INET, NULL, localip); + linphone_core_get_local_ip(marie->lc, AF_INET6, NULL, localip6); call_ok = call(marie, pauline); if (call_ok){ check_ice(marie, pauline, LinphoneIceStateHostConnection); - BC_ASSERT_STRING_EQUAL(marie->lc->current_call->localdesc->addr, localip); - BC_ASSERT_STRING_EQUAL(pauline->lc->current_call->resultdesc->addr, localip); - BC_ASSERT_STRING_EQUAL(marie->lc->current_call->localdesc->streams[0].rtp_addr, localip); - BC_ASSERT_STRING_EQUAL(pauline->lc->current_call->resultdesc->streams[0].rtp_addr, ""); + BC_ASSERT_TRUE(is_matching_local_v4_or_v6(_linphone_call_get_local_desc(linphone_core_get_current_call(marie->lc))->addr, localip, localip6)); + BC_ASSERT_TRUE(is_matching_local_v4_or_v6(_linphone_call_get_local_desc(linphone_core_get_current_call(marie->lc))->streams[0].rtp_addr, localip, localip6)); + BC_ASSERT_TRUE(is_matching_local_v4_or_v6(_linphone_call_get_local_desc(linphone_core_get_current_call(marie->lc))->streams[0].rtp_addr, localip, localip6)); + BC_ASSERT_TRUE(is_matching_local_v4_or_v6(_linphone_call_get_result_desc(linphone_core_get_current_call(pauline->lc))->streams[0].rtp_addr, localip, localip6) + || is_matching_local_v4_or_v6(_linphone_call_get_result_desc(linphone_core_get_current_call(pauline->lc))->addr, localip, localip6) + ); } end_call(marie, pauline); linphone_core_manager_destroy(marie); @@ -5858,6 +6015,20 @@ static void call_with_ice_without_stun2(void){ linphone_core_manager_destroy(pauline); } +static void call_with_ice_stun_not_responding(void){ + LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + /*set dummy stun servers*/ + linphone_core_set_stun_server(marie->lc, "belledonne-communications.com:443"); + linphone_core_set_stun_server(pauline->lc, "belledonne-communications.com:443"); + /*we expect ICE to continue without stun candidates*/ + _call_with_ice_base(marie, pauline, TRUE, TRUE, TRUE, FALSE); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void call_with_zrtp_configured_calling_side(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -5923,7 +6094,8 @@ static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandator LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCallStats *marie_stats, *pauline_stats; /*marie doesn't support ZRTP at all*/ - marie->lc->zrtp_not_available_simulation=1; + // marie->lc->zrtp_not_available_simulation=1; + linphone_core_set_zrtp_not_available_simulation(marie->lc, TRUE); /*pauline requests encryption to be mandatory*/ linphone_core_set_media_encryption(pauline->lc, LinphoneMediaEncryptionZRTP); @@ -5944,8 +6116,8 @@ static void call_with_encryption_mandatory(bool_t caller_has_encryption_mandator /*however we can trust packet_recv from the other party instead */ 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)); - BC_ASSERT_EQUAL((int)marie_stats->rtp_stats.packet_recv, 0, int, "%i"); - BC_ASSERT_EQUAL((int)pauline_stats->rtp_stats.packet_recv, 0, int, "%i"); + BC_ASSERT_EQUAL((int)linphone_call_stats_get_rtp_stats(marie_stats)->packet_recv, 0, int, "%i"); + BC_ASSERT_EQUAL((int)linphone_call_stats_get_rtp_stats(pauline_stats)->packet_recv, 0, int, "%i"); linphone_call_stats_unref(marie_stats); linphone_call_stats_unref(pauline_stats); end_call(marie, pauline); @@ -6205,18 +6377,17 @@ static void simple_call_with_gruu(void) { linphone_core_manager_init(pauline, "pauline_tcp_rc", NULL); linphone_core_add_supported_tag(pauline->lc,"gruu"); linphone_core_manager_start(pauline,TRUE); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); pauline_cfg = linphone_core_get_default_proxy_config(pauline->lc); pauline_addr = linphone_proxy_config_get_contact(pauline_cfg); - + BC_ASSERT_PTR_NOT_NULL(pauline_addr); BC_ASSERT_TRUE(linphone_address_has_uri_param(pauline_addr,"gr")); BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(pauline_addr),"sip.example.org"); - + marie_call = linphone_core_invite_address(marie->lc, pauline_addr); BC_ASSERT_PTR_NOT_NULL(marie_call); if(!marie_call) goto end; @@ -6224,7 +6395,7 @@ static void simple_call_with_gruu(void) { pauline_call = linphone_core_get_current_call(pauline->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); if(!pauline_call) goto end; - + marie_addr = linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(marie->lc)); BC_ASSERT_TRUE(linphone_address_has_uri_param(marie_addr,"gr")); BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(marie_addr),"sip.example.org"); @@ -6237,12 +6408,12 @@ static void simple_call_with_gruu(void) { ms_free(result); } linphone_address_unref(contact_addr); - + linphone_call_accept(pauline_call); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); - + contact_addr = linphone_address_new(linphone_call_get_remote_contact(marie_call)); if (!BC_ASSERT_TRUE(linphone_address_equal(contact_addr, pauline_addr))) { char* expected = linphone_address_as_string(pauline_addr); @@ -6252,10 +6423,10 @@ static void simple_call_with_gruu(void) { ms_free(result); } linphone_address_unref(contact_addr); - + liblinphone_tester_check_rtcp(marie,pauline); end_call(marie,pauline); - + //BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); //BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); @@ -6327,6 +6498,7 @@ end: test_t call_tests[] = { TEST_NO_TAG("Early declined call", early_declined_call), TEST_NO_TAG("Call declined", call_declined), + TEST_NO_TAG("Call declined on timeout",call_declined_on_timeout), TEST_NO_TAG("Call declined with error", call_declined_with_error), TEST_NO_TAG("Cancelled call", cancelled_call), TEST_NO_TAG("Early cancelled call", early_cancelled_call), @@ -6454,6 +6626,8 @@ test_t call_tests[] = { TEST_ONE_TAG("Recovered call on network switch during re-invite 2", recovered_call_on_network_switch_during_reinvite_2, "CallRecovery"), TEST_ONE_TAG("Recovered call on network switch during re-invite 3", recovered_call_on_network_switch_during_reinvite_3, "CallRecovery"), TEST_ONE_TAG("Recovered call on network switch during re-invite 4", recovered_call_on_network_switch_during_reinvite_4, "CallRecovery"), + TEST_ONE_TAG("Recovered call on network switch in early media 1", recovered_call_on_network_switch_in_early_media_1, "CallRecovery"), + TEST_ONE_TAG("Recovered call on network switch in early media 2", recovered_call_on_network_switch_in_early_media_2, "CallRecovery"), TEST_ONE_TAG("Call with network switch in paused state", call_with_network_switch_in_paused_state, "CallRecovery"), TEST_ONE_TAG("Call with network switch in paused by remote state", call_with_network_switch_in_paused_by_remote_state, "CallRecovery"), TEST_ONE_TAG("Call with network switch and ICE", call_with_network_switch_and_ice, "ICE"), @@ -6467,6 +6641,7 @@ test_t call_tests[] = { TEST_ONE_TAG("Call with ICE with default candidate not stun", call_with_ice_with_default_candidate_not_stun, "ICE"), TEST_ONE_TAG("Call with ICE without stun server", call_with_ice_without_stun, "ICE"), TEST_ONE_TAG("Call with ICE without stun server one side", call_with_ice_without_stun2, "ICE"), + TEST_ONE_TAG("Call with ICE and stun server not responding", call_with_ice_stun_not_responding, "ICE"), TEST_NO_TAG("Call with ZRTP configured calling side only", call_with_zrtp_configured_calling_side), TEST_NO_TAG("Call with ZRTP configured receiver side only", call_with_zrtp_configured_callee_side), TEST_NO_TAG("Call from plain RTP to ZRTP mandatory should be silent", call_from_plain_rtp_to_zrtp), diff --git a/tester/call_video_tester.c b/tester/call_video_tester.c index c5481569d..ee6320373 100644 --- a/tester/call_video_tester.c +++ b/tester/call_video_tester.c @@ -18,7 +18,7 @@ #include "linphone/core.h" #include "liblinphone_tester.h" -#include "private.h" +#include "tester_utils.h" #ifdef VIDEO_ENABLED @@ -42,8 +42,8 @@ static void call_paused_resumed_with_video_base(bool_t sdp_200_ack bctbx_list_t *lcs = NULL; LinphoneVideoPolicy vpol; bool_t call_ok; - LinphoneCoreVTable *vtable = linphone_core_v_table_new(); - vtable->call_state_changed = call_paused_resumed_with_video_base_call_cb; + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_paused_resumed_with_video_base_call_cb); lcs = bctbx_list_append(lcs, pauline->lc); lcs = bctbx_list_append(lcs, marie->lc); @@ -93,9 +93,8 @@ static void call_paused_resumed_with_video_base(bool_t sdp_200_ack wait_for_until(pauline->lc, marie->lc, NULL, 5, 2000); /*check if video stream is still offered even if disabled*/ - - BC_ASSERT_EQUAL(call_pauline->localdesc->nb_streams, 2, int, "%i"); - BC_ASSERT_EQUAL(call_marie->localdesc->nb_streams, 2, int, "%i"); + BC_ASSERT_EQUAL(_linphone_call_get_local_desc(call_pauline)->nb_streams, 2, int, "%i"); + BC_ASSERT_EQUAL(_linphone_call_get_local_desc(call_marie)->nb_streams, 2, int, "%i"); linphone_core_enable_sdp_200_ack(pauline->lc,sdp_200_ack); @@ -116,7 +115,7 @@ static void call_paused_resumed_with_video_base(bool_t sdp_200_ack linphone_call_params_set_audio_direction(params,LinphoneMediaDirectionSendRecv); linphone_call_params_set_video_direction(params,LinphoneMediaDirectionSendRecv); if (with_call_accept) { - linphone_core_add_listener(marie->lc, vtable); + linphone_core_add_callbacks(marie->lc, cbs); } linphone_call_update(call_pauline,params); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,4)); @@ -139,6 +138,7 @@ static void call_paused_resumed_with_video_base(bool_t sdp_200_ack end_call(marie, pauline); end: + linphone_core_cbs_unref(cbs); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); bctbx_list_free(lcs); @@ -165,7 +165,7 @@ static void zrtp_video_call(void) { } static void call_state_changed_callback_to_accept_video(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState state, const char *message){ - LinphoneCoreVTable *vtable; + LinphoneCoreCbs *cbs; if (state == LinphoneCallUpdatedByRemote){ LinphoneCallParams *params = linphone_core_create_call_params(lc, call); linphone_call_params_enable_video(params, TRUE); @@ -173,9 +173,8 @@ static void call_state_changed_callback_to_accept_video(LinphoneCore *lc, Linpho linphone_call_params_unref(params); } ms_message("video acceptance listener about to be dropped"); - vtable = belle_sip_object_data_get(BELLE_SIP_OBJECT(call), - "call_state_changed_callback_to_accept_video"); - linphone_core_remove_listener(lc, vtable); + cbs = belle_sip_object_data_get(BELLE_SIP_OBJECT(call), "call_state_changed_callback_to_accept_video"); + linphone_core_remove_callbacks(lc, cbs); belle_sip_object_data_set(BELLE_SIP_OBJECT(call), "call_state_changed_callback_to_accept_video", NULL, NULL); } @@ -194,11 +193,11 @@ static LinphoneCall* _request_video(LinphoneCoreManager* caller,LinphoneCoreMana } if (accept_with_params) { - LinphoneCoreVTable *vtable = linphone_core_v_table_new(); - vtable->call_state_changed = call_state_changed_callback_to_accept_video; - linphone_core_add_listener(caller->lc, vtable); - belle_sip_object_data_set(BELLE_SIP_OBJECT(linphone_core_get_current_call(caller->lc)), "call_state_changed_callback_to_accept_video", - vtable, (void (*)(void*))linphone_core_v_table_destroy); + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_call_state_changed(cbs, call_state_changed_callback_to_accept_video); + linphone_core_add_callbacks(caller->lc, cbs); + belle_sip_object_data_set(BELLE_SIP_OBJECT(linphone_core_get_current_call(caller->lc)), + "call_state_changed_callback_to_accept_video", cbs, (void (*)(void*))linphone_core_cbs_unref); } linphone_core_enable_video_capture(callee->lc, TRUE); linphone_core_enable_video_display(callee->lc, TRUE); @@ -235,7 +234,7 @@ bool_t request_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bo BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&caller->stat.number_of_LinphoneCallStreamsRunning,initial_caller_stat.number_of_LinphoneCallStreamsRunning+1)); video_policy = linphone_core_get_video_activation_policy(caller->lc); - if (video_policy->automatically_accept || accept_with_params) { + if (linphone_video_activation_policy_get_automatically_accept(video_policy) || accept_with_params) { video_added = BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); video_added = BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))) @@ -277,7 +276,7 @@ bool_t request_video(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bo } if (video_added) { - linphone_call_set_first_video_frame_decoded_cb(call_obj); + liblinphone_tester_set_next_video_frame_decoded_cb(call_obj); /*send vfu*/ linphone_call_send_vfu_request(call_obj); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_IframeDecoded,initial_callee_stat.number_of_IframeDecoded+1)); @@ -567,13 +566,13 @@ void video_call_base_2(LinphoneCoreManager* caller,LinphoneCoreManager* callee, if (mode==LinphoneMediaEncryptionDTLS) { /* for DTLS we must access certificates or at least have a directory to store them */ char *path = bc_tester_file("certificates-marie"); - callee->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(callee->lc, path); bc_free(path); path = bc_tester_file("certificates-pauline"); - caller->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(caller->lc, path); bc_free(path); - belle_sip_mkdir(callee->lc->user_certificates_path); - belle_sip_mkdir(caller->lc->user_certificates_path); + belle_sip_mkdir(linphone_core_get_user_certificates_path(callee->lc)); + belle_sip_mkdir(linphone_core_get_user_certificates_path(caller->lc)); } linphone_core_set_media_encryption(callee->lc,mode); @@ -601,7 +600,7 @@ void video_call_base_2(LinphoneCoreManager* caller,LinphoneCoreManager* callee, BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(caller_call))); /*check video path*/ - linphone_call_set_first_video_frame_decoded_cb(callee_call); + liblinphone_tester_set_next_video_frame_decoded_cb(callee_call); linphone_call_send_vfu_request(callee_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_IframeDecoded,1)); } else { @@ -616,42 +615,42 @@ void video_call_base_2(LinphoneCoreManager* caller,LinphoneCoreManager* callee, static void check_fir(LinphoneCoreManager* caller,LinphoneCoreManager* callee ){ LinphoneCall* callee_call; LinphoneCall* caller_call; + VideoStream *callee_vstream; + VideoStream *caller_vstream; callee_call=linphone_core_get_current_call(callee->lc); caller_call=linphone_core_get_current_call(caller->lc); /*check video path is established in both directions. Indeed, FIR are ignored until the first RTP packet is received, because SSRC is not known.*/ - linphone_call_set_first_video_frame_decoded_cb(callee_call); - linphone_call_set_first_video_frame_decoded_cb(caller_call); + liblinphone_tester_set_next_video_frame_decoded_cb(callee_call); + liblinphone_tester_set_next_video_frame_decoded_cb(caller_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_IframeDecoded,1)); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_IframeDecoded,1)); linphone_call_send_vfu_request(callee_call); - if (rtp_session_avpf_enabled(callee_call->sessions->rtp_session)){ - BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&caller_call->videostream->ms_video_stat.counter_rcvd_fir, 1)); - }else{ - BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&caller_call->videostream->ms_video_stat.counter_rcvd_fir, 0)); - } - ms_message ("check_fir : [%p] received %d FIR ",&caller_call ,caller_call->videostream->ms_video_stat.counter_rcvd_fir); - ms_message ("check_fir : [%p] stat number of iframe decoded %d ",&callee_call, callee->stat.number_of_IframeDecoded); + callee_vstream = (VideoStream *)linphone_call_get_stream(callee_call, LinphoneStreamTypeVideo); + caller_vstream = (VideoStream *)linphone_call_get_stream(caller_call, LinphoneStreamTypeVideo); + if (media_stream_avpf_enabled(&callee_vstream->ms)) + BC_ASSERT_TRUE(wait_for(callee->lc, caller->lc, &caller_vstream->ms_video_stat.counter_rcvd_fir, 1)); + else + BC_ASSERT_TRUE(wait_for(callee->lc, caller->lc, &caller_vstream->ms_video_stat.counter_rcvd_fir, 0)); + ms_message("check_fir: [%p] received %d FIR ",&caller_call ,caller_vstream->ms_video_stat.counter_rcvd_fir); + ms_message("check_fir: [%p] stat number of iframe decoded %d ",&callee_call, callee->stat.number_of_IframeDecoded); - linphone_call_set_first_video_frame_decoded_cb(caller_call); + liblinphone_tester_set_next_video_frame_decoded_cb(caller_call); linphone_call_send_vfu_request(caller_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_IframeDecoded,1)); - if (rtp_session_avpf_enabled(caller_call->sessions->rtp_session)) { - if (rtp_session_avpf_enabled(callee_call->sessions->rtp_session)){ - BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee_call->videostream->ms_video_stat.counter_rcvd_fir, 1)); - } - }else{ - BC_ASSERT_TRUE(wait_for(callee->lc,caller->lc,&callee_call->videostream->ms_video_stat.counter_rcvd_fir, 0)); - } - ms_message ("check_fir : [%p] received %d FIR ",&callee_call ,callee_call->videostream->ms_video_stat.counter_rcvd_fir); - ms_message ("check_fir : [%p] stat number of iframe decoded %d ",&caller_call, caller->stat.number_of_IframeDecoded); - + if (media_stream_avpf_enabled(&caller_vstream->ms)) { + if (media_stream_avpf_enabled(&callee_vstream->ms)) + BC_ASSERT_TRUE(wait_for(callee->lc, caller->lc, &callee_vstream->ms_video_stat.counter_rcvd_fir, 1)); + } else + BC_ASSERT_TRUE(wait_for(callee->lc, caller->lc, &callee_vstream->ms_video_stat.counter_rcvd_fir, 0)); + ms_message("check_fir: [%p] received %d FIR ", &callee_call, callee_vstream->ms_video_stat.counter_rcvd_fir); + ms_message("check_fir: [%p] stat number of iframe decoded %d ", &caller_call, caller->stat.number_of_IframeDecoded); } void video_call_base_3(LinphoneCoreManager* caller,LinphoneCoreManager* callee, bool_t using_policy,LinphoneMediaEncryption mode, bool_t callee_video_enabled, bool_t caller_video_enabled) { @@ -671,6 +670,12 @@ void video_call_base_3(LinphoneCoreManager* caller,LinphoneCoreManager* callee, linphone_core_set_video_policy(caller->lc,&caller_policy); } + linphone_core_set_preferred_video_size_by_name(caller->lc, "QVGA"); + linphone_core_set_preferred_video_size_by_name(callee->lc, "QVGA"); + + linphone_core_set_video_device(caller->lc, "Mire: Mire (synthetic moving picture)"); + linphone_core_set_video_device(callee->lc, "Mire: Mire (synthetic moving picture)"); + linphone_core_enable_video_display(callee->lc, callee_video_enabled); linphone_core_enable_video_capture(callee->lc, callee_video_enabled); @@ -679,13 +684,13 @@ void video_call_base_3(LinphoneCoreManager* caller,LinphoneCoreManager* callee, if (mode==LinphoneMediaEncryptionDTLS) { /* for DTLS we must access certificates or at least have a directory to store them */ char *path = bc_tester_file("certificates-marie"); - callee->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(callee->lc, path); bc_free(path); path = bc_tester_file("certificates-pauline"); - caller->lc->user_certificates_path = ms_strdup(path); + linphone_core_set_user_certificates_path(caller->lc, path); bc_free(path); - belle_sip_mkdir(callee->lc->user_certificates_path); - belle_sip_mkdir(caller->lc->user_certificates_path); + belle_sip_mkdir(linphone_core_get_user_certificates_path(callee->lc)); + belle_sip_mkdir(linphone_core_get_user_certificates_path(caller->lc)); } linphone_core_set_media_encryption(callee->lc,mode); @@ -833,6 +838,7 @@ static void video_call_established_by_reinvite_with_implicit_avpf(void) { LinphoneVideoPolicy policy; LinphoneCall * caller_call, *callee_call; LinphoneCallParams *params; + VideoStream *vstream; policy.automatically_initiate=FALSE; policy.automatically_accept=FALSE; @@ -877,14 +883,16 @@ static void video_call_established_by_reinvite_with_implicit_avpf(void) { BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(callee_call))); BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(caller_call))); - linphone_call_set_first_video_frame_decoded_cb(caller_call); - linphone_call_set_first_video_frame_decoded_cb(callee_call); + liblinphone_tester_set_next_video_frame_decoded_cb(caller_call); + liblinphone_tester_set_next_video_frame_decoded_cb(callee_call); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&callee->stat.number_of_IframeDecoded,1)); BC_ASSERT_TRUE( wait_for(callee->lc,caller->lc,&caller->stat.number_of_IframeDecoded,1)); - BC_ASSERT_TRUE(media_stream_avpf_enabled((MediaStream*)caller_call->videostream)); - BC_ASSERT_TRUE(media_stream_avpf_enabled((MediaStream*)callee_call->videostream)); + vstream = (VideoStream *)linphone_call_get_stream(caller_call, LinphoneStreamTypeVideo); + BC_ASSERT_TRUE(media_stream_avpf_enabled((MediaStream*)vstream)); + vstream = (VideoStream *)linphone_call_get_stream(callee_call, LinphoneStreamTypeVideo); + BC_ASSERT_TRUE(media_stream_avpf_enabled((MediaStream*)vstream)); } end_call(caller, callee); @@ -1221,6 +1229,7 @@ static void video_call_with_early_media_no_matching_audio_codecs(void) { LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall *out_call, *pauline_call; LinphoneVideoPolicy vpol={0}; + AudioStream *astream; linphone_core_enable_video_capture(marie->lc, TRUE); linphone_core_enable_video_display(marie->lc, TRUE); @@ -1249,7 +1258,8 @@ static void video_call_with_early_media_no_matching_audio_codecs(void) { BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingEarlyMedia, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallOutgoingEarlyMedia, 1)); /*audio stream shall not have been requested to start*/ - BC_ASSERT_PTR_NULL(pauline_call->audiostream->soundread); + astream = (AudioStream *)linphone_call_get_stream(pauline_call, LinphoneStreamTypeAudio); + BC_ASSERT_PTR_NULL(astream->soundread); BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(out_call))); BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(pauline_call))); @@ -1321,10 +1331,9 @@ static void accept_call_in_send_only_base(LinphoneCoreManager* pauline, Linphone linphone_core_set_video_device(marie->lc,liblinphone_tester_mire_id); /*The send-only client shall set rtp symmetric in absence of media relay for this test.*/ - lp_config_set_int(marie->lc->config,"rtp","symmetric",1); - - linphone_call_set_first_video_frame_decoded_cb(linphone_core_invite_address(pauline->lc,marie->identity)); + lp_config_set_int(linphone_core_get_config(marie->lc),"rtp","symmetric",1); + liblinphone_tester_set_next_video_frame_decoded_cb(linphone_core_invite_address(pauline->lc,marie->identity)); BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphoneCallIncomingReceived,1,DEFAULT_WAIT_FOR)); @@ -1415,13 +1424,12 @@ static void video_early_media_call(void) { LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); LinphoneCall *pauline_to_marie; - linphone_core_set_video_device(pauline->lc, "Mire: Mire (synthetic moving picture)"); - video_call_base_3(pauline, marie, TRUE, LinphoneMediaEncryptionNone, TRUE, TRUE); BC_ASSERT_PTR_NOT_NULL(pauline_to_marie = linphone_core_get_current_call(pauline->lc)); if(pauline_to_marie) { - BC_ASSERT_EQUAL(pauline_to_marie->videostream->source->desc->id, MS_MIRE_ID, int, "%d"); + VideoStream *vstream = (VideoStream *)linphone_call_get_stream(pauline_to_marie, LinphoneStreamTypeVideo); + BC_ASSERT_EQUAL(vstream->source->desc->id, MS_MIRE_ID, int, "%d"); } end_call(pauline, marie); @@ -1898,7 +1906,7 @@ static void incoming_reinvite_with_invalid_ack_sdp(void){ const LinphoneCallParams *caller_params; stats initial_caller_stat=caller->stat; stats initial_callee_stat=callee->stat; - sal_call_set_sdp_handling(inc_call->op, SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(inc_call), SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ BC_ASSERT_PTR_NOT_NULL(_request_video(caller, callee, TRUE)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1)); @@ -1912,9 +1920,9 @@ static void incoming_reinvite_with_invalid_ack_sdp(void){ BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); caller_params = linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)); - BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,(int*)&caller_params->has_video,FALSE)); - - sal_call_set_sdp_handling(inc_call->op, SalOpSDPNormal); + // TODO [refactoring]: BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,(int*)&caller_params->has_video,FALSE)); + (void)caller_params; + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(inc_call), SalOpSDPNormal); } end_call(caller, callee); @@ -1933,7 +1941,7 @@ static void outgoing_reinvite_with_invalid_ack_sdp(void) { if (out_call) { stats initial_caller_stat=caller->stat; stats initial_callee_stat=callee->stat; - sal_call_set_sdp_handling(out_call->op, SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(out_call), SalOpSDPSimulateError); /* will force a parse error for the ACK SDP*/ BC_ASSERT_PTR_NOT_NULL(_request_video(caller, callee, TRUE)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallUpdating,initial_callee_stat.number_of_LinphoneCallUpdating+1)); BC_ASSERT_TRUE(wait_for(caller->lc,callee->lc,&callee->stat.number_of_LinphoneCallStreamsRunning,initial_callee_stat.number_of_LinphoneCallStreamsRunning+1)); @@ -1947,7 +1955,7 @@ static void outgoing_reinvite_with_invalid_ack_sdp(void) { BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(callee->lc)))); BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(linphone_core_get_current_call(caller->lc)))); - sal_call_set_sdp_handling(out_call->op, SalOpSDPNormal); + sal_call_set_sdp_handling(linphone_call_get_op_as_sal_op(out_call), SalOpSDPNormal); } end_call(caller, callee); @@ -2069,13 +2077,13 @@ static void video_call_with_thin_congestion(void){ } static void on_tmmbr_received(LinphoneCall *call, int stream_index, int tmmbr) { - if (stream_index == call->main_video_stream_index) { - stats* stat = get_stats(call->core); + if (stream_index == _linphone_call_get_main_video_stream_index(call)) { + stats* stat = get_stats(linphone_call_get_core(call)); stat->tmmbr_received_from_cb = tmmbr; } } -static void call_created(LinphoneCore *lc, LinphoneCall *call){ +static void call_created(LinphoneCore *lc, LinphoneCall *call) { LinphoneCallCbs *cbs = linphone_factory_create_call_cbs(linphone_factory_get()); linphone_call_cbs_set_tmmbr_received(cbs, on_tmmbr_received); linphone_call_add_callbacks(call, cbs); @@ -2122,8 +2130,8 @@ static void video_call_with_high_bandwidth_available(void) { /*wait a little in order to have traffic*/ BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, NULL, 5, 50000)); - BC_ASSERT_GREATER((float)marie->stat.tmmbr_received_from_cb, 850000.f, float, "%f"); - BC_ASSERT_LOWER((float)marie->stat.tmmbr_received_from_cb, 1150000.f, float, "%f"); + BC_ASSERT_GREATER((float)marie->stat.last_tmmbr_value_received, 870000.f, float, "%f"); + BC_ASSERT_LOWER((float)marie->stat.last_tmmbr_value_received, 1150000.f, float, "%f"); end_call(marie, pauline); } @@ -2138,7 +2146,7 @@ static void video_call_expected_fps_for_specified_bandwidth(int bandwidth, int f LinphoneVideoPolicy pol = {0}; OrtpNetworkSimulatorParams simparams = { 0 }; - if (ms_factory_get_cpu_count(marie->lc->factory) >= 2) { + if (ms_factory_get_cpu_count(linphone_core_get_ms_factory(marie->lc)) >= 2) { linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)"); linphone_core_enable_video_capture(marie->lc, TRUE); linphone_core_enable_video_display(marie->lc, TRUE); @@ -2161,11 +2169,23 @@ static void video_call_expected_fps_for_specified_bandwidth(int bandwidth, int f if (BC_ASSERT_TRUE(call(marie, pauline))){ LinphoneCall *call = linphone_core_get_current_call(marie->lc); + VideoStream *vstream = (VideoStream *)linphone_call_get_stream(call, LinphoneStreamTypeVideo); + int count; + /*wait some time until the target fps is reached. Indeed the bandwidth measurement may take several iterations to converge + to a value big enough to allow mediastreamer2 to switch to the high fps profile*/ - /*wait for the first TMMBR*/ - BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.last_tmmbr_value_received, 1, 10000)); - BC_ASSERT_EQUAL((int)call->videostream->configured_fps, fps, int, "%d"); + for (count = 0 ; count < 3; count++){ + /*wait for at least the first TMMBR to arrive*/ + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.last_tmmbr_value_received, 1, 10000)); + if ((int)vstream->configured_fps == fps){ + break; + }else{ + /*target fps not reached yet, wait more time*/ + wait_for_until(marie->lc, pauline->lc, NULL, 0, 2000); + } + } + BC_ASSERT_EQUAL((int)vstream->configured_fps, fps, int, "%d"); end_call(marie, pauline); } } else { @@ -2236,7 +2256,6 @@ test_t call_video_tests[] = { TEST_NO_TAG("Simple video call implicit AVPF to AVPF", video_call_implicit_AVPF_to_AVPF), TEST_NO_TAG("Video added by reINVITE, with implicit AVPF", video_call_established_by_reinvite_with_implicit_avpf), TEST_NO_TAG("Simple video call", video_call), - TEST_NO_TAG("Simple video call with snapshot", video_call_snapshot), TEST_NO_TAG("Simple video call without rtcp",video_call_without_rtcp), TEST_NO_TAG("Simple ZRTP video call", video_call_zrtp), TEST_NO_TAG("Simple DTLS video call", video_call_dtls), diff --git a/tester/certificates/client/cert2.pem b/tester/certificates/client/cert2.pem index dec9835a8..bec3c3668 100644 --- a/tester/certificates/client/cert2.pem +++ b/tester/certificates/client/cert2.pem @@ -1,35 +1,35 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15 (0xf) - Signature Algorithm: sha1WithRSAEncryption + Serial Number: 16 (0x10) + Signature Algorithm: sha256WithRSAEncryption Issuer: C=FR, ST=Some-State, L=Grenoble, O=Belledonne Communications, OU=LAB, CN=Jehan Monnier/emailAddress=jehan.monnier@belledonne-communications.com Validity - Not Before: Sep 25 08:39:36 2017 GMT - Not After : Sep 23 08:39:36 2027 GMT - Subject: C=FR, ST=Some-State, L=Lorien, O=Internet Widgits Pty Ltd, CN=sip:galadrielle@sip.example.org + Not Before: Mar 21 16:35:56 2018 GMT + Not After : Mar 18 16:35:56 2028 GMT + Subject: C=FR, ST=Lorien, O=Elfes, CN=sip:galadrielle@sip.example.org Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public Key: (2048 bit) - Modulus (2048 bit): - 00:ae:3c:ab:f2:34:4b:dd:3e:96:b4:0f:76:61:5f: - 59:dd:d0:93:6f:05:04:a2:2e:f7:f5:2f:65:35:02: - f5:6f:ed:dd:46:bb:72:3e:7c:47:b5:37:15:1d:1d: - 90:a7:dc:0f:bf:cc:a8:58:43:86:fb:b8:c7:7e:13: - 7f:05:09:47:6b:bf:a1:d1:76:7d:7a:d3:09:3a:46: - 78:22:08:49:cd:02:8d:80:10:ee:d1:18:3c:e4:df: - 50:be:05:80:88:56:c3:d4:36:2c:05:5d:57:07:9a: - 4a:13:99:7f:46:d9:0b:dd:81:51:29:bd:8e:3a:55: - b2:33:f2:e6:3e:1c:ce:f9:2f:80:68:ca:5a:78:c5: - e1:27:4a:b4:0b:65:9b:24:ee:df:8c:16:f0:74:dc: - fe:a5:9f:52:5a:a1:f9:09:1d:47:00:d9:8a:84:72: - e2:19:7b:cb:cd:62:b3:44:e3:4f:cf:9b:1c:a1:bc: - 70:d3:e0:10:8b:f2:51:28:91:84:61:92:56:03:3a: - 2c:bf:11:8d:b6:4b:c8:4f:1c:e7:75:54:b9:cd:f3: - d5:be:6b:af:6e:9f:ca:77:45:44:5c:55:6a:23:49: - e0:52:fc:30:3d:a9:a8:66:f1:d8:d0:a8:5b:97:3c: - a7:de:70:db:7b:85:c1:f5:8e:54:3c:f8:0f:3a:9f: - 36:2d + Public-Key: (2048 bit) + Modulus: + 00:e5:0b:bd:b3:f7:e7:c2:1f:27:40:1f:57:7f:0b: + 47:67:08:54:aa:6f:78:f9:02:32:10:fa:0c:fd:4a: + 0f:3c:a3:f2:34:d0:60:93:1c:c5:fe:25:a5:66:7f: + 02:11:23:cc:98:b2:34:3e:1b:31:8a:f4:9d:d6:89: + a6:41:d5:8f:fc:db:24:0f:61:af:e2:15:7b:71:d7: + 10:3e:25:ea:a4:dd:f6:c5:6b:ac:b8:a8:f5:34:fe: + a2:7e:fc:8e:b5:99:55:2a:74:c4:55:3f:9a:ae:a0: + 62:b3:03:50:aa:39:dd:8c:62:22:ac:3d:0d:60:d0: + da:49:0d:31:79:01:e4:59:9b:54:d8:78:e6:90:3d: + 8a:d6:1b:6c:1f:4e:4e:d7:76:a2:16:e7:37:d8:c8: + cf:33:95:b9:eb:fe:e0:b5:10:6f:b6:0d:31:a5:d4: + d5:86:07:1b:05:43:f1:42:0b:f7:ba:20:96:45:48: + ec:6f:c9:29:8c:fe:15:55:d8:26:f2:20:c6:db:37: + 67:e6:42:de:4b:66:fa:68:a1:4c:6f:39:01:56:92: + 5c:7d:68:2d:58:85:4a:67:a5:03:cb:c5:1d:22:7c: + 00:24:cd:49:3b:68:af:1a:0f:cf:ed:09:9f:74:7a: + 54:69:6c:2e:bf:72:76:46:b0:26:24:14:e0:74:8e: + 0e:23 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: @@ -37,38 +37,37 @@ Certificate: Netscape Comment: OpenSSL Generated Certificate X509v3 Subject Key Identifier: - 33:D0:36:5B:62:9B:1C:4D:31:47:9E:C0:91:41:E3:AE:29:61:AB:DB + 22:E0:9B:5C:30:1A:B0:02:A3:88:63:73:16:01:60:E1:16:1A:8A:AD X509v3 Authority Key Identifier: keyid:06:5F:5D:C7:16:AF:62:F8:2D:6E:71:03:88:A0:D6:1D:2B:04:7F:BA - Signature Algorithm: sha1WithRSAEncryption - 73:17:ec:83:67:5c:3a:85:c2:16:37:94:ff:dc:4f:4e:97:39: - 5c:07:96:95:5c:eb:f1:7f:98:c8:27:c3:ba:8a:7c:15:a3:c6: - 80:bd:1f:56:7e:4a:d2:de:e7:44:03:75:48:f1:10:89:46:eb: - 8b:b3:6e:f1:b7:00:67:43:7e:5d:d2:1d:84:67:e5:be:ff:40: - 14:92:c7:15:b5:5b:4b:70:b1:62:59:09:4b:28:72:b7:99:e3: - 7a:4c:ff:4f:8e:40:83:98:27:df:2d:5b:62:03:a0:a6:ee:71: - 47:2c:95:91:2c:a6:a4:8e:1c:57:6d:e8:e9:5a:76:cf:77:f5: - fc:1e + Signature Algorithm: sha256WithRSAEncryption + 12:78:7f:19:e2:38:d1:aa:9d:fe:c7:30:fb:00:00:ce:ce:28: + 66:fc:fe:d2:fb:3c:f8:af:68:83:11:96:30:ab:97:f9:f0:cd: + 09:67:12:4f:9f:97:ad:39:1c:a2:d2:f2:8c:38:71:be:1f:0a: + c8:12:93:8b:42:d7:1a:3a:29:6e:01:08:50:44:a3:cc:09:39: + 63:90:5f:20:09:70:a8:70:ed:91:1e:78:1b:f3:5c:2d:84:a8: + 6e:71:ff:36:0b:fa:b5:26:63:8b:d4:80:43:f0:4a:89:86:d5: + 37:3b:23:c2:2b:40:14:04:e6:67:5e:a5:61:68:8e:03:b7:4c: + cd:16 -----BEGIN CERTIFICATE----- -MIIDsjCCAxugAwIBAgIBDzANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx +MIIDiTCCAvKgAwIBAgIBEDANBgkqhkiG9w0BAQsFADCBuzELMAkGA1UEBhMCRlIx EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK DBlCZWxsZWRvbm5lIENvbW11bmljYXRpb25zMQwwCgYDVQQLDANMQUIxFjAUBgNV BAMMDUplaGFuIE1vbm5pZXIxOjA4BgkqhkiG9w0BCQEWK2plaGFuLm1vbm5pZXJA -YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTcwOTI1MDgzOTM2WhcN -MjcwOTIzMDgzOTM2WjCBgDELMAkGA1UEBhMCRlIxEzARBgNVBAgMClNvbWUtU3Rh -dGUxDzANBgNVBAcMBkxvcmllbjEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ -dHkgTHRkMSgwJgYDVQQDDB9zaXA6Z2FsYWRyaWVsbGVAc2lwLmV4YW1wbGUub3Jn -MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArjyr8jRL3T6WtA92YV9Z -3dCTbwUEoi739S9lNQL1b+3dRrtyPnxHtTcVHR2Qp9wPv8yoWEOG+7jHfhN/BQlH -a7+h0XZ9etMJOkZ4IghJzQKNgBDu0Rg85N9QvgWAiFbD1DYsBV1XB5pKE5l/RtkL -3YFRKb2OOlWyM/LmPhzO+S+AaMpaeMXhJ0q0C2WbJO7fjBbwdNz+pZ9SWqH5CR1H -ANmKhHLiGXvLzWKzRONPz5scobxw0+AQi/JRKJGEYZJWAzosvxGNtkvITxzndVS5 -zfPVvmuvbp/Kd0VEXFVqI0ngUvwwPamoZvHY0Khblzyn3nDbe4XB9Y5UPPgPOp82 -LQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdl -bmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUM9A2W2KbHE0xR57AkUHjrilh -q9swHwYDVR0jBBgwFoAUBl9dxxavYvgtbnEDiKDWHSsEf7owDQYJKoZIhvcNAQEF -BQADgYEAcxfsg2dcOoXCFjeU/9xPTpc5XAeWlVzr8X+YyCfDuop8FaPGgL0fVn5K -0t7nRAN1SPEQiUbri7Nu8bcAZ0N+XdIdhGflvv9AFJLHFbVbS3CxYlkJSyhyt5nj -ekz/T45Ag5gn3y1bYgOgpu5xRyyVkSympI4cV23o6Vp2z3f1/B4= +YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTgwMzIxMTYzNTU2WhcN +MjgwMzE4MTYzNTU2WjBYMQswCQYDVQQGEwJGUjEPMA0GA1UECAwGTG9yaWVuMQ4w +DAYDVQQKDAVFbGZlczEoMCYGA1UEAwwfc2lwOmdhbGFkcmllbGxlQHNpcC5leGFt +cGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOULvbP358If +J0AfV38LR2cIVKpvePkCMhD6DP1KDzyj8jTQYJMcxf4lpWZ/AhEjzJiyND4bMYr0 +ndaJpkHVj/zbJA9hr+IVe3HXED4l6qTd9sVrrLio9TT+on78jrWZVSp0xFU/mq6g +YrMDUKo53YxiIqw9DWDQ2kkNMXkB5FmbVNh45pA9itYbbB9OTtd2ohbnN9jIzzOV +uev+4LUQb7YNMaXU1YYHGwVD8UIL97oglkVI7G/JKYz+FVXYJvIgxts3Z+ZC3ktm ++mihTG85AVaSXH1oLViFSmelA8vFHSJ8ACTNSTtorxoPz+0Jn3R6VGlsLr9ydkaw +JiQU4HSODiMCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3Bl +blNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFCLgm1wwGrACo4hj +cxYBYOEWGoqtMB8GA1UdIwQYMBaAFAZfXccWr2L4LW5xA4ig1h0rBH+6MA0GCSqG +SIb3DQEBCwUAA4GBABJ4fxniONGqnf7HMPsAAM7OKGb8/tL7PPivaIMRljCrl/nw +zQlnEk+fl605HKLS8ow4cb4fCsgSk4tC1xo6KW4BCFBEo8wJOWOQXyAJcKhw7ZEe +eBvzXC2EqG5x/zYL+rUmY4vUgEPwSomG1Tc7I8IrQBQE5mdepWFojgO3TM0W -----END CERTIFICATE----- diff --git a/tester/certificates/client/key2.pem b/tester/certificates/client/key2.pem index d6eab8da5..e3b6c9551 100644 --- a/tester/certificates/client/key2.pem +++ b/tester/certificates/client/key2.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCuPKvyNEvdPpa0 -D3ZhX1nd0JNvBQSiLvf1L2U1AvVv7d1Gu3I+fEe1NxUdHZCn3A+/zKhYQ4b7uMd+ -E38FCUdrv6HRdn160wk6RngiCEnNAo2AEO7RGDzk31C+BYCIVsPUNiwFXVcHmkoT -mX9G2QvdgVEpvY46VbIz8uY+HM75L4Boylp4xeEnSrQLZZsk7t+MFvB03P6ln1Ja -ofkJHUcA2YqEcuIZe8vNYrNE40/PmxyhvHDT4BCL8lEokYRhklYDOiy/EY22S8hP -HOd1VLnN89W+a69un8p3RURcVWojSeBS/DA9qahm8djQqFuXPKfecNt7hcH1jlQ8 -+A86nzYtAgMBAAECggEAHyf8O0A8vKA/hI0rRvgs8qwkYPrNvE6XykEiYNtZlh07 -rzU/lYrVq8LgxKcPweRo8IwhIj9Y+NQu4A2ObhEds1e+EN2WTItGICSPwM4onD8z -nE3q1nr2EJsaLhB/zmFtfRn+vyrUsChXzK9rAfk31PEV2VfrAeVnC0EJCNxP6mDX -gAjTNN/+Elqzr8Cr7aofthaMnCWnI6JBJ0MCqaozDBreyfGkaFC+RkRxUpZQerqN -tvcurKn0C/Q5ZcfIugvnEFa4nL/V4s+j4Kv1SWgvfi2z4eR7wyiZVT+mStMiHvg5 -JCLNli4GtFyhYzsTqUnd3S2t0unEdaFLEzJakHGjQQKBgQDdjw9UN354QS2Aiqoe -Gu5e9nc3gi3e/dHmPyk4jKPC/cqrQ3AVrXILLjU/FHpT7OrkwoQNvI0qG39r1Akq -hnztTqDw0HVskuWJmPmUxfdl6DIOUln7pEX4yZMreDwdEjxx/oZzbu7bhU3k7zNV -zKv54deN78AmtVI5KzrEdvKfnQKBgQDJUnAtvDeuwE44XUU0mBoH3XdLULLaVeAl -4vovM/8U283+wiBkASXamFimboBKe34TGH/v10hmKxBHyPCgl9ps6o9iFbPRNzOB -kmGrTTojSOJ6u9EXvQ+wTYjzl2n/RlivIsOZRC0YXmk3n+mRPa0TGwnpxH13cEFV -RnEUnYdT0QKBgBZXw/L5Oa7E2+LXmPo6OwmmjzUw0pFnRVCT1ANY43bZgyOsRFRb -TmHkQghfd0qZXMK+/vQnrJCvfzUPh/Ea6ORBhqdiTkUpty4eGCUxpZZISSv6kAp5 -cXj6UvYSRPWljiTsxwBDEqFemxFYMfQYFMu5Q7STlewRYv5S5rVDTYpdAoGAG77I -xwTRh7vpC8uO5hiwPbU/45lTjNOY+J+3axn3ZaCFWz7Vx/KAjQfB7+36sEkkru0J -dLxuteXpcHs47mj/KVOKPzJOfd7lsk3COCGEiahZziBkSKk9qEaHQUr0yMGhJ0Hb -QxwqOtmIFqprPiEJ4UAwtY7m27cUyfPTUcwEAoECgYBEoCn8kmRXuBoDVNPK1IPh -vQcD0RDdtGhOrM36Pmmbky6oS37c3AV4sXOhw7aTYs4GejpeH0tX7F0hiwaZ/SqG -WxliyHCpUxpl+LsGzdfqCa9nEPn4B27/jFYHVCiSheOfVEwjGavkO+VIZbuHXAP4 -V8rXqdmFIbiVb43P6yoMhg== +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDlC72z9+fCHydA +H1d/C0dnCFSqb3j5AjIQ+gz9Sg88o/I00GCTHMX+JaVmfwIRI8yYsjQ+GzGK9J3W +iaZB1Y/82yQPYa/iFXtx1xA+Jeqk3fbFa6y4qPU0/qJ+/I61mVUqdMRVP5quoGKz +A1CqOd2MYiKsPQ1g0NpJDTF5AeRZm1TYeOaQPYrWG2wfTk7XdqIW5zfYyM8zlbnr +/uC1EG+2DTGl1NWGBxsFQ/FCC/e6IJZFSOxvySmM/hVV2CbyIMbbN2fmQt5LZvpo +oUxvOQFWklx9aC1YhUpnpQPLxR0ifAAkzUk7aK8aD8/tCZ90elRpbC6/cnZGsCYk +FOB0jg4jAgMBAAECggEBAJ5dZNfHQ23b3maehP+pS8A4aVnCY1FALF/ClDKY/zn9 +XR0ZKnzs+xSC8P6SOFqjdvXo2OhMIxAhm/RXDiYcxEafOiqMb3CRS93lRizCSJ+f +fNz5Wt3+rDPtD2tfskhrcRA+1fTfWlL9P+DoHODly4Ih5DlUqShUn2i8/4TcQweU +aM/Kii6s5lf76nqEd4ztzseyn1f3sklxFHI1p0+mzk57YghTdaD/qJiFV0Lxf6jw +SLb5eMmo+BRucV9Rl7jXlhJW00pTIc38ssRdH2XvHw5h51kv9CBRQFSmdnGrzj1/ +D2l+C5gxLIGshbEoAaFDJWZi2v01wWCpe7N0GXxl4HECgYEA9SNHCpWIehydIra1 +h0tBWOxv9gac7OiW64bDd5op6XYXNTwI8GIGX3VsV+avDhPWTptI0+cCOAgBqPyi +LCwT3HrXTyzRcJctlwHRZIUkzlr26Z+5WUJK0+bdCWiOCE31+pS6qX9bjreq1pL6 +C9Gfl3m4FXCICXCGSSutKBT8FRkCgYEA7zHsqzvBmJS8T57lNPBCqmpFI6viR5Vu +qza6zlJLSP7OTlWBiQ+coq4YmsAv2pF+i9j4VDizf77nF2tkNcC/2CJk70oXxj/Y +ahci9M5xnX9WyPn9x53clepT+XXUQ8yW/OvjKUc5gut1g5OZFsjGmWFk/EkzJLSz +p5lXMJl4iJsCgYA+5FQfpQmkup6d/15HXclgNRjsd/ne1jWSK7sOfmDuYrvFjqeE +dMHJz+iCDM8wv2omNLTUmNn64iL65gX9azmVQXbn+0mop0CtE2xTa81rm+7pNW9q +NRXZk8t11HtMKiRHq8zQG7qzvO95qa+5RIi7ZiESbxKXyWTKdQgx1mBuUQKBgHy1 +gdhRIoGj4n58sLImJgvltkB/6E08KuQXd9QEcf4P445R5GSKgDcNIATm+MwzGVBe +gjKfEW8kICZEto2T/jH41Lkx3y1csj+16mLKk8/yyVOli1wdARokfz3L4iyrKXma +nugxm1mX28ALH0ES0wC7F8S1gXW8xQI3346WJZLLAoGBALXykdDntTZ6RG5ahvQx +rLTr95sLxyujG2oyn7hatPcAfvqFatx2m+FiYVDw5x511XHJ49oFsxQ/+kiZrojJ +eKPvsy2gP8EievsEtK5+YDSkZQtZjzP65lOHd8g/0AmQGmO7RQ456GoG4qAhRc7+ +YwPlbSK0lTSXxcloSc2WW6ak -----END PRIVATE KEY----- diff --git a/tester/clonable-object-tester.cpp b/tester/clonable-object-tester.cpp new file mode 100644 index 000000000..c23cd55c1 --- /dev/null +++ b/tester/clonable-object-tester.cpp @@ -0,0 +1,67 @@ +/* + * clonable-object-tester.cpp + * Copyright (C) 2017 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "object/clonable-object-p.h" +#include "object/clonable-object.h" + +#include "liblinphone_tester.h" +#include "tester_utils.h" + +// ============================================================================= + +using namespace std; + +using namespace LinphonePrivate; + +// ----------------------------------------------------------------------------- + +class TestObjectPrivate : public ClonableObjectPrivate { +public: + TestObjectPrivate () = default; + + TestObjectPrivate (const TestObjectPrivate &) : TestObjectPrivate() {} +}; + +class TestObject : public ClonableObject { +public: + TestObject () : ClonableObject(*new TestObjectPrivate) {} + + TestObject (const TestObject &src) : ClonableObject(*new TestObjectPrivate(*src.getPrivate())) {} + +private: + L_DECLARE_PRIVATE(TestObject); +}; + +// ----------------------------------------------------------------------------- + +static void check_clonable_object_creation () { + TestObject *object = new TestObject(); + TestObject *object2 = new TestObject(*object); + + delete object; + delete object2; +} + +test_t clonable_object_tests[] = { + TEST_NO_TAG("Check clonable object creation", check_clonable_object_creation) +}; + +test_suite_t clonable_object_test_suite = { + "ClonableObject", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + sizeof(clonable_object_tests) / sizeof(clonable_object_tests[0]), clonable_object_tests +}; diff --git a/tester/complex_sip_case_tester.c b/tester/complex_sip_case_tester.c index 93323dfbf..fc2ad0c43 100644 --- a/tester/complex_sip_case_tester.c +++ b/tester/complex_sip_case_tester.c @@ -20,7 +20,7 @@ #include "linphone/core.h" #include "liblinphone_tester.h" #include "linphone/lpconfig.h" -#include "private.h" +#include "tester_utils.h" #if HAVE_SIPP @@ -39,7 +39,7 @@ void check_rtcp(LinphoneCall *call) { } linphone_call_stats_unref(audio_stats); if (video_stats) linphone_call_stats_unref(video_stats); - wait_for_until(call->core, NULL, NULL, 0, 20); /*just to sleep while iterating*/ + wait_for_until(linphone_call_get_core(call), NULL, NULL, 0, 20); /*just to sleep while iterating*/ } while (!liblinphone_tester_clock_elapsed(&ts, 15000)); audio_stats = linphone_call_get_audio_stats(call); @@ -103,14 +103,14 @@ LinphoneAddress * linphone_core_manager_resolve(LinphoneCoreManager *mgr, const int err; int port = linphone_address_get_port(source); LinphoneAddress * dest; - - sal_resolve_a( mgr->lc->sal + + sal_resolve_a(linphone_core_get_sal(mgr->lc) ,linphone_address_get_domain(source) ,linphone_address_get_port(source) ,AF_INET ,dest_server_server_resolved ,&addrinfo); - + dest=linphone_address_new(NULL); wait_for_until(mgr->lc, mgr->lc, (int*)&addrinfo, 1,2000); @@ -121,7 +121,7 @@ LinphoneAddress * linphone_core_manager_resolve(LinphoneCoreManager *mgr, const linphone_address_set_domain(dest, ipstring); if (port > 0) linphone_address_set_port(dest, port); - + return dest; } @@ -181,9 +181,9 @@ static void call_with_audio_mline_before_video_in_sdp(void) { if (call) { linphone_call_accept(call); BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1)); - BC_ASSERT_EQUAL(call->main_audio_stream_index, 0, int, "%d"); - BC_ASSERT_EQUAL(call->main_video_stream_index, 1, int, "%d"); - BC_ASSERT_TRUE(call->main_text_stream_index > 1); + BC_ASSERT_EQUAL(_linphone_call_get_main_audio_stream_index(call), 0, int, "%d"); + BC_ASSERT_EQUAL(_linphone_call_get_main_video_stream_index(call), 1, int, "%d"); + BC_ASSERT_TRUE(_linphone_call_get_main_text_stream_index(call) > 1); BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call))); check_rtcp(call); @@ -222,9 +222,9 @@ static void call_with_video_mline_before_audio_in_sdp(void) { if (call) { linphone_call_accept(call); BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1)); - BC_ASSERT_EQUAL(call->main_audio_stream_index, 1, int, "%d"); - BC_ASSERT_EQUAL(call->main_video_stream_index, 0, int, "%d"); - BC_ASSERT_TRUE(call->main_text_stream_index > 1); + BC_ASSERT_EQUAL(_linphone_call_get_main_audio_stream_index(call), 1, int, "%d"); + BC_ASSERT_EQUAL(_linphone_call_get_main_video_stream_index(call), 0, int, "%d"); + BC_ASSERT_TRUE(_linphone_call_get_main_text_stream_index(call) > 1); BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call))); check_rtcp(call); @@ -263,9 +263,9 @@ static void call_with_multiple_audio_mline_in_sdp(void) { if (call) { linphone_call_accept(call); BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1)); - BC_ASSERT_EQUAL(call->main_audio_stream_index, 0, int, "%d"); - BC_ASSERT_EQUAL(call->main_video_stream_index, 2, int, "%d"); - BC_ASSERT_TRUE(call->main_text_stream_index > 2); + BC_ASSERT_EQUAL(_linphone_call_get_main_audio_stream_index(call), 0, int, "%d"); + BC_ASSERT_EQUAL(_linphone_call_get_main_video_stream_index(call), 2, int, "%d"); + BC_ASSERT_TRUE(_linphone_call_get_main_text_stream_index(call) > 2); BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call))); check_rtcp(call); @@ -304,9 +304,9 @@ static void call_with_multiple_video_mline_in_sdp(void) { if (call) { linphone_call_accept(call); BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1)); - BC_ASSERT_EQUAL(call->main_audio_stream_index, 0, int, "%d"); - BC_ASSERT_EQUAL(call->main_video_stream_index, 1, int, "%d"); - BC_ASSERT_TRUE(call->main_text_stream_index > 3); + BC_ASSERT_EQUAL(_linphone_call_get_main_audio_stream_index(call), 0, int, "%d"); + BC_ASSERT_EQUAL(_linphone_call_get_main_video_stream_index(call), 1, int, "%d"); + BC_ASSERT_TRUE(_linphone_call_get_main_text_stream_index(call) > 3); BC_ASSERT_TRUE(linphone_call_log_video_enabled(linphone_call_get_call_log(call))); check_rtcp(call); diff --git a/tester/conference-event-tester.cpp b/tester/conference-event-tester.cpp new file mode 100644 index 000000000..42b341d4a --- /dev/null +++ b/tester/conference-event-tester.cpp @@ -0,0 +1,1364 @@ +/* + * conference-event-tester.cpp + * Copyright (C) 2017 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include + +#include "address/identity-address.h" +#include "conference/conference-listener.h" +#include "conference/handlers/local-conference-event-handler-p.h" +#include "conference/handlers/remote-conference-event-handler-p.h" +#include "conference/local-conference-p.h" +#include "conference/local-conference.h" +#include "conference/participant-p.h" +#include "conference/remote-conference.h" +#include "liblinphone_tester.h" +#include "linphone/core.h" +#include "private.h" +#include "tester_utils.h" +#include "tools/private-access.h" +#include "tools/tester.h" + +using namespace LinphonePrivate; +using namespace std; + +static const char *first_notify = \ +" "\ +" "\ +" "\ +" "\ +" Agenda: This month's goals"\ +" "\ +" "\ +" http://sharepoint/salesgroup/"\ +" web-page"\ +" "\ +" "\ +" "\ +" "\ +" "\ +" 33"\ +" "\ +" "\ +" "\ +" "\ +" Bob Hoskins"\ +" "\ +" "\ +" Bob's Laptop"\ +" disconnected"\ +" departed"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" bad voice quality"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 432424"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" "\ +" "\ +" Alice"\ +" "\ +" admin"\ +" participant"\ +" "\ +" "\ +" "\ +" connected"\ +" dialed-out"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 534232"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" connected"\ +" dialed-out"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 534232"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" "\ +" "; + +static const char *participant_added_notify = \ +" "\ +" "\ +" "\ +" "\ +" Agenda: This month's goals"\ +" "\ +" "\ +" http://sharepoint/salesgroup/"\ +" web-page"\ +" "\ +" "\ +" "\ +" "\ +" "\ +" 33"\ +" "\ +" "\ +" "\ +" "\ +" Bob Hoskins"\ +" "\ +" "\ +" Frank's Laptop"\ +" disconnected"\ +" departed"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" bad voice quality"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 432424"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" "\ +" "; + +static const char *participant_not_added_notify = \ +" "\ +" "\ +" "\ +" "\ +" Agenda: This month's goals"\ +" "\ +" "\ +" http://sharepoint/salesgroup/"\ +" web-page"\ +" "\ +" "\ +" "\ +" "\ +" "\ +" 33"\ +" "\ +" "\ +" "\ +" "\ +" Bob Hoskins"\ +" "\ +" "\ +" Frank's Laptop"\ +" disconnected"\ +" departed"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" bad voice quality"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 432424"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" "\ +" "; + +static const char *participant_deleted_notify = \ +" "\ +" "\ +" "\ +" "\ +" Agenda: This month's goals"\ +" "\ +" "\ +" http://sharepoint/salesgroup/"\ +" web-page"\ +" "\ +" "\ +" "\ +" "\ +" "\ +" 33"\ +" "\ +" "\ +" "\ +" "\ +" Bob Hoskins"\ +" "\ +" "\ +" Bob's Laptop"\ +" disconnected"\ +" departed"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" bad voice quality"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 432424"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" "\ +" "; + +static const char *participant_admined_notify = \ +" "\ +" "\ +" "\ +" "\ +" Agenda: This month's goals"\ +" "\ +" "\ +" http://sharepoint/salesgroup/"\ +" web-page"\ +" "\ +" "\ +" "\ +" "\ +" "\ +" 33"\ +" "\ +" "\ +" "\ +" "\ +" Bob Hoskins"\ +" "\ +" participant"\ +" admin"\ +" "\ +" "\ +" "\ +" Bob's Laptop"\ +" disconnected"\ +" departed"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" bad voice quality"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 432424"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" "\ +" "; + +static const char *participant_unadmined_notify = \ +" "\ +" "\ +" "\ +" "\ +" Agenda: This month's goals"\ +" "\ +" "\ +" http://sharepoint/salesgroup/"\ +" web-page"\ +" "\ +" "\ +" "\ +" "\ +" "\ +" 33"\ +" "\ +" "\ +" "\ +" "\ +" Alice Hoskins"\ +" "\ +" participant"\ +" "\ +" "\ +" "\ +" Alice's Laptop"\ +" disconnected"\ +" departed"\ +" "\ +" 2005-03-04T20:00:00Z"\ +" bad voice quality"\ +" sip:mike@example.com"\ +" "\ +" "\ +" "\ +" main audio"\ +" audio"\ +" "\ +" 432424"\ +" sendrecv"\ +" "\ +" "\ +" "\ +" "\ +" "; + +static const char *bobUri = "sip:bob@example.com"; +static const char *aliceUri = "sip:alice@example.com"; +static const char *frankUri = "sip:frank@example.com"; +static const char *confUri = "sips:conf233@example.com"; + +L_ENABLE_ATTR_ACCESS(LocalConferencePrivate, unique_ptr, eventHandler); + +class ConferenceEventTester : public RemoteConference { +public: + ConferenceEventTester (const shared_ptr &core, const Address &confAddr); + ~ConferenceEventTester (); + +private: + void onConferenceCreated (const IdentityAddress &addr) override; + void onConferenceKeywordsChanged (const vector &keywords) override; + void onConferenceTerminated (const IdentityAddress &addr) override; + void onFirstNotifyReceived (const IdentityAddress &addr) override; + void onParticipantAdded (const shared_ptr &event, bool isFullState) override; + void onParticipantRemoved (const shared_ptr &event, bool isFullState) override; + void onParticipantSetAdmin (const shared_ptr &event, bool isFullState) override; + void onSubjectChanged (const shared_ptr &event, bool isFullState) override; + void onParticipantDeviceAdded (const shared_ptr &event, bool isFullState) override; + void onParticipantDeviceRemoved (const shared_ptr &event, bool isFullState) override; + +public: + RemoteConferenceEventHandler *handler; + map participants; + map participantDevices; + string confSubject; + bool oneToOne = false; +}; + +ConferenceEventTester::ConferenceEventTester (const shared_ptr &core, const Address &confAddr) + : RemoteConference(core, confAddr, nullptr) { + handler = new RemoteConferenceEventHandler(this); +} + +ConferenceEventTester::~ConferenceEventTester () { + delete handler; +} + +void ConferenceEventTester::onConferenceCreated (const IdentityAddress &addr) {} + +void ConferenceEventTester::onConferenceKeywordsChanged (const vector &keywords) { + for (const auto &k : keywords) { + if (k == "one-to-one") + oneToOne = true; + } +} + +void ConferenceEventTester::onConferenceTerminated (const IdentityAddress &addr) {} + +void ConferenceEventTester::onFirstNotifyReceived (const IdentityAddress &addr) {} + +void ConferenceEventTester::onParticipantAdded (const shared_ptr &event, bool isFullState) { + (void)isFullState; // unused + const IdentityAddress addr = event->getParticipantAddress(); + participants.insert({ addr.asString(), false }); + participantDevices.insert({ addr.asString(), 0 }); +} + +void ConferenceEventTester::onParticipantRemoved (const shared_ptr &event, bool isFullState) { + (void)isFullState; // unused + const IdentityAddress addr = event->getParticipantAddress(); + participants.erase(addr.asString()); + participantDevices.erase(addr.asString()); +} + +void ConferenceEventTester::onParticipantSetAdmin (const shared_ptr &event, bool isFullState) { + (void)isFullState; // unused + const IdentityAddress addr = event->getParticipantAddress(); + auto it = participants.find(addr.asString()); + if (it != participants.end()) + it->second = (event->getType() == EventLog::Type::ConferenceParticipantSetAdmin); +} + +void ConferenceEventTester::onSubjectChanged(const shared_ptr &event, bool isFullState) { + (void)isFullState; // unused + confSubject = event->getSubject(); +} + +void ConferenceEventTester::onParticipantDeviceAdded (const shared_ptr &event, bool isFullState) { + (void)isFullState; // unused + const IdentityAddress addr = event->getParticipantAddress(); + auto it = participantDevices.find(addr.asString()); + if (it != participantDevices.end()) + it->second++; + +} + +void ConferenceEventTester::onParticipantDeviceRemoved (const shared_ptr &event, bool isFullState) { + (void)isFullState; // unused + const IdentityAddress addr = event->getParticipantAddress(); + auto it = participantDevices.find(addr.asString()); + if (it != participantDevices.end() && it->second > 0) + it->second--; +} + +void first_notify_parsing() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri); + char *confAddressStr = linphone_address_as_string(confAddress); + Address addr(confAddressStr); + bctbx_free(confAddressStr); + linphone_address_unref(confAddress); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri); + LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + size_t size = strlen(first_notify) + strlen(confUri); + char *notify = new char[size]; + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + + snprintf(notify, size, first_notify, confUri); + tester->handler->notifyReceived(notify); + + delete[] notify; + + BC_ASSERT_STRING_EQUAL(tester->confSubject.c_str(), "Agenda: This month's goals"); + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(bobAddr))->second); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr))->second); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(linphone_address_as_string(bobAddr)) != tester->participantDevices.end()); + BC_ASSERT_TRUE(tester->participantDevices.find(linphone_address_as_string(aliceAddr)) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(linphone_address_as_string(bobAddr))->second, 1, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.find(linphone_address_as_string(aliceAddr))->second, 2, int, "%d"); + + linphone_address_unref(bobAddr); + linphone_address_unref(aliceAddr); + tester = nullptr; + linphone_core_manager_destroy(marie); +} + +void first_notify_parsing_wrong_conf() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, "sips:conf322@example.com"); + char *confAddressStr = linphone_address_as_string(confAddress); + Address addr(confAddressStr); + bctbx_free(confAddressStr); + linphone_address_unref(confAddress); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri); + LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + size_t size = strlen(first_notify) + strlen(confUri); + char *notify = new char[size]; + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + snprintf(notify, size, first_notify, confUri); + tester->handler->notifyReceived(notify); + + delete[] notify; + + BC_ASSERT_EQUAL(tester->participants.size(), 0, int, "%d"); + BC_ASSERT_FALSE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_FALSE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + + linphone_address_unref(bobAddr); + linphone_address_unref(aliceAddr); + tester = nullptr; + linphone_core_manager_destroy(marie); +} + +void participant_added_parsing() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri); + char *confAddressStr = linphone_address_as_string(confAddress); + Address addr(confAddressStr); + bctbx_free(confAddressStr); + linphone_address_unref(confAddress); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri); + LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + LinphoneAddress *frankAddr = linphone_core_interpret_url(marie->lc, frankUri); + size_t size = strlen(first_notify) + strlen(confUri); + char *notify = new char[size]; + size_t size2 = strlen(participant_added_notify) + strlen(confUri); + char *notify_added = new char[size2]; + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + snprintf(notify, size, first_notify, confUri); + tester->handler->notifyReceived(notify); + + delete[] notify; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(bobAddr))->second); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr))->second); + + snprintf(notify_added, size2, participant_added_notify, confUri); + tester->handler->notifyReceived(notify_added); + + delete[] notify_added; + + BC_ASSERT_EQUAL(tester->participants.size(), 3, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 3, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(frankAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(frankAddr))->second); + + linphone_address_unref(bobAddr); + linphone_address_unref(aliceAddr); + linphone_address_unref(frankAddr); + tester = nullptr; + linphone_core_manager_destroy(marie); +} + +void participant_not_added_parsing() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri); + char *confAddressStr = linphone_address_as_string(confAddress); + Address addr(confAddressStr); + bctbx_free(confAddressStr); + linphone_address_unref(confAddress); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri); + LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + LinphoneAddress *frankAddr = linphone_core_interpret_url(marie->lc, frankUri); + size_t size = strlen(first_notify) + strlen(confUri); + char *notify = new char[size]; + size_t size2 = strlen(participant_not_added_notify) + strlen(confUri); + char *notify_not_added = new char[size2]; + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + snprintf(notify, size, first_notify, confUri); + tester->handler->notifyReceived(notify); + + delete[] notify; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(bobAddr))->second); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr))->second); + + snprintf(notify_not_added, size2, participant_not_added_notify, confUri); + tester->handler->notifyReceived(notify_not_added); + + delete[] notify_not_added; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_FALSE(tester->participants.find(linphone_address_as_string(frankAddr)) != tester->participants.end()); + + linphone_address_unref(bobAddr); + linphone_address_unref(aliceAddr); + linphone_address_unref(frankAddr); + tester = nullptr; + linphone_core_manager_destroy(marie); +} + +void participant_deleted_parsing() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri); + char *confAddressStr = linphone_address_as_string(confAddress); + Address addr(confAddressStr); + bctbx_free(confAddressStr); + linphone_address_unref(confAddress); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri); + LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + size_t size = strlen(first_notify) + strlen(confUri); + char *notify = new char[size]; + size_t size2 = strlen(participant_deleted_notify) + strlen(confUri); + char *notify_deleted = new char[size2]; + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + snprintf(notify, size, first_notify, confUri); + tester->handler->notifyReceived(notify); + + delete[] notify; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(bobAddr))->second); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr))->second); + + snprintf(notify_deleted, size2, participant_deleted_notify, confUri); + tester->handler->notifyReceived(notify_deleted); + + delete[] notify_deleted; + + BC_ASSERT_EQUAL(tester->participants.size(), 1, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 1, int, "%d"); + BC_ASSERT_FALSE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + + linphone_address_unref(bobAddr); + linphone_address_unref(aliceAddr); + tester = nullptr; + linphone_core_manager_destroy(marie); +} + +void participant_admined_parsing() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri); + char *confAddressStr = linphone_address_as_string(confAddress); + Address addr(confAddressStr); + bctbx_free(confAddressStr); + linphone_address_unref(confAddress); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri); + LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + size_t size = strlen(first_notify) + strlen(confUri); + char *notify = new char[size]; + size_t size2 = strlen(participant_admined_notify) + strlen(confUri); + char *notify_admined = new char[size2]; + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + snprintf(notify, size, first_notify, confUri); + tester->handler->notifyReceived(notify); + + delete[] notify; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(bobAddr))->second); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr))->second); + + snprintf(notify_admined, size2, participant_admined_notify, confUri); + tester->handler->notifyReceived(notify_admined); + + delete[] notify_admined; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr))->second); + + linphone_address_unref(bobAddr); + linphone_address_unref(aliceAddr); + tester = nullptr; + linphone_core_manager_destroy(marie); +} + +void participant_unadmined_parsing() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneAddress *confAddress = linphone_core_interpret_url(marie->lc, confUri); + char *confAddressStr = linphone_address_as_string(confAddress); + Address addr(confAddressStr); + bctbx_free(confAddressStr); + linphone_address_unref(confAddress); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + LinphoneAddress *bobAddr = linphone_core_interpret_url(marie->lc, bobUri); + LinphoneAddress *aliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + size_t size = strlen(first_notify) + strlen(confUri); + char *notify = new char[size]; + size_t size2 = strlen(participant_unadmined_notify) + strlen(confUri); + char *notify_unadmined = new char[size2]; + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + snprintf(notify, size, first_notify, confUri); + tester->handler->notifyReceived(notify); + + delete[] notify; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(bobAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(bobAddr))->second); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr))->second); + + snprintf(notify_unadmined, size2, participant_unadmined_notify, confUri); + tester->handler->notifyReceived(notify_unadmined); + + delete[] notify_unadmined; + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(linphone_address_as_string(aliceAddr)) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(linphone_address_as_string(aliceAddr))->second); + + linphone_address_unref(bobAddr); + linphone_address_unref(aliceAddr); + tester = nullptr; + linphone_core_manager_destroy(marie); +} + +void send_first_notify() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + localConf->setSubject("A random test subject"); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_STRING_EQUAL(tester->confSubject.c_str(), "A random test subject"); + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void send_added_notify() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + LinphoneAddress *cFrankAddr = linphone_core_interpret_url(marie->lc, frankUri); + char *frankAddrStr = linphone_address_as_string(cFrankAddr); + Address frankAddr(frankAddrStr); + bctbx_free(frankAddrStr); + linphone_address_unref(cFrankAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantAdded(frankAddr); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 3, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 3, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(frankAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + BC_ASSERT_TRUE(!tester->participants.find(frankAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void send_removed_notify() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantRemoved(bobAddr); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 1, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.size(), 1, int, "%d"); + BC_ASSERT_FALSE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void send_admined_notify() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantAdminStatusChanged(bobAddr, true); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void send_unadmined_notify() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantAdminStatusChanged(aliceAddr, false); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(aliceAddr.asString())->second); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void send_subject_changed_notify () { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + localConf->setSubject("A random test subject"); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_STRING_EQUAL(tester->confSubject.c_str(), "A random test subject"); + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_EQUAL(tester->handler->getLastNotify(), 1, int, "%d"); + BC_ASSERT_EQUAL(localHandlerPrivate->getLastNotify(), 1, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + localConf->setSubject("Another random test subject..."); + notify = localHandlerPrivate->createNotifySubjectChanged(); + tester->handler->notifyReceived(notify); + + BC_ASSERT_STRING_EQUAL(tester->confSubject.c_str(), "Another random test subject..."); + BC_ASSERT_EQUAL(tester->participants.size(), 2, int, "%d"); + BC_ASSERT_EQUAL(tester->handler->getLastNotify(), 2, int, "%d"); + BC_ASSERT_EQUAL(localHandlerPrivate->getLastNotify(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participants.find(bobAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString()) != tester->participants.end()); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void send_device_added_notify() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantDeviceAdded(aliceAddr, aliceAddr); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddr.asString())->second, 1, int, "%d"); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void send_device_removed_notify() { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + LinphoneAddress *cAliceAddr = linphone_core_interpret_url(marie->lc, aliceUri); + char *aliceAddrStr = linphone_address_as_string(cAliceAddr); + Address aliceAddr(aliceAddrStr); + bctbx_free(aliceAddrStr); + linphone_address_unref(cAliceAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + localConf->addParticipant(aliceAddr, ¶ms, false); + localConf->setSubject("A random test subject"); + shared_ptr alice = localConf->findParticipant(aliceAddr); + L_GET_PRIVATE(alice)->setAdmin(true); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantDeviceAdded(aliceAddr, aliceAddr); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddr.asString())->second, 1, int, "%d"); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantDeviceRemoved(aliceAddr, aliceAddr); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + notify = localHandlerPrivate->createNotifyParticipantDeviceRemoved(aliceAddr, aliceAddr); + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participantDevices.size(), 2, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_TRUE(tester->participantDevices.find(aliceAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_EQUAL(tester->participantDevices.find(aliceAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_TRUE(!tester->participants.find(bobAddr.asString())->second); + BC_ASSERT_TRUE(tester->participants.find(aliceAddr.asString())->second); + + tester = nullptr; + localConf = nullptr; + alice = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +void one_to_one_keyword () { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + char *identityStr = linphone_address_as_string(pauline->identity); + Address addr(identityStr); + bctbx_free(identityStr); + shared_ptr tester = make_shared(marie->lc->cppPtr, addr); + shared_ptr localConf = make_shared(pauline->lc->cppPtr, addr, nullptr); + LinphoneAddress *cBobAddr = linphone_core_interpret_url(marie->lc, bobUri); + char *bobAddrStr = linphone_address_as_string(cBobAddr); + Address bobAddr(bobAddrStr); + bctbx_free(bobAddrStr); + linphone_address_unref(cBobAddr); + + CallSessionParams params; + localConf->addParticipant(bobAddr, ¶ms, false); + LocalConferenceEventHandlerPrivate *localHandlerPrivate = L_GET_PRIVATE( + L_ATTR_GET(L_GET_PRIVATE(localConf), eventHandler) + ); + const_cast(localConf->getConferenceAddress()) = addr; + string notify = localHandlerPrivate->createNotifyFullState(-1, true); + + const_cast(tester->handler->getChatRoomId().getPeerAddress()) = addr; + tester->handler->notifyReceived(notify); + + BC_ASSERT_EQUAL(tester->participantDevices.size(), 1, int, "%d"); + BC_ASSERT_TRUE(tester->participantDevices.find(bobAddr.asString()) != tester->participantDevices.end()); + BC_ASSERT_EQUAL(tester->participantDevices.find(bobAddr.asString())->second, 0, int, "%d"); + BC_ASSERT_TRUE(tester->oneToOne); + + tester = nullptr; + localConf = nullptr; + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +test_t conference_event_tests[] = { + TEST_NO_TAG("First notify parsing", first_notify_parsing), + TEST_NO_TAG("First notify parsing wrong conf", first_notify_parsing_wrong_conf), + TEST_NO_TAG("Participant added", participant_added_parsing), + TEST_NO_TAG("Participant not added", participant_not_added_parsing), + TEST_NO_TAG("Participant deleted", participant_deleted_parsing), + TEST_NO_TAG("Participant admined", participant_admined_parsing), + TEST_NO_TAG("Participant unadmined", participant_unadmined_parsing), + TEST_NO_TAG("Send first notify", send_first_notify), + TEST_NO_TAG("Send participant added notify", send_added_notify), + TEST_NO_TAG("Send participant removed notify", send_removed_notify), + TEST_NO_TAG("Send participant admined notify", send_admined_notify), + TEST_NO_TAG("Send participant unadmined notify", send_unadmined_notify), + TEST_NO_TAG("Send subject changed notify", send_subject_changed_notify), + TEST_NO_TAG("Send device added notify", send_device_added_notify), + TEST_NO_TAG("Send device removed notify", send_device_removed_notify), + TEST_NO_TAG("one-to-one keyword", one_to_one_keyword) +}; + +test_suite_t conference_event_test_suite = { + "Conference event", + nullptr, + nullptr, + liblinphone_tester_before_each, + liblinphone_tester_after_each, + sizeof(conference_event_tests) / sizeof(conference_event_tests[0]), conference_event_tests +}; diff --git a/tester/contents-tester.cpp b/tester/contents-tester.cpp new file mode 100644 index 000000000..99ecee08d --- /dev/null +++ b/tester/contents-tester.cpp @@ -0,0 +1,435 @@ +/* + * conference-event-tester.cpp + * Copyright (C) 2017 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include + +#include "content/content-manager.h" +#include "content/content-type.h" +#include "content/content.h" +#include "content/header/header-param.h" +#include "liblinphone_tester.h" +#include "tester_utils.h" +#include "logger/logger.h" + +using namespace LinphonePrivate; +using namespace std; + +static const char* source_multipart = \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+YYYYYYYYYY@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Encoding: b64\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+XXXXXXXXXX@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Id: toto;param1=value1;param2;param3=value3\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:someone@sip.linphone.org" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449--\r\n"; + +static const char* generated_multipart = \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/rlmi+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:582\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:561\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+YYYYYYYYYY@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Encoding:b64\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:561\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+XXXXXXXXXX@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449\r\n" \ +"Content-Id:toto;param1=value1;param2;param3=value3\r\n" \ +"Content-Type: application/pidf+xml;charset=\"UTF-8\"\r\n" \ +"Content-Length:546\r\n\r\n" \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:someone@sip.linphone.org" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" \ +"-----------------------------14737809831466499882746641449--\r\n"; + +static const char* part1 = \ +"" \ +"" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +""; + +static const char* part2 = \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+YYYYYYYYYY@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +"" ; + +static const char* part3 = \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:+XXXXXXXXXX@sip.linphone.org;user=phone" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +""; + +static const char* part4 = \ +"" \ +"" \ +" " \ +" " \ +" open" \ +" " \ +" sip:someone@sip.linphone.org" \ +" 2017-10-25T13:18:26" \ +" " \ +" " \ +" " \ +" " \ +" " \ +" " \ +""; + +void multipart_to_list () { + Content multipartContent; + multipartContent.setBody(source_multipart); + multipartContent.setContentType(ContentType("multipart", "related")); + + list contents = ContentManager::multipartToContentList(multipartContent); + BC_ASSERT_EQUAL(contents.size(), 4, int, "%d"); + Content content1 = contents.front(); + contents.pop_front(); + string originalStr1(part1); + originalStr1.erase(std::remove(originalStr1.begin(), originalStr1.end(), ' '), originalStr1.end()); + originalStr1.erase(std::remove(originalStr1.begin(), originalStr1.end(), '\t'), originalStr1.end()); + originalStr1.erase(std::remove(originalStr1.begin(), originalStr1.end(), '\r'), originalStr1.end()); + originalStr1.erase(std::remove(originalStr1.begin(), originalStr1.end(), '\n'), originalStr1.end()); + string generatedStr1 = content1.getBodyAsString(); + generatedStr1.erase(std::remove(generatedStr1.begin(), generatedStr1.end(), ' '), generatedStr1.end()); + generatedStr1.erase(std::remove(generatedStr1.begin(), generatedStr1.end(), '\t'), generatedStr1.end()); + generatedStr1.erase(std::remove(generatedStr1.begin(), generatedStr1.end(), '\r'), generatedStr1.end()); + generatedStr1.erase(std::remove(generatedStr1.begin(), generatedStr1.end(), '\n'), generatedStr1.end()); + ms_message("\n\n----- Generated part 1 -----"); + ms_message("%s", generatedStr1.c_str()); + ms_message("\n\n----- Original part 1 -----"); + ms_message("%s", originalStr1.c_str()); + BC_ASSERT_TRUE(originalStr1 == generatedStr1); + + Content content2 = contents.front(); + contents.pop_front(); + string originalStr2(part2); + originalStr2.erase(std::remove(originalStr2.begin(), originalStr2.end(), ' '), originalStr2.end()); + originalStr2.erase(std::remove(originalStr2.begin(), originalStr2.end(), '\t'), originalStr2.end()); + originalStr2.erase(std::remove(originalStr2.begin(), originalStr2.end(), '\r'), originalStr2.end()); + originalStr2.erase(std::remove(originalStr2.begin(), originalStr2.end(), '\n'), originalStr2.end()); + string generatedStr2 = content2.getBodyAsString(); + generatedStr2.erase(std::remove(generatedStr2.begin(), generatedStr2.end(), ' '), generatedStr2.end()); + generatedStr2.erase(std::remove(generatedStr2.begin(), generatedStr2.end(), '\t'), generatedStr2.end()); + generatedStr2.erase(std::remove(generatedStr2.begin(), generatedStr2.end(), '\r'), generatedStr2.end()); + generatedStr2.erase(std::remove(generatedStr2.begin(), generatedStr2.end(), '\n'), generatedStr2.end()); + ms_message("\n\n----- Generated part 2 -----"); + ms_message("%s", generatedStr2.c_str()); + ms_message("\n\n----- Original part 2 -----"); + ms_message("%s", originalStr2.c_str()); + BC_ASSERT_TRUE(originalStr2 == generatedStr2); + + Content content3 = contents.front(); + contents.pop_front(); + string originalStr3(part3); + originalStr3.erase(std::remove(originalStr3.begin(), originalStr3.end(), ' '), originalStr3.end()); + originalStr3.erase(std::remove(originalStr3.begin(), originalStr3.end(), '\t'), originalStr3.end()); + originalStr3.erase(std::remove(originalStr3.begin(), originalStr3.end(), '\r'), originalStr3.end()); + originalStr3.erase(std::remove(originalStr3.begin(), originalStr3.end(), '\n'), originalStr3.end()); + string generatedStr3 = content3.getBodyAsString(); + generatedStr3.erase(std::remove(generatedStr3.begin(), generatedStr3.end(), ' '), generatedStr3.end()); + generatedStr3.erase(std::remove(generatedStr3.begin(), generatedStr3.end(), '\t'), generatedStr3.end()); + generatedStr3.erase(std::remove(generatedStr3.begin(), generatedStr3.end(), '\r'), generatedStr3.end()); + generatedStr3.erase(std::remove(generatedStr3.begin(), generatedStr3.end(), '\n'), generatedStr3.end()); + ms_message("\n\n----- Generated part 3 -----"); + ms_message("%s", generatedStr3.c_str()); + ms_message("\n\n----- Original part 3 -----"); + ms_message("%s", originalStr3.c_str()); + BC_ASSERT_TRUE(originalStr3 == generatedStr3); + BC_ASSERT_TRUE(content3.getHeader("Content-Encoding").getValue() == "b64"); + + Content content4 = contents.front(); + contents.pop_front(); + string originalStr4(part4); + originalStr4.erase(std::remove(originalStr4.begin(), originalStr4.end(), ' '), originalStr4.end()); + originalStr4.erase(std::remove(originalStr4.begin(), originalStr4.end(), '\t'), originalStr4.end()); + originalStr4.erase(std::remove(originalStr4.begin(), originalStr4.end(), '\r'), originalStr4.end()); + originalStr4.erase(std::remove(originalStr4.begin(), originalStr4.end(), '\n'), originalStr4.end()); + string generatedStr4 = content4.getBodyAsString(); + generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), ' '), generatedStr4.end()); + generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\t'), generatedStr4.end()); + generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\r'), generatedStr4.end()); + generatedStr4.erase(std::remove(generatedStr4.begin(), generatedStr4.end(), '\n'), generatedStr4.end()); + ms_message("\n\n----- Generated part 4 -----"); + ms_message("%s", generatedStr4.c_str()); + ms_message("\n\n----- Original part 4 -----"); + ms_message("%s", originalStr4.c_str()); + BC_ASSERT_TRUE(originalStr4 == generatedStr4); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getValue() == "toto"); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param1").getValue() == "value1"); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param2").getValue().empty()); + BC_ASSERT_TRUE(content4.getHeader("Content-Id").getParameter("param3").getValue() == "value3"); +} + +void list_to_multipart () { + ContentType contentType = ContentType("application", "rlmi+xml"); + contentType.addParameter("charset", "\"UTF-8\""); + Content content1; + content1.setBody(part1); + content1.setContentType(contentType); + contentType = ContentType("application", "pidf+xml"); + contentType.addParameter("charset", "\"UTF-8\""); + Content content2; + content2.setBody(part2); + content2.setContentType(contentType); + Content content3; + content3.setBody(part3); + content3.addHeader("Content-Encoding", "b64"); + content3.setContentType(contentType); + Content content4; + Header header = Header("Content-Id", "toto"); + header.addParameter("param1", "value1"); + header.addParameter("param2", ""); + header.addParameter("param3", "value3"); + content4.addHeader(header); + content4.setBody(part4); + content4.setContentType(contentType); + list contents = {&content1, &content2, &content3, &content4}; + + Content multipartContent = ContentManager::contentListToMultipart(contents); + string originalStr(generated_multipart); + originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), ' '), originalStr.end()); + originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\t'), originalStr.end()); + originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\r'), originalStr.end()); + originalStr.erase(std::remove(originalStr.begin(), originalStr.end(), '\n'), originalStr.end()); + + string generatedStr = multipartContent.getBodyAsString(); + generatedStr.erase(std::remove(generatedStr.begin(), generatedStr.end(), ' '), generatedStr.end()); + generatedStr.erase(std::remove(generatedStr.begin(), generatedStr.end(), '\t'), generatedStr.end()); + generatedStr.erase(std::remove(generatedStr.begin(), generatedStr.end(), '\r'), generatedStr.end()); + generatedStr.erase(std::remove(generatedStr.begin(), generatedStr.end(), '\n'), generatedStr.end()); + + ms_message("\n\n----- Generated multipart -----"); + ms_message("%s", generatedStr.c_str()); + + ms_message("\n\n----- Original multipart -----"); + ms_message("%s", originalStr.c_str()); + BC_ASSERT_TRUE(originalStr == generatedStr); +} + +static void content_type_parsing(void) { + string type = "message/external-body;access-type=URL;URL=\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\""; + ContentType contentType = ContentType(type); + BC_ASSERT_STRING_EQUAL("message", contentType.getType().c_str()); + BC_ASSERT_STRING_EQUAL("external-body", contentType.getSubType().c_str()); + BC_ASSERT_STRING_EQUAL("URL", contentType.getParameter("access-type").getValue().c_str()); + BC_ASSERT_STRING_EQUAL("\"https://www.linphone.org/img/linphone-open-source-voip-projectX2.png\"", contentType.getParameter("URL").getValue().c_str()); + BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); + BC_ASSERT_EQUAL(2, contentType.getParameters().size(), int, "%d"); + lInfo() << "Content-Type is " << contentType; + BC_ASSERT_TRUE(type == contentType.asString()); + + type = "multipart/mixed;boundary=-----------------------------14737809831466499882746641450"; + contentType = ContentType(type); + BC_ASSERT_STRING_EQUAL("multipart", contentType.getType().c_str()); + BC_ASSERT_STRING_EQUAL("mixed", contentType.getSubType().c_str()); + BC_ASSERT_STRING_EQUAL("-----------------------------14737809831466499882746641450", contentType.getParameter("boundary").getValue().c_str()); + BC_ASSERT_STRING_EQUAL("", contentType.getParameter("access-type").getValue().c_str()); + BC_ASSERT_EQUAL(1, contentType.getParameters().size(), int, "%d"); + lInfo() << "Content-Type is " << contentType; + BC_ASSERT_TRUE(type == contentType.asString()); + + type = "plain/text"; + contentType = ContentType(type); + BC_ASSERT_STRING_EQUAL("plain", contentType.getType().c_str()); + BC_ASSERT_STRING_EQUAL("text", contentType.getSubType().c_str()); + BC_ASSERT_STRING_EQUAL("", contentType.getParameter("boundary").getValue().c_str()); + BC_ASSERT_EQUAL(0, contentType.getParameters().size(), int, "%d"); + lInfo() << "Content-Type is " << contentType; + BC_ASSERT_TRUE(type == contentType.asString()); +} + +static void content_header_parsing(void) { + string value = "toto;param1=value1;param2;param3=value3"; + Header header = Header("Content-Id", value); + BC_ASSERT_TRUE(header.getValue() == "toto"); + BC_ASSERT_TRUE(header.getParameter("param1").getValue() == "value1"); + BC_ASSERT_TRUE(header.getParameter("param2").getValue().empty()); + BC_ASSERT_TRUE(header.getParameter("param3").getValue() == "value3"); + BC_ASSERT_EQUAL(3, header.getParameters().size(), int, "%d"); + BC_ASSERT_STRING_EQUAL("", header.getParameter("encoding").getValue().c_str()); + + value = "b64"; + header = Header("Content-Encoding", value); + BC_ASSERT_TRUE(header.getValue() == value); + BC_ASSERT_EQUAL(0, header.getParameters().size(), int, "%d"); + BC_ASSERT_STRING_EQUAL("", header.getParameter("access-type").getValue().c_str()); +} + +test_t contents_tests[] = { + TEST_NO_TAG("Multipart to list", multipart_to_list), + TEST_NO_TAG("List to multipart", list_to_multipart), + TEST_NO_TAG("Content type parsing", content_type_parsing), + TEST_NO_TAG("Content header parsing", content_header_parsing) +}; + +test_suite_t contents_test_suite = { + "Contents", + nullptr, + nullptr, + liblinphone_tester_before_each, + liblinphone_tester_after_each, + sizeof(contents_tests) / sizeof(contents_tests[0]), contents_tests +}; diff --git a/tester/cpim-tester.cpp b/tester/cpim-tester.cpp new file mode 100644 index 000000000..cb8007551 --- /dev/null +++ b/tester/cpim-tester.cpp @@ -0,0 +1,329 @@ +/* + * cpim-tester.cpp + * Copyright (C) 2017 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "address/address.h" +#include "chat/chat-message/chat-message.h" +#include "chat/chat-room/basic-chat-room.h" +#include "chat/cpim/cpim.h" +#include "content/content-type.h" +#include "content/content.h" +#include "core/core.h" +#include "belr/grammarbuilder.h" +// TODO: Remove me later. +#include "private.h" + +#include "liblinphone_tester.h" +#include "tester_utils.h" + +// ============================================================================= + +using namespace std; + +using namespace LinphonePrivate; + +static void parse_minimal_message () { + const string str = "Subject: the weather will be fine today\r\n" + "\r\n" + "Content-Type: text/plain; charset=utf-8\r\n" + "\r\n"; + + shared_ptr message = Cpim::Message::createFromString(str); + if (!BC_ASSERT_PTR_NOT_NULL(message)) return; + + const string str2 = message->asString(); + BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); + + const string content = message->getContent(); + BC_ASSERT_STRING_EQUAL(content.c_str(), ""); +} + +static void set_generic_header_name () { + const list > entries = { + // Reserved. + { "From", false }, + { "To", false }, + { "cc", false }, + { "DateTime", false }, + { "Subject", false }, + { "NS", false }, + { "Require", false } + }; + + for (const auto &entry : entries) { + Cpim::GenericHeader genericHeader(entry.first, ""); + + const string name = genericHeader.getName(); + BC_ASSERT_STRING_EQUAL(name.c_str(), ""); + } +} + +static void check_core_header_names () { + const list, string> > entries = { + { make_shared(), "From" }, + { make_shared(), "To" }, + { make_shared(), "cc" }, + { make_shared(), "DateTime" }, + { make_shared(), "Subject" }, + { make_shared(), "NS" }, + { make_shared(), "Require" } + }; + + for (const auto &entry : entries) { + const string name = entry.first->getName(); + BC_ASSERT_STRING_EQUAL(name.c_str(), entry.second.c_str()); + } +} + +static void parse_rfc_example () { + const string body = "" + "Here is the text of my message." + ""; + + const string str = "From: \"MR SANDERS\"\r\n" + "To: \"Depressed Donkey\"\r\n" + "DateTime: 2000-12-13T13:40:00-08:00\r\n" + "Subject: the weather will be fine today\r\n" + "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" + "NS: MyFeatures \r\n" + "Require: MyFeatures.VitalMessageOption\r\n" + "MyFeatures.VitalMessageOption: Confirmation-requested\r\n" + "MyFeatures.WackyMessageOption: Use-silly-font\r\n" + "\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Content-ID: <1234567890@foo.com>\r\n" + "\r\n" + body; + + shared_ptr message = Cpim::Message::createFromString(str); + if (!BC_ASSERT_PTR_NOT_NULL(message)) return; + + const string str2 = message->asString(); + BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); + + string content = message->getContent(); + BC_ASSERT_STRING_EQUAL(content.c_str(), body.c_str()); + + Cpim::Message::HeaderList list = message->getMessageHeaders(); + if (!BC_ASSERT_PTR_NOT_NULL(list)) return; + BC_ASSERT_EQUAL(list->size(), 7, int, "%d"); + + list = message->getMessageHeaders("MyFeatures"); + if (!BC_ASSERT_PTR_NOT_NULL(list)) return; + BC_ASSERT_EQUAL(list->size(), 2, int, "%d"); +} + +static void parse_message_with_generic_header_parameters () { + const string body = "" + "Here is the text of my message." + ""; + + const string str = "From: \"MR SANDERS\"\r\n" + "Test:;aaa=bbb;yes=no CheckMe\r\n" + "yaya: coucou\r\n" + "yepee:;good=bad ugly\r\n" + "\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Content-ID: <1234567890@foo.com>\r\n" + "\r\n" + body; + + shared_ptr message = Cpim::Message::createFromString(str); + if (!BC_ASSERT_PTR_NOT_NULL(message)) return; + + const string str2 = message->asString(); + BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); + + string content = message->getContent(); + BC_ASSERT_STRING_EQUAL(content.c_str(), body.c_str()); +} + +static void build_message () { + + Cpim::Message message; + + // Set message headers. + Cpim::FromHeader fromHeader("im:piglet@100akerwood.com", "MR SANDERS"); + + Cpim::ToHeader toHeader("im:eeyore@100akerwood.com", "Depressed Donkey"); + + // 976686000 is 2000-12-13T13:40:00-08:00 + Cpim::DateTimeHeader dateTimeHeader(976686000); + BC_ASSERT_EQUAL((int)dateTimeHeader.getTime(), 976686000, int, "%d"); + + Cpim::SubjectHeader subjectHeader("the weather will be fine today"); + + Cpim::SubjectHeader subjectWithLanguageHeader("beau temps prevu pour aujourd'hui", "fr"); + + Cpim::NsHeader nsHeader("mid:MessageFeatures@id.foo.com", "MyFeatures"); + + Cpim::RequireHeader requireHeader("MyFeatures.VitalMessageOption"); + + Cpim::GenericHeader vitalMessageHeader("MyFeatures.VitalMessageOption", "Confirmation-requested"); + + Cpim::GenericHeader wackyMessageHeader("MyFeatures.WackyMessageOption", "Use-silly-font"); + + if (!BC_ASSERT_TRUE(message.addMessageHeader(fromHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(toHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectWithLanguageHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(nsHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(requireHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(vitalMessageHeader))) return; + if (!BC_ASSERT_TRUE(message.addMessageHeader(wackyMessageHeader))) return; + + // Set Content headers. + Cpim::GenericHeader contentTypeHeader("Content-Type", "text/xml; charset=utf-8"); + if (!BC_ASSERT_TRUE(message.addContentHeader(contentTypeHeader))) return; + + Cpim::GenericHeader contentIdHeader("Content-ID", "<1234567890@foo.com>"); + if (!BC_ASSERT_TRUE(message.addContentHeader(contentIdHeader))) return; + + // Add a wrong message header and a wrong content header + Cpim::FromHeader wrongFromHeader("", ""); + if (!BC_ASSERT_FALSE(message.addMessageHeader(wrongFromHeader))) return; + + Cpim::GenericHeader wrongContentHeader("", ""); + if (!BC_ASSERT_FALSE(message.addContentHeader(wrongContentHeader))) return; + + const string content = "" + "Here is the text of my message." + ""; + + if (!BC_ASSERT_TRUE(message.setContent(content))) return; + + const string strMessage = message.asString(); + const string expectedMessage = "From: \"MR SANDERS\"\r\n" + "To: \"Depressed Donkey\"\r\n" + "DateTime: 2000-12-13T05:40:00Z\r\n" + "Subject: the weather will be fine today\r\n" + "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" + "NS: MyFeatures \r\n" + "Require: MyFeatures.VitalMessageOption\r\n" + "MyFeatures.VitalMessageOption: Confirmation-requested\r\n" + "MyFeatures.WackyMessageOption: Use-silly-font\r\n" + "\r\n" + "Content-Type: text/xml; charset=utf-8\r\n" + "Content-ID: <1234567890@foo.com>\r\n" + "\r\n" + "" + "Here is the text of my message." + ""; + + BC_ASSERT_STRING_EQUAL(strMessage.c_str(), expectedMessage.c_str()); +} + +static int fake_im_encryption_engine_process_incoming_message_cb ( + LinphoneImEncryptionEngine *engine, + LinphoneChatRoom *room, + LinphoneChatMessage *msg +) { + // Encryption is the first receiving step, so this message should be CPIM. + const string expected = ContentType::Cpim.asString(); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(msg), expected.c_str()); + return -1; +} + +static int fake_im_encryption_engine_process_outgoing_message_cb ( + LinphoneImEncryptionEngine *engine, + LinphoneChatRoom *room, + LinphoneChatMessage *msg +) { + // Encryption is the last sending step, so this message should be CPIM. + const string expected = ContentType::Cpim.asString(); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(msg), expected.c_str()); + return -1; +} + +static void cpim_chat_message_modifier_base (bool useMultipart) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + + // We use a fake encryption engine just to check the internal content type during the sending/receiving process. + LinphoneImEncryptionEngine *marie_imee = linphone_im_encryption_engine_new(); + LinphoneImEncryptionEngineCbs *marie_cbs = linphone_im_encryption_engine_get_callbacks(marie_imee); + LinphoneImEncryptionEngine *pauline_imee = linphone_im_encryption_engine_new(); + LinphoneImEncryptionEngineCbs *pauline_cbs = linphone_im_encryption_engine_get_callbacks(pauline_imee); + linphone_im_encryption_engine_cbs_set_process_outgoing_message(marie_cbs, fake_im_encryption_engine_process_outgoing_message_cb); + linphone_im_encryption_engine_cbs_set_process_incoming_message(pauline_cbs, fake_im_encryption_engine_process_incoming_message_cb); + linphone_core_set_im_encryption_engine(marie->lc, marie_imee); + linphone_core_set_im_encryption_engine(pauline->lc, pauline_imee); + + char *paulineUri = linphone_address_as_string_uri_only(pauline->identity); + IdentityAddress paulineAddress(paulineUri); + bctbx_free(paulineUri); + + shared_ptr marieRoom = marie->lc->cppPtr->getOrCreateBasicChatRoom(paulineAddress); + marieRoom->allowCpim(true); + + shared_ptr marieMessage = marieRoom->createChatMessage("Hello CPIM"); + if (useMultipart) { + marieRoom->allowMultipart(true); + Content *content = new Content(); + content->setContentType(ContentType::PlainText); + content->setBody("Hello Part 2"); + marieMessage->addContent(content); + } + marieMessage->send(); + + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); + BC_ASSERT_TRUE(marieMessage->getInternalContent().getContentType().isEmpty()); // Internal content is cleaned after message is sent or received + + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); + if (pauline->stat.last_received_chat_message != NULL) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), "Hello CPIM"); + const string expected = ContentType::PlainText.asString(); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), expected.c_str()); + } + + marieMessage.reset(); + marieRoom.reset(); + + linphone_im_encryption_engine_unref(marie_imee); + linphone_im_encryption_engine_unref(pauline_imee); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void cpim_chat_message_modifier () { + cpim_chat_message_modifier_base(FALSE); +} + +static void cpim_chat_message_modifier_with_multipart_body () { + cpim_chat_message_modifier_base(TRUE); +} + +test_t cpim_tests[] = { + TEST_NO_TAG("Parse minimal CPIM message", parse_minimal_message), + TEST_NO_TAG("Set generic header name", set_generic_header_name), + TEST_NO_TAG("Check core header names", check_core_header_names), + TEST_NO_TAG("Parse RFC example", parse_rfc_example), + TEST_NO_TAG("Parse Message with generic header parameters", parse_message_with_generic_header_parameters), + TEST_NO_TAG("Build Message", build_message), + TEST_NO_TAG("CPIM chat message modifier", cpim_chat_message_modifier), + TEST_NO_TAG("CPIM chat message modifier with multipart body", cpim_chat_message_modifier_with_multipart_body) +}; + +static int suite_begin(void) { + //Supposed to be done by platform helper, but in this case, we don't have it" + belr::GrammarLoader::get().addPath(std::string(bc_tester_get_resource_dir_prefix()).append("/share/belr/grammars")); + return 0; +} +test_suite_t cpim_test_suite = { + "Cpim", suite_begin, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + sizeof(cpim_tests) / sizeof(cpim_tests[0]), cpim_tests +}; diff --git a/tester/cpim_tester.cpp b/tester/cpim_tester.cpp deleted file mode 100644 index 27df3690c..000000000 --- a/tester/cpim_tester.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* - * liblinphone_tester - liblinphone test suite - * Copyright (C) 2017 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 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "cpim/cpim.h" - -#include "liblinphone_tester.h" - -using namespace std; - -using namespace LinphonePrivate; - -// ============================================================================= - -static void parse_minimal_message (void) { - const string str = "Content-type: Message/CPIM\r\n" - "\r\n" - "Content-Type: text/plain; charset=utf-8\r\n" - "\r\n"; - - shared_ptr message = Cpim::Message::createFromString(str); - if (!BC_ASSERT_PTR_NOT_NULL(message)) return; - - const string str2 = message->asString(); - BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); -} - -static void set_generic_header_name (void) { - const list > entries = { - { "toto", true }, - { "george.abitbol", true }, - { "tata/titi", false }, - { "hey ho", false }, - { " fail", false }, - { "fail2 ", false }, - - // Reserved. - { "From", false }, - { "To", false }, - { "cc", false }, - { "DateTime", false }, - { "Subject", false }, - { "NS", false }, - { "Require", false }, - - // Case sensitivity. - { "FROM", true }, - { "to", true }, - { "cC", true }, - { "Datetime", true }, - { "SuBject", true }, - { "nS", true }, - { "requirE", true } - }; - - for (const auto &entry : entries) { - Cpim::GenericHeader genericHeader; - - const bool result = genericHeader.setName(entry.first); - BC_ASSERT_EQUAL(result, entry.second, bool, "%d"); - - const string name = genericHeader.getName(); - - if (result) - BC_ASSERT_STRING_EQUAL(name.c_str(), entry.first.c_str()); - else - BC_ASSERT_STRING_EQUAL(name.c_str(), ""); - } -} - -static void set_generic_header_value (void) { - const list > entries = { - { "MyFeatures ", true }, - { "2000-12-13T13:40:00-08:00", true }, - { "2000-12-13T13:40:00-08:00", true }, - { "text/xml; charset=utf-8", true }, - { "text/xml; charset=ut\r\nf-8", false } - }; - - for (const auto &entry : entries) { - Cpim::GenericHeader genericHeader; - - const bool result = genericHeader.setValue(entry.first); - BC_ASSERT_EQUAL(result, entry.second, bool, "%d"); - - const string value = genericHeader.getValue(); - - if (result) - BC_ASSERT_STRING_EQUAL(value.c_str(), entry.first.c_str()); - else - BC_ASSERT_STRING_EQUAL(value.c_str(), ""); - } -} - -static void check_core_header_names (void) { - const list, string> > entries = { - { make_shared(), "From" }, - { make_shared(), "To" }, - { make_shared(), "cc" }, - { make_shared(), "DateTime" }, - { make_shared(), "Subject" }, - { make_shared(), "NS" }, - { make_shared(), "Require" } - }; - - for (const auto &entry : entries) { - const string name = entry.first->getName(); - BC_ASSERT_STRING_EQUAL(name.c_str(), entry.second.c_str()); - } -} - -static void set_core_header_values (void) { - const list, list > > > entries = { - { make_shared(), { - { "Winnie the Pooh ", true }, - { "", true }, - { "", true }, - { "toto", false } - } }, - { make_shared(), { - { "", true }, - { "toto", false }, - { "", true }, - { "", true } - } }, - { make_shared(), { - { "", true }, - { "", true }, - { "", true }, - { "toto", false } - } }, - { make_shared(), { - { "abcd", false }, - { "1985-04-12T23:20:50.52Z", true }, - { "1996-12-19T16:39:57-08:00", true }, - { "1990-12-31T23:59:60Z", true }, - { "1990-12-31T15:59:60-08:00", true }, - { "2001-02-29T10:10:10Z", false }, - { "2000-02-29T10:10:10Z", true }, - { "1937-01-01T12:00:27.87+00:20", true }, - { "1937-01-01T12:00:27.87Z", true }, - { "1956", false } - } }, - { make_shared(), { - { "Eeyore's feeling very depressed today", true }, - { "🤣", true }, - { "hello", true } - } }, - { make_shared(), { - { "MyAlias ", true }, - { "What is this? - Barry Burton", false }, - { "", true }, - { "(), { - { "MyAlias.VitalHeader", true }, - { "MyAlias.VitalHeader,Test", true }, - { "MyAlias.VitalHeader,🤣", false } - } } - }; - - for (const auto &entry : entries) { - const shared_ptr header = entry.first; - string previousValue; - - for (const auto &test : entry.second) { - const bool result = header->setValue(test.first); - BC_ASSERT_EQUAL(result, test.second, bool, "%d"); - - const string value = header->getValue(); - - if (result) - BC_ASSERT_STRING_EQUAL(value.c_str(), test.first.c_str()); - else - BC_ASSERT_STRING_EQUAL(value.c_str(), previousValue.c_str()); - - previousValue = value; - } - } -} - -static void check_subject_header_language (void) { - Cpim::SubjectHeader subjectHeader; - - // Check for not defined language. - { - const string language = subjectHeader.getLanguage(); - BC_ASSERT_STRING_EQUAL(language.c_str(), ""); - } - - // Set valid language. - { - const string languageToSet = "fr"; - - BC_ASSERT_TRUE(subjectHeader.setLanguage(languageToSet)); - BC_ASSERT_TRUE(languageToSet == subjectHeader.getLanguage()); - - const string str = subjectHeader.asString(); - const string expected = "Subject:;lang=" + languageToSet + " \r\n"; - BC_ASSERT_STRING_EQUAL(str.c_str(), expected.c_str()); - } - - // Set invalid language. - { - const string languageToSet = "fr--"; - BC_ASSERT_FALSE(subjectHeader.setLanguage(languageToSet)); - BC_ASSERT_FALSE(languageToSet == subjectHeader.getLanguage()); - BC_ASSERT_FALSE(subjectHeader.isValid()); - } -} - -static void parse_rfc_example (void) { - const string str = "Content-type: Message/CPIM\r\n" - "\r\n" - "From: MR SANDERS \r\n" - "To: Depressed Donkey \r\n" - "DateTime: 2000-12-13T13:40:00-08:00\r\n" - "Subject: the weather will be fine today\r\n" - "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" - "NS: MyFeatures \r\n" - "Require: MyFeatures.VitalMessageOption\r\n" - "MyFeatures.VitalMessageOption: Confirmation-requested\r\n" - "MyFeatures.WackyMessageOption: Use-silly-font\r\n" - "\r\n" - "Content-type text/xml; charset=utf-8\r\n" - "Content-ID: <1234567890@foo.com>\r\n" - "\r\n" - "" - "Here is the text of my message." - ""; - - shared_ptr message = Cpim::Message::createFromString(str); - if (!BC_ASSERT_PTR_NOT_NULL(message)) return; - - const string str2 = message->asString(); - BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); -} - -static void parse_message_with_generic_header_parameters (void) { - const string str = "Content-type: Message/CPIM\r\n" - "\r\n" - "From: MR SANDERS \r\n" - "Test:;aaa=bbb;yes=no CheckMe\r\n" - "yaya: coucou\r\n" - "yepee:;good=bad ugly\r\n" - "\r\n" - "Content-type text/xml; charset=utf-8\r\n" - "Content-ID: <1234567890@foo.com>\r\n" - "\r\n" - "" - "Here is the text of my message." - ""; - - shared_ptr message = Cpim::Message::createFromString(str); - if (!BC_ASSERT_PTR_NOT_NULL(message)) return; - - const string str2 = message->asString(); - BC_ASSERT_STRING_EQUAL(str2.c_str(), str.c_str()); -} - -static void build_message (void) { - Cpim::Message message; - if (!BC_ASSERT_FALSE(message.isValid())) - return; - - // Set CPIM headers. - Cpim::GenericHeader contentTypeHeader; - if (!BC_ASSERT_TRUE(contentTypeHeader.setName("Content-Type"))) return; - if (!BC_ASSERT_TRUE(contentTypeHeader.setValue("Message/CPIM"))) return; - - if (!BC_ASSERT_TRUE(message.addCpimHeader(contentTypeHeader))) return; - - // Set message headers. - Cpim::FromHeader fromHeader; - if (!BC_ASSERT_TRUE(fromHeader.setValue("MR SANDERS "))) return; - - Cpim::ToHeader toHeader; - if (!BC_ASSERT_TRUE(toHeader.setValue("Depressed Donkey "))) return; - - Cpim::DateTimeHeader dateTimeHeader; - if (!BC_ASSERT_TRUE(dateTimeHeader.setValue("2000-12-13T13:40:00-08:00"))) return; - - Cpim::SubjectHeader subjectHeader; - if (!BC_ASSERT_TRUE(subjectHeader.setValue("the weather will be fine today"))) return; - - Cpim::SubjectHeader subjectWithLanguageHeader; - if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setValue("beau temps prevu pour aujourd'hui"))) return; - if (!BC_ASSERT_TRUE(subjectWithLanguageHeader.setLanguage("fr"))) return; - - Cpim::NsHeader nsHeader; - if (!BC_ASSERT_TRUE(nsHeader.setValue("MyFeatures "))) return; - - Cpim::RequireHeader requireHeader; - if (!BC_ASSERT_TRUE(requireHeader.setValue("MyFeatures.VitalMessageOption"))) return; - - Cpim::GenericHeader vitalMessageHeader; - if (!BC_ASSERT_TRUE(vitalMessageHeader.setName("MyFeatures.VitalMessageOption"))) return; - if (!BC_ASSERT_TRUE(vitalMessageHeader.setValue("Confirmation-requested"))) return; - - Cpim::GenericHeader wackyMessageHeader; - if (!BC_ASSERT_TRUE(wackyMessageHeader.setName("MyFeatures.WackyMessageOption"))) return; - if (!BC_ASSERT_TRUE(wackyMessageHeader.setValue("Use-silly-font"))) return; - - if (!BC_ASSERT_TRUE(message.addMessageHeader(fromHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(toHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(dateTimeHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(subjectWithLanguageHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(nsHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(requireHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(vitalMessageHeader))) return; - if (!BC_ASSERT_TRUE(message.addMessageHeader(wackyMessageHeader))) return; - - const string content = "Content-type text/xml; charset=utf-8\r\n" - "Content-ID: <1234567890@foo.com>\r\n" - "\r\n" - "" - "Here is the text of my message." - ""; - - if (!BC_ASSERT_TRUE(message.setContent(content))) return; - if (!BC_ASSERT_TRUE(message.isValid())) return; - - const string strMessage = message.asString(); - const string expectedMessage = "Content-Type: Message/CPIM\r\n" - "\r\n" - "From: MR SANDERS \r\n" - "To: Depressed Donkey \r\n" - "DateTime: 2000-12-13T13:40:00-08:00\r\n" - "Subject: the weather will be fine today\r\n" - "Subject:;lang=fr beau temps prevu pour aujourd'hui\r\n" - "NS: MyFeatures \r\n" - "Require: MyFeatures.VitalMessageOption\r\n" - "MyFeatures.VitalMessageOption: Confirmation-requested\r\n" - "MyFeatures.WackyMessageOption: Use-silly-font\r\n" - "\r\n" - "Content-type text/xml; charset=utf-8\r\n" - "Content-ID: <1234567890@foo.com>\r\n" - "\r\n" - "" - "Here is the text of my message." - ""; - - BC_ASSERT_STRING_EQUAL(strMessage.c_str(), expectedMessage.c_str()); -} - -test_t cpim_tests[] = { - TEST_NO_TAG("Parse minimal CPIM message", parse_minimal_message), - TEST_NO_TAG("Set generic header name", set_generic_header_name), - TEST_NO_TAG("Set generic header value", set_generic_header_value), - TEST_NO_TAG("Check core header names", check_core_header_names), - TEST_NO_TAG("Set core header values", set_core_header_values), - TEST_NO_TAG("Check Subject header language", check_subject_header_language), - TEST_NO_TAG("Parse RFC example", parse_rfc_example), - TEST_NO_TAG("Parse Message with generic header parameters", parse_message_with_generic_header_parameters), - TEST_NO_TAG("Build Message", build_message) -}; - -test_suite_t cpim_test_suite = { - "Cpim", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(cpim_tests) / sizeof(cpim_tests[0]), cpim_tests -}; diff --git a/tester/db/friends.db b/tester/db/friends.db new file mode 100644 index 000000000..20fd191ea Binary files /dev/null and b/tester/db/friends.db differ diff --git a/tester/db/linphone.db b/tester/db/linphone.db new file mode 100644 index 000000000..a3be0fceb Binary files /dev/null and b/tester/db/linphone.db differ diff --git a/tester/db/messages.db b/tester/db/messages.db new file mode 100644 index 000000000..2eb613810 Binary files /dev/null and b/tester/db/messages.db differ diff --git a/tester/dtmf_tester.c b/tester/dtmf_tester.c index 65a45f0a6..3523fd339 100644 --- a/tester/dtmf_tester.c +++ b/tester/dtmf_tester.c @@ -17,14 +17,12 @@ */ #include "liblinphone_tester.h" -#include "private.h" +#include "tester_utils.h" void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf) { stats* counters = get_stats(lc); char** dst = &counters->dtmf_list_received; - *dst = *dst ? - ms_strcat_printf(*dst, "%c", dtmf) - : ms_strdup_printf("%c", dtmf); + *dst = *dst ? ms_strcat_printf(*dst, "%c", dtmf) : ms_strdup_printf("%c", dtmf); counters->dtmf_count++; } @@ -37,7 +35,7 @@ void send_dtmf_base(LinphoneCoreManager **pmarie, LinphoneCoreManager **ppauline if (use_opus) { //if (!ms_filter_codec_supported("opus")) { - if(!ms_factory_codec_supported(marie->lc->factory, "opus") && !ms_factory_codec_supported(pauline->lc->factory, "opus")){ + if(!ms_factory_codec_supported(linphone_core_get_ms_factory(marie->lc), "opus") && !ms_factory_codec_supported(linphone_core_get_ms_factory(pauline->lc), "opus")){ ms_warning("Opus not supported, skipping test."); return; @@ -69,7 +67,7 @@ void send_dtmf_base(LinphoneCoreManager **pmarie, LinphoneCoreManager **ppauline } if (dtmf_seq != NULL) { - int dtmf_delay_ms = lp_config_get_int(marie_call->core->config,"net","dtmf_delay_ms",200); + int dtmf_delay_ms = lp_config_get_int(linphone_core_get_config(linphone_call_get_core(marie_call)),"net","dtmf_delay_ms",200); dtmf_count_prev = pauline->stat.dtmf_count; linphone_call_send_dtmfs(marie_call, dtmf_seq); @@ -92,8 +90,8 @@ void send_dtmf_base(LinphoneCoreManager **pmarie, LinphoneCoreManager **ppauline void send_dtmf_cleanup(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) { LinphoneCall *marie_call = linphone_core_get_current_call(marie->lc); if (marie_call) { - BC_ASSERT_PTR_NULL(marie_call->dtmfs_timer); - BC_ASSERT_PTR_NULL(marie_call->dtmf_sequence); + BC_ASSERT_PTR_NULL(_linphone_call_get_dtmf_timer(marie_call)); + BC_ASSERT_FALSE(_linphone_call_has_dtmf_sequence(marie_call)); /*just to sleep*/ linphone_core_terminate_all_calls(pauline->lc); diff --git a/tester/eventapi_tester.c b/tester/eventapi_tester.c index 7bc39eba8..4eddf6db7 100644 --- a/tester/eventapi_tester.c +++ b/tester/eventapi_tester.c @@ -19,10 +19,10 @@ #include "linphone/core.h" -#include "private.h" #include "linphone/lpconfig.h" #include #include "liblinphone_tester.h" +#include "tester_utils.h" static const char *subscribe_content="blabla"; static const char *notify_content="blabla"; @@ -41,12 +41,20 @@ void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char * if (!BC_ASSERT_PTR_NOT_NULL(content)) return; if (!linphone_content_is_multipart(content) && (!ua || !strstr(ua, "flexisip"))) { /*disable check for full presence server support*/ /*hack to disable content checking for list notify */ - BC_ASSERT_STRING_EQUAL(notify_content,(const char*)linphone_content_get_buffer(content)); + BC_ASSERT_STRING_EQUAL(linphone_content_get_string_buffer(content), notify_content); } - mgr=get_manager(lc); + mgr = get_manager(lc); mgr->stat.number_of_NotifyReceived++; } +void linphone_subscribe_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content) { + LinphoneCoreManager *mgr = get_manager(lc); + if (!mgr->decline_subscribe) + linphone_event_accept_subscription(lev); + else + linphone_event_deny_subscription(lev, LinphoneReasonDeclined); +} + void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, LinphoneSubscriptionState state) { stats* counters = get_stats(lc); LinphoneCoreManager *mgr=get_manager(lc); @@ -56,7 +64,7 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li content = linphone_core_create_content(lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml2"); - linphone_content_set_buffer(content,notify_content,strlen(notify_content)); + linphone_content_set_buffer(content,(const uint8_t *)notify_content,strlen(notify_content)); ms_message("Subscription state [%s] from [%s]",linphone_subscription_state_to_string(state),from); ms_free(from); @@ -67,10 +75,6 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li case LinphoneSubscriptionIncomingReceived: counters->number_of_LinphoneSubscriptionIncomingReceived++; mgr->lev=lev; - if (!mgr->decline_subscribe) - linphone_event_accept_subscription(lev); - else - linphone_event_deny_subscription(lev, LinphoneReasonDeclined); break; case LinphoneSubscriptionOutgoingProgress: counters->number_of_LinphoneSubscriptionOutgoingProgress++; @@ -82,7 +86,11 @@ void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *lev, Li counters->number_of_LinphoneSubscriptionActive++; if (linphone_event_get_subscription_dir(lev)==LinphoneSubscriptionIncoming){ mgr->lev=lev; - linphone_event_notify(lev,content); + if(strcmp(linphone_event_get_name(lev), "conference") == 0) { + // TODO : Get LocalConfEventHandler and call handler->subscribeReceived(lev) + } else { + linphone_event_notify(lev,content); + } } break; case LinphoneSubscriptionTerminated: @@ -135,7 +143,7 @@ static void subscribe_test_declined(void) { content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); pauline->decline_subscribe=TRUE; @@ -177,13 +185,13 @@ static void subscribe_test_with_args(bool_t terminated_by_subscriber, RefreshTes lcs=bctbx_list_append(lcs,pauline->lc); if (refresh_type==ManualRefresh){ - lp_config_set_int(marie->lc->config,"sip","refresh_generic_subscribe",0); + lp_config_set_int(linphone_core_get_config(marie->lc),"sip","refresh_generic_subscribe",0); } content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",expires,content); linphone_event_ref(lev); @@ -235,13 +243,13 @@ static void subscribe_test_with_args2(bool_t terminated_by_subscriber, RefreshTe lcs=bctbx_list_append(lcs,pauline->lc); if (refresh_type==ManualRefresh){ - lp_config_set_int(marie->lc->config,"sip","refresh_generic_subscribe",0); + lp_config_set_int(linphone_core_get_config(marie->lc),"sip","refresh_generic_subscribe",0); } content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); lev=linphone_core_create_subscribe(marie->lc,pauline->identity,"dodo",expires); linphone_event_add_custom_header(lev,"My-Header","pouet"); @@ -329,7 +337,7 @@ static void subscribe_loosing_dialog(void) { content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); lev=linphone_core_create_subscribe(marie->lc,pauline->identity,"dodo",expires); linphone_event_add_custom_header(lev,"My-Header","pouet"); @@ -339,7 +347,7 @@ static void subscribe_loosing_dialog(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingProgress,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); - + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,5000)); @@ -354,7 +362,7 @@ static void subscribe_loosing_dialog(void) { linphone_core_manager_destroy(pauline); pauline = linphone_core_manager_new( "pauline_tcp_rc"); lcs = bctbx_list_append(lcs, pauline->lc); - + /* Marie will retry the subscription. * She will first receive a 503 Service unavailable from flexisip thanks the ICMP error returned by the no longer existing Pauline. * Then she will forge a new SUBSCRIBE in order to restart a new dialog, and this one will reach the new Pauline.*/ @@ -364,10 +372,10 @@ static void subscribe_loosing_dialog(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,5000)); BC_ASSERT_PTR_NOT_NULL(pauline->lev); if (pauline->lev) BC_ASSERT_EQUAL(linphone_event_get_subscription_state(pauline->lev), LinphoneSubscriptionActive, int, "%d"); - + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,2,5000)); linphone_event_terminate(lev); - + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionTerminated,1,5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionTerminated,1,5000)); @@ -392,7 +400,7 @@ static void subscribe_with_io_error(void) { content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); lev=linphone_core_create_subscribe(marie->lc,pauline->identity,"dodo",expires); linphone_event_add_custom_header(lev,"My-Header","pouet"); @@ -402,7 +410,7 @@ static void subscribe_with_io_error(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingProgress,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); - + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,5000)); @@ -410,19 +418,19 @@ static void subscribe_with_io_error(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,1,5000)); /* now marie gets network errors when refreshing*/ - sal_set_send_error(marie->lc->sal, -1); - + sal_set_send_error(linphone_core_get_sal(marie->lc), -1); + /*marie will retry the subscription*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingProgress,2,8000)); - sal_set_send_error(marie->lc->sal, 0); - + sal_set_send_error(linphone_core_get_sal(marie->lc), 0); + /*and get it accepted again*/ BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,2,10000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,2,5000)); BC_ASSERT_EQUAL(linphone_event_get_subscription_state(pauline->lev), LinphoneSubscriptionActive, int, "%d"); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,2,5000)); linphone_event_terminate(lev); - + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionTerminated,1,5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionTerminated,1,5000)); @@ -446,7 +454,7 @@ static void subscribe_not_timely_responded(void) { content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); lev=linphone_core_create_subscribe(marie->lc,pauline->identity,"dodo",expires); linphone_event_add_custom_header(lev,"My-Header","pouet"); @@ -456,7 +464,7 @@ static void subscribe_not_timely_responded(void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionOutgoingProgress,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionIncomingReceived,1,3000)); - + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionActive,1,5000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneSubscriptionActive,1,5000)); @@ -467,7 +475,7 @@ static void subscribe_not_timely_responded(void) { lcs = bctbx_list_remove(lcs, pauline->lc); /*marie's dialog will expire while the SUBSCRIBE refresh is in progress*/ wait_for_list(lcs, NULL, 0, 8000); - + lcs = bctbx_list_append(lcs, pauline->lc); wait_for_list(lcs, NULL, 0, 3000); linphone_event_terminate(lev); @@ -492,15 +500,15 @@ static void publish_test_with_args(bool_t refresh, int expires){ content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); - lp_config_set_int(marie->lc->config,"sip","refresh_generic_publish",refresh); + lp_config_set_int(linphone_core_get_config(marie->lc),"sip","refresh_generic_publish",refresh); lev=linphone_core_create_publish(marie->lc,pauline->identity,"dodo",expires); linphone_event_add_custom_header(lev,"CustomHeader","someValue"); linphone_event_ref(lev); linphone_event_send_publish(lev,content); - + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishProgress,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphonePublishOk,1,3000)); @@ -548,13 +556,13 @@ static void out_of_dialog_notify(void){ content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content,notify_content,strlen(notify_content)); + linphone_content_set_buffer(content,(const uint8_t *)notify_content,strlen(notify_content)); lev = linphone_core_create_notify(marie->lc,pauline->identity,"dodo"); linphone_event_ref(lev); linphone_event_add_custom_header(lev,"CustomHeader","someValue"); linphone_event_notify(lev,content); - + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_NotifyReceived,1,3000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneSubscriptionTerminated,1,3000)); diff --git a/tester/flexisip/flexisip.conf b/tester/flexisip/flexisip.conf index e5b20e444..e4db91c04 100644 --- a/tester/flexisip/flexisip.conf +++ b/tester/flexisip/flexisip.conf @@ -18,7 +18,7 @@ auto-respawn=true # List of white space separated host names pointing to this machine. # This is to prevent loops while routing SIP messages. # Default value: localhost -aliases=localhost sip2.linphone.org sipopen.example.org sip.example.org auth.example.org auth1.example.org auth2.example.org client.example.org sipv4.example.org sipv4-nat64.example.org +aliases=localhost sip2.linphone.org sipopen.example.org sip.example.org auth.example.org auth1.example.org auth2.example.org client.example.org sipv4.example.org sipv4-nat64.example.org conf.example.org # List of white space separated SIP uris where the proxy must listen.Wildcard # (*) can be used to mean 'all local ip addresses'. If 'transport' @@ -266,7 +266,7 @@ max-contacts-by-aor=15 # Maximum expire time for a REGISTER, in seconds. # Default value: 86400 -max-expires=60 +max-expires=600 # Minimum expire time for a REGISTER, in seconds. # Default value: 60 @@ -624,4 +624,29 @@ only-list-subscription = !(user-agent contains 'full-presence-support') [presence-server] expires = 600 transports = sip:127.0.0.1:5065;transport=tcp +bypass-condition = bypass +# +# Flexisip conference server parameters. +# +[conference-server] + +# Enable conference server +# Default value: true +enabled=true + +# uri where the conference server must listen. +# Default value: sip:127.0.0.1:6064 +transport= + +# uri where the client must ask to create a conference. +# Default value: sip:conference-factory@sip1.linphone.org +conference-factory-uri=sip:conference-factory@conf.example.org + + +# Default value: sip:127.0.0.1:5060;transport=tcp +outbound-proxy=sip:127.0.0.1:5060;transport=tcp + +database-backend=mysql + +database-connection-string=db='flexisip_conference_sip_test' user='flexisip_user' password='cotcot' host='127.0.0.1' port='3307' diff --git a/tester/flexisip/userdb.conf b/tester/flexisip/userdb.conf index 1616df5b0..b5d995365 100644 --- a/tester/flexisip/userdb.conf +++ b/tester/flexisip/userdb.conf @@ -1,9 +1,2012 @@ version:1 -liblinphone_tester@sip.example.org clrtxt:secret ; -liblinphone_tester@auth.example.org clrtxt:secret ; -liblinphone_tester@auth1.example.org clrtxt:secret ; -tester@sip.example.org clrtxt:secret ; -pauline@sip.example.org clrtxt:secret ; -marie@sip.example.org clrtxt:secret ; -laure@sip.example.org clrtxt:secret ; -bellesip@sip.example.org clrtxt:secret ; +liblinphone_tester@sip.example.org md5:19ffdcec6adc70629617046a60e529fc ; liblinphone_tester +33123456789 +liblinphone_tester@auth.example.org md5:db9ddf59cb75ae15f51745192d23ddae ; +liblinphone_tester@auth1.example.org md5:fe32fa7157d629145f1282a73a36a961 ; +tester@sip.example.org md5:61d963d04c360eceb424043e0d53676b ; +pauline@sip.example.org md5:46b03c8f72e61f4340a6d3d06a726d2e ; +marie@sip.example.org md5:c4ce0fe4c1c82e4b700726e085aee9b3 ; +laure@sip.example.org md5:63d09951793c1361768531f9a9011331 ; +bellesip@sip.example.org md5:2fc013743b860819a784b0e6c4bee11a ; +liblinphone_sha_tester@sip.example.org clrtxt:secret ; +test%20username@sip.example.org clrtxt:secret ; + +sip:user_1@sip.example.org clrtxt:secret ; +sip:user_2@sip.example.org clrtxt:secret ; +sip:user_3@sip.example.org clrtxt:secret ; +sip:user_4@sip.example.org clrtxt:secret ; +sip:user_5@sip.example.org clrtxt:secret ; +sip:user_6@sip.example.org clrtxt:secret ; +sip:user_7@sip.example.org clrtxt:secret ; +sip:user_8@sip.example.org clrtxt:secret ; +sip:user_9@sip.example.org clrtxt:secret ; +sip:user_10@sip.example.org clrtxt:secret ; +sip:user_11@sip.example.org clrtxt:secret ; +sip:user_12@sip.example.org clrtxt:secret ; +sip:user_13@sip.example.org clrtxt:secret ; +sip:user_14@sip.example.org clrtxt:secret ; +sip:user_15@sip.example.org clrtxt:secret ; +sip:user_16@sip.example.org clrtxt:secret ; +sip:user_17@sip.example.org clrtxt:secret ; +sip:user_18@sip.example.org clrtxt:secret ; +sip:user_19@sip.example.org clrtxt:secret ; +sip:user_20@sip.example.org clrtxt:secret ; +sip:user_21@sip.example.org clrtxt:secret ; +sip:user_22@sip.example.org clrtxt:secret ; +sip:user_23@sip.example.org clrtxt:secret ; +sip:user_24@sip.example.org clrtxt:secret ; +sip:user_25@sip.example.org clrtxt:secret ; +sip:user_26@sip.example.org clrtxt:secret ; +sip:user_27@sip.example.org clrtxt:secret ; +sip:user_28@sip.example.org clrtxt:secret ; +sip:user_29@sip.example.org clrtxt:secret ; +sip:user_30@sip.example.org clrtxt:secret ; +sip:user_31@sip.example.org clrtxt:secret ; +sip:user_32@sip.example.org clrtxt:secret ; +sip:user_33@sip.example.org clrtxt:secret ; +sip:user_34@sip.example.org clrtxt:secret ; +sip:user_35@sip.example.org clrtxt:secret ; +sip:user_36@sip.example.org clrtxt:secret ; +sip:user_37@sip.example.org clrtxt:secret ; +sip:user_38@sip.example.org clrtxt:secret ; +sip:user_39@sip.example.org clrtxt:secret ; +sip:user_40@sip.example.org clrtxt:secret ; +sip:user_41@sip.example.org clrtxt:secret ; +sip:user_42@sip.example.org clrtxt:secret ; +sip:user_43@sip.example.org clrtxt:secret ; +sip:user_44@sip.example.org clrtxt:secret ; +sip:user_45@sip.example.org clrtxt:secret ; +sip:user_46@sip.example.org clrtxt:secret ; +sip:user_47@sip.example.org clrtxt:secret ; +sip:user_48@sip.example.org clrtxt:secret ; +sip:user_49@sip.example.org clrtxt:secret ; +sip:user_50@sip.example.org clrtxt:secret ; +sip:user_51@sip.example.org clrtxt:secret ; +sip:user_52@sip.example.org clrtxt:secret ; +sip:user_53@sip.example.org clrtxt:secret ; +sip:user_54@sip.example.org clrtxt:secret ; +sip:user_55@sip.example.org clrtxt:secret ; +sip:user_56@sip.example.org clrtxt:secret ; +sip:user_57@sip.example.org clrtxt:secret ; +sip:user_58@sip.example.org clrtxt:secret ; +sip:user_59@sip.example.org clrtxt:secret ; +sip:user_60@sip.example.org clrtxt:secret ; +sip:user_61@sip.example.org clrtxt:secret ; +sip:user_62@sip.example.org clrtxt:secret ; +sip:user_63@sip.example.org clrtxt:secret ; +sip:user_64@sip.example.org clrtxt:secret ; +sip:user_65@sip.example.org clrtxt:secret ; +sip:user_66@sip.example.org clrtxt:secret ; +sip:user_67@sip.example.org clrtxt:secret ; +sip:user_68@sip.example.org clrtxt:secret ; +sip:user_69@sip.example.org clrtxt:secret ; +sip:user_70@sip.example.org clrtxt:secret ; +sip:user_71@sip.example.org clrtxt:secret ; +sip:user_72@sip.example.org clrtxt:secret ; +sip:user_73@sip.example.org clrtxt:secret ; +sip:user_74@sip.example.org clrtxt:secret ; +sip:user_75@sip.example.org clrtxt:secret ; +sip:user_76@sip.example.org clrtxt:secret ; +sip:user_77@sip.example.org clrtxt:secret ; +sip:user_78@sip.example.org clrtxt:secret ; +sip:user_79@sip.example.org clrtxt:secret ; +sip:user_80@sip.example.org clrtxt:secret ; +sip:user_81@sip.example.org clrtxt:secret ; +sip:user_82@sip.example.org clrtxt:secret ; +sip:user_83@sip.example.org clrtxt:secret ; +sip:user_84@sip.example.org clrtxt:secret ; +sip:user_85@sip.example.org clrtxt:secret ; +sip:user_86@sip.example.org clrtxt:secret ; +sip:user_87@sip.example.org clrtxt:secret ; +sip:user_88@sip.example.org clrtxt:secret ; +sip:user_89@sip.example.org clrtxt:secret ; +sip:user_90@sip.example.org clrtxt:secret ; +sip:user_91@sip.example.org clrtxt:secret ; +sip:user_92@sip.example.org clrtxt:secret ; +sip:user_93@sip.example.org clrtxt:secret ; +sip:user_94@sip.example.org clrtxt:secret ; +sip:user_95@sip.example.org clrtxt:secret ; +sip:user_96@sip.example.org clrtxt:secret ; +sip:user_97@sip.example.org clrtxt:secret ; +sip:user_98@sip.example.org clrtxt:secret ; +sip:user_99@sip.example.org clrtxt:secret ; +sip:user_100@sip.example.org clrtxt:secret ; +sip:user_101@sip.example.org clrtxt:secret ; +sip:user_102@sip.example.org clrtxt:secret ; +sip:user_103@sip.example.org clrtxt:secret ; +sip:user_104@sip.example.org clrtxt:secret ; +sip:user_105@sip.example.org clrtxt:secret ; +sip:user_106@sip.example.org clrtxt:secret ; +sip:user_107@sip.example.org clrtxt:secret ; +sip:user_108@sip.example.org clrtxt:secret ; +sip:user_109@sip.example.org clrtxt:secret ; +sip:user_110@sip.example.org clrtxt:secret ; +sip:user_111@sip.example.org clrtxt:secret ; +sip:user_112@sip.example.org clrtxt:secret ; +sip:user_113@sip.example.org clrtxt:secret ; +sip:user_114@sip.example.org clrtxt:secret ; +sip:user_115@sip.example.org clrtxt:secret ; +sip:user_116@sip.example.org clrtxt:secret ; +sip:user_117@sip.example.org clrtxt:secret ; +sip:user_118@sip.example.org clrtxt:secret ; +sip:user_119@sip.example.org clrtxt:secret ; +sip:user_120@sip.example.org clrtxt:secret ; +sip:user_121@sip.example.org clrtxt:secret ; +sip:user_122@sip.example.org clrtxt:secret ; +sip:user_123@sip.example.org clrtxt:secret ; +sip:user_124@sip.example.org clrtxt:secret ; +sip:user_125@sip.example.org clrtxt:secret ; +sip:user_126@sip.example.org clrtxt:secret ; +sip:user_127@sip.example.org clrtxt:secret ; +sip:user_128@sip.example.org clrtxt:secret ; +sip:user_129@sip.example.org clrtxt:secret ; +sip:user_130@sip.example.org clrtxt:secret ; +sip:user_131@sip.example.org clrtxt:secret ; +sip:user_132@sip.example.org clrtxt:secret ; +sip:user_133@sip.example.org clrtxt:secret ; +sip:user_134@sip.example.org clrtxt:secret ; +sip:user_135@sip.example.org clrtxt:secret ; +sip:user_136@sip.example.org clrtxt:secret ; +sip:user_137@sip.example.org clrtxt:secret ; +sip:user_138@sip.example.org clrtxt:secret ; +sip:user_139@sip.example.org clrtxt:secret ; +sip:user_140@sip.example.org clrtxt:secret ; +sip:user_141@sip.example.org clrtxt:secret ; +sip:user_142@sip.example.org clrtxt:secret ; +sip:user_143@sip.example.org clrtxt:secret ; +sip:user_144@sip.example.org clrtxt:secret ; +sip:user_145@sip.example.org clrtxt:secret ; +sip:user_146@sip.example.org clrtxt:secret ; +sip:user_147@sip.example.org clrtxt:secret ; +sip:user_148@sip.example.org clrtxt:secret ; +sip:user_149@sip.example.org clrtxt:secret ; +sip:user_150@sip.example.org clrtxt:secret ; +sip:user_151@sip.example.org clrtxt:secret ; +sip:user_152@sip.example.org clrtxt:secret ; +sip:user_153@sip.example.org clrtxt:secret ; +sip:user_154@sip.example.org clrtxt:secret ; +sip:user_155@sip.example.org clrtxt:secret ; +sip:user_156@sip.example.org clrtxt:secret ; +sip:user_157@sip.example.org clrtxt:secret ; +sip:user_158@sip.example.org clrtxt:secret ; +sip:user_159@sip.example.org clrtxt:secret ; +sip:user_160@sip.example.org clrtxt:secret ; +sip:user_161@sip.example.org clrtxt:secret ; +sip:user_162@sip.example.org clrtxt:secret ; +sip:user_163@sip.example.org clrtxt:secret ; +sip:user_164@sip.example.org clrtxt:secret ; +sip:user_165@sip.example.org clrtxt:secret ; +sip:user_166@sip.example.org clrtxt:secret ; +sip:user_167@sip.example.org clrtxt:secret ; +sip:user_168@sip.example.org clrtxt:secret ; +sip:user_169@sip.example.org clrtxt:secret ; +sip:user_170@sip.example.org clrtxt:secret ; +sip:user_171@sip.example.org clrtxt:secret ; +sip:user_172@sip.example.org clrtxt:secret ; +sip:user_173@sip.example.org clrtxt:secret ; +sip:user_174@sip.example.org clrtxt:secret ; +sip:user_175@sip.example.org clrtxt:secret ; +sip:user_176@sip.example.org clrtxt:secret ; +sip:user_177@sip.example.org clrtxt:secret ; +sip:user_178@sip.example.org clrtxt:secret ; +sip:user_179@sip.example.org clrtxt:secret ; +sip:user_180@sip.example.org clrtxt:secret ; +sip:user_181@sip.example.org clrtxt:secret ; +sip:user_182@sip.example.org clrtxt:secret ; +sip:user_183@sip.example.org clrtxt:secret ; +sip:user_184@sip.example.org clrtxt:secret ; +sip:user_185@sip.example.org clrtxt:secret ; +sip:user_186@sip.example.org clrtxt:secret ; +sip:user_187@sip.example.org clrtxt:secret ; +sip:user_188@sip.example.org clrtxt:secret ; +sip:user_189@sip.example.org clrtxt:secret ; +sip:user_190@sip.example.org clrtxt:secret ; +sip:user_191@sip.example.org clrtxt:secret ; +sip:user_192@sip.example.org clrtxt:secret ; +sip:user_193@sip.example.org clrtxt:secret ; +sip:user_194@sip.example.org clrtxt:secret ; +sip:user_195@sip.example.org clrtxt:secret ; +sip:user_196@sip.example.org clrtxt:secret ; +sip:user_197@sip.example.org clrtxt:secret ; +sip:user_198@sip.example.org clrtxt:secret ; +sip:user_199@sip.example.org clrtxt:secret ; +sip:user_200@sip.example.org clrtxt:secret ; +sip:user_201@sip.example.org clrtxt:secret ; +sip:user_202@sip.example.org clrtxt:secret ; +sip:user_203@sip.example.org clrtxt:secret ; +sip:user_204@sip.example.org clrtxt:secret ; +sip:user_205@sip.example.org clrtxt:secret ; +sip:user_206@sip.example.org clrtxt:secret ; +sip:user_207@sip.example.org clrtxt:secret ; +sip:user_208@sip.example.org clrtxt:secret ; +sip:user_209@sip.example.org clrtxt:secret ; +sip:user_210@sip.example.org clrtxt:secret ; +sip:user_211@sip.example.org clrtxt:secret ; +sip:user_212@sip.example.org clrtxt:secret ; +sip:user_213@sip.example.org clrtxt:secret ; +sip:user_214@sip.example.org clrtxt:secret ; +sip:user_215@sip.example.org clrtxt:secret ; +sip:user_216@sip.example.org clrtxt:secret ; +sip:user_217@sip.example.org clrtxt:secret ; +sip:user_218@sip.example.org clrtxt:secret ; +sip:user_219@sip.example.org clrtxt:secret ; +sip:user_220@sip.example.org clrtxt:secret ; +sip:user_221@sip.example.org clrtxt:secret ; +sip:user_222@sip.example.org clrtxt:secret ; +sip:user_223@sip.example.org clrtxt:secret ; +sip:user_224@sip.example.org clrtxt:secret ; +sip:user_225@sip.example.org clrtxt:secret ; +sip:user_226@sip.example.org clrtxt:secret ; +sip:user_227@sip.example.org clrtxt:secret ; +sip:user_228@sip.example.org clrtxt:secret ; +sip:user_229@sip.example.org clrtxt:secret ; +sip:user_230@sip.example.org clrtxt:secret ; +sip:user_231@sip.example.org clrtxt:secret ; +sip:user_232@sip.example.org clrtxt:secret ; +sip:user_233@sip.example.org clrtxt:secret ; +sip:user_234@sip.example.org clrtxt:secret ; +sip:user_235@sip.example.org clrtxt:secret ; +sip:user_236@sip.example.org clrtxt:secret ; +sip:user_237@sip.example.org clrtxt:secret ; +sip:user_238@sip.example.org clrtxt:secret ; +sip:user_239@sip.example.org clrtxt:secret ; +sip:user_240@sip.example.org clrtxt:secret ; +sip:user_241@sip.example.org clrtxt:secret ; +sip:user_242@sip.example.org clrtxt:secret ; +sip:user_243@sip.example.org clrtxt:secret ; +sip:user_244@sip.example.org clrtxt:secret ; +sip:user_245@sip.example.org clrtxt:secret ; +sip:user_246@sip.example.org clrtxt:secret ; +sip:user_247@sip.example.org clrtxt:secret ; +sip:user_248@sip.example.org clrtxt:secret ; +sip:user_249@sip.example.org clrtxt:secret ; +sip:user_250@sip.example.org clrtxt:secret ; +sip:user_251@sip.example.org clrtxt:secret ; +sip:user_252@sip.example.org clrtxt:secret ; +sip:user_253@sip.example.org clrtxt:secret ; +sip:user_254@sip.example.org clrtxt:secret ; +sip:user_255@sip.example.org clrtxt:secret ; +sip:user_256@sip.example.org clrtxt:secret ; +sip:user_257@sip.example.org clrtxt:secret ; +sip:user_258@sip.example.org clrtxt:secret ; +sip:user_259@sip.example.org clrtxt:secret ; +sip:user_260@sip.example.org clrtxt:secret ; +sip:user_261@sip.example.org clrtxt:secret ; +sip:user_262@sip.example.org clrtxt:secret ; +sip:user_263@sip.example.org clrtxt:secret ; +sip:user_264@sip.example.org clrtxt:secret ; +sip:user_265@sip.example.org clrtxt:secret ; +sip:user_266@sip.example.org clrtxt:secret ; +sip:user_267@sip.example.org clrtxt:secret ; +sip:user_268@sip.example.org clrtxt:secret ; +sip:user_269@sip.example.org clrtxt:secret ; +sip:user_270@sip.example.org clrtxt:secret ; +sip:user_271@sip.example.org clrtxt:secret ; +sip:user_272@sip.example.org clrtxt:secret ; +sip:user_273@sip.example.org clrtxt:secret ; +sip:user_274@sip.example.org clrtxt:secret ; +sip:user_275@sip.example.org clrtxt:secret ; +sip:user_276@sip.example.org clrtxt:secret ; +sip:user_277@sip.example.org clrtxt:secret ; +sip:user_278@sip.example.org clrtxt:secret ; +sip:user_279@sip.example.org clrtxt:secret ; +sip:user_280@sip.example.org clrtxt:secret ; +sip:user_281@sip.example.org clrtxt:secret ; +sip:user_282@sip.example.org clrtxt:secret ; +sip:user_283@sip.example.org clrtxt:secret ; +sip:user_284@sip.example.org clrtxt:secret ; +sip:user_285@sip.example.org clrtxt:secret ; +sip:user_286@sip.example.org clrtxt:secret ; +sip:user_287@sip.example.org clrtxt:secret ; +sip:user_288@sip.example.org clrtxt:secret ; +sip:user_289@sip.example.org clrtxt:secret ; +sip:user_290@sip.example.org clrtxt:secret ; +sip:user_291@sip.example.org clrtxt:secret ; +sip:user_292@sip.example.org clrtxt:secret ; +sip:user_293@sip.example.org clrtxt:secret ; +sip:user_294@sip.example.org clrtxt:secret ; +sip:user_295@sip.example.org clrtxt:secret ; +sip:user_296@sip.example.org clrtxt:secret ; +sip:user_297@sip.example.org clrtxt:secret ; +sip:user_298@sip.example.org clrtxt:secret ; +sip:user_299@sip.example.org clrtxt:secret ; +sip:user_300@sip.example.org clrtxt:secret ; +sip:user_301@sip.example.org clrtxt:secret ; +sip:user_302@sip.example.org clrtxt:secret ; +sip:user_303@sip.example.org clrtxt:secret ; +sip:user_304@sip.example.org clrtxt:secret ; +sip:user_305@sip.example.org clrtxt:secret ; +sip:user_306@sip.example.org clrtxt:secret ; +sip:user_307@sip.example.org clrtxt:secret ; +sip:user_308@sip.example.org clrtxt:secret ; +sip:user_309@sip.example.org clrtxt:secret ; +sip:user_310@sip.example.org clrtxt:secret ; +sip:user_311@sip.example.org clrtxt:secret ; +sip:user_312@sip.example.org clrtxt:secret ; +sip:user_313@sip.example.org clrtxt:secret ; +sip:user_314@sip.example.org clrtxt:secret ; +sip:user_315@sip.example.org clrtxt:secret ; +sip:user_316@sip.example.org clrtxt:secret ; +sip:user_317@sip.example.org clrtxt:secret ; +sip:user_318@sip.example.org clrtxt:secret ; +sip:user_319@sip.example.org clrtxt:secret ; +sip:user_320@sip.example.org clrtxt:secret ; +sip:user_321@sip.example.org clrtxt:secret ; +sip:user_322@sip.example.org clrtxt:secret ; +sip:user_323@sip.example.org clrtxt:secret ; +sip:user_324@sip.example.org clrtxt:secret ; +sip:user_325@sip.example.org clrtxt:secret ; +sip:user_326@sip.example.org clrtxt:secret ; +sip:user_327@sip.example.org clrtxt:secret ; +sip:user_328@sip.example.org clrtxt:secret ; +sip:user_329@sip.example.org clrtxt:secret ; +sip:user_330@sip.example.org clrtxt:secret ; +sip:user_331@sip.example.org clrtxt:secret ; +sip:user_332@sip.example.org clrtxt:secret ; +sip:user_333@sip.example.org clrtxt:secret ; +sip:user_334@sip.example.org clrtxt:secret ; +sip:user_335@sip.example.org clrtxt:secret ; +sip:user_336@sip.example.org clrtxt:secret ; +sip:user_337@sip.example.org clrtxt:secret ; +sip:user_338@sip.example.org clrtxt:secret ; +sip:user_339@sip.example.org clrtxt:secret ; +sip:user_340@sip.example.org clrtxt:secret ; +sip:user_341@sip.example.org clrtxt:secret ; +sip:user_342@sip.example.org clrtxt:secret ; +sip:user_343@sip.example.org clrtxt:secret ; +sip:user_344@sip.example.org clrtxt:secret ; +sip:user_345@sip.example.org clrtxt:secret ; +sip:user_346@sip.example.org clrtxt:secret ; +sip:user_347@sip.example.org clrtxt:secret ; +sip:user_348@sip.example.org clrtxt:secret ; +sip:user_349@sip.example.org clrtxt:secret ; +sip:user_350@sip.example.org clrtxt:secret ; +sip:user_351@sip.example.org clrtxt:secret ; +sip:user_352@sip.example.org clrtxt:secret ; +sip:user_353@sip.example.org clrtxt:secret ; +sip:user_354@sip.example.org clrtxt:secret ; +sip:user_355@sip.example.org clrtxt:secret ; +sip:user_356@sip.example.org clrtxt:secret ; +sip:user_357@sip.example.org clrtxt:secret ; +sip:user_358@sip.example.org clrtxt:secret ; +sip:user_359@sip.example.org clrtxt:secret ; +sip:user_360@sip.example.org clrtxt:secret ; +sip:user_361@sip.example.org clrtxt:secret ; +sip:user_362@sip.example.org clrtxt:secret ; +sip:user_363@sip.example.org clrtxt:secret ; +sip:user_364@sip.example.org clrtxt:secret ; +sip:user_365@sip.example.org clrtxt:secret ; +sip:user_366@sip.example.org clrtxt:secret ; +sip:user_367@sip.example.org clrtxt:secret ; +sip:user_368@sip.example.org clrtxt:secret ; +sip:user_369@sip.example.org clrtxt:secret ; +sip:user_370@sip.example.org clrtxt:secret ; +sip:user_371@sip.example.org clrtxt:secret ; +sip:user_372@sip.example.org clrtxt:secret ; +sip:user_373@sip.example.org clrtxt:secret ; +sip:user_374@sip.example.org clrtxt:secret ; +sip:user_375@sip.example.org clrtxt:secret ; +sip:user_376@sip.example.org clrtxt:secret ; +sip:user_377@sip.example.org clrtxt:secret ; +sip:user_378@sip.example.org clrtxt:secret ; +sip:user_379@sip.example.org clrtxt:secret ; +sip:user_380@sip.example.org clrtxt:secret ; +sip:user_381@sip.example.org clrtxt:secret ; +sip:user_382@sip.example.org clrtxt:secret ; +sip:user_383@sip.example.org clrtxt:secret ; +sip:user_384@sip.example.org clrtxt:secret ; +sip:user_385@sip.example.org clrtxt:secret ; +sip:user_386@sip.example.org clrtxt:secret ; +sip:user_387@sip.example.org clrtxt:secret ; +sip:user_388@sip.example.org clrtxt:secret ; +sip:user_389@sip.example.org clrtxt:secret ; +sip:user_390@sip.example.org clrtxt:secret ; +sip:user_391@sip.example.org clrtxt:secret ; +sip:user_392@sip.example.org clrtxt:secret ; +sip:user_393@sip.example.org clrtxt:secret ; +sip:user_394@sip.example.org clrtxt:secret ; +sip:user_395@sip.example.org clrtxt:secret ; +sip:user_396@sip.example.org clrtxt:secret ; +sip:user_397@sip.example.org clrtxt:secret ; +sip:user_398@sip.example.org clrtxt:secret ; +sip:user_399@sip.example.org clrtxt:secret ; +sip:user_400@sip.example.org clrtxt:secret ; +sip:user_401@sip.example.org clrtxt:secret ; +sip:user_402@sip.example.org clrtxt:secret ; +sip:user_403@sip.example.org clrtxt:secret ; +sip:user_404@sip.example.org clrtxt:secret ; +sip:user_405@sip.example.org clrtxt:secret ; +sip:user_406@sip.example.org clrtxt:secret ; +sip:user_407@sip.example.org clrtxt:secret ; +sip:user_408@sip.example.org clrtxt:secret ; +sip:user_409@sip.example.org clrtxt:secret ; +sip:user_410@sip.example.org clrtxt:secret ; +sip:user_411@sip.example.org clrtxt:secret ; +sip:user_412@sip.example.org clrtxt:secret ; +sip:user_413@sip.example.org clrtxt:secret ; +sip:user_414@sip.example.org clrtxt:secret ; +sip:user_415@sip.example.org clrtxt:secret ; +sip:user_416@sip.example.org clrtxt:secret ; +sip:user_417@sip.example.org clrtxt:secret ; +sip:user_418@sip.example.org clrtxt:secret ; +sip:user_419@sip.example.org clrtxt:secret ; +sip:user_420@sip.example.org clrtxt:secret ; +sip:user_421@sip.example.org clrtxt:secret ; +sip:user_422@sip.example.org clrtxt:secret ; +sip:user_423@sip.example.org clrtxt:secret ; +sip:user_424@sip.example.org clrtxt:secret ; +sip:user_425@sip.example.org clrtxt:secret ; +sip:user_426@sip.example.org clrtxt:secret ; +sip:user_427@sip.example.org clrtxt:secret ; +sip:user_428@sip.example.org clrtxt:secret ; +sip:user_429@sip.example.org clrtxt:secret ; +sip:user_430@sip.example.org clrtxt:secret ; +sip:user_431@sip.example.org clrtxt:secret ; +sip:user_432@sip.example.org clrtxt:secret ; +sip:user_433@sip.example.org clrtxt:secret ; +sip:user_434@sip.example.org clrtxt:secret ; +sip:user_435@sip.example.org clrtxt:secret ; +sip:user_436@sip.example.org clrtxt:secret ; +sip:user_437@sip.example.org clrtxt:secret ; +sip:user_438@sip.example.org clrtxt:secret ; +sip:user_439@sip.example.org clrtxt:secret ; +sip:user_440@sip.example.org clrtxt:secret ; +sip:user_441@sip.example.org clrtxt:secret ; +sip:user_442@sip.example.org clrtxt:secret ; +sip:user_443@sip.example.org clrtxt:secret ; +sip:user_444@sip.example.org clrtxt:secret ; +sip:user_445@sip.example.org clrtxt:secret ; +sip:user_446@sip.example.org clrtxt:secret ; +sip:user_447@sip.example.org clrtxt:secret ; +sip:user_448@sip.example.org clrtxt:secret ; +sip:user_449@sip.example.org clrtxt:secret ; +sip:user_450@sip.example.org clrtxt:secret ; +sip:user_451@sip.example.org clrtxt:secret ; +sip:user_452@sip.example.org clrtxt:secret ; +sip:user_453@sip.example.org clrtxt:secret ; +sip:user_454@sip.example.org clrtxt:secret ; +sip:user_455@sip.example.org clrtxt:secret ; +sip:user_456@sip.example.org clrtxt:secret ; +sip:user_457@sip.example.org clrtxt:secret ; +sip:user_458@sip.example.org clrtxt:secret ; +sip:user_459@sip.example.org clrtxt:secret ; +sip:user_460@sip.example.org clrtxt:secret ; +sip:user_461@sip.example.org clrtxt:secret ; +sip:user_462@sip.example.org clrtxt:secret ; +sip:user_463@sip.example.org clrtxt:secret ; +sip:user_464@sip.example.org clrtxt:secret ; +sip:user_465@sip.example.org clrtxt:secret ; +sip:user_466@sip.example.org clrtxt:secret ; +sip:user_467@sip.example.org clrtxt:secret ; +sip:user_468@sip.example.org clrtxt:secret ; +sip:user_469@sip.example.org clrtxt:secret ; +sip:user_470@sip.example.org clrtxt:secret ; +sip:user_471@sip.example.org clrtxt:secret ; +sip:user_472@sip.example.org clrtxt:secret ; +sip:user_473@sip.example.org clrtxt:secret ; +sip:user_474@sip.example.org clrtxt:secret ; +sip:user_475@sip.example.org clrtxt:secret ; +sip:user_476@sip.example.org clrtxt:secret ; +sip:user_477@sip.example.org clrtxt:secret ; +sip:user_478@sip.example.org clrtxt:secret ; +sip:user_479@sip.example.org clrtxt:secret ; +sip:user_480@sip.example.org clrtxt:secret ; +sip:user_481@sip.example.org clrtxt:secret ; +sip:user_482@sip.example.org clrtxt:secret ; +sip:user_483@sip.example.org clrtxt:secret ; +sip:user_484@sip.example.org clrtxt:secret ; +sip:user_485@sip.example.org clrtxt:secret ; +sip:user_486@sip.example.org clrtxt:secret ; +sip:user_487@sip.example.org clrtxt:secret ; +sip:user_488@sip.example.org clrtxt:secret ; +sip:user_489@sip.example.org clrtxt:secret ; +sip:user_490@sip.example.org clrtxt:secret ; +sip:user_491@sip.example.org clrtxt:secret ; +sip:user_492@sip.example.org clrtxt:secret ; +sip:user_493@sip.example.org clrtxt:secret ; +sip:user_494@sip.example.org clrtxt:secret ; +sip:user_495@sip.example.org clrtxt:secret ; +sip:user_496@sip.example.org clrtxt:secret ; +sip:user_497@sip.example.org clrtxt:secret ; +sip:user_498@sip.example.org clrtxt:secret ; +sip:user_499@sip.example.org clrtxt:secret ; +sip:user_500@sip.example.org clrtxt:secret ; +sip:user_501@sip.example.org clrtxt:secret ; +sip:user_502@sip.example.org clrtxt:secret ; +sip:user_503@sip.example.org clrtxt:secret ; +sip:user_504@sip.example.org clrtxt:secret ; +sip:user_505@sip.example.org clrtxt:secret ; +sip:user_506@sip.example.org clrtxt:secret ; +sip:user_507@sip.example.org clrtxt:secret ; +sip:user_508@sip.example.org clrtxt:secret ; +sip:user_509@sip.example.org clrtxt:secret ; +sip:user_510@sip.example.org clrtxt:secret ; +sip:user_511@sip.example.org clrtxt:secret ; +sip:user_512@sip.example.org clrtxt:secret ; +sip:user_513@sip.example.org clrtxt:secret ; +sip:user_514@sip.example.org clrtxt:secret ; +sip:user_515@sip.example.org clrtxt:secret ; +sip:user_516@sip.example.org clrtxt:secret ; +sip:user_517@sip.example.org clrtxt:secret ; +sip:user_518@sip.example.org clrtxt:secret ; +sip:user_519@sip.example.org clrtxt:secret ; +sip:user_520@sip.example.org clrtxt:secret ; +sip:user_521@sip.example.org clrtxt:secret ; +sip:user_522@sip.example.org clrtxt:secret ; +sip:user_523@sip.example.org clrtxt:secret ; +sip:user_524@sip.example.org clrtxt:secret ; +sip:user_525@sip.example.org clrtxt:secret ; +sip:user_526@sip.example.org clrtxt:secret ; +sip:user_527@sip.example.org clrtxt:secret ; +sip:user_528@sip.example.org clrtxt:secret ; +sip:user_529@sip.example.org clrtxt:secret ; +sip:user_530@sip.example.org clrtxt:secret ; +sip:user_531@sip.example.org clrtxt:secret ; +sip:user_532@sip.example.org clrtxt:secret ; +sip:user_533@sip.example.org clrtxt:secret ; +sip:user_534@sip.example.org clrtxt:secret ; +sip:user_535@sip.example.org clrtxt:secret ; +sip:user_536@sip.example.org clrtxt:secret ; +sip:user_537@sip.example.org clrtxt:secret ; +sip:user_538@sip.example.org clrtxt:secret ; +sip:user_539@sip.example.org clrtxt:secret ; +sip:user_540@sip.example.org clrtxt:secret ; +sip:user_541@sip.example.org clrtxt:secret ; +sip:user_542@sip.example.org clrtxt:secret ; +sip:user_543@sip.example.org clrtxt:secret ; +sip:user_544@sip.example.org clrtxt:secret ; +sip:user_545@sip.example.org clrtxt:secret ; +sip:user_546@sip.example.org clrtxt:secret ; +sip:user_547@sip.example.org clrtxt:secret ; +sip:user_548@sip.example.org clrtxt:secret ; +sip:user_549@sip.example.org clrtxt:secret ; +sip:user_550@sip.example.org clrtxt:secret ; +sip:user_551@sip.example.org clrtxt:secret ; +sip:user_552@sip.example.org clrtxt:secret ; +sip:user_553@sip.example.org clrtxt:secret ; +sip:user_554@sip.example.org clrtxt:secret ; +sip:user_555@sip.example.org clrtxt:secret ; +sip:user_556@sip.example.org clrtxt:secret ; +sip:user_557@sip.example.org clrtxt:secret ; +sip:user_558@sip.example.org clrtxt:secret ; +sip:user_559@sip.example.org clrtxt:secret ; +sip:user_560@sip.example.org clrtxt:secret ; +sip:user_561@sip.example.org clrtxt:secret ; +sip:user_562@sip.example.org clrtxt:secret ; +sip:user_563@sip.example.org clrtxt:secret ; +sip:user_564@sip.example.org clrtxt:secret ; +sip:user_565@sip.example.org clrtxt:secret ; +sip:user_566@sip.example.org clrtxt:secret ; +sip:user_567@sip.example.org clrtxt:secret ; +sip:user_568@sip.example.org clrtxt:secret ; +sip:user_569@sip.example.org clrtxt:secret ; +sip:user_570@sip.example.org clrtxt:secret ; +sip:user_571@sip.example.org clrtxt:secret ; +sip:user_572@sip.example.org clrtxt:secret ; +sip:user_573@sip.example.org clrtxt:secret ; +sip:user_574@sip.example.org clrtxt:secret ; +sip:user_575@sip.example.org clrtxt:secret ; +sip:user_576@sip.example.org clrtxt:secret ; +sip:user_577@sip.example.org clrtxt:secret ; +sip:user_578@sip.example.org clrtxt:secret ; +sip:user_579@sip.example.org clrtxt:secret ; +sip:user_580@sip.example.org clrtxt:secret ; +sip:user_581@sip.example.org clrtxt:secret ; +sip:user_582@sip.example.org clrtxt:secret ; +sip:user_583@sip.example.org clrtxt:secret ; +sip:user_584@sip.example.org clrtxt:secret ; +sip:user_585@sip.example.org clrtxt:secret ; +sip:user_586@sip.example.org clrtxt:secret ; +sip:user_587@sip.example.org clrtxt:secret ; +sip:user_588@sip.example.org clrtxt:secret ; +sip:user_589@sip.example.org clrtxt:secret ; +sip:user_590@sip.example.org clrtxt:secret ; +sip:user_591@sip.example.org clrtxt:secret ; +sip:user_592@sip.example.org clrtxt:secret ; +sip:user_593@sip.example.org clrtxt:secret ; +sip:user_594@sip.example.org clrtxt:secret ; +sip:user_595@sip.example.org clrtxt:secret ; +sip:user_596@sip.example.org clrtxt:secret ; +sip:user_597@sip.example.org clrtxt:secret ; +sip:user_598@sip.example.org clrtxt:secret ; +sip:user_599@sip.example.org clrtxt:secret ; +sip:user_600@sip.example.org clrtxt:secret ; +sip:user_601@sip.example.org clrtxt:secret ; +sip:user_602@sip.example.org clrtxt:secret ; +sip:user_603@sip.example.org clrtxt:secret ; +sip:user_604@sip.example.org clrtxt:secret ; +sip:user_605@sip.example.org clrtxt:secret ; +sip:user_606@sip.example.org clrtxt:secret ; +sip:user_607@sip.example.org clrtxt:secret ; +sip:user_608@sip.example.org clrtxt:secret ; +sip:user_609@sip.example.org clrtxt:secret ; +sip:user_610@sip.example.org clrtxt:secret ; +sip:user_611@sip.example.org clrtxt:secret ; +sip:user_612@sip.example.org clrtxt:secret ; +sip:user_613@sip.example.org clrtxt:secret ; +sip:user_614@sip.example.org clrtxt:secret ; +sip:user_615@sip.example.org clrtxt:secret ; +sip:user_616@sip.example.org clrtxt:secret ; +sip:user_617@sip.example.org clrtxt:secret ; +sip:user_618@sip.example.org clrtxt:secret ; +sip:user_619@sip.example.org clrtxt:secret ; +sip:user_620@sip.example.org clrtxt:secret ; +sip:user_621@sip.example.org clrtxt:secret ; +sip:user_622@sip.example.org clrtxt:secret ; +sip:user_623@sip.example.org clrtxt:secret ; +sip:user_624@sip.example.org clrtxt:secret ; +sip:user_625@sip.example.org clrtxt:secret ; +sip:user_626@sip.example.org clrtxt:secret ; +sip:user_627@sip.example.org clrtxt:secret ; +sip:user_628@sip.example.org clrtxt:secret ; +sip:user_629@sip.example.org clrtxt:secret ; +sip:user_630@sip.example.org clrtxt:secret ; +sip:user_631@sip.example.org clrtxt:secret ; +sip:user_632@sip.example.org clrtxt:secret ; +sip:user_633@sip.example.org clrtxt:secret ; +sip:user_634@sip.example.org clrtxt:secret ; +sip:user_635@sip.example.org clrtxt:secret ; +sip:user_636@sip.example.org clrtxt:secret ; +sip:user_637@sip.example.org clrtxt:secret ; +sip:user_638@sip.example.org clrtxt:secret ; +sip:user_639@sip.example.org clrtxt:secret ; +sip:user_640@sip.example.org clrtxt:secret ; +sip:user_641@sip.example.org clrtxt:secret ; +sip:user_642@sip.example.org clrtxt:secret ; +sip:user_643@sip.example.org clrtxt:secret ; +sip:user_644@sip.example.org clrtxt:secret ; +sip:user_645@sip.example.org clrtxt:secret ; +sip:user_646@sip.example.org clrtxt:secret ; +sip:user_647@sip.example.org clrtxt:secret ; +sip:user_648@sip.example.org clrtxt:secret ; +sip:user_649@sip.example.org clrtxt:secret ; +sip:user_650@sip.example.org clrtxt:secret ; +sip:user_651@sip.example.org clrtxt:secret ; +sip:user_652@sip.example.org clrtxt:secret ; +sip:user_653@sip.example.org clrtxt:secret ; +sip:user_654@sip.example.org clrtxt:secret ; +sip:user_655@sip.example.org clrtxt:secret ; +sip:user_656@sip.example.org clrtxt:secret ; +sip:user_657@sip.example.org clrtxt:secret ; +sip:user_658@sip.example.org clrtxt:secret ; +sip:user_659@sip.example.org clrtxt:secret ; +sip:user_660@sip.example.org clrtxt:secret ; +sip:user_661@sip.example.org clrtxt:secret ; +sip:user_662@sip.example.org clrtxt:secret ; +sip:user_663@sip.example.org clrtxt:secret ; +sip:user_664@sip.example.org clrtxt:secret ; +sip:user_665@sip.example.org clrtxt:secret ; +sip:user_666@sip.example.org clrtxt:secret ; +sip:user_667@sip.example.org clrtxt:secret ; +sip:user_668@sip.example.org clrtxt:secret ; +sip:user_669@sip.example.org clrtxt:secret ; +sip:user_670@sip.example.org clrtxt:secret ; +sip:user_671@sip.example.org clrtxt:secret ; +sip:user_672@sip.example.org clrtxt:secret ; +sip:user_673@sip.example.org clrtxt:secret ; +sip:user_674@sip.example.org clrtxt:secret ; +sip:user_675@sip.example.org clrtxt:secret ; +sip:user_676@sip.example.org clrtxt:secret ; +sip:user_677@sip.example.org clrtxt:secret ; +sip:user_678@sip.example.org clrtxt:secret ; +sip:user_679@sip.example.org clrtxt:secret ; +sip:user_680@sip.example.org clrtxt:secret ; +sip:user_681@sip.example.org clrtxt:secret ; +sip:user_682@sip.example.org clrtxt:secret ; +sip:user_683@sip.example.org clrtxt:secret ; +sip:user_684@sip.example.org clrtxt:secret ; +sip:user_685@sip.example.org clrtxt:secret ; +sip:user_686@sip.example.org clrtxt:secret ; +sip:user_687@sip.example.org clrtxt:secret ; +sip:user_688@sip.example.org clrtxt:secret ; +sip:user_689@sip.example.org clrtxt:secret ; +sip:user_690@sip.example.org clrtxt:secret ; +sip:user_691@sip.example.org clrtxt:secret ; +sip:user_692@sip.example.org clrtxt:secret ; +sip:user_693@sip.example.org clrtxt:secret ; +sip:user_694@sip.example.org clrtxt:secret ; +sip:user_695@sip.example.org clrtxt:secret ; +sip:user_696@sip.example.org clrtxt:secret ; +sip:user_697@sip.example.org clrtxt:secret ; +sip:user_698@sip.example.org clrtxt:secret ; +sip:user_699@sip.example.org clrtxt:secret ; +sip:user_700@sip.example.org clrtxt:secret ; +sip:user_701@sip.example.org clrtxt:secret ; +sip:user_702@sip.example.org clrtxt:secret ; +sip:user_703@sip.example.org clrtxt:secret ; +sip:user_704@sip.example.org clrtxt:secret ; +sip:user_705@sip.example.org clrtxt:secret ; +sip:user_706@sip.example.org clrtxt:secret ; +sip:user_707@sip.example.org clrtxt:secret ; +sip:user_708@sip.example.org clrtxt:secret ; +sip:user_709@sip.example.org clrtxt:secret ; +sip:user_710@sip.example.org clrtxt:secret ; +sip:user_711@sip.example.org clrtxt:secret ; +sip:user_712@sip.example.org clrtxt:secret ; +sip:user_713@sip.example.org clrtxt:secret ; +sip:user_714@sip.example.org clrtxt:secret ; +sip:user_715@sip.example.org clrtxt:secret ; +sip:user_716@sip.example.org clrtxt:secret ; +sip:user_717@sip.example.org clrtxt:secret ; +sip:user_718@sip.example.org clrtxt:secret ; +sip:user_719@sip.example.org clrtxt:secret ; +sip:user_720@sip.example.org clrtxt:secret ; +sip:user_721@sip.example.org clrtxt:secret ; +sip:user_722@sip.example.org clrtxt:secret ; +sip:user_723@sip.example.org clrtxt:secret ; +sip:user_724@sip.example.org clrtxt:secret ; +sip:user_725@sip.example.org clrtxt:secret ; +sip:user_726@sip.example.org clrtxt:secret ; +sip:user_727@sip.example.org clrtxt:secret ; +sip:user_728@sip.example.org clrtxt:secret ; +sip:user_729@sip.example.org clrtxt:secret ; +sip:user_730@sip.example.org clrtxt:secret ; +sip:user_731@sip.example.org clrtxt:secret ; +sip:user_732@sip.example.org clrtxt:secret ; +sip:user_733@sip.example.org clrtxt:secret ; +sip:user_734@sip.example.org clrtxt:secret ; +sip:user_735@sip.example.org clrtxt:secret ; +sip:user_736@sip.example.org clrtxt:secret ; +sip:user_737@sip.example.org clrtxt:secret ; +sip:user_738@sip.example.org clrtxt:secret ; +sip:user_739@sip.example.org clrtxt:secret ; +sip:user_740@sip.example.org clrtxt:secret ; +sip:user_741@sip.example.org clrtxt:secret ; +sip:user_742@sip.example.org clrtxt:secret ; +sip:user_743@sip.example.org clrtxt:secret ; +sip:user_744@sip.example.org clrtxt:secret ; +sip:user_745@sip.example.org clrtxt:secret ; +sip:user_746@sip.example.org clrtxt:secret ; +sip:user_747@sip.example.org clrtxt:secret ; +sip:user_748@sip.example.org clrtxt:secret ; +sip:user_749@sip.example.org clrtxt:secret ; +sip:user_750@sip.example.org clrtxt:secret ; +sip:user_751@sip.example.org clrtxt:secret ; +sip:user_752@sip.example.org clrtxt:secret ; +sip:user_753@sip.example.org clrtxt:secret ; +sip:user_754@sip.example.org clrtxt:secret ; +sip:user_755@sip.example.org clrtxt:secret ; +sip:user_756@sip.example.org clrtxt:secret ; +sip:user_757@sip.example.org clrtxt:secret ; +sip:user_758@sip.example.org clrtxt:secret ; +sip:user_759@sip.example.org clrtxt:secret ; +sip:user_760@sip.example.org clrtxt:secret ; +sip:user_761@sip.example.org clrtxt:secret ; +sip:user_762@sip.example.org clrtxt:secret ; +sip:user_763@sip.example.org clrtxt:secret ; +sip:user_764@sip.example.org clrtxt:secret ; +sip:user_765@sip.example.org clrtxt:secret ; +sip:user_766@sip.example.org clrtxt:secret ; +sip:user_767@sip.example.org clrtxt:secret ; +sip:user_768@sip.example.org clrtxt:secret ; +sip:user_769@sip.example.org clrtxt:secret ; +sip:user_770@sip.example.org clrtxt:secret ; +sip:user_771@sip.example.org clrtxt:secret ; +sip:user_772@sip.example.org clrtxt:secret ; +sip:user_773@sip.example.org clrtxt:secret ; +sip:user_774@sip.example.org clrtxt:secret ; +sip:user_775@sip.example.org clrtxt:secret ; +sip:user_776@sip.example.org clrtxt:secret ; +sip:user_777@sip.example.org clrtxt:secret ; +sip:user_778@sip.example.org clrtxt:secret ; +sip:user_779@sip.example.org clrtxt:secret ; +sip:user_780@sip.example.org clrtxt:secret ; +sip:user_781@sip.example.org clrtxt:secret ; +sip:user_782@sip.example.org clrtxt:secret ; +sip:user_783@sip.example.org clrtxt:secret ; +sip:user_784@sip.example.org clrtxt:secret ; +sip:user_785@sip.example.org clrtxt:secret ; +sip:user_786@sip.example.org clrtxt:secret ; +sip:user_787@sip.example.org clrtxt:secret ; +sip:user_788@sip.example.org clrtxt:secret ; +sip:user_789@sip.example.org clrtxt:secret ; +sip:user_790@sip.example.org clrtxt:secret ; +sip:user_791@sip.example.org clrtxt:secret ; +sip:user_792@sip.example.org clrtxt:secret ; +sip:user_793@sip.example.org clrtxt:secret ; +sip:user_794@sip.example.org clrtxt:secret ; +sip:user_795@sip.example.org clrtxt:secret ; +sip:user_796@sip.example.org clrtxt:secret ; +sip:user_797@sip.example.org clrtxt:secret ; +sip:user_798@sip.example.org clrtxt:secret ; +sip:user_799@sip.example.org clrtxt:secret ; +sip:user_800@sip.example.org clrtxt:secret ; +sip:user_801@sip.example.org clrtxt:secret ; +sip:user_802@sip.example.org clrtxt:secret ; +sip:user_803@sip.example.org clrtxt:secret ; +sip:user_804@sip.example.org clrtxt:secret ; +sip:user_805@sip.example.org clrtxt:secret ; +sip:user_806@sip.example.org clrtxt:secret ; +sip:user_807@sip.example.org clrtxt:secret ; +sip:user_808@sip.example.org clrtxt:secret ; +sip:user_809@sip.example.org clrtxt:secret ; +sip:user_810@sip.example.org clrtxt:secret ; +sip:user_811@sip.example.org clrtxt:secret ; +sip:user_812@sip.example.org clrtxt:secret ; +sip:user_813@sip.example.org clrtxt:secret ; +sip:user_814@sip.example.org clrtxt:secret ; +sip:user_815@sip.example.org clrtxt:secret ; +sip:user_816@sip.example.org clrtxt:secret ; +sip:user_817@sip.example.org clrtxt:secret ; +sip:user_818@sip.example.org clrtxt:secret ; +sip:user_819@sip.example.org clrtxt:secret ; +sip:user_820@sip.example.org clrtxt:secret ; +sip:user_821@sip.example.org clrtxt:secret ; +sip:user_822@sip.example.org clrtxt:secret ; +sip:user_823@sip.example.org clrtxt:secret ; +sip:user_824@sip.example.org clrtxt:secret ; +sip:user_825@sip.example.org clrtxt:secret ; +sip:user_826@sip.example.org clrtxt:secret ; +sip:user_827@sip.example.org clrtxt:secret ; +sip:user_828@sip.example.org clrtxt:secret ; +sip:user_829@sip.example.org clrtxt:secret ; +sip:user_830@sip.example.org clrtxt:secret ; +sip:user_831@sip.example.org clrtxt:secret ; +sip:user_832@sip.example.org clrtxt:secret ; +sip:user_833@sip.example.org clrtxt:secret ; +sip:user_834@sip.example.org clrtxt:secret ; +sip:user_835@sip.example.org clrtxt:secret ; +sip:user_836@sip.example.org clrtxt:secret ; +sip:user_837@sip.example.org clrtxt:secret ; +sip:user_838@sip.example.org clrtxt:secret ; +sip:user_839@sip.example.org clrtxt:secret ; +sip:user_840@sip.example.org clrtxt:secret ; +sip:user_841@sip.example.org clrtxt:secret ; +sip:user_842@sip.example.org clrtxt:secret ; +sip:user_843@sip.example.org clrtxt:secret ; +sip:user_844@sip.example.org clrtxt:secret ; +sip:user_845@sip.example.org clrtxt:secret ; +sip:user_846@sip.example.org clrtxt:secret ; +sip:user_847@sip.example.org clrtxt:secret ; +sip:user_848@sip.example.org clrtxt:secret ; +sip:user_849@sip.example.org clrtxt:secret ; +sip:user_850@sip.example.org clrtxt:secret ; +sip:user_851@sip.example.org clrtxt:secret ; +sip:user_852@sip.example.org clrtxt:secret ; +sip:user_853@sip.example.org clrtxt:secret ; +sip:user_854@sip.example.org clrtxt:secret ; +sip:user_855@sip.example.org clrtxt:secret ; +sip:user_856@sip.example.org clrtxt:secret ; +sip:user_857@sip.example.org clrtxt:secret ; +sip:user_858@sip.example.org clrtxt:secret ; +sip:user_859@sip.example.org clrtxt:secret ; +sip:user_860@sip.example.org clrtxt:secret ; +sip:user_861@sip.example.org clrtxt:secret ; +sip:user_862@sip.example.org clrtxt:secret ; +sip:user_863@sip.example.org clrtxt:secret ; +sip:user_864@sip.example.org clrtxt:secret ; +sip:user_865@sip.example.org clrtxt:secret ; +sip:user_866@sip.example.org clrtxt:secret ; +sip:user_867@sip.example.org clrtxt:secret ; +sip:user_868@sip.example.org clrtxt:secret ; +sip:user_869@sip.example.org clrtxt:secret ; +sip:user_870@sip.example.org clrtxt:secret ; +sip:user_871@sip.example.org clrtxt:secret ; +sip:user_872@sip.example.org clrtxt:secret ; +sip:user_873@sip.example.org clrtxt:secret ; +sip:user_874@sip.example.org clrtxt:secret ; +sip:user_875@sip.example.org clrtxt:secret ; +sip:user_876@sip.example.org clrtxt:secret ; +sip:user_877@sip.example.org clrtxt:secret ; +sip:user_878@sip.example.org clrtxt:secret ; +sip:user_879@sip.example.org clrtxt:secret ; +sip:user_880@sip.example.org clrtxt:secret ; +sip:user_881@sip.example.org clrtxt:secret ; +sip:user_882@sip.example.org clrtxt:secret ; +sip:user_883@sip.example.org clrtxt:secret ; +sip:user_884@sip.example.org clrtxt:secret ; +sip:user_885@sip.example.org clrtxt:secret ; +sip:user_886@sip.example.org clrtxt:secret ; +sip:user_887@sip.example.org clrtxt:secret ; +sip:user_888@sip.example.org clrtxt:secret ; +sip:user_889@sip.example.org clrtxt:secret ; +sip:user_890@sip.example.org clrtxt:secret ; +sip:user_891@sip.example.org clrtxt:secret ; +sip:user_892@sip.example.org clrtxt:secret ; +sip:user_893@sip.example.org clrtxt:secret ; +sip:user_894@sip.example.org clrtxt:secret ; +sip:user_895@sip.example.org clrtxt:secret ; +sip:user_896@sip.example.org clrtxt:secret ; +sip:user_897@sip.example.org clrtxt:secret ; +sip:user_898@sip.example.org clrtxt:secret ; +sip:user_899@sip.example.org clrtxt:secret ; +sip:user_900@sip.example.org clrtxt:secret ; +sip:user_901@sip.example.org clrtxt:secret ; +sip:user_902@sip.example.org clrtxt:secret ; +sip:user_903@sip.example.org clrtxt:secret ; +sip:user_904@sip.example.org clrtxt:secret ; +sip:user_905@sip.example.org clrtxt:secret ; +sip:user_906@sip.example.org clrtxt:secret ; +sip:user_907@sip.example.org clrtxt:secret ; +sip:user_908@sip.example.org clrtxt:secret ; +sip:user_909@sip.example.org clrtxt:secret ; +sip:user_910@sip.example.org clrtxt:secret ; +sip:user_911@sip.example.org clrtxt:secret ; +sip:user_912@sip.example.org clrtxt:secret ; +sip:user_913@sip.example.org clrtxt:secret ; +sip:user_914@sip.example.org clrtxt:secret ; +sip:user_915@sip.example.org clrtxt:secret ; +sip:user_916@sip.example.org clrtxt:secret ; +sip:user_917@sip.example.org clrtxt:secret ; +sip:user_918@sip.example.org clrtxt:secret ; +sip:user_919@sip.example.org clrtxt:secret ; +sip:user_920@sip.example.org clrtxt:secret ; +sip:user_921@sip.example.org clrtxt:secret ; +sip:user_922@sip.example.org clrtxt:secret ; +sip:user_923@sip.example.org clrtxt:secret ; +sip:user_924@sip.example.org clrtxt:secret ; +sip:user_925@sip.example.org clrtxt:secret ; +sip:user_926@sip.example.org clrtxt:secret ; +sip:user_927@sip.example.org clrtxt:secret ; +sip:user_928@sip.example.org clrtxt:secret ; +sip:user_929@sip.example.org clrtxt:secret ; +sip:user_930@sip.example.org clrtxt:secret ; +sip:user_931@sip.example.org clrtxt:secret ; +sip:user_932@sip.example.org clrtxt:secret ; +sip:user_933@sip.example.org clrtxt:secret ; +sip:user_934@sip.example.org clrtxt:secret ; +sip:user_935@sip.example.org clrtxt:secret ; +sip:user_936@sip.example.org clrtxt:secret ; +sip:user_937@sip.example.org clrtxt:secret ; +sip:user_938@sip.example.org clrtxt:secret ; +sip:user_939@sip.example.org clrtxt:secret ; +sip:user_940@sip.example.org clrtxt:secret ; +sip:user_941@sip.example.org clrtxt:secret ; +sip:user_942@sip.example.org clrtxt:secret ; +sip:user_943@sip.example.org clrtxt:secret ; +sip:user_944@sip.example.org clrtxt:secret ; +sip:user_945@sip.example.org clrtxt:secret ; +sip:user_946@sip.example.org clrtxt:secret ; +sip:user_947@sip.example.org clrtxt:secret ; +sip:user_948@sip.example.org clrtxt:secret ; +sip:user_949@sip.example.org clrtxt:secret ; +sip:user_950@sip.example.org clrtxt:secret ; +sip:user_951@sip.example.org clrtxt:secret ; +sip:user_952@sip.example.org clrtxt:secret ; +sip:user_953@sip.example.org clrtxt:secret ; +sip:user_954@sip.example.org clrtxt:secret ; +sip:user_955@sip.example.org clrtxt:secret ; +sip:user_956@sip.example.org clrtxt:secret ; +sip:user_957@sip.example.org clrtxt:secret ; +sip:user_958@sip.example.org clrtxt:secret ; +sip:user_959@sip.example.org clrtxt:secret ; +sip:user_960@sip.example.org clrtxt:secret ; +sip:user_961@sip.example.org clrtxt:secret ; +sip:user_962@sip.example.org clrtxt:secret ; +sip:user_963@sip.example.org clrtxt:secret ; +sip:user_964@sip.example.org clrtxt:secret ; +sip:user_965@sip.example.org clrtxt:secret ; +sip:user_966@sip.example.org clrtxt:secret ; +sip:user_967@sip.example.org clrtxt:secret ; +sip:user_968@sip.example.org clrtxt:secret ; +sip:user_969@sip.example.org clrtxt:secret ; +sip:user_970@sip.example.org clrtxt:secret ; +sip:user_971@sip.example.org clrtxt:secret ; +sip:user_972@sip.example.org clrtxt:secret ; +sip:user_973@sip.example.org clrtxt:secret ; +sip:user_974@sip.example.org clrtxt:secret ; +sip:user_975@sip.example.org clrtxt:secret ; +sip:user_976@sip.example.org clrtxt:secret ; +sip:user_977@sip.example.org clrtxt:secret ; +sip:user_978@sip.example.org clrtxt:secret ; +sip:user_979@sip.example.org clrtxt:secret ; +sip:user_980@sip.example.org clrtxt:secret ; +sip:user_981@sip.example.org clrtxt:secret ; +sip:user_982@sip.example.org clrtxt:secret ; +sip:user_983@sip.example.org clrtxt:secret ; +sip:user_984@sip.example.org clrtxt:secret ; +sip:user_985@sip.example.org clrtxt:secret ; +sip:user_986@sip.example.org clrtxt:secret ; +sip:user_987@sip.example.org clrtxt:secret ; +sip:user_988@sip.example.org clrtxt:secret ; +sip:user_989@sip.example.org clrtxt:secret ; +sip:user_990@sip.example.org clrtxt:secret ; +sip:user_991@sip.example.org clrtxt:secret ; +sip:user_992@sip.example.org clrtxt:secret ; +sip:user_993@sip.example.org clrtxt:secret ; +sip:user_994@sip.example.org clrtxt:secret ; +sip:user_995@sip.example.org clrtxt:secret ; +sip:user_996@sip.example.org clrtxt:secret ; +sip:user_997@sip.example.org clrtxt:secret ; +sip:user_998@sip.example.org clrtxt:secret ; +sip:user_999@sip.example.org clrtxt:secret ; +sip:user_1000@sip.example.org clrtxt:secret ; +sip:user_1001@sip.example.org clrtxt:secret ; +sip:user_1002@sip.example.org clrtxt:secret ; +sip:user_1003@sip.example.org clrtxt:secret ; +sip:user_1004@sip.example.org clrtxt:secret ; +sip:user_1005@sip.example.org clrtxt:secret ; +sip:user_1006@sip.example.org clrtxt:secret ; +sip:user_1007@sip.example.org clrtxt:secret ; +sip:user_1008@sip.example.org clrtxt:secret ; +sip:user_1009@sip.example.org clrtxt:secret ; +sip:user_1010@sip.example.org clrtxt:secret ; +sip:user_1011@sip.example.org clrtxt:secret ; +sip:user_1012@sip.example.org clrtxt:secret ; +sip:user_1013@sip.example.org clrtxt:secret ; +sip:user_1014@sip.example.org clrtxt:secret ; +sip:user_1015@sip.example.org clrtxt:secret ; +sip:user_1016@sip.example.org clrtxt:secret ; +sip:user_1017@sip.example.org clrtxt:secret ; +sip:user_1018@sip.example.org clrtxt:secret ; +sip:user_1019@sip.example.org clrtxt:secret ; +sip:user_1020@sip.example.org clrtxt:secret ; +sip:user_1021@sip.example.org clrtxt:secret ; +sip:user_1022@sip.example.org clrtxt:secret ; +sip:user_1023@sip.example.org clrtxt:secret ; +sip:user_1024@sip.example.org clrtxt:secret ; +sip:user_1025@sip.example.org clrtxt:secret ; +sip:user_1026@sip.example.org clrtxt:secret ; +sip:user_1027@sip.example.org clrtxt:secret ; +sip:user_1028@sip.example.org clrtxt:secret ; +sip:user_1029@sip.example.org clrtxt:secret ; +sip:user_1030@sip.example.org clrtxt:secret ; +sip:user_1031@sip.example.org clrtxt:secret ; +sip:user_1032@sip.example.org clrtxt:secret ; +sip:user_1033@sip.example.org clrtxt:secret ; +sip:user_1034@sip.example.org clrtxt:secret ; +sip:user_1035@sip.example.org clrtxt:secret ; +sip:user_1036@sip.example.org clrtxt:secret ; +sip:user_1037@sip.example.org clrtxt:secret ; +sip:user_1038@sip.example.org clrtxt:secret ; +sip:user_1039@sip.example.org clrtxt:secret ; +sip:user_1040@sip.example.org clrtxt:secret ; +sip:user_1041@sip.example.org clrtxt:secret ; +sip:user_1042@sip.example.org clrtxt:secret ; +sip:user_1043@sip.example.org clrtxt:secret ; +sip:user_1044@sip.example.org clrtxt:secret ; +sip:user_1045@sip.example.org clrtxt:secret ; +sip:user_1046@sip.example.org clrtxt:secret ; +sip:user_1047@sip.example.org clrtxt:secret ; +sip:user_1048@sip.example.org clrtxt:secret ; +sip:user_1049@sip.example.org clrtxt:secret ; +sip:user_1050@sip.example.org clrtxt:secret ; +sip:user_1051@sip.example.org clrtxt:secret ; +sip:user_1052@sip.example.org clrtxt:secret ; +sip:user_1053@sip.example.org clrtxt:secret ; +sip:user_1054@sip.example.org clrtxt:secret ; +sip:user_1055@sip.example.org clrtxt:secret ; +sip:user_1056@sip.example.org clrtxt:secret ; +sip:user_1057@sip.example.org clrtxt:secret ; +sip:user_1058@sip.example.org clrtxt:secret ; +sip:user_1059@sip.example.org clrtxt:secret ; +sip:user_1060@sip.example.org clrtxt:secret ; +sip:user_1061@sip.example.org clrtxt:secret ; +sip:user_1062@sip.example.org clrtxt:secret ; +sip:user_1063@sip.example.org clrtxt:secret ; +sip:user_1064@sip.example.org clrtxt:secret ; +sip:user_1065@sip.example.org clrtxt:secret ; +sip:user_1066@sip.example.org clrtxt:secret ; +sip:user_1067@sip.example.org clrtxt:secret ; +sip:user_1068@sip.example.org clrtxt:secret ; +sip:user_1069@sip.example.org clrtxt:secret ; +sip:user_1070@sip.example.org clrtxt:secret ; +sip:user_1071@sip.example.org clrtxt:secret ; +sip:user_1072@sip.example.org clrtxt:secret ; +sip:user_1073@sip.example.org clrtxt:secret ; +sip:user_1074@sip.example.org clrtxt:secret ; +sip:user_1075@sip.example.org clrtxt:secret ; +sip:user_1076@sip.example.org clrtxt:secret ; +sip:user_1077@sip.example.org clrtxt:secret ; +sip:user_1078@sip.example.org clrtxt:secret ; +sip:user_1079@sip.example.org clrtxt:secret ; +sip:user_1080@sip.example.org clrtxt:secret ; +sip:user_1081@sip.example.org clrtxt:secret ; +sip:user_1082@sip.example.org clrtxt:secret ; +sip:user_1083@sip.example.org clrtxt:secret ; +sip:user_1084@sip.example.org clrtxt:secret ; +sip:user_1085@sip.example.org clrtxt:secret ; +sip:user_1086@sip.example.org clrtxt:secret ; +sip:user_1087@sip.example.org clrtxt:secret ; +sip:user_1088@sip.example.org clrtxt:secret ; +sip:user_1089@sip.example.org clrtxt:secret ; +sip:user_1090@sip.example.org clrtxt:secret ; +sip:user_1091@sip.example.org clrtxt:secret ; +sip:user_1092@sip.example.org clrtxt:secret ; +sip:user_1093@sip.example.org clrtxt:secret ; +sip:user_1094@sip.example.org clrtxt:secret ; +sip:user_1095@sip.example.org clrtxt:secret ; +sip:user_1096@sip.example.org clrtxt:secret ; +sip:user_1097@sip.example.org clrtxt:secret ; +sip:user_1098@sip.example.org clrtxt:secret ; +sip:user_1099@sip.example.org clrtxt:secret ; +sip:user_1100@sip.example.org clrtxt:secret ; +sip:user_1101@sip.example.org clrtxt:secret ; +sip:user_1102@sip.example.org clrtxt:secret ; +sip:user_1103@sip.example.org clrtxt:secret ; +sip:user_1104@sip.example.org clrtxt:secret ; +sip:user_1105@sip.example.org clrtxt:secret ; +sip:user_1106@sip.example.org clrtxt:secret ; +sip:user_1107@sip.example.org clrtxt:secret ; +sip:user_1108@sip.example.org clrtxt:secret ; +sip:user_1109@sip.example.org clrtxt:secret ; +sip:user_1110@sip.example.org clrtxt:secret ; +sip:user_1111@sip.example.org clrtxt:secret ; +sip:user_1112@sip.example.org clrtxt:secret ; +sip:user_1113@sip.example.org clrtxt:secret ; +sip:user_1114@sip.example.org clrtxt:secret ; +sip:user_1115@sip.example.org clrtxt:secret ; +sip:user_1116@sip.example.org clrtxt:secret ; +sip:user_1117@sip.example.org clrtxt:secret ; +sip:user_1118@sip.example.org clrtxt:secret ; +sip:user_1119@sip.example.org clrtxt:secret ; +sip:user_1120@sip.example.org clrtxt:secret ; +sip:user_1121@sip.example.org clrtxt:secret ; +sip:user_1122@sip.example.org clrtxt:secret ; +sip:user_1123@sip.example.org clrtxt:secret ; +sip:user_1124@sip.example.org clrtxt:secret ; +sip:user_1125@sip.example.org clrtxt:secret ; +sip:user_1126@sip.example.org clrtxt:secret ; +sip:user_1127@sip.example.org clrtxt:secret ; +sip:user_1128@sip.example.org clrtxt:secret ; +sip:user_1129@sip.example.org clrtxt:secret ; +sip:user_1130@sip.example.org clrtxt:secret ; +sip:user_1131@sip.example.org clrtxt:secret ; +sip:user_1132@sip.example.org clrtxt:secret ; +sip:user_1133@sip.example.org clrtxt:secret ; +sip:user_1134@sip.example.org clrtxt:secret ; +sip:user_1135@sip.example.org clrtxt:secret ; +sip:user_1136@sip.example.org clrtxt:secret ; +sip:user_1137@sip.example.org clrtxt:secret ; +sip:user_1138@sip.example.org clrtxt:secret ; +sip:user_1139@sip.example.org clrtxt:secret ; +sip:user_1140@sip.example.org clrtxt:secret ; +sip:user_1141@sip.example.org clrtxt:secret ; +sip:user_1142@sip.example.org clrtxt:secret ; +sip:user_1143@sip.example.org clrtxt:secret ; +sip:user_1144@sip.example.org clrtxt:secret ; +sip:user_1145@sip.example.org clrtxt:secret ; +sip:user_1146@sip.example.org clrtxt:secret ; +sip:user_1147@sip.example.org clrtxt:secret ; +sip:user_1148@sip.example.org clrtxt:secret ; +sip:user_1149@sip.example.org clrtxt:secret ; +sip:user_1150@sip.example.org clrtxt:secret ; +sip:user_1151@sip.example.org clrtxt:secret ; +sip:user_1152@sip.example.org clrtxt:secret ; +sip:user_1153@sip.example.org clrtxt:secret ; +sip:user_1154@sip.example.org clrtxt:secret ; +sip:user_1155@sip.example.org clrtxt:secret ; +sip:user_1156@sip.example.org clrtxt:secret ; +sip:user_1157@sip.example.org clrtxt:secret ; +sip:user_1158@sip.example.org clrtxt:secret ; +sip:user_1159@sip.example.org clrtxt:secret ; +sip:user_1160@sip.example.org clrtxt:secret ; +sip:user_1161@sip.example.org clrtxt:secret ; +sip:user_1162@sip.example.org clrtxt:secret ; +sip:user_1163@sip.example.org clrtxt:secret ; +sip:user_1164@sip.example.org clrtxt:secret ; +sip:user_1165@sip.example.org clrtxt:secret ; +sip:user_1166@sip.example.org clrtxt:secret ; +sip:user_1167@sip.example.org clrtxt:secret ; +sip:user_1168@sip.example.org clrtxt:secret ; +sip:user_1169@sip.example.org clrtxt:secret ; +sip:user_1170@sip.example.org clrtxt:secret ; +sip:user_1171@sip.example.org clrtxt:secret ; +sip:user_1172@sip.example.org clrtxt:secret ; +sip:user_1173@sip.example.org clrtxt:secret ; +sip:user_1174@sip.example.org clrtxt:secret ; +sip:user_1175@sip.example.org clrtxt:secret ; +sip:user_1176@sip.example.org clrtxt:secret ; +sip:user_1177@sip.example.org clrtxt:secret ; +sip:user_1178@sip.example.org clrtxt:secret ; +sip:user_1179@sip.example.org clrtxt:secret ; +sip:user_1180@sip.example.org clrtxt:secret ; +sip:user_1181@sip.example.org clrtxt:secret ; +sip:user_1182@sip.example.org clrtxt:secret ; +sip:user_1183@sip.example.org clrtxt:secret ; +sip:user_1184@sip.example.org clrtxt:secret ; +sip:user_1185@sip.example.org clrtxt:secret ; +sip:user_1186@sip.example.org clrtxt:secret ; +sip:user_1187@sip.example.org clrtxt:secret ; +sip:user_1188@sip.example.org clrtxt:secret ; +sip:user_1189@sip.example.org clrtxt:secret ; +sip:user_1190@sip.example.org clrtxt:secret ; +sip:user_1191@sip.example.org clrtxt:secret ; +sip:user_1192@sip.example.org clrtxt:secret ; +sip:user_1193@sip.example.org clrtxt:secret ; +sip:user_1194@sip.example.org clrtxt:secret ; +sip:user_1195@sip.example.org clrtxt:secret ; +sip:user_1196@sip.example.org clrtxt:secret ; +sip:user_1197@sip.example.org clrtxt:secret ; +sip:user_1198@sip.example.org clrtxt:secret ; +sip:user_1199@sip.example.org clrtxt:secret ; +sip:user_1200@sip.example.org clrtxt:secret ; +sip:user_1201@sip.example.org clrtxt:secret ; +sip:user_1202@sip.example.org clrtxt:secret ; +sip:user_1203@sip.example.org clrtxt:secret ; +sip:user_1204@sip.example.org clrtxt:secret ; +sip:user_1205@sip.example.org clrtxt:secret ; +sip:user_1206@sip.example.org clrtxt:secret ; +sip:user_1207@sip.example.org clrtxt:secret ; +sip:user_1208@sip.example.org clrtxt:secret ; +sip:user_1209@sip.example.org clrtxt:secret ; +sip:user_1210@sip.example.org clrtxt:secret ; +sip:user_1211@sip.example.org clrtxt:secret ; +sip:user_1212@sip.example.org clrtxt:secret ; +sip:user_1213@sip.example.org clrtxt:secret ; +sip:user_1214@sip.example.org clrtxt:secret ; +sip:user_1215@sip.example.org clrtxt:secret ; +sip:user_1216@sip.example.org clrtxt:secret ; +sip:user_1217@sip.example.org clrtxt:secret ; +sip:user_1218@sip.example.org clrtxt:secret ; +sip:user_1219@sip.example.org clrtxt:secret ; +sip:user_1220@sip.example.org clrtxt:secret ; +sip:user_1221@sip.example.org clrtxt:secret ; +sip:user_1222@sip.example.org clrtxt:secret ; +sip:user_1223@sip.example.org clrtxt:secret ; +sip:user_1224@sip.example.org clrtxt:secret ; +sip:user_1225@sip.example.org clrtxt:secret ; +sip:user_1226@sip.example.org clrtxt:secret ; +sip:user_1227@sip.example.org clrtxt:secret ; +sip:user_1228@sip.example.org clrtxt:secret ; +sip:user_1229@sip.example.org clrtxt:secret ; +sip:user_1230@sip.example.org clrtxt:secret ; +sip:user_1231@sip.example.org clrtxt:secret ; +sip:user_1232@sip.example.org clrtxt:secret ; +sip:user_1233@sip.example.org clrtxt:secret ; +sip:user_1234@sip.example.org clrtxt:secret ; +sip:user_1235@sip.example.org clrtxt:secret ; +sip:user_1236@sip.example.org clrtxt:secret ; +sip:user_1237@sip.example.org clrtxt:secret ; +sip:user_1238@sip.example.org clrtxt:secret ; +sip:user_1239@sip.example.org clrtxt:secret ; +sip:user_1240@sip.example.org clrtxt:secret ; +sip:user_1241@sip.example.org clrtxt:secret ; +sip:user_1242@sip.example.org clrtxt:secret ; +sip:user_1243@sip.example.org clrtxt:secret ; +sip:user_1244@sip.example.org clrtxt:secret ; +sip:user_1245@sip.example.org clrtxt:secret ; +sip:user_1246@sip.example.org clrtxt:secret ; +sip:user_1247@sip.example.org clrtxt:secret ; +sip:user_1248@sip.example.org clrtxt:secret ; +sip:user_1249@sip.example.org clrtxt:secret ; +sip:user_1250@sip.example.org clrtxt:secret ; +sip:user_1251@sip.example.org clrtxt:secret ; +sip:user_1252@sip.example.org clrtxt:secret ; +sip:user_1253@sip.example.org clrtxt:secret ; +sip:user_1254@sip.example.org clrtxt:secret ; +sip:user_1255@sip.example.org clrtxt:secret ; +sip:user_1256@sip.example.org clrtxt:secret ; +sip:user_1257@sip.example.org clrtxt:secret ; +sip:user_1258@sip.example.org clrtxt:secret ; +sip:user_1259@sip.example.org clrtxt:secret ; +sip:user_1260@sip.example.org clrtxt:secret ; +sip:user_1261@sip.example.org clrtxt:secret ; +sip:user_1262@sip.example.org clrtxt:secret ; +sip:user_1263@sip.example.org clrtxt:secret ; +sip:user_1264@sip.example.org clrtxt:secret ; +sip:user_1265@sip.example.org clrtxt:secret ; +sip:user_1266@sip.example.org clrtxt:secret ; +sip:user_1267@sip.example.org clrtxt:secret ; +sip:user_1268@sip.example.org clrtxt:secret ; +sip:user_1269@sip.example.org clrtxt:secret ; +sip:user_1270@sip.example.org clrtxt:secret ; +sip:user_1271@sip.example.org clrtxt:secret ; +sip:user_1272@sip.example.org clrtxt:secret ; +sip:user_1273@sip.example.org clrtxt:secret ; +sip:user_1274@sip.example.org clrtxt:secret ; +sip:user_1275@sip.example.org clrtxt:secret ; +sip:user_1276@sip.example.org clrtxt:secret ; +sip:user_1277@sip.example.org clrtxt:secret ; +sip:user_1278@sip.example.org clrtxt:secret ; +sip:user_1279@sip.example.org clrtxt:secret ; +sip:user_1280@sip.example.org clrtxt:secret ; +sip:user_1281@sip.example.org clrtxt:secret ; +sip:user_1282@sip.example.org clrtxt:secret ; +sip:user_1283@sip.example.org clrtxt:secret ; +sip:user_1284@sip.example.org clrtxt:secret ; +sip:user_1285@sip.example.org clrtxt:secret ; +sip:user_1286@sip.example.org clrtxt:secret ; +sip:user_1287@sip.example.org clrtxt:secret ; +sip:user_1288@sip.example.org clrtxt:secret ; +sip:user_1289@sip.example.org clrtxt:secret ; +sip:user_1290@sip.example.org clrtxt:secret ; +sip:user_1291@sip.example.org clrtxt:secret ; +sip:user_1292@sip.example.org clrtxt:secret ; +sip:user_1293@sip.example.org clrtxt:secret ; +sip:user_1294@sip.example.org clrtxt:secret ; +sip:user_1295@sip.example.org clrtxt:secret ; +sip:user_1296@sip.example.org clrtxt:secret ; +sip:user_1297@sip.example.org clrtxt:secret ; +sip:user_1298@sip.example.org clrtxt:secret ; +sip:user_1299@sip.example.org clrtxt:secret ; +sip:user_1300@sip.example.org clrtxt:secret ; +sip:user_1301@sip.example.org clrtxt:secret ; +sip:user_1302@sip.example.org clrtxt:secret ; +sip:user_1303@sip.example.org clrtxt:secret ; +sip:user_1304@sip.example.org clrtxt:secret ; +sip:user_1305@sip.example.org clrtxt:secret ; +sip:user_1306@sip.example.org clrtxt:secret ; +sip:user_1307@sip.example.org clrtxt:secret ; +sip:user_1308@sip.example.org clrtxt:secret ; +sip:user_1309@sip.example.org clrtxt:secret ; +sip:user_1310@sip.example.org clrtxt:secret ; +sip:user_1311@sip.example.org clrtxt:secret ; +sip:user_1312@sip.example.org clrtxt:secret ; +sip:user_1313@sip.example.org clrtxt:secret ; +sip:user_1314@sip.example.org clrtxt:secret ; +sip:user_1315@sip.example.org clrtxt:secret ; +sip:user_1316@sip.example.org clrtxt:secret ; +sip:user_1317@sip.example.org clrtxt:secret ; +sip:user_1318@sip.example.org clrtxt:secret ; +sip:user_1319@sip.example.org clrtxt:secret ; +sip:user_1320@sip.example.org clrtxt:secret ; +sip:user_1321@sip.example.org clrtxt:secret ; +sip:user_1322@sip.example.org clrtxt:secret ; +sip:user_1323@sip.example.org clrtxt:secret ; +sip:user_1324@sip.example.org clrtxt:secret ; +sip:user_1325@sip.example.org clrtxt:secret ; +sip:user_1326@sip.example.org clrtxt:secret ; +sip:user_1327@sip.example.org clrtxt:secret ; +sip:user_1328@sip.example.org clrtxt:secret ; +sip:user_1329@sip.example.org clrtxt:secret ; +sip:user_1330@sip.example.org clrtxt:secret ; +sip:user_1331@sip.example.org clrtxt:secret ; +sip:user_1332@sip.example.org clrtxt:secret ; +sip:user_1333@sip.example.org clrtxt:secret ; +sip:user_1334@sip.example.org clrtxt:secret ; +sip:user_1335@sip.example.org clrtxt:secret ; +sip:user_1336@sip.example.org clrtxt:secret ; +sip:user_1337@sip.example.org clrtxt:secret ; +sip:user_1338@sip.example.org clrtxt:secret ; +sip:user_1339@sip.example.org clrtxt:secret ; +sip:user_1340@sip.example.org clrtxt:secret ; +sip:user_1341@sip.example.org clrtxt:secret ; +sip:user_1342@sip.example.org clrtxt:secret ; +sip:user_1343@sip.example.org clrtxt:secret ; +sip:user_1344@sip.example.org clrtxt:secret ; +sip:user_1345@sip.example.org clrtxt:secret ; +sip:user_1346@sip.example.org clrtxt:secret ; +sip:user_1347@sip.example.org clrtxt:secret ; +sip:user_1348@sip.example.org clrtxt:secret ; +sip:user_1349@sip.example.org clrtxt:secret ; +sip:user_1350@sip.example.org clrtxt:secret ; +sip:user_1351@sip.example.org clrtxt:secret ; +sip:user_1352@sip.example.org clrtxt:secret ; +sip:user_1353@sip.example.org clrtxt:secret ; +sip:user_1354@sip.example.org clrtxt:secret ; +sip:user_1355@sip.example.org clrtxt:secret ; +sip:user_1356@sip.example.org clrtxt:secret ; +sip:user_1357@sip.example.org clrtxt:secret ; +sip:user_1358@sip.example.org clrtxt:secret ; +sip:user_1359@sip.example.org clrtxt:secret ; +sip:user_1360@sip.example.org clrtxt:secret ; +sip:user_1361@sip.example.org clrtxt:secret ; +sip:user_1362@sip.example.org clrtxt:secret ; +sip:user_1363@sip.example.org clrtxt:secret ; +sip:user_1364@sip.example.org clrtxt:secret ; +sip:user_1365@sip.example.org clrtxt:secret ; +sip:user_1366@sip.example.org clrtxt:secret ; +sip:user_1367@sip.example.org clrtxt:secret ; +sip:user_1368@sip.example.org clrtxt:secret ; +sip:user_1369@sip.example.org clrtxt:secret ; +sip:user_1370@sip.example.org clrtxt:secret ; +sip:user_1371@sip.example.org clrtxt:secret ; +sip:user_1372@sip.example.org clrtxt:secret ; +sip:user_1373@sip.example.org clrtxt:secret ; +sip:user_1374@sip.example.org clrtxt:secret ; +sip:user_1375@sip.example.org clrtxt:secret ; +sip:user_1376@sip.example.org clrtxt:secret ; +sip:user_1377@sip.example.org clrtxt:secret ; +sip:user_1378@sip.example.org clrtxt:secret ; +sip:user_1379@sip.example.org clrtxt:secret ; +sip:user_1380@sip.example.org clrtxt:secret ; +sip:user_1381@sip.example.org clrtxt:secret ; +sip:user_1382@sip.example.org clrtxt:secret ; +sip:user_1383@sip.example.org clrtxt:secret ; +sip:user_1384@sip.example.org clrtxt:secret ; +sip:user_1385@sip.example.org clrtxt:secret ; +sip:user_1386@sip.example.org clrtxt:secret ; +sip:user_1387@sip.example.org clrtxt:secret ; +sip:user_1388@sip.example.org clrtxt:secret ; +sip:user_1389@sip.example.org clrtxt:secret ; +sip:user_1390@sip.example.org clrtxt:secret ; +sip:user_1391@sip.example.org clrtxt:secret ; +sip:user_1392@sip.example.org clrtxt:secret ; +sip:user_1393@sip.example.org clrtxt:secret ; +sip:user_1394@sip.example.org clrtxt:secret ; +sip:user_1395@sip.example.org clrtxt:secret ; +sip:user_1396@sip.example.org clrtxt:secret ; +sip:user_1397@sip.example.org clrtxt:secret ; +sip:user_1398@sip.example.org clrtxt:secret ; +sip:user_1399@sip.example.org clrtxt:secret ; +sip:user_1400@sip.example.org clrtxt:secret ; +sip:user_1401@sip.example.org clrtxt:secret ; +sip:user_1402@sip.example.org clrtxt:secret ; +sip:user_1403@sip.example.org clrtxt:secret ; +sip:user_1404@sip.example.org clrtxt:secret ; +sip:user_1405@sip.example.org clrtxt:secret ; +sip:user_1406@sip.example.org clrtxt:secret ; +sip:user_1407@sip.example.org clrtxt:secret ; +sip:user_1408@sip.example.org clrtxt:secret ; +sip:user_1409@sip.example.org clrtxt:secret ; +sip:user_1410@sip.example.org clrtxt:secret ; +sip:user_1411@sip.example.org clrtxt:secret ; +sip:user_1412@sip.example.org clrtxt:secret ; +sip:user_1413@sip.example.org clrtxt:secret ; +sip:user_1414@sip.example.org clrtxt:secret ; +sip:user_1415@sip.example.org clrtxt:secret ; +sip:user_1416@sip.example.org clrtxt:secret ; +sip:user_1417@sip.example.org clrtxt:secret ; +sip:user_1418@sip.example.org clrtxt:secret ; +sip:user_1419@sip.example.org clrtxt:secret ; +sip:user_1420@sip.example.org clrtxt:secret ; +sip:user_1421@sip.example.org clrtxt:secret ; +sip:user_1422@sip.example.org clrtxt:secret ; +sip:user_1423@sip.example.org clrtxt:secret ; +sip:user_1424@sip.example.org clrtxt:secret ; +sip:user_1425@sip.example.org clrtxt:secret ; +sip:user_1426@sip.example.org clrtxt:secret ; +sip:user_1427@sip.example.org clrtxt:secret ; +sip:user_1428@sip.example.org clrtxt:secret ; +sip:user_1429@sip.example.org clrtxt:secret ; +sip:user_1430@sip.example.org clrtxt:secret ; +sip:user_1431@sip.example.org clrtxt:secret ; +sip:user_1432@sip.example.org clrtxt:secret ; +sip:user_1433@sip.example.org clrtxt:secret ; +sip:user_1434@sip.example.org clrtxt:secret ; +sip:user_1435@sip.example.org clrtxt:secret ; +sip:user_1436@sip.example.org clrtxt:secret ; +sip:user_1437@sip.example.org clrtxt:secret ; +sip:user_1438@sip.example.org clrtxt:secret ; +sip:user_1439@sip.example.org clrtxt:secret ; +sip:user_1440@sip.example.org clrtxt:secret ; +sip:user_1441@sip.example.org clrtxt:secret ; +sip:user_1442@sip.example.org clrtxt:secret ; +sip:user_1443@sip.example.org clrtxt:secret ; +sip:user_1444@sip.example.org clrtxt:secret ; +sip:user_1445@sip.example.org clrtxt:secret ; +sip:user_1446@sip.example.org clrtxt:secret ; +sip:user_1447@sip.example.org clrtxt:secret ; +sip:user_1448@sip.example.org clrtxt:secret ; +sip:user_1449@sip.example.org clrtxt:secret ; +sip:user_1450@sip.example.org clrtxt:secret ; +sip:user_1451@sip.example.org clrtxt:secret ; +sip:user_1452@sip.example.org clrtxt:secret ; +sip:user_1453@sip.example.org clrtxt:secret ; +sip:user_1454@sip.example.org clrtxt:secret ; +sip:user_1455@sip.example.org clrtxt:secret ; +sip:user_1456@sip.example.org clrtxt:secret ; +sip:user_1457@sip.example.org clrtxt:secret ; +sip:user_1458@sip.example.org clrtxt:secret ; +sip:user_1459@sip.example.org clrtxt:secret ; +sip:user_1460@sip.example.org clrtxt:secret ; +sip:user_1461@sip.example.org clrtxt:secret ; +sip:user_1462@sip.example.org clrtxt:secret ; +sip:user_1463@sip.example.org clrtxt:secret ; +sip:user_1464@sip.example.org clrtxt:secret ; +sip:user_1465@sip.example.org clrtxt:secret ; +sip:user_1466@sip.example.org clrtxt:secret ; +sip:user_1467@sip.example.org clrtxt:secret ; +sip:user_1468@sip.example.org clrtxt:secret ; +sip:user_1469@sip.example.org clrtxt:secret ; +sip:user_1470@sip.example.org clrtxt:secret ; +sip:user_1471@sip.example.org clrtxt:secret ; +sip:user_1472@sip.example.org clrtxt:secret ; +sip:user_1473@sip.example.org clrtxt:secret ; +sip:user_1474@sip.example.org clrtxt:secret ; +sip:user_1475@sip.example.org clrtxt:secret ; +sip:user_1476@sip.example.org clrtxt:secret ; +sip:user_1477@sip.example.org clrtxt:secret ; +sip:user_1478@sip.example.org clrtxt:secret ; +sip:user_1479@sip.example.org clrtxt:secret ; +sip:user_1480@sip.example.org clrtxt:secret ; +sip:user_1481@sip.example.org clrtxt:secret ; +sip:user_1482@sip.example.org clrtxt:secret ; +sip:user_1483@sip.example.org clrtxt:secret ; +sip:user_1484@sip.example.org clrtxt:secret ; +sip:user_1485@sip.example.org clrtxt:secret ; +sip:user_1486@sip.example.org clrtxt:secret ; +sip:user_1487@sip.example.org clrtxt:secret ; +sip:user_1488@sip.example.org clrtxt:secret ; +sip:user_1489@sip.example.org clrtxt:secret ; +sip:user_1490@sip.example.org clrtxt:secret ; +sip:user_1491@sip.example.org clrtxt:secret ; +sip:user_1492@sip.example.org clrtxt:secret ; +sip:user_1493@sip.example.org clrtxt:secret ; +sip:user_1494@sip.example.org clrtxt:secret ; +sip:user_1495@sip.example.org clrtxt:secret ; +sip:user_1496@sip.example.org clrtxt:secret ; +sip:user_1497@sip.example.org clrtxt:secret ; +sip:user_1498@sip.example.org clrtxt:secret ; +sip:user_1499@sip.example.org clrtxt:secret ; +sip:user_1500@sip.example.org clrtxt:secret ; +sip:user_1501@sip.example.org clrtxt:secret ; +sip:user_1502@sip.example.org clrtxt:secret ; +sip:user_1503@sip.example.org clrtxt:secret ; +sip:user_1504@sip.example.org clrtxt:secret ; +sip:user_1505@sip.example.org clrtxt:secret ; +sip:user_1506@sip.example.org clrtxt:secret ; +sip:user_1507@sip.example.org clrtxt:secret ; +sip:user_1508@sip.example.org clrtxt:secret ; +sip:user_1509@sip.example.org clrtxt:secret ; +sip:user_1510@sip.example.org clrtxt:secret ; +sip:user_1511@sip.example.org clrtxt:secret ; +sip:user_1512@sip.example.org clrtxt:secret ; +sip:user_1513@sip.example.org clrtxt:secret ; +sip:user_1514@sip.example.org clrtxt:secret ; +sip:user_1515@sip.example.org clrtxt:secret ; +sip:user_1516@sip.example.org clrtxt:secret ; +sip:user_1517@sip.example.org clrtxt:secret ; +sip:user_1518@sip.example.org clrtxt:secret ; +sip:user_1519@sip.example.org clrtxt:secret ; +sip:user_1520@sip.example.org clrtxt:secret ; +sip:user_1521@sip.example.org clrtxt:secret ; +sip:user_1522@sip.example.org clrtxt:secret ; +sip:user_1523@sip.example.org clrtxt:secret ; +sip:user_1524@sip.example.org clrtxt:secret ; +sip:user_1525@sip.example.org clrtxt:secret ; +sip:user_1526@sip.example.org clrtxt:secret ; +sip:user_1527@sip.example.org clrtxt:secret ; +sip:user_1528@sip.example.org clrtxt:secret ; +sip:user_1529@sip.example.org clrtxt:secret ; +sip:user_1530@sip.example.org clrtxt:secret ; +sip:user_1531@sip.example.org clrtxt:secret ; +sip:user_1532@sip.example.org clrtxt:secret ; +sip:user_1533@sip.example.org clrtxt:secret ; +sip:user_1534@sip.example.org clrtxt:secret ; +sip:user_1535@sip.example.org clrtxt:secret ; +sip:user_1536@sip.example.org clrtxt:secret ; +sip:user_1537@sip.example.org clrtxt:secret ; +sip:user_1538@sip.example.org clrtxt:secret ; +sip:user_1539@sip.example.org clrtxt:secret ; +sip:user_1540@sip.example.org clrtxt:secret ; +sip:user_1541@sip.example.org clrtxt:secret ; +sip:user_1542@sip.example.org clrtxt:secret ; +sip:user_1543@sip.example.org clrtxt:secret ; +sip:user_1544@sip.example.org clrtxt:secret ; +sip:user_1545@sip.example.org clrtxt:secret ; +sip:user_1546@sip.example.org clrtxt:secret ; +sip:user_1547@sip.example.org clrtxt:secret ; +sip:user_1548@sip.example.org clrtxt:secret ; +sip:user_1549@sip.example.org clrtxt:secret ; +sip:user_1550@sip.example.org clrtxt:secret ; +sip:user_1551@sip.example.org clrtxt:secret ; +sip:user_1552@sip.example.org clrtxt:secret ; +sip:user_1553@sip.example.org clrtxt:secret ; +sip:user_1554@sip.example.org clrtxt:secret ; +sip:user_1555@sip.example.org clrtxt:secret ; +sip:user_1556@sip.example.org clrtxt:secret ; +sip:user_1557@sip.example.org clrtxt:secret ; +sip:user_1558@sip.example.org clrtxt:secret ; +sip:user_1559@sip.example.org clrtxt:secret ; +sip:user_1560@sip.example.org clrtxt:secret ; +sip:user_1561@sip.example.org clrtxt:secret ; +sip:user_1562@sip.example.org clrtxt:secret ; +sip:user_1563@sip.example.org clrtxt:secret ; +sip:user_1564@sip.example.org clrtxt:secret ; +sip:user_1565@sip.example.org clrtxt:secret ; +sip:user_1566@sip.example.org clrtxt:secret ; +sip:user_1567@sip.example.org clrtxt:secret ; +sip:user_1568@sip.example.org clrtxt:secret ; +sip:user_1569@sip.example.org clrtxt:secret ; +sip:user_1570@sip.example.org clrtxt:secret ; +sip:user_1571@sip.example.org clrtxt:secret ; +sip:user_1572@sip.example.org clrtxt:secret ; +sip:user_1573@sip.example.org clrtxt:secret ; +sip:user_1574@sip.example.org clrtxt:secret ; +sip:user_1575@sip.example.org clrtxt:secret ; +sip:user_1576@sip.example.org clrtxt:secret ; +sip:user_1577@sip.example.org clrtxt:secret ; +sip:user_1578@sip.example.org clrtxt:secret ; +sip:user_1579@sip.example.org clrtxt:secret ; +sip:user_1580@sip.example.org clrtxt:secret ; +sip:user_1581@sip.example.org clrtxt:secret ; +sip:user_1582@sip.example.org clrtxt:secret ; +sip:user_1583@sip.example.org clrtxt:secret ; +sip:user_1584@sip.example.org clrtxt:secret ; +sip:user_1585@sip.example.org clrtxt:secret ; +sip:user_1586@sip.example.org clrtxt:secret ; +sip:user_1587@sip.example.org clrtxt:secret ; +sip:user_1588@sip.example.org clrtxt:secret ; +sip:user_1589@sip.example.org clrtxt:secret ; +sip:user_1590@sip.example.org clrtxt:secret ; +sip:user_1591@sip.example.org clrtxt:secret ; +sip:user_1592@sip.example.org clrtxt:secret ; +sip:user_1593@sip.example.org clrtxt:secret ; +sip:user_1594@sip.example.org clrtxt:secret ; +sip:user_1595@sip.example.org clrtxt:secret ; +sip:user_1596@sip.example.org clrtxt:secret ; +sip:user_1597@sip.example.org clrtxt:secret ; +sip:user_1598@sip.example.org clrtxt:secret ; +sip:user_1599@sip.example.org clrtxt:secret ; +sip:user_1600@sip.example.org clrtxt:secret ; +sip:user_1601@sip.example.org clrtxt:secret ; +sip:user_1602@sip.example.org clrtxt:secret ; +sip:user_1603@sip.example.org clrtxt:secret ; +sip:user_1604@sip.example.org clrtxt:secret ; +sip:user_1605@sip.example.org clrtxt:secret ; +sip:user_1606@sip.example.org clrtxt:secret ; +sip:user_1607@sip.example.org clrtxt:secret ; +sip:user_1608@sip.example.org clrtxt:secret ; +sip:user_1609@sip.example.org clrtxt:secret ; +sip:user_1610@sip.example.org clrtxt:secret ; +sip:user_1611@sip.example.org clrtxt:secret ; +sip:user_1612@sip.example.org clrtxt:secret ; +sip:user_1613@sip.example.org clrtxt:secret ; +sip:user_1614@sip.example.org clrtxt:secret ; +sip:user_1615@sip.example.org clrtxt:secret ; +sip:user_1616@sip.example.org clrtxt:secret ; +sip:user_1617@sip.example.org clrtxt:secret ; +sip:user_1618@sip.example.org clrtxt:secret ; +sip:user_1619@sip.example.org clrtxt:secret ; +sip:user_1620@sip.example.org clrtxt:secret ; +sip:user_1621@sip.example.org clrtxt:secret ; +sip:user_1622@sip.example.org clrtxt:secret ; +sip:user_1623@sip.example.org clrtxt:secret ; +sip:user_1624@sip.example.org clrtxt:secret ; +sip:user_1625@sip.example.org clrtxt:secret ; +sip:user_1626@sip.example.org clrtxt:secret ; +sip:user_1627@sip.example.org clrtxt:secret ; +sip:user_1628@sip.example.org clrtxt:secret ; +sip:user_1629@sip.example.org clrtxt:secret ; +sip:user_1630@sip.example.org clrtxt:secret ; +sip:user_1631@sip.example.org clrtxt:secret ; +sip:user_1632@sip.example.org clrtxt:secret ; +sip:user_1633@sip.example.org clrtxt:secret ; +sip:user_1634@sip.example.org clrtxt:secret ; +sip:user_1635@sip.example.org clrtxt:secret ; +sip:user_1636@sip.example.org clrtxt:secret ; +sip:user_1637@sip.example.org clrtxt:secret ; +sip:user_1638@sip.example.org clrtxt:secret ; +sip:user_1639@sip.example.org clrtxt:secret ; +sip:user_1640@sip.example.org clrtxt:secret ; +sip:user_1641@sip.example.org clrtxt:secret ; +sip:user_1642@sip.example.org clrtxt:secret ; +sip:user_1643@sip.example.org clrtxt:secret ; +sip:user_1644@sip.example.org clrtxt:secret ; +sip:user_1645@sip.example.org clrtxt:secret ; +sip:user_1646@sip.example.org clrtxt:secret ; +sip:user_1647@sip.example.org clrtxt:secret ; +sip:user_1648@sip.example.org clrtxt:secret ; +sip:user_1649@sip.example.org clrtxt:secret ; +sip:user_1650@sip.example.org clrtxt:secret ; +sip:user_1651@sip.example.org clrtxt:secret ; +sip:user_1652@sip.example.org clrtxt:secret ; +sip:user_1653@sip.example.org clrtxt:secret ; +sip:user_1654@sip.example.org clrtxt:secret ; +sip:user_1655@sip.example.org clrtxt:secret ; +sip:user_1656@sip.example.org clrtxt:secret ; +sip:user_1657@sip.example.org clrtxt:secret ; +sip:user_1658@sip.example.org clrtxt:secret ; +sip:user_1659@sip.example.org clrtxt:secret ; +sip:user_1660@sip.example.org clrtxt:secret ; +sip:user_1661@sip.example.org clrtxt:secret ; +sip:user_1662@sip.example.org clrtxt:secret ; +sip:user_1663@sip.example.org clrtxt:secret ; +sip:user_1664@sip.example.org clrtxt:secret ; +sip:user_1665@sip.example.org clrtxt:secret ; +sip:user_1666@sip.example.org clrtxt:secret ; +sip:user_1667@sip.example.org clrtxt:secret ; +sip:user_1668@sip.example.org clrtxt:secret ; +sip:user_1669@sip.example.org clrtxt:secret ; +sip:user_1670@sip.example.org clrtxt:secret ; +sip:user_1671@sip.example.org clrtxt:secret ; +sip:user_1672@sip.example.org clrtxt:secret ; +sip:user_1673@sip.example.org clrtxt:secret ; +sip:user_1674@sip.example.org clrtxt:secret ; +sip:user_1675@sip.example.org clrtxt:secret ; +sip:user_1676@sip.example.org clrtxt:secret ; +sip:user_1677@sip.example.org clrtxt:secret ; +sip:user_1678@sip.example.org clrtxt:secret ; +sip:user_1679@sip.example.org clrtxt:secret ; +sip:user_1680@sip.example.org clrtxt:secret ; +sip:user_1681@sip.example.org clrtxt:secret ; +sip:user_1682@sip.example.org clrtxt:secret ; +sip:user_1683@sip.example.org clrtxt:secret ; +sip:user_1684@sip.example.org clrtxt:secret ; +sip:user_1685@sip.example.org clrtxt:secret ; +sip:user_1686@sip.example.org clrtxt:secret ; +sip:user_1687@sip.example.org clrtxt:secret ; +sip:user_1688@sip.example.org clrtxt:secret ; +sip:user_1689@sip.example.org clrtxt:secret ; +sip:user_1690@sip.example.org clrtxt:secret ; +sip:user_1691@sip.example.org clrtxt:secret ; +sip:user_1692@sip.example.org clrtxt:secret ; +sip:user_1693@sip.example.org clrtxt:secret ; +sip:user_1694@sip.example.org clrtxt:secret ; +sip:user_1695@sip.example.org clrtxt:secret ; +sip:user_1696@sip.example.org clrtxt:secret ; +sip:user_1697@sip.example.org clrtxt:secret ; +sip:user_1698@sip.example.org clrtxt:secret ; +sip:user_1699@sip.example.org clrtxt:secret ; +sip:user_1700@sip.example.org clrtxt:secret ; +sip:user_1701@sip.example.org clrtxt:secret ; +sip:user_1702@sip.example.org clrtxt:secret ; +sip:user_1703@sip.example.org clrtxt:secret ; +sip:user_1704@sip.example.org clrtxt:secret ; +sip:user_1705@sip.example.org clrtxt:secret ; +sip:user_1706@sip.example.org clrtxt:secret ; +sip:user_1707@sip.example.org clrtxt:secret ; +sip:user_1708@sip.example.org clrtxt:secret ; +sip:user_1709@sip.example.org clrtxt:secret ; +sip:user_1710@sip.example.org clrtxt:secret ; +sip:user_1711@sip.example.org clrtxt:secret ; +sip:user_1712@sip.example.org clrtxt:secret ; +sip:user_1713@sip.example.org clrtxt:secret ; +sip:user_1714@sip.example.org clrtxt:secret ; +sip:user_1715@sip.example.org clrtxt:secret ; +sip:user_1716@sip.example.org clrtxt:secret ; +sip:user_1717@sip.example.org clrtxt:secret ; +sip:user_1718@sip.example.org clrtxt:secret ; +sip:user_1719@sip.example.org clrtxt:secret ; +sip:user_1720@sip.example.org clrtxt:secret ; +sip:user_1721@sip.example.org clrtxt:secret ; +sip:user_1722@sip.example.org clrtxt:secret ; +sip:user_1723@sip.example.org clrtxt:secret ; +sip:user_1724@sip.example.org clrtxt:secret ; +sip:user_1725@sip.example.org clrtxt:secret ; +sip:user_1726@sip.example.org clrtxt:secret ; +sip:user_1727@sip.example.org clrtxt:secret ; +sip:user_1728@sip.example.org clrtxt:secret ; +sip:user_1729@sip.example.org clrtxt:secret ; +sip:user_1730@sip.example.org clrtxt:secret ; +sip:user_1731@sip.example.org clrtxt:secret ; +sip:user_1732@sip.example.org clrtxt:secret ; +sip:user_1733@sip.example.org clrtxt:secret ; +sip:user_1734@sip.example.org clrtxt:secret ; +sip:user_1735@sip.example.org clrtxt:secret ; +sip:user_1736@sip.example.org clrtxt:secret ; +sip:user_1737@sip.example.org clrtxt:secret ; +sip:user_1738@sip.example.org clrtxt:secret ; +sip:user_1739@sip.example.org clrtxt:secret ; +sip:user_1740@sip.example.org clrtxt:secret ; +sip:user_1741@sip.example.org clrtxt:secret ; +sip:user_1742@sip.example.org clrtxt:secret ; +sip:user_1743@sip.example.org clrtxt:secret ; +sip:user_1744@sip.example.org clrtxt:secret ; +sip:user_1745@sip.example.org clrtxt:secret ; +sip:user_1746@sip.example.org clrtxt:secret ; +sip:user_1747@sip.example.org clrtxt:secret ; +sip:user_1748@sip.example.org clrtxt:secret ; +sip:user_1749@sip.example.org clrtxt:secret ; +sip:user_1750@sip.example.org clrtxt:secret ; +sip:user_1751@sip.example.org clrtxt:secret ; +sip:user_1752@sip.example.org clrtxt:secret ; +sip:user_1753@sip.example.org clrtxt:secret ; +sip:user_1754@sip.example.org clrtxt:secret ; +sip:user_1755@sip.example.org clrtxt:secret ; +sip:user_1756@sip.example.org clrtxt:secret ; +sip:user_1757@sip.example.org clrtxt:secret ; +sip:user_1758@sip.example.org clrtxt:secret ; +sip:user_1759@sip.example.org clrtxt:secret ; +sip:user_1760@sip.example.org clrtxt:secret ; +sip:user_1761@sip.example.org clrtxt:secret ; +sip:user_1762@sip.example.org clrtxt:secret ; +sip:user_1763@sip.example.org clrtxt:secret ; +sip:user_1764@sip.example.org clrtxt:secret ; +sip:user_1765@sip.example.org clrtxt:secret ; +sip:user_1766@sip.example.org clrtxt:secret ; +sip:user_1767@sip.example.org clrtxt:secret ; +sip:user_1768@sip.example.org clrtxt:secret ; +sip:user_1769@sip.example.org clrtxt:secret ; +sip:user_1770@sip.example.org clrtxt:secret ; +sip:user_1771@sip.example.org clrtxt:secret ; +sip:user_1772@sip.example.org clrtxt:secret ; +sip:user_1773@sip.example.org clrtxt:secret ; +sip:user_1774@sip.example.org clrtxt:secret ; +sip:user_1775@sip.example.org clrtxt:secret ; +sip:user_1776@sip.example.org clrtxt:secret ; +sip:user_1777@sip.example.org clrtxt:secret ; +sip:user_1778@sip.example.org clrtxt:secret ; +sip:user_1779@sip.example.org clrtxt:secret ; +sip:user_1780@sip.example.org clrtxt:secret ; +sip:user_1781@sip.example.org clrtxt:secret ; +sip:user_1782@sip.example.org clrtxt:secret ; +sip:user_1783@sip.example.org clrtxt:secret ; +sip:user_1784@sip.example.org clrtxt:secret ; +sip:user_1785@sip.example.org clrtxt:secret ; +sip:user_1786@sip.example.org clrtxt:secret ; +sip:user_1787@sip.example.org clrtxt:secret ; +sip:user_1788@sip.example.org clrtxt:secret ; +sip:user_1789@sip.example.org clrtxt:secret ; +sip:user_1790@sip.example.org clrtxt:secret ; +sip:user_1791@sip.example.org clrtxt:secret ; +sip:user_1792@sip.example.org clrtxt:secret ; +sip:user_1793@sip.example.org clrtxt:secret ; +sip:user_1794@sip.example.org clrtxt:secret ; +sip:user_1795@sip.example.org clrtxt:secret ; +sip:user_1796@sip.example.org clrtxt:secret ; +sip:user_1797@sip.example.org clrtxt:secret ; +sip:user_1798@sip.example.org clrtxt:secret ; +sip:user_1799@sip.example.org clrtxt:secret ; +sip:user_1800@sip.example.org clrtxt:secret ; +sip:user_1801@sip.example.org clrtxt:secret ; +sip:user_1802@sip.example.org clrtxt:secret ; +sip:user_1803@sip.example.org clrtxt:secret ; +sip:user_1804@sip.example.org clrtxt:secret ; +sip:user_1805@sip.example.org clrtxt:secret ; +sip:user_1806@sip.example.org clrtxt:secret ; +sip:user_1807@sip.example.org clrtxt:secret ; +sip:user_1808@sip.example.org clrtxt:secret ; +sip:user_1809@sip.example.org clrtxt:secret ; +sip:user_1810@sip.example.org clrtxt:secret ; +sip:user_1811@sip.example.org clrtxt:secret ; +sip:user_1812@sip.example.org clrtxt:secret ; +sip:user_1813@sip.example.org clrtxt:secret ; +sip:user_1814@sip.example.org clrtxt:secret ; +sip:user_1815@sip.example.org clrtxt:secret ; +sip:user_1816@sip.example.org clrtxt:secret ; +sip:user_1817@sip.example.org clrtxt:secret ; +sip:user_1818@sip.example.org clrtxt:secret ; +sip:user_1819@sip.example.org clrtxt:secret ; +sip:user_1820@sip.example.org clrtxt:secret ; +sip:user_1821@sip.example.org clrtxt:secret ; +sip:user_1822@sip.example.org clrtxt:secret ; +sip:user_1823@sip.example.org clrtxt:secret ; +sip:user_1824@sip.example.org clrtxt:secret ; +sip:user_1825@sip.example.org clrtxt:secret ; +sip:user_1826@sip.example.org clrtxt:secret ; +sip:user_1827@sip.example.org clrtxt:secret ; +sip:user_1828@sip.example.org clrtxt:secret ; +sip:user_1829@sip.example.org clrtxt:secret ; +sip:user_1830@sip.example.org clrtxt:secret ; +sip:user_1831@sip.example.org clrtxt:secret ; +sip:user_1832@sip.example.org clrtxt:secret ; +sip:user_1833@sip.example.org clrtxt:secret ; +sip:user_1834@sip.example.org clrtxt:secret ; +sip:user_1835@sip.example.org clrtxt:secret ; +sip:user_1836@sip.example.org clrtxt:secret ; +sip:user_1837@sip.example.org clrtxt:secret ; +sip:user_1838@sip.example.org clrtxt:secret ; +sip:user_1839@sip.example.org clrtxt:secret ; +sip:user_1840@sip.example.org clrtxt:secret ; +sip:user_1841@sip.example.org clrtxt:secret ; +sip:user_1842@sip.example.org clrtxt:secret ; +sip:user_1843@sip.example.org clrtxt:secret ; +sip:user_1844@sip.example.org clrtxt:secret ; +sip:user_1845@sip.example.org clrtxt:secret ; +sip:user_1846@sip.example.org clrtxt:secret ; +sip:user_1847@sip.example.org clrtxt:secret ; +sip:user_1848@sip.example.org clrtxt:secret ; +sip:user_1849@sip.example.org clrtxt:secret ; +sip:user_1850@sip.example.org clrtxt:secret ; +sip:user_1851@sip.example.org clrtxt:secret ; +sip:user_1852@sip.example.org clrtxt:secret ; +sip:user_1853@sip.example.org clrtxt:secret ; +sip:user_1854@sip.example.org clrtxt:secret ; +sip:user_1855@sip.example.org clrtxt:secret ; +sip:user_1856@sip.example.org clrtxt:secret ; +sip:user_1857@sip.example.org clrtxt:secret ; +sip:user_1858@sip.example.org clrtxt:secret ; +sip:user_1859@sip.example.org clrtxt:secret ; +sip:user_1860@sip.example.org clrtxt:secret ; +sip:user_1861@sip.example.org clrtxt:secret ; +sip:user_1862@sip.example.org clrtxt:secret ; +sip:user_1863@sip.example.org clrtxt:secret ; +sip:user_1864@sip.example.org clrtxt:secret ; +sip:user_1865@sip.example.org clrtxt:secret ; +sip:user_1866@sip.example.org clrtxt:secret ; +sip:user_1867@sip.example.org clrtxt:secret ; +sip:user_1868@sip.example.org clrtxt:secret ; +sip:user_1869@sip.example.org clrtxt:secret ; +sip:user_1870@sip.example.org clrtxt:secret ; +sip:user_1871@sip.example.org clrtxt:secret ; +sip:user_1872@sip.example.org clrtxt:secret ; +sip:user_1873@sip.example.org clrtxt:secret ; +sip:user_1874@sip.example.org clrtxt:secret ; +sip:user_1875@sip.example.org clrtxt:secret ; +sip:user_1876@sip.example.org clrtxt:secret ; +sip:user_1877@sip.example.org clrtxt:secret ; +sip:user_1878@sip.example.org clrtxt:secret ; +sip:user_1879@sip.example.org clrtxt:secret ; +sip:user_1880@sip.example.org clrtxt:secret ; +sip:user_1881@sip.example.org clrtxt:secret ; +sip:user_1882@sip.example.org clrtxt:secret ; +sip:user_1883@sip.example.org clrtxt:secret ; +sip:user_1884@sip.example.org clrtxt:secret ; +sip:user_1885@sip.example.org clrtxt:secret ; +sip:user_1886@sip.example.org clrtxt:secret ; +sip:user_1887@sip.example.org clrtxt:secret ; +sip:user_1888@sip.example.org clrtxt:secret ; +sip:user_1889@sip.example.org clrtxt:secret ; +sip:user_1890@sip.example.org clrtxt:secret ; +sip:user_1891@sip.example.org clrtxt:secret ; +sip:user_1892@sip.example.org clrtxt:secret ; +sip:user_1893@sip.example.org clrtxt:secret ; +sip:user_1894@sip.example.org clrtxt:secret ; +sip:user_1895@sip.example.org clrtxt:secret ; +sip:user_1896@sip.example.org clrtxt:secret ; +sip:user_1897@sip.example.org clrtxt:secret ; +sip:user_1898@sip.example.org clrtxt:secret ; +sip:user_1899@sip.example.org clrtxt:secret ; +sip:user_1900@sip.example.org clrtxt:secret ; +sip:user_1901@sip.example.org clrtxt:secret ; +sip:user_1902@sip.example.org clrtxt:secret ; +sip:user_1903@sip.example.org clrtxt:secret ; +sip:user_1904@sip.example.org clrtxt:secret ; +sip:user_1905@sip.example.org clrtxt:secret ; +sip:user_1906@sip.example.org clrtxt:secret ; +sip:user_1907@sip.example.org clrtxt:secret ; +sip:user_1908@sip.example.org clrtxt:secret ; +sip:user_1909@sip.example.org clrtxt:secret ; +sip:user_1910@sip.example.org clrtxt:secret ; +sip:user_1911@sip.example.org clrtxt:secret ; +sip:user_1912@sip.example.org clrtxt:secret ; +sip:user_1913@sip.example.org clrtxt:secret ; +sip:user_1914@sip.example.org clrtxt:secret ; +sip:user_1915@sip.example.org clrtxt:secret ; +sip:user_1916@sip.example.org clrtxt:secret ; +sip:user_1917@sip.example.org clrtxt:secret ; +sip:user_1918@sip.example.org clrtxt:secret ; +sip:user_1919@sip.example.org clrtxt:secret ; +sip:user_1920@sip.example.org clrtxt:secret ; +sip:user_1921@sip.example.org clrtxt:secret ; +sip:user_1922@sip.example.org clrtxt:secret ; +sip:user_1923@sip.example.org clrtxt:secret ; +sip:user_1924@sip.example.org clrtxt:secret ; +sip:user_1925@sip.example.org clrtxt:secret ; +sip:user_1926@sip.example.org clrtxt:secret ; +sip:user_1927@sip.example.org clrtxt:secret ; +sip:user_1928@sip.example.org clrtxt:secret ; +sip:user_1929@sip.example.org clrtxt:secret ; +sip:user_1930@sip.example.org clrtxt:secret ; +sip:user_1931@sip.example.org clrtxt:secret ; +sip:user_1932@sip.example.org clrtxt:secret ; +sip:user_1933@sip.example.org clrtxt:secret ; +sip:user_1934@sip.example.org clrtxt:secret ; +sip:user_1935@sip.example.org clrtxt:secret ; +sip:user_1936@sip.example.org clrtxt:secret ; +sip:user_1937@sip.example.org clrtxt:secret ; +sip:user_1938@sip.example.org clrtxt:secret ; +sip:user_1939@sip.example.org clrtxt:secret ; +sip:user_1940@sip.example.org clrtxt:secret ; +sip:user_1941@sip.example.org clrtxt:secret ; +sip:user_1942@sip.example.org clrtxt:secret ; +sip:user_1943@sip.example.org clrtxt:secret ; +sip:user_1944@sip.example.org clrtxt:secret ; +sip:user_1945@sip.example.org clrtxt:secret ; +sip:user_1946@sip.example.org clrtxt:secret ; +sip:user_1947@sip.example.org clrtxt:secret ; +sip:user_1948@sip.example.org clrtxt:secret ; +sip:user_1949@sip.example.org clrtxt:secret ; +sip:user_1950@sip.example.org clrtxt:secret ; +sip:user_1951@sip.example.org clrtxt:secret ; +sip:user_1952@sip.example.org clrtxt:secret ; +sip:user_1953@sip.example.org clrtxt:secret ; +sip:user_1954@sip.example.org clrtxt:secret ; +sip:user_1955@sip.example.org clrtxt:secret ; +sip:user_1956@sip.example.org clrtxt:secret ; +sip:user_1957@sip.example.org clrtxt:secret ; +sip:user_1958@sip.example.org clrtxt:secret ; +sip:user_1959@sip.example.org clrtxt:secret ; +sip:user_1960@sip.example.org clrtxt:secret ; +sip:user_1961@sip.example.org clrtxt:secret ; +sip:user_1962@sip.example.org clrtxt:secret ; +sip:user_1963@sip.example.org clrtxt:secret ; +sip:user_1964@sip.example.org clrtxt:secret ; +sip:user_1965@sip.example.org clrtxt:secret ; +sip:user_1966@sip.example.org clrtxt:secret ; +sip:user_1967@sip.example.org clrtxt:secret ; +sip:user_1968@sip.example.org clrtxt:secret ; +sip:user_1969@sip.example.org clrtxt:secret ; +sip:user_1970@sip.example.org clrtxt:secret ; +sip:user_1971@sip.example.org clrtxt:secret ; +sip:user_1972@sip.example.org clrtxt:secret ; +sip:user_1973@sip.example.org clrtxt:secret ; +sip:user_1974@sip.example.org clrtxt:secret ; +sip:user_1975@sip.example.org clrtxt:secret ; +sip:user_1976@sip.example.org clrtxt:secret ; +sip:user_1977@sip.example.org clrtxt:secret ; +sip:user_1978@sip.example.org clrtxt:secret ; +sip:user_1979@sip.example.org clrtxt:secret ; +sip:user_1980@sip.example.org clrtxt:secret ; +sip:user_1981@sip.example.org clrtxt:secret ; +sip:user_1982@sip.example.org clrtxt:secret ; +sip:user_1983@sip.example.org clrtxt:secret ; +sip:user_1984@sip.example.org clrtxt:secret ; +sip:user_1985@sip.example.org clrtxt:secret ; +sip:user_1986@sip.example.org clrtxt:secret ; +sip:user_1987@sip.example.org clrtxt:secret ; +sip:user_1988@sip.example.org clrtxt:secret ; +sip:user_1989@sip.example.org clrtxt:secret ; +sip:user_1990@sip.example.org clrtxt:secret ; +sip:user_1991@sip.example.org clrtxt:secret ; +sip:user_1992@sip.example.org clrtxt:secret ; +sip:user_1993@sip.example.org clrtxt:secret ; +sip:user_1994@sip.example.org clrtxt:secret ; +sip:user_1995@sip.example.org clrtxt:secret ; +sip:user_1996@sip.example.org clrtxt:secret ; +sip:user_1997@sip.example.org clrtxt:secret ; +sip:user_1998@sip.example.org clrtxt:secret ; +sip:user_1999@sip.example.org clrtxt:secret ; +sip:user_2000@sip.example.org clrtxt:secret ; diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 96f09aac7..20aaa059b 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -19,8 +19,8 @@ #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" static void setPublish(LinphoneProxyConfig * proxy_config, bool_t enable) { linphone_proxy_config_edit(proxy_config); @@ -43,7 +43,7 @@ static void subscribe_forking(void) { content = linphone_core_create_content(marie->lc); linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"somexml"); - linphone_content_set_buffer(content, liblinphone_tester_get_subscribe_content(), strlen(liblinphone_tester_get_subscribe_content())); + linphone_content_set_buffer(content, (const uint8_t *)liblinphone_tester_get_subscribe_content(), strlen(liblinphone_tester_get_subscribe_content())); lev=linphone_core_subscribe(marie->lc,pauline->identity,"dodo",expires,content); @@ -77,10 +77,11 @@ static void message_forking(void) { lcs=bctbx_list_append(lcs,marie2->lc); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room, message); + linphone_chat_message_send(message); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,3000)); BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneMessageReceived,1,1000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneMessageDelivered,1,1000)); + linphone_chat_message_unref(message); /*wait a bit that 200Ok for MESSAGE are sent to server before shuting down the cores, because otherwise Flexisip will consider the messages * as not delivered and will expedite them in the next test, after receiving the REGISTER from marie's instances*/ @@ -119,12 +120,14 @@ static void message_forking_with_unreachable_recipients(void) { linphone_core_set_network_reachable(marie3->lc,FALSE); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room, message); + linphone_chat_message_send(message); BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneMessageReceived,1,3000)); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneMessageDelivered,1,1000)); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1, int, "%d"); BC_ASSERT_EQUAL(marie2->stat.number_of_LinphoneMessageReceived, 0, int, "%d"); BC_ASSERT_EQUAL(marie3->stat.number_of_LinphoneMessageReceived, 0, int, "%d"); + linphone_chat_message_unref(message); + /*marie 2 goes online */ linphone_core_set_network_reachable(marie2->lc,TRUE); BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneMessageReceived,1,3000)); @@ -171,7 +174,7 @@ static void message_forking_with_all_recipients_unreachable(void) { linphone_core_set_network_reachable(marie3->lc,FALSE); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room, message); + linphone_chat_message_send(message); BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneMessageInProgress,1,5000)); /*flexisip will accept the message with 202 after 16 seconds*/ @@ -179,6 +182,7 @@ static void message_forking_with_all_recipients_unreachable(void) { BC_ASSERT_EQUAL( marie->stat.number_of_LinphoneMessageReceived, 0, int, "%d"); BC_ASSERT_EQUAL( marie2->stat.number_of_LinphoneMessageReceived, 0, int, "%d"); BC_ASSERT_EQUAL( marie3->stat.number_of_LinphoneMessageReceived, 0, int, "%d"); + linphone_chat_message_unref(message); /*marie 1 goes online */ linphone_core_set_network_reachable(marie->lc,TRUE); @@ -239,7 +243,6 @@ static void message_forking_with_unreachable_recipients_with_gruu(void) { linphone_core_set_network_reachable(marie->lc,FALSE); linphone_core_set_network_reachable(marie2->lc,FALSE); - linphone_chat_message_ref(message_1); linphone_chat_room_send_chat_message(chat_room_1, message_1); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceived, 0, int, "%d"); @@ -275,7 +278,7 @@ static void text_message_expires(void) { linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc,marie->identity), "hello"); linphone_core_set_network_reachable(marie->lc, TRUE); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,1)); + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); @@ -853,12 +856,12 @@ static void call_with_sips_not_achievable(void){ } - static bool_t is_sending_ipv6(RtpSession *session, bool_t rtcp){ const struct sockaddr *dest = rtcp ? (struct sockaddr*)&session->rtcp.gs.rem_addr : (struct sockaddr*)&session->rtp.gs.rem_addr; struct sockaddr_in6 *in6=(struct sockaddr_in6*)dest; return dest->sa_family == AF_INET6 && !IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr); } + static bool_t is_remote_contact_ipv6(LinphoneCall *call){ const char *contact=linphone_call_get_remote_contact(call); LinphoneAddress *ct_addr; @@ -890,10 +893,12 @@ static void _call_with_ipv6(bool_t caller_with_ipv6, bool_t callee_with_ipv6) { } marie = linphone_core_manager_new2( "marie_rc", FALSE); + linphone_core_remove_supported_tag(marie->lc,"gruu"); // With gruu, we have no access to the "public IP from contact linphone_core_enable_ipv6(marie->lc, caller_with_ipv6); linphone_core_manager_start(marie, TRUE); pauline = linphone_core_manager_new2( transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", FALSE); + linphone_core_remove_supported_tag(pauline->lc,"gruu"); // With gruu, we have no access to the "public IP from contact linphone_core_enable_ipv6(pauline->lc, callee_with_ipv6); linphone_core_manager_start(pauline, TRUE); @@ -910,11 +915,10 @@ static void _call_with_ipv6(bool_t caller_with_ipv6, bool_t callee_with_ipv6) { BC_ASSERT_EQUAL(is_remote_contact_ipv6(marie_call), callee_with_ipv6, int, "%i"); /*check that the RTP destinations are IPv6 (flexisip should propose an IPv6 relay for parties with IPv6)*/ - BC_ASSERT_EQUAL(is_sending_ipv6(marie_call->sessions[0].rtp_session, FALSE), caller_with_ipv6, int, "%i"); - BC_ASSERT_EQUAL(is_sending_ipv6(marie_call->sessions[0].rtp_session, TRUE), caller_with_ipv6, int, "%i"); - BC_ASSERT_EQUAL(is_sending_ipv6(pauline_call->sessions[0].rtp_session, FALSE), callee_with_ipv6, int, "%i"); - BC_ASSERT_EQUAL(is_sending_ipv6(pauline_call->sessions[0].rtp_session, TRUE), callee_with_ipv6, int, "%i"); - + BC_ASSERT_EQUAL(is_sending_ipv6(linphone_call_get_stream(marie_call, LinphoneStreamTypeAudio)->sessions.rtp_session, FALSE), caller_with_ipv6, int, "%i"); + BC_ASSERT_EQUAL(is_sending_ipv6(linphone_call_get_stream(marie_call, LinphoneStreamTypeAudio)->sessions.rtp_session, TRUE), caller_with_ipv6, int, "%i"); + BC_ASSERT_EQUAL(is_sending_ipv6(linphone_call_get_stream(pauline_call, LinphoneStreamTypeAudio)->sessions.rtp_session, FALSE), callee_with_ipv6, int, "%i"); + BC_ASSERT_EQUAL(is_sending_ipv6(linphone_call_get_stream(pauline_call, LinphoneStreamTypeAudio)->sessions.rtp_session, TRUE), callee_with_ipv6, int, "%i"); } liblinphone_tester_check_rtcp(marie,pauline); @@ -953,12 +957,12 @@ static void file_transfer_message_rcs_to_external_body_client(void) { linphone_core_set_network_reachable(marie->lc, FALSE); linphone_core_set_network_reachable(pauline->lc, FALSE); - linphone_proxy_config_set_custom_header(marie->lc->default_proxy, "Accept", "application/sdp"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(marie->lc), "Accept", "application/sdp"); linphone_core_set_network_reachable(marie->lc, TRUE); linphone_core_manager_start(marie, TRUE); - linphone_proxy_config_set_custom_header(pauline->lc->default_proxy, "Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); + linphone_proxy_config_set_custom_header(linphone_core_get_default_proxy_config(pauline->lc), "Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); linphone_core_set_network_reachable(pauline->lc, TRUE); linphone_core_manager_start(pauline, TRUE); @@ -993,8 +997,8 @@ static void file_transfer_message_rcs_to_external_body_client(void) { } linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); linphone_chat_message_cbs_set_file_transfer_send(cbs, tester_file_transfer_send); - linphone_chat_room_send_chat_message(chat_room,message); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageExtBodyReceived,1)); + linphone_chat_message_send(message); + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1)); if (marie->stat.last_received_chat_message ) { cbs = linphone_chat_message_get_callbacks(marie->stat.last_received_chat_message); @@ -1006,9 +1010,10 @@ static void file_transfer_message_rcs_to_external_body_client(void) { BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedWithFile,1, int, "%d"); compare_files(send_filepath, receive_filepath); + linphone_chat_message_unref(message); linphone_content_unref(content); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); @@ -1017,80 +1022,6 @@ static void file_transfer_message_rcs_to_external_body_client(void) { } } -void send_file_transfer_message_using_external_body_url(LinphoneCoreManager *marie, LinphoneCoreManager *pauline) { - LinphoneChatMessageCbs *cbs; - LinphoneChatRoom *chat_room; - LinphoneChatMessage *message; - - /* create a chatroom on pauline's side */ - chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); - - message = linphone_chat_room_create_message(chat_room, NULL); - - cbs = linphone_chat_message_get_callbacks(message); - linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - - linphone_chat_message_set_external_body_url(message, "https://www.linphone.org:444//tmp/54ec58280ace9_c30709218df8eaba61d1.jpg"); - linphone_chat_room_send_chat_message(chat_room, message); - - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - if (marie->stat.last_received_chat_message) { - linphone_chat_message_download_file(marie->stat.last_received_chat_message); - } - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageExtBodyReceived, 1)); - - BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress, 1, int, "%d"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived, 1, int, "%d"); - - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDelivered, 1)); - -} - -static void file_transfer_message_external_body_to_external_body_client(void) { - if (transport_supported(LinphoneTransportTls)) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - - linphone_proxy_config_set_custom_header(marie->lc->default_proxy, "Accept", "application/sdp"); - linphone_core_manager_start(marie, TRUE); - - linphone_proxy_config_set_custom_header(pauline->lc->default_proxy, "Accept", "application/sdp"); - linphone_core_manager_start(pauline, TRUE); - - reset_counters(&marie->stat); - reset_counters(&pauline->stat); - - linphone_core_refresh_registers(marie->lc); - linphone_core_refresh_registers(pauline->lc); - - send_file_transfer_message_using_external_body_url(marie, pauline); - - linphone_core_manager_destroy(pauline); - linphone_core_manager_destroy(marie); - } -} - -static void file_transfer_message_external_body_to_rcs_client(void) { - if (transport_supported(LinphoneTransportTls)) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); - - linphone_proxy_config_set_custom_header(marie->lc->default_proxy, "Accept", "application/sdp"); - linphone_core_manager_start(marie, TRUE); - - linphone_proxy_config_set_custom_header(pauline->lc->default_proxy, "Accept", "application/sdp, text/plain, application/vnd.gsma.rcs-ft-http+xml"); - linphone_core_manager_start(pauline, TRUE); - - reset_counters(&marie->stat); - reset_counters(&pauline->stat); - - send_file_transfer_message_using_external_body_url(marie, pauline); - - linphone_core_manager_destroy(pauline); - linphone_core_manager_destroy(marie); - } -} - static void dos_module_trigger(void) { LinphoneChatRoom *chat_room; int i = 0; @@ -1110,7 +1041,7 @@ static void dos_module_trigger(void) { char msg[128]; sprintf(msg, "Flood message number %i", i); chat_msg = linphone_chat_room_create_message(chat_room, msg); - linphone_chat_room_send_chat_message(chat_room, chat_msg); + linphone_chat_message_send(chat_msg); wait_for_until(marie->lc, pauline->lc, &dummy, 1, 10); i++; } while (i < number_of_messge_to_send); @@ -1122,7 +1053,7 @@ static void dos_module_trigger(void) { reset_counters(&marie->stat); reset_counters(&pauline->stat); chat_msg = linphone_chat_room_create_message(chat_room, passmsg); - linphone_chat_room_send_chat_message(chat_room, chat_msg); + linphone_chat_message_send(chat_msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived, 1)); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceived, 1, int, "%d"); if (marie->stat.last_received_chat_message) { @@ -1263,7 +1194,7 @@ static void test_list_subscribe (void) { linphone_content_set_type(content,"application"); linphone_content_set_subtype(content,"resource-lists+xml"); - linphone_content_set_buffer(content,subscribe_content,strlen(subscribe_content)); + linphone_content_set_buffer(content,(const uint8_t *)subscribe_content,strlen(subscribe_content)); lev=linphone_core_create_subscribe(marie->lc,list_name,"presence",60); @@ -1281,15 +1212,17 @@ static void test_list_subscribe (void) { BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,1,5000)); /*dummy wait to avoid derred notify*/ wait_for_list(lcs,&dummy,1,2000); + int initial_number_of_notify = marie->stat.number_of_NotifyReceived; + setPublish(linphone_core_get_default_proxy_config(pauline->lc), TRUE); - BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,2,5000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,initial_number_of_notify + 1,5000)); setPublish(linphone_core_get_default_proxy_config(laure->lc), TRUE); - /*make sure notify is not sent "imadiatly but defered*/ - BC_ASSERT_FALSE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,3,1000)); + /*make sure notify is not sent "immediatly but defered*/ + BC_ASSERT_FALSE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,initial_number_of_notify + 2,1000)); - BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,3,5000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_NotifyReceived,initial_number_of_notify + 2,5000)); linphone_event_terminate(lev); @@ -1448,9 +1381,11 @@ static void tls_client_auth_try_register(const char *identity, LinphoneCoreAuthe }else{ BC_ASSERT_TRUE(wait_for(lcm->lc, NULL, &lcm->stat.number_of_LinphoneRegistrationFailed, 1)); BC_ASSERT_EQUAL(lcm->stat.number_of_LinphoneRegistrationOk,0, int, "%d"); - /*we should expect 2 "auth_requested": one for the TLS certificate, another one because the server rejects the REGISTER with 401.*/ + /*we should expect at least 2 "auth_requested": one for the TLS certificate, another one because the server rejects the REGISTER with 401, + with eventually MD5 + SHA256 challenge*/ /*If the certificate isn't recognized at all, the connection will not happen and no SIP response will be received from server.*/ - if (good_cert) BC_ASSERT_EQUAL(lcm->stat.number_of_auth_info_requested,2, int, "%d"); + if (good_cert) BC_ASSERT_GREATER(lcm->stat.number_of_auth_info_requested,2, int, "%d"); + else BC_ASSERT_EQUAL(lcm->stat.number_of_auth_info_requested,1, int, "%d"); } @@ -1567,28 +1502,428 @@ static void register_without_regid(void) { } void test_removing_old_tport(void) { - bctbx_list_t* lcs; - LinphoneCoreManager* marie2; LinphoneCoreManager* marie1 = linphone_core_manager_new("marie_rc"); - lcs=bctbx_list_append(NULL,marie1->lc); + bctbx_list_t *lcs = bctbx_list_append(NULL, marie1->lc); BC_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneRegistrationOk,1,5000)); - marie2 = ms_new0(LinphoneCoreManager, 1); - linphone_core_manager_init(marie2, "marie_rc", NULL); - sal_set_uuid(marie2->lc->sal, linphone_config_get_string(linphone_core_get_config(marie1->lc),"misc", "uuid", "0")); + LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc"); + const char *uuid = linphone_config_get_string(linphone_core_get_config(marie1->lc), "misc", "uuid", "0"); + lp_config_set_string(linphone_core_get_config(marie2->lc), "misc", "uuid", uuid); linphone_core_manager_start(marie2, TRUE); - lcs=bctbx_list_append(lcs, marie2->lc); + lcs = bctbx_list_append(lcs, marie2->lc); linphone_core_refresh_registers(marie2->lc); - BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneRegistrationOk,1,5000)); - - BC_ASSERT_TRUE(wait_for_list(lcs,&marie1->stat.number_of_LinphoneRegistrationProgress,2,5000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneRegistrationOk, 1, 5000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneRegistrationProgress, 2, 5000)); linphone_core_manager_destroy(marie1); linphone_core_manager_destroy(marie2); bctbx_list_free(lcs); } +#if 0 +/* SM: I comment this test out. It doesn't unregister participants properly, which confuses subsequent tests. + * The storage of REFER request by flexisip in late forking is no longer required in group chat "release" version. + * It is not essential to keep testing this feature. + */ + +static const char* get_laure_rc(void) { + if (liblinphone_tester_ipv6_available()) { + return "laure_tcp_rc"; + } else { + return "laure_rc_udp"; + } +} + +static void on_refer_received(SalOp *op, const SalAddress *refer_to) { + Sal *sal = sal_op_get_sal(op); + LinphoneCoreManager *receiver = (LinphoneCoreManager*)sal_get_user_pointer(sal); + receiver->stat.number_of_LinphoneCallRefered++; + +} + + +void resend_refer_other_devices(void) { + LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc"); + LinphoneCoreManager* laure = linphone_core_manager_new( get_laure_rc()); + LinphoneCoreManager* pauline2; + bctbx_list_t* lcs = NULL; + + lcs=bctbx_list_append(lcs,marie->lc); + lcs=bctbx_list_append(lcs,pauline->lc); + lcs=bctbx_list_append(lcs,laure->lc); + + /* We set Pauline's Sal callback and pass the core manager to access stats */ + Sal *pauline_sal = linphone_core_get_sal(pauline->lc); + sal_set_user_pointer(pauline_sal, (void*)pauline); + sal_set_call_refer_callback(pauline_sal, on_refer_received); + + + char *marie_address = linphone_address_as_string(marie->identity); + char *pauline_address = linphone_address_as_string(pauline->identity); + char *laure_address = linphone_address_as_string(laure->identity); + + /* Then we create a refer from marie to pauline that refers to laure */ + SalOp *op = sal_create_refer_op(linphone_core_get_sal(marie->lc)); + sal_op_set_from(op, marie_address); + sal_op_set_to(op, pauline_address); + + SalAddress *address = sal_address_new(laure_address); + sal_address_set_param(address, "text", NULL); + sal_op_send_refer(op, address); + + ms_free(marie_address); + ms_free(pauline_address); + ms_free(laure_address); + + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallRefered,1,5000)); + + /* We create another pauline and check if it has received a refer */ + pauline2 = linphone_core_manager_new( "pauline_rc"); + lcs=bctbx_list_append(lcs,pauline2->lc); + + Sal *pauline2_sal = linphone_core_get_sal(pauline2->lc); + sal_set_user_pointer(pauline2_sal, (void*)pauline2); + sal_set_call_refer_callback(pauline2_sal, on_refer_received); + + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline2->stat.number_of_LinphoneCallRefered,1,5000)); + + sal_address_unref(address); + sal_release_op(op); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); + linphone_core_manager_destroy(pauline2); + bctbx_list_free(lcs); +} + +#endif + +void sequential_forking(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCoreManager* marie2 = linphone_core_manager_create("marie_rc"); + + bctbx_list_t* lcs=bctbx_list_append(NULL,pauline->lc); + + /*we don't set marie "q" because it is by default at 1.0 if it is not present (RFC 4596)*/ + linphone_proxy_config_set_contact_parameters( + linphone_core_get_default_proxy_config(marie2->lc), + "q=0.5;"); + + linphone_core_manager_start(marie2, TRUE); + + lcs=bctbx_list_append(lcs,marie->lc); + lcs=bctbx_list_append(lcs,marie2->lc); + + linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(marie2->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); + + linphone_core_invite_address(pauline->lc,marie->identity); + /*pauline should hear ringback*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); + /*first device from Marie should be ringing*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,3000)); + /*the second should not*/ + BC_ASSERT_EQUAL(marie2->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); + + LinphoneCall *call = linphone_core_get_current_call(marie->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; + + /*marie accepts the call on its second device*/ + linphone_call_accept(call); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + + /*second device should have received nothing*/ + BC_ASSERT_EQUAL(marie2->stat.number_of_LinphoneCallEnd, 0, int, "%d"); + + linphone_call_terminate(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); + +end: + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(marie2); + bctbx_list_free(lcs); +} + +void sequential_forking_with_timeout_for_highest_priority(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCoreManager* marie2 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager* marie3 = linphone_core_manager_create("marie_rc"); + + bctbx_list_t* lcs=bctbx_list_append(NULL,pauline->lc); + + /*we don't set marie "q" because it is by default at 1.0 if it is not present (RFC 4596)*/ + linphone_proxy_config_set_contact_parameters( + linphone_core_get_default_proxy_config(marie2->lc), + "q=0.5;"); + + linphone_proxy_config_set_contact_parameters( + linphone_core_get_default_proxy_config(marie3->lc), + "q=0.5;"); + + linphone_core_manager_start(marie2, TRUE); + linphone_core_manager_start(marie3, TRUE); + + lcs=bctbx_list_append(lcs,marie->lc); + lcs=bctbx_list_append(lcs,marie2->lc); + lcs=bctbx_list_append(lcs,marie3->lc); + + linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(marie2->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(marie3->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); + + /*set first device not reachable*/ + linphone_core_set_network_reachable(marie->lc,FALSE); + + linphone_core_invite_address(pauline->lc,marie->identity); + + /*second and third devices should have received the call*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,13000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallIncomingReceived,1,3000)); + /*pauline should hear ringback*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); + /*first device should receive nothing since it is disconnected*/ + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); + + + LinphoneCall *call = linphone_core_get_current_call(marie3->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; + + /*marie accepts the call on her third device*/ + linphone_call_accept(call); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + + /*second device should stop ringing*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000)); + + linphone_call_terminate(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallEnd,1,1000)); + + /*first device should have received nothing*/ + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallEnd, 0, int, "%d"); + +end: + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(marie3); + bctbx_list_free(lcs); +} + +void sequential_forking_with_no_response_for_highest_priority(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCoreManager* marie2 = linphone_core_manager_create("marie_rc"); + + bctbx_list_t* lcs=bctbx_list_append(NULL,pauline->lc); + + /*we don't set marie "q" because it is by default at 1.0 if it is not present (RFC 4596)*/ + linphone_proxy_config_set_contact_parameters( + linphone_core_get_default_proxy_config(marie2->lc), + "q=0.5;"); + + linphone_core_manager_start(marie2, TRUE); + + lcs=bctbx_list_append(lcs,marie->lc); + lcs=bctbx_list_append(lcs,marie2->lc); + + linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(marie2->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); + + linphone_core_invite_address(pauline->lc,marie->identity); + + /*first device should receive the call*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallIncomingReceived,1,3000)); + /*pauline should hear ringback*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); + /*second device should have not received the call yet*/ + BC_ASSERT_EQUAL(marie2->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); + + /*we wait for the call to try the next branches*/ + wait_for_list(lcs,NULL,0,10000); + + /*then the second device should receive the call*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived, 1, 3000)); + + LinphoneCall *call = linphone_core_get_current_call(marie2->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; + + /*marie accepts the call on her second device*/ + linphone_call_accept(call); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + + /*the first device should finish*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd, 1, 3000)); + + linphone_call_terminate(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000)); + +end: + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(marie2); + bctbx_list_free(lcs); +} + +void sequential_forking_with_insertion_of_higher_priority(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCoreManager* marie2 = linphone_core_manager_create("marie_rc"); + + bctbx_list_t* lcs=bctbx_list_append(NULL,pauline->lc); + + /*we don't set marie "q" because it is by default at 1.0 if it is not present (RFC 4596)*/ + linphone_proxy_config_set_contact_parameters( + linphone_core_get_default_proxy_config(marie2->lc), + "q=0.5;"); + + linphone_core_manager_start(marie2, TRUE); + + lcs=bctbx_list_append(lcs,marie->lc); + lcs=bctbx_list_append(lcs,marie2->lc); + + linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(marie2->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); + + /*set first device not reachable*/ + linphone_core_set_network_reachable(marie->lc,FALSE); + + linphone_core_invite_address(pauline->lc,marie->identity); + + /*second device should have received the call*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallIncomingReceived,1,13000)); + /*pauline should hear ringback*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); + /*first device should receive nothing since it is disconnected*/ + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); + + /*we create a new device*/ + LinphoneCoreManager* marie3 = linphone_core_manager_new("marie_rc"); + lcs=bctbx_list_append(lcs,marie3->lc); + linphone_core_set_user_agent(marie3->lc,"Natted Linphone",NULL); + + /*this device should receive the call*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallIncomingReceived,1,3000)); + + LinphoneCall *call = linphone_core_get_current_call(marie3->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; + + /*marie accepts the call on her third device*/ + linphone_call_accept(call); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + + /*second device should stop ringing*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie2->stat.number_of_LinphoneCallEnd,1,1000)); + + linphone_call_terminate(linphone_core_get_current_call(pauline->lc)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie3->stat.number_of_LinphoneCallEnd,1,1000)); + + /*first device should have received nothing*/ + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallEnd, 0, int, "%d"); + +end: + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(marie3); + bctbx_list_free(lcs); +} + +void sequential_forking_with_fallback_route(void) { + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCoreManager* pauline2 = linphone_core_manager_create(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCoreManager* marie = linphone_core_manager_create("marie_rc"); + + bctbx_list_t* lcs=bctbx_list_append(NULL,pauline->lc); + + /*we set pauline2 and marie to another test server that is configured with a fallback route*/ + linphone_proxy_config_set_server_addr( + linphone_core_get_default_proxy_config(pauline2->lc), + "sip:sip2.linphone.org:5071;transport=tls"); + + linphone_proxy_config_set_route( + linphone_core_get_default_proxy_config(pauline2->lc), + "sip:sip2.linphone.org:5071;transport=tls"); + + linphone_proxy_config_set_server_addr( + linphone_core_get_default_proxy_config(marie->lc), + "sip:sip2.linphone.org:5070;transport=tcp"); + + linphone_proxy_config_set_route( + linphone_core_get_default_proxy_config(marie->lc), + "sip:sip2.linphone.org:5070;transport=tcp;lr"); + + linphone_core_manager_start(pauline2, TRUE); + linphone_core_manager_start(marie, TRUE); + + lcs=bctbx_list_append(lcs,pauline2->lc); + lcs=bctbx_list_append(lcs,marie->lc); + + linphone_core_set_user_agent(pauline->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(pauline2->lc,"Natted Linphone",NULL); + linphone_core_set_user_agent(marie->lc,"Natted Linphone",NULL); + + /*set pauline2 not reachable*/ + linphone_core_set_network_reachable(pauline2->lc,FALSE); + + /*marie invites pauline2 on the other server*/ + linphone_core_invite_address(marie->lc,pauline2->identity); + + /*the call should be routed to the first server with pauline account*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallIncomingReceived,1,13000)); + + /*marie should hear ringback*/ + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallOutgoingRinging,1,3000)); + /*pauline2 should receive nothing since it is disconnected*/ + BC_ASSERT_EQUAL(pauline2->stat.number_of_LinphoneCallIncomingReceived, 0, int, "%d"); + + LinphoneCall *call = linphone_core_get_current_call(pauline->lc); + if (!BC_ASSERT_PTR_NOT_NULL(call)) goto end; + + /*pauline accepts the call*/ + linphone_call_accept(call); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallConnected,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallStreamsRunning,1,1000)); + + linphone_call_terminate(linphone_core_get_current_call(marie->lc)); + BC_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallEnd,1,1000)); + BC_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallEnd,1,1000)); + + /*first device should have received nothing*/ + BC_ASSERT_EQUAL(pauline2->stat.number_of_LinphoneCallEnd, 0, int, "%d"); + +end: + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(pauline2); + linphone_core_manager_destroy(marie); + bctbx_list_free(lcs); +} static void deal_with_jwe_auth_module(const char *jwe, bool_t invalid_jwe, bool_t invalid_oid) { if (!transport_supported(LinphoneTransportTls)) @@ -1729,8 +2064,6 @@ test_t flexisip_tests[] = { TEST_NO_TAG("List subscribe", test_list_subscribe), TEST_NO_TAG("List subscribe without body", test_list_subscribe_wrong_body), TEST_NO_TAG("File transfer message rcs to external body client", file_transfer_message_rcs_to_external_body_client), - TEST_ONE_TAG("File transfer message external body to rcs client", file_transfer_message_external_body_to_rcs_client, "LeaksMemory"), - TEST_ONE_TAG("File transfer message external body to external body client", file_transfer_message_external_body_to_external_body_client, "LeaksMemory"), TEST_NO_TAG("DoS module trigger by sending a lot of chat messages", dos_module_trigger), #if HAVE_SIPP TEST_NO_TAG("Subscribe on wrong dialog", test_subscribe_on_wrong_dialog), @@ -1741,6 +2074,12 @@ test_t flexisip_tests[] = { TEST_NO_TAG("TLS authentication - client rejected due to unmatched certificate subject", tls_client_rejected_due_to_unmatched_subject), TEST_NO_TAG("Transcoder", transcoder_tester), TEST_NO_TAG("Removing old tport on flexisip for the same client", test_removing_old_tport), + /*TEST_NO_TAG("Resend of REFER with other devices", resend_refer_other_devices),*/ + TEST_NO_TAG("Sequential forking", sequential_forking), + TEST_NO_TAG("Sequential forking with timeout for highest priority", sequential_forking_with_timeout_for_highest_priority), + TEST_NO_TAG("Sequential forking with no response from highest priority", sequential_forking_with_no_response_for_highest_priority), + TEST_NO_TAG("Sequential forking with insertion of higher priority", sequential_forking_with_insertion_of_higher_priority), + TEST_NO_TAG("Sequential forking with fallback route", sequential_forking_with_fallback_route), TEST_NO_TAG("Registered contact does not have regid param", register_without_regid), TEST_NO_TAG("Use JweAuth module", use_jwe_auth_module), TEST_NO_TAG("Use JweAuth module with invalid oid", use_jwe_auth_module_with_invalid_oid), diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c new file mode 100644 index 000000000..12a5a6ad6 --- /dev/null +++ b/tester/group_chat_tester.c @@ -0,0 +1,3890 @@ +/* + liblinphone_tester - liblinphone test suite + Copyright (C) 2013 Belledonne Communications SARL + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + + + +#include "linphone/core.h" +#include "tester_utils.h" +#include "linphone/wrapper_utils.h" +#include "liblinphone_tester.h" +#include "bctoolbox/crypto.h" + +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic push +#endif +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#endif + +static const char sFactoryUri[] = "sip:conference-factory@conf.example.org"; + +static void chat_room_is_composing_received (LinphoneChatRoom *cr, const LinphoneAddress *remoteAddr, bool_t isComposing) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + if (isComposing) + manager->stat.number_of_LinphoneIsComposingActiveReceived++; + else + manager->stat.number_of_LinphoneIsComposingIdleReceived++; +} + +static void chat_room_participant_added (LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + manager->stat.number_of_participants_added++; +} + +static void chat_room_participant_admin_status_changed (LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + manager->stat.number_of_participant_admin_statuses_changed++; +} + +static void chat_room_participant_removed (LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + manager->stat.number_of_participants_removed++; +} + +static void chat_room_participant_device_added (LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + manager->stat.number_of_participant_devices_added++; +} + +static void chat_room_state_changed (LinphoneChatRoom *cr, LinphoneChatRoomState newState) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + ms_message("ChatRoom [%p] state changed: %d", cr, newState); + switch (newState) { + case LinphoneChatRoomStateNone: + break; + case LinphoneChatRoomStateInstantiated: + manager->stat.number_of_LinphoneChatRoomStateInstantiated++; + break; + case LinphoneChatRoomStateCreationPending: + manager->stat.number_of_LinphoneChatRoomStateCreationPending++; + break; + case LinphoneChatRoomStateCreated: + manager->stat.number_of_LinphoneChatRoomStateCreated++; + break; + case LinphoneChatRoomStateCreationFailed: + manager->stat.number_of_LinphoneChatRoomStateCreationFailed++; + break; + case LinphoneChatRoomStateTerminationPending: + manager->stat.number_of_LinphoneChatRoomStateTerminationPending++; + break; + case LinphoneChatRoomStateTerminated: + manager->stat.number_of_LinphoneChatRoomStateTerminated++; + break; + case LinphoneChatRoomStateTerminationFailed: + manager->stat.number_of_LinphoneChatRoomStateTerminationFailed++; + break; + case LinphoneChatRoomStateDeleted: + manager->stat.number_of_LinphoneChatRoomStateDeleted++; + break; + } +} + +static void chat_room_subject_changed (LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + manager->stat.number_of_subject_changed++; +} + +static void chat_room_conference_joined (LinphoneChatRoom *cr, const LinphoneEventLog *event_log) { + LinphoneCore *core = linphone_chat_room_get_core(cr); + LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core); + manager->stat.number_of_LinphoneChatRoomConferenceJoined++; +} + +static void core_chat_room_state_changed (LinphoneCore *core, LinphoneChatRoom *cr, LinphoneChatRoomState state) { + if (state == LinphoneChatRoomStateInstantiated) { + LinphoneChatRoomCbs *cbs = linphone_factory_create_chat_room_cbs(linphone_factory_get()); + linphone_chat_room_cbs_set_is_composing_received(cbs, chat_room_is_composing_received); + linphone_chat_room_cbs_set_participant_added(cbs, chat_room_participant_added); + linphone_chat_room_cbs_set_participant_admin_status_changed(cbs, chat_room_participant_admin_status_changed); + linphone_chat_room_cbs_set_participant_removed(cbs, chat_room_participant_removed); + linphone_chat_room_cbs_set_state_changed(cbs, chat_room_state_changed); + linphone_chat_room_cbs_set_subject_changed(cbs, chat_room_subject_changed); + linphone_chat_room_cbs_set_participant_device_added(cbs, chat_room_participant_device_added); + linphone_chat_room_cbs_set_conference_joined(cbs, chat_room_conference_joined); + linphone_chat_room_add_callbacks(cr, cbs); + linphone_chat_room_cbs_unref(cbs); + } +} + +static void configure_core_for_conference (LinphoneCore *core, const char* username, const LinphoneAddress *factoryAddr, bool_t server) { + const char *identity = linphone_core_get_identity(core); + const char *new_username; + LinphoneAddress *addr = linphone_address_new(identity); + if (!username) { + new_username = linphone_address_get_username(addr); + } + linphone_address_set_username(addr, (username) ? username : new_username); + char *newIdentity = linphone_address_as_string_uri_only(addr); + linphone_address_unref(addr); + linphone_core_set_primary_contact(core, newIdentity); + bctbx_free(newIdentity); + linphone_core_enable_conference_server(core, server); + char *factoryUri = linphone_address_as_string(factoryAddr); + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(core); + linphone_proxy_config_set_conference_factory_uri(proxy, factoryUri); + bctbx_free(factoryUri); + linphone_core_set_linphone_specs(core, "groupchat"); +} + +static void _configure_core_for_conference (LinphoneCoreManager *lcm, LinphoneAddress *factoryAddr) { + configure_core_for_conference(lcm->lc, NULL, factoryAddr, FALSE); +} + +static void _configure_core_for_callbacks(LinphoneCoreManager *lcm, LinphoneCoreCbs *cbs) { + // Remove is-composing callback from the core, we use our own on the chat room + linphone_core_cbs_set_is_composing_received(lcm->cbs, NULL); + linphone_core_add_callbacks(lcm->lc, cbs); + linphone_core_set_user_data(lcm->lc, lcm); +} + +static void _start_core(LinphoneCoreManager *lcm) { + linphone_core_manager_start(lcm, TRUE); +} + +static LinphoneChatMessage *_send_message(LinphoneChatRoom *chatRoom, const char *message) { + LinphoneChatMessage *msg = linphone_chat_room_create_message(chatRoom, message); + LinphoneChatMessageCbs *msgCbs = linphone_chat_message_get_callbacks(msg); + linphone_chat_message_cbs_set_msg_state_changed(msgCbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_send(msg); + return msg; +} + +static void _send_file_plus_text(LinphoneChatRoom* cr, const char *sendFilepath, const char *text) { + LinphoneChatMessage *msg; + LinphoneChatMessageCbs *cbs; + LinphoneContent *content = linphone_core_create_content(linphone_chat_room_get_core(cr)); + belle_sip_object_set_name(BELLE_SIP_OBJECT(content), "sintel trailer content"); + linphone_content_set_type(content,"video"); + linphone_content_set_subtype(content,"mkv"); + linphone_content_set_name(content,"sintel_trailer_opus_h264.mkv"); + + msg = linphone_chat_room_create_file_transfer_message(cr, content); + linphone_chat_message_set_file_transfer_filepath(msg, sendFilepath); + + if (text) + linphone_chat_message_add_text_content(msg, text); + + cbs = linphone_chat_message_get_callbacks(msg); + linphone_chat_message_cbs_set_file_transfer_send(cbs, tester_file_transfer_send); + linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); + linphone_chat_message_send(msg); + linphone_content_unref(content); + linphone_chat_message_unref(msg); +} + +static void _send_file(LinphoneChatRoom* cr, const char *sendFilepath) { + _send_file_plus_text(cr, sendFilepath, NULL); +} + +static void _receive_file(bctbx_list_t *coresList, LinphoneCoreManager *lcm, stats *receiverStats, const char *receive_filepath, const char *sendFilepath) { + if (BC_ASSERT_TRUE(wait_for_list(coresList, &lcm->stat.number_of_LinphoneMessageReceivedWithFile, receiverStats->number_of_LinphoneMessageReceivedWithFile + 1, 10000))) { + LinphoneChatMessageCbs *cbs; + LinphoneChatMessage *msg = lcm->stat.last_received_chat_message; + + cbs = linphone_chat_message_get_callbacks(msg); + linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received); + linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); + linphone_chat_message_set_file_transfer_filepath(msg, receive_filepath); + linphone_chat_message_download_file(msg); + + if (BC_ASSERT_TRUE(wait_for_list(coresList, &lcm->stat.number_of_LinphoneFileTransferDownloadSuccessful,receiverStats->number_of_LinphoneFileTransferDownloadSuccessful + 1, 20000))) { + compare_files(sendFilepath, receive_filepath); + } + } +} + +static void _receive_file_plus_text(bctbx_list_t *coresList, LinphoneCoreManager *lcm, stats *receiverStats, const char *receive_filepath, const char *sendFilepath, const char *text) { + if (BC_ASSERT_TRUE(wait_for_list(coresList, &lcm->stat.number_of_LinphoneMessageReceivedWithFile, receiverStats->number_of_LinphoneMessageReceivedWithFile + 1, 10000))) { + LinphoneChatMessageCbs *cbs; + LinphoneChatMessage *msg = lcm->stat.last_received_chat_message; + + BC_ASSERT_TRUE(linphone_chat_message_has_text_content(msg)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text_content(msg), text); + + cbs = linphone_chat_message_get_callbacks(msg); + linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received); + linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); + linphone_chat_message_set_file_transfer_filepath(msg, receive_filepath); + linphone_chat_message_download_file(msg); + + if (BC_ASSERT_TRUE(wait_for_list(coresList, &lcm->stat.number_of_LinphoneFileTransferDownloadSuccessful,receiverStats->number_of_LinphoneFileTransferDownloadSuccessful + 1, 20000))) { + compare_files(sendFilepath, receive_filepath); + } + } +} + +// Configure list of core manager for conference and add the listener +static bctbx_list_t * init_core_for_conference(bctbx_list_t *coreManagerList) { + LinphoneAddress *factoryAddr = linphone_address_new(sFactoryUri); + bctbx_list_for_each2(coreManagerList, (void (*)(void *, void *))_configure_core_for_conference, (void *) factoryAddr); + linphone_address_unref(factoryAddr); + + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_chat_room_state_changed(cbs, core_chat_room_state_changed); + bctbx_list_for_each2(coreManagerList, (void (*)(void *, void *))_configure_core_for_callbacks, (void *) cbs); + linphone_core_cbs_unref(cbs); + + bctbx_list_t *coresList = NULL; + bctbx_list_t *item = coreManagerList; + for (item = coreManagerList; item; item = bctbx_list_next(item)) + coresList = bctbx_list_append(coresList, ((LinphoneCoreManager *)(bctbx_list_get_data(item)))->lc); + return coresList; +} + +static void start_core_for_conference(bctbx_list_t *coreManagerList) { + bctbx_list_for_each(coreManagerList, (void (*)(void *))_start_core); +} + +static LinphoneChatRoom * check_creation_chat_room_client_side(bctbx_list_t *lcs, LinphoneCoreManager *lcm, stats *initialStats, const LinphoneAddress *confAddr, const char* subject, int participantNumber, bool_t isAdmin) { + BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomStateCreationPending, initialStats->number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomStateCreated, initialStats->number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomConferenceJoined, initialStats->number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + char *deviceIdentity = linphone_core_get_device_identity(lcm->lc); + LinphoneAddress *localAddr = linphone_address_new(deviceIdentity); + bctbx_free(deviceIdentity); + LinphoneChatRoom *chatRoom = linphone_core_find_chat_room(lcm->lc, confAddr, localAddr); + linphone_address_unref(localAddr); + BC_ASSERT_PTR_NOT_NULL(chatRoom); + if (chatRoom) { + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(chatRoom), participantNumber, int, "%d"); + LinphoneParticipant *participant = linphone_chat_room_get_me(chatRoom); + BC_ASSERT_PTR_NOT_NULL(participant); + if (!(linphone_chat_room_get_capabilities(chatRoom) & LinphoneChatRoomCapabilitiesOneToOne)) + BC_ASSERT(isAdmin == linphone_participant_is_admin(participant)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(chatRoom), subject); + } + return chatRoom; +} + +static LinphoneChatRoom * create_chat_room_client_side(bctbx_list_t *lcs, LinphoneCoreManager *lcm, stats *initialStats, bctbx_list_t *participantsAddresses, const char* initialSubject, int expectedParticipantSize) { + LinphoneChatRoom *chatRoom = linphone_core_create_client_group_chat_room(lcm->lc, initialSubject, FALSE); + if (!chatRoom) return NULL; + + BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomStateInstantiated, initialStats->number_of_LinphoneChatRoomStateInstantiated + 1, 100)); + + // Add participants + linphone_chat_room_add_participants(chatRoom, participantsAddresses); + + // Check that the chat room is correctly created on Marie's side and that the participants are added + BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomStateCreationPending, initialStats->number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomStateCreated, initialStats->number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(lcs, &lcm->stat.number_of_LinphoneChatRoomConferenceJoined, initialStats->number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(chatRoom), + (expectedParticipantSize >= 0) ? expectedParticipantSize : (int)bctbx_list_size(participantsAddresses), + int, "%d"); + LinphoneParticipant *participant = linphone_chat_room_get_me(chatRoom); + BC_ASSERT_PTR_NOT_NULL(participant); + if (participant) + BC_ASSERT_TRUE(linphone_participant_is_admin(participant)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(chatRoom), initialSubject); + + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + + return chatRoom; +} + +static void group_chat_room_creation_server (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + int dummy = 0; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + + start_core_for_conference(coresManagerList); + + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + stats initialChloeStats = chloe->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Pauline tries to change the subject but is not admin so it fails + const char *newSubject = "Let's go drink a beer"; + linphone_chat_room_set_subject(paulineCr, newSubject); + wait_for_list(coresList, &dummy, 1, 1000); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), initialSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), initialSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), initialSubject); + + // Marie now changes the subject + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); + + // Marie designates Pauline as admin + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + LinphoneParticipant *paulineParticipant = linphone_chat_room_find_participant(marieCr, paulineAddr); + linphone_address_unref(paulineAddr); + BC_ASSERT_PTR_NOT_NULL(paulineParticipant); + linphone_chat_room_set_participant_admin_status(marieCr, paulineParticipant, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 1, 3000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(paulineParticipant)); + + // Pauline adds Chloe to the chat room + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + linphone_chat_room_add_participants(paulineCr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + + // Check that the chat room is correctly created on Chloe's side and that she was added everywhere + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, newSubject, 3, FALSE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_added, initialMarieStats.number_of_participants_added + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_added, initialPaulineStats.number_of_participants_added + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participants_added, initialLaureStats.number_of_participants_added + 1, 3000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 3, int, "%d"); + + // Pauline revokes the admin status of Marie + LinphoneAddress *marieAddr = linphone_address_new(linphone_core_get_identity(marie->lc)); + LinphoneParticipant *marieParticipant = linphone_chat_room_find_participant(paulineCr, marieAddr); + linphone_address_unref(marieAddr); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + linphone_chat_room_set_participant_admin_status(paulineCr, marieParticipant, FALSE); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 2, 3000)); + BC_ASSERT_FALSE(linphone_participant_is_admin(marieParticipant)); + + // Marie tries to change the subject again but is not admin, so it is not changed + linphone_chat_room_set_subject(marieCr, initialSubject); + wait_for_list(coresList, &dummy, 1, 1000); + + // Chloe begins composing a message + linphone_chat_room_compose(chloeCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingActiveReceived, initialMarieStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, initialPaulineStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneIsComposingActiveReceived, initialLaureStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + const char *chloeTextMessage = "Hello"; + LinphoneChatMessage *chloeMessage = _send_message(chloeCr, chloeTextMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDelivered, initialChloeStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneMessageReceived, initialLaureStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingIdleReceived, initialMarieStats.number_of_LinphoneIsComposingIdleReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingIdleReceived, initialPaulineStats.number_of_LinphoneIsComposingIdleReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneIsComposingIdleReceived, initialLaureStats.number_of_LinphoneIsComposingIdleReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), chloeTextMessage); + linphone_chat_message_unref(chloeMessage); + LinphoneAddress *chloeAddr = linphone_address_new(linphone_core_get_identity(chloe->lc)); + BC_ASSERT_TRUE(linphone_address_weak_equal(chloeAddr, linphone_chat_message_get_from_address(marie->stat.last_received_chat_message))); + linphone_address_unref(chloeAddr); + + // Pauline removes Laure from the chat room + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(paulineCr, laureAddr); + linphone_address_unref(laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + linphone_chat_room_remove_participant(paulineCr, laureParticipant); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_participants_removed, initialChloeStats.number_of_participants_removed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_removed, initialMarieStats.number_of_participants_removed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 1, 3000)); + + // Pauline removes Marie and Chloe from the chat room + marieAddr = linphone_address_new(linphone_core_get_identity(marie->lc)); + marieParticipant = linphone_chat_room_find_participant(paulineCr, marieAddr); + linphone_address_unref(marieAddr); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + chloeAddr = linphone_address_new(linphone_core_get_identity(chloe->lc)); + LinphoneParticipant *chloeParticipant = linphone_chat_room_find_participant(paulineCr, chloeAddr); + linphone_address_unref(chloeAddr); + BC_ASSERT_PTR_NOT_NULL(chloeParticipant); + bctbx_list_t *participantsToRemove = NULL; + initialPaulineStats = pauline->stat; + participantsToRemove = bctbx_list_append(participantsToRemove, marieParticipant); + participantsToRemove = bctbx_list_append(participantsToRemove, chloeParticipant); + linphone_chat_room_remove_participants(paulineCr, participantsToRemove); + bctbx_list_free_with_data(participantsToRemove, (bctbx_list_free_func)linphone_participant_unref); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateTerminated, initialMarieStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneChatRoomStateTerminated, initialChloeStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 2, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 0, int, "%d"); + + // Pauline leaves the chat room + wait_for_list(coresList, &dummy, 1, 1000); + linphone_chat_room_leave(paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateTerminationPending, initialPaulineStats.number_of_LinphoneChatRoomStateTerminationPending + 1, 100)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateTerminated, initialPaulineStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(marie->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(laure->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(pauline->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(chloe->lc), 0, int,"%i"); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); + linphone_core_manager_destroy(chloe); +} + +static void group_chat_room_add_participant (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + linphone_core_set_linphone_specs(chloe->lc, ""); // Disable group chat for Chloe + + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(marie->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + stats initialChloeStats = chloe->stat; + + // Pauline creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *paulineCr = create_chat_room_client_side(coresList, pauline, &initialPaulineStats, participantsAddresses, initialSubject, -1); + LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(paulineCr)); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *marieCr = check_creation_chat_room_client_side(coresList, marie, &initialMarieStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // To simulate dialog removal for Pauline + linphone_core_set_network_reachable(pauline->lc, FALSE); + LinphoneAddress *paulineAddr = linphone_address_clone(linphone_chat_room_get_peer_address(paulineCr)); + coresList = bctbx_list_remove(coresList, pauline->lc); + linphone_core_manager_reinit(pauline); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, pauline); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(pauline, TRUE); + paulineCr = linphone_core_get_chat_room(pauline->lc, paulineAddr); + linphone_address_unref(paulineAddr); + + // Pauline adds Chloe to the chat room + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + linphone_chat_room_add_participants(paulineCr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + + // Refused by server because group chat disabled for Chloe + BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_participants_added, initialMarieStats.number_of_participants_added + 1, 1000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_participants_added, initialPaulineStats.number_of_participants_added + 1, 1000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &laure->stat.number_of_participants_added, initialLaureStats.number_of_participants_added + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 2, int, "%d"); + + // Pauline begins composing a message + linphone_chat_room_compose(paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingActiveReceived, initialMarieStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneIsComposingActiveReceived, initialPaulineStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + + // Now, Chloe is upgrading to group chat client + linphone_core_set_network_reachable(chloe->lc, FALSE); + coresList = bctbx_list_remove(coresList, chloe->lc); + linphone_core_manager_reinit(chloe); + tmpCoresManagerList = bctbx_list_append(NULL, chloe); + tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(chloe, TRUE); + + // Pauline adds Chloe to the chat room + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + linphone_chat_room_add_participants(paulineCr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + + // Check that the chat room is correctly created on Chloe's side and that she was added everywhere + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, initialSubject, 3, FALSE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_added, initialMarieStats.number_of_participants_added + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_added, initialPaulineStats.number_of_participants_added + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participants_added, initialLaureStats.number_of_participants_added + 1, 3000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 3, int, "%d"); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(marie->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(laure->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(pauline->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(chloe->lc), 0, int,"%i"); + + linphone_address_unref(confAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); + linphone_core_manager_destroy(chloe); +} + +static int im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { + if (linphone_chat_message_get_content_type(msg)) { + if (strcmp(linphone_chat_message_get_content_type(msg), "cipher/b64") == 0) { + size_t b64Size = 0; + unsigned char *output; + const char * msg_str = linphone_chat_message_get_text(msg); + bctbx_base64_decode(NULL, &b64Size, (unsigned char *)msg_str, strlen(msg_str)); + output = (unsigned char *)ms_malloc(b64Size+1), + bctbx_base64_decode(output, &b64Size, (unsigned char *)msg_str, strlen(msg_str)); + output[b64Size] = '\0'; + linphone_chat_message_set_text(msg, (char *)output); + ms_free(output); + linphone_chat_message_set_content_type(msg, "message/cpim"); + return 0; + } else if (strcmp(linphone_chat_message_get_content_type(msg), "application/im-iscomposing+xml") == 0) { + return -1; // Not encrypted, nothing to do + } else { + return 488; // Not acceptable + } + } + return 500; +} + +static int im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { + if (strcmp(linphone_chat_message_get_content_type(msg),"message/cpim") == 0) { + size_t b64Size = 0; + unsigned char *output; + const char * msg_str = linphone_chat_message_get_text(msg); + bctbx_base64_encode(NULL, &b64Size, (unsigned char *)msg_str, strlen(msg_str)); + output = (unsigned char *)ms_malloc0(b64Size+1); + bctbx_base64_encode(output, &b64Size, (unsigned char *)msg_str, strlen(msg_str)); + output[b64Size] = '\0'; + linphone_chat_message_set_text(msg,(const char*)output); + ms_free(output); + linphone_chat_message_set_content_type(msg, "cipher/b64"); + return 0; + } + return -1; +} + +static void group_chat_room_message (bool_t encrypt) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialChloeStats = chloe->stat; + LinphoneImEncryptionEngine *marie_imee = linphone_im_encryption_engine_new(); + LinphoneImEncryptionEngineCbs *marie_cbs = linphone_im_encryption_engine_get_callbacks(marie_imee); + LinphoneImEncryptionEngine *pauline_imee = linphone_im_encryption_engine_new(); + LinphoneImEncryptionEngineCbs *pauline_cbs = linphone_im_encryption_engine_get_callbacks(pauline_imee); + LinphoneImEncryptionEngine *chloe_imee = linphone_im_encryption_engine_new(); + LinphoneImEncryptionEngineCbs *chloe_cbs = linphone_im_encryption_engine_get_callbacks(chloe_imee); + + if (encrypt) { + linphone_im_encryption_engine_cbs_set_process_outgoing_message(marie_cbs, im_encryption_engine_process_outgoing_message_cb); + linphone_im_encryption_engine_cbs_set_process_outgoing_message(pauline_cbs, im_encryption_engine_process_outgoing_message_cb); + linphone_im_encryption_engine_cbs_set_process_outgoing_message(chloe_cbs, im_encryption_engine_process_outgoing_message_cb); + + linphone_im_encryption_engine_cbs_set_process_incoming_message(marie_cbs, im_encryption_engine_process_incoming_message_cb); + linphone_im_encryption_engine_cbs_set_process_incoming_message(pauline_cbs, im_encryption_engine_process_incoming_message_cb); + linphone_im_encryption_engine_cbs_set_process_incoming_message(chloe_cbs, im_encryption_engine_process_incoming_message_cb); + + linphone_core_set_im_encryption_engine(marie->lc, marie_imee); + linphone_core_set_im_encryption_engine(pauline->lc, pauline_imee); + linphone_core_set_im_encryption_engine(chloe->lc, chloe_imee); + } + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Chloe's side and that the participants are added + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, initialSubject, 2, FALSE); + + // Chloe begins composing a message + linphone_chat_room_compose(chloeCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingActiveReceived, initialMarieStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, initialPaulineStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + const char *chloeTextMessage = "Hello"; + LinphoneChatMessage *chloeMessage = _send_message(chloeCr, chloeTextMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingIdleReceived, initialMarieStats.number_of_LinphoneIsComposingIdleReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingIdleReceived, initialPaulineStats.number_of_LinphoneIsComposingIdleReceived + 1, 3000)); + LinphoneChatMessage *marieLastMsg = marie->stat.last_received_chat_message; + if (!BC_ASSERT_PTR_NOT_NULL(marieLastMsg)) + goto end; + + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marieLastMsg), chloeTextMessage); + linphone_chat_message_unref(chloeMessage); + LinphoneAddress *chloeAddr = linphone_address_new(linphone_core_get_identity(chloe->lc)); + BC_ASSERT_TRUE(linphone_address_weak_equal(chloeAddr, linphone_chat_message_get_from_address(marieLastMsg))); + linphone_address_unref(chloeAddr); + + // Pauline begins composing a messagewith some accents + linphone_chat_room_compose(paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingActiveReceived, initialMarieStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneIsComposingActiveReceived, initialChloeStats.number_of_LinphoneIsComposingActiveReceived + 1, 3000)); + const char *paulineTextMessage = "Héllö Dàrling"; + LinphoneChatMessage *paulineMessage = _send_message(paulineCr, paulineTextMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageReceived, initialChloeStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingIdleReceived, initialMarieStats.number_of_LinphoneIsComposingIdleReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneIsComposingIdleReceived, initialChloeStats.number_of_LinphoneIsComposingIdleReceived + 1, 3000)); + marieLastMsg = marie->stat.last_received_chat_message; + if (!BC_ASSERT_PTR_NOT_NULL(marieLastMsg)) + goto end; + + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marieLastMsg), paulineTextMessage); + linphone_chat_message_unref(paulineMessage); + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + BC_ASSERT_TRUE(linphone_address_weak_equal(paulineAddr, linphone_chat_message_get_from_address(marieLastMsg))); + linphone_address_unref(paulineAddr); + +end: + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + linphone_im_encryption_engine_unref(marie_imee); + linphone_im_encryption_engine_unref(pauline_imee); + linphone_im_encryption_engine_unref(chloe_imee); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(chloe); +} + +static void group_chat_room_send_message(void) { + group_chat_room_message(FALSE); +} + +static void group_chat_room_send_message_encrypted(void) { + group_chat_room_message(TRUE); +} + +static void group_chat_room_invite_multi_register_account (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline1 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *pauline2 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline1); + coresManagerList = bctbx_list_append(coresManagerList, pauline2); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline1->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPauline1Stats = pauline1->stat; + stats initialPauline2Stats = pauline2->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline1's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline1, &initialPauline1Stats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Pauline2's side and that the participants are added + LinphoneChatRoom *paulineCr2 = check_creation_chat_room_client_side(coresList, pauline2, &initialPauline2Stats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline1, paulineCr, coresList); + linphone_core_delete_chat_room(pauline2->lc, paulineCr2); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline1); + linphone_core_manager_destroy(pauline2); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_add_admin (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie designates Pauline as admin + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + LinphoneParticipant *paulineParticipant = linphone_chat_room_find_participant(marieCr, paulineAddr); + linphone_address_unref(paulineAddr); + BC_ASSERT_PTR_NOT_NULL(paulineParticipant); + linphone_chat_room_set_participant_admin_status(marieCr, paulineParticipant, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(paulineParticipant)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_add_admin_lately_notified (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + //simulate pauline has disapeared + linphone_core_set_network_reachable(pauline->lc, FALSE); + + // Marie designates Pauline as admin + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + LinphoneParticipant *paulineParticipant = linphone_chat_room_find_participant(marieCr, paulineAddr); + linphone_address_unref(paulineAddr); + BC_ASSERT_PTR_NOT_NULL(paulineParticipant); + linphone_chat_room_set_participant_admin_status(marieCr, paulineParticipant, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 1, 1000)); + + //make sure pauline is not notified + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 1000)); + linphone_core_set_network_reachable(pauline->lc, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 3000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(paulineParticipant)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + + + +static void group_chat_room_add_admin_non_admin (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Pauline designates Laure as admin + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(paulineCr, laureAddr); + linphone_address_unref(laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + linphone_chat_room_set_participant_admin_status(paulineCr, laureParticipant, TRUE); + BC_ASSERT_FALSE(linphone_participant_is_admin(laureParticipant)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_remove_admin (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie designates Pauline as admin + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + LinphoneParticipant *paulineParticipant = linphone_chat_room_find_participant(marieCr, paulineAddr); + linphone_address_unref(paulineAddr); + BC_ASSERT_PTR_NOT_NULL(paulineParticipant); + linphone_chat_room_set_participant_admin_status(marieCr, paulineParticipant, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(paulineParticipant)); + + // Pauline revokes the admin status of Marie + LinphoneAddress *marieAddr = linphone_address_new(linphone_core_get_identity(marie->lc)); + LinphoneParticipant *marieParticipant = linphone_chat_room_find_participant(paulineCr, marieAddr); + linphone_address_unref(marieAddr); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + linphone_chat_room_set_participant_admin_status(paulineCr, marieParticipant, FALSE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 2, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 2, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 2, 1000)); + BC_ASSERT_FALSE(linphone_participant_is_admin(marieParticipant)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_admin_creator_leaves_the_room (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie leaves the room + linphone_chat_room_leave(marieCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateTerminated, initialMarieStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participants_removed, initialLaureStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(linphone_chat_room_get_me(laureCr))); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_change_subject (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + const char *newSubject = "New subject"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie now changes the subject + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_change_subject_non_admin (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + const char *newSubject = "New subject"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie now changes the subject + linphone_chat_room_set_subject(paulineCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), initialSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), initialSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), initialSubject); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_remove_participant (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie removes Laure from the chat room + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(marieCr, laureAddr); + linphone_address_unref(laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + linphone_chat_room_remove_participant(marieCr, laureParticipant); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_removed, initialMarieStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 1, 1000)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_send_message_with_participant_removed (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie removes Laure from the chat room + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(marieCr, laureAddr); + linphone_address_unref(laureAddr); + if(!BC_ASSERT_PTR_NOT_NULL(laureParticipant)) + goto end; + + linphone_chat_room_remove_participant(marieCr, laureParticipant); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_removed, initialMarieStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 1, 1000)); + + // Laure try to send a message with the chat room where she was removed + const char *laureTextMessage = "Hello"; + LinphoneChatMessage *laureMessage = _send_message(laureCr, laureTextMessage); + linphone_chat_message_unref(laureMessage); + + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageDelivered, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingIdleReceived, initialMarieStats.number_of_LinphoneIsComposingIdleReceived, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingIdleReceived, initialPaulineStats.number_of_LinphoneIsComposingIdleReceived, 3000)); + +end: + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_leave (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + linphone_chat_room_leave(paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateTerminated, initialPaulineStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_removed, initialMarieStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participants_removed, initialLaureStats.number_of_participants_removed + 1, 1000)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_come_back_after_disconnection (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + int dummy = 0; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + const char *newSubject = "New subject"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + linphone_core_set_network_reachable(marie->lc, FALSE); + + wait_for_list(coresList, &dummy, 1, 1000); + + linphone_core_set_network_reachable(marie->lc, TRUE); + + wait_for_list(coresList, &dummy, 1, 1000); + + // Marie now changes the subject + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_create_room_with_disconnected_friends_base (bool_t initial_message) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + int dummy = 0; + LinphoneChatRoom *paulineCr = NULL; + LinphoneChatRoom *laureCr = NULL; + + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + + wait_for_list(coresList, &dummy, 1, 2000); + + // Disconnect pauline and laure + linphone_core_set_network_reachable(pauline->lc, FALSE); + linphone_core_set_network_reachable(laure->lc, FALSE); + + wait_for_list(coresList, &dummy, 1, 2000); + + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + if (initial_message) { + LinphoneChatMessage *msg = linphone_chat_room_create_message(marieCr, "Salut"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + } + + wait_for_list(coresList, &dummy, 1, 4000); + + // Reconnect Pauline and check that the chat room is correctly created on Pauline's side and that the participants are added + linphone_core_set_network_reachable(pauline->lc, TRUE); + paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + if (!BC_ASSERT_PTR_NOT_NULL(paulineCr)) + goto end; + + // Reconnect Laure and check that the chat room is correctly created on Laure's side and that the participants are added + linphone_core_set_network_reachable(laure->lc, TRUE); + laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + if (!BC_ASSERT_PTR_NOT_NULL(laureCr)) + goto end; + + if (initial_message) { + if (BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, 1, 3000))) { + LinphoneChatMessage *msg = linphone_chat_room_get_last_message_in_history(paulineCr); + if (BC_ASSERT_PTR_NOT_NULL(msg)) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), "Salut"); + linphone_chat_message_unref(msg); + } + } + if (BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneMessageReceived, 1, 3000))) { + LinphoneChatMessage *msg = linphone_chat_room_get_last_message_in_history(laureCr); + if (BC_ASSERT_PTR_NOT_NULL(msg)) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), "Salut"); + linphone_chat_message_unref(msg); + } + } + } + +end: + // Clean db from chat room + if (marieCr) linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + if (laureCr) linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + if (paulineCr) linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_create_room_with_disconnected_friends (void) { + group_chat_room_create_room_with_disconnected_friends_base(FALSE); +} + +static void group_chat_room_create_room_with_disconnected_friends_and_initial_message (void) { + group_chat_room_create_room_with_disconnected_friends_base(TRUE); +} + +static void group_chat_room_reinvited_after_removed_base (bool_t offline_when_removed, bool_t offline_when_reinvited, bool_t restart_after_reinvited) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + char *savedLaureUuid = NULL; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + if (offline_when_removed) { + savedLaureUuid = bctbx_strdup(lp_config_get_string(linphone_core_get_config(laure->lc), "misc", "uuid", NULL)); + coresList = bctbx_list_remove(coresList, laure->lc); + coresManagerList = bctbx_list_remove(coresManagerList, laure); + linphone_core_set_network_reachable(laure->lc, FALSE); + linphone_core_manager_stop(laure); + } + + // Marie removes Laure from the chat room + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(marieCr, laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + linphone_chat_room_remove_participant(marieCr, laureParticipant); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_removed, initialMarieStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 1, 1000)); + + if (offline_when_removed && !offline_when_reinvited) { + linphone_core_manager_configure(laure); + lp_config_set_string(linphone_core_get_config(laure->lc), "misc", "uuid", savedLaureUuid); + bctbx_free(savedLaureUuid); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, laure); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + linphone_core_manager_start(laure, TRUE); + coresList = bctbx_list_concat(coresList, tmpCoresList); + coresManagerList = bctbx_list_append(coresManagerList, laure); + } + if (!offline_when_reinvited) + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 5000)); + + wait_for_list(coresList,0, 1, 2000); + initialLaureStats = laure->stat; + + // Marie adds Laure to the chat room + participantsAddresses = bctbx_list_append(participantsAddresses, laureAddr); + linphone_chat_room_add_participants(marieCr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_added, initialMarieStats.number_of_participants_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_added, initialPaulineStats.number_of_participants_added + 1, 1000)); + if (offline_when_reinvited) { + linphone_core_manager_configure(laure); + lp_config_set_string(linphone_core_get_config(laure->lc), "misc", "uuid", savedLaureUuid); + bctbx_free(savedLaureUuid); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, laure); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + linphone_core_manager_start(laure, TRUE); + coresList = bctbx_list_concat(coresList, tmpCoresList); + coresManagerList = bctbx_list_append(coresManagerList, laure); + } + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateCreationPending, initialLaureStats.number_of_LinphoneChatRoomStateCreationPending + 1, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateCreated, initialLaureStats.number_of_LinphoneChatRoomStateCreated + 1, 5000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomConferenceJoined, initialLaureStats.number_of_LinphoneChatRoomConferenceJoined + 1, 5000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 2, int, "%d"); + char *laureIdentity = linphone_core_get_device_identity(laure->lc); + laureAddr = linphone_address_new(laureIdentity); + bctbx_free(laureIdentity); + LinphoneChatRoom *newLaureCr = linphone_core_find_chat_room(laure->lc, confAddr, laureAddr); + linphone_address_unref(laureAddr); + if (!offline_when_removed) + BC_ASSERT_PTR_EQUAL(newLaureCr, laureCr); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(newLaureCr), 2, int, "%d"); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(newLaureCr), initialSubject); + BC_ASSERT_FALSE(linphone_chat_room_has_been_left(newLaureCr)); + + unsigned int nbLaureConferenceCreatedEventsBeforeRestart = 0; + bctbx_list_t *laureHistory = linphone_chat_room_get_history_events(newLaureCr, 0); + for (bctbx_list_t *item = laureHistory; item; item = bctbx_list_next(item)) { + LinphoneEventLog *event = (LinphoneEventLog *)bctbx_list_get_data(item); + if (linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceCreated) + nbLaureConferenceCreatedEventsBeforeRestart++; + } + bctbx_list_free_with_data(laureHistory, (bctbx_list_free_func)linphone_event_log_unref); + BC_ASSERT_EQUAL(nbLaureConferenceCreatedEventsBeforeRestart, 2, unsigned int, "%u"); + + if (restart_after_reinvited) { + coresList = bctbx_list_remove(coresList, laure->lc); + linphone_core_manager_reinit(laure); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, laure); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(laure, TRUE); + laureIdentity = linphone_core_get_device_identity(laure->lc); + laureAddr = linphone_address_new(laureIdentity); + newLaureCr = linphone_core_find_chat_room(laure->lc, confAddr, laureAddr); + linphone_address_unref(laureAddr); + wait_for_list(coresList,0, 1, 2000); + BC_ASSERT_FALSE(linphone_chat_room_has_been_left(newLaureCr)); + + unsigned int nbLaureConferenceCreatedEventsAfterRestart = 0; + bctbx_list_t *laureHistory = linphone_chat_room_get_history_events(newLaureCr, 0); + for (bctbx_list_t *item = laureHistory; item; item = bctbx_list_next(item)) { + LinphoneEventLog *event = (LinphoneEventLog *)bctbx_list_get_data(item); + if (linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceCreated) + nbLaureConferenceCreatedEventsAfterRestart++; + } + bctbx_list_free_with_data(laureHistory, (bctbx_list_free_func)linphone_event_log_unref); + BC_ASSERT_EQUAL(nbLaureConferenceCreatedEventsAfterRestart, nbLaureConferenceCreatedEventsBeforeRestart, unsigned int, "%u"); + } + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, newLaureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_reinvited_after_removed (void) { + group_chat_room_reinvited_after_removed_base(FALSE, FALSE, FALSE); +} + +static void group_chat_room_reinvited_after_removed_2 (void) { + group_chat_room_reinvited_after_removed_base(FALSE, FALSE, TRUE); +} + +static void group_chat_room_reinvited_after_removed_while_offline (void) { + group_chat_room_reinvited_after_removed_base(TRUE, FALSE, FALSE); +} + +static void group_chat_room_reinvited_after_removed_while_offline_2 (void) { + group_chat_room_reinvited_after_removed_base(TRUE, TRUE, FALSE); +} + +static void group_chat_room_reinvited_after_removed_with_several_devices (void) { + LinphoneCoreManager *marie1 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline1 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *pauline2 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie1); + coresManagerList = bctbx_list_append(coresManagerList, marie2); + coresManagerList = bctbx_list_append(coresManagerList, pauline1); + coresManagerList = bctbx_list_append(coresManagerList, pauline2); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline1->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarie1Stats = marie1->stat; + stats initialMarie2Stats = marie2->stat; + stats initialPauline1Stats = pauline1->stat; + stats initialPauline2Stats = pauline2->stat; + stats initialLaureStats = laure->stat; + + // Marie2 is initially offline + linphone_core_set_network_reachable(marie2->lc, FALSE); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marie1Cr = create_chat_room_client_side(coresList, marie1, &initialMarie1Stats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marie1Cr); + + // Check that the chat room is correctly created on Pauline1 and Pauline2's sides and that the participants are added + LinphoneChatRoom *pauline1Cr = check_creation_chat_room_client_side(coresList, pauline1, &initialPauline1Stats, confAddr, initialSubject, 2, FALSE); + LinphoneChatRoom *pauline2Cr = check_creation_chat_room_client_side(coresList, pauline2, &initialPauline2Stats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie1 removes Pauline from the chat room while Pauline2 is offline + linphone_core_set_network_reachable(pauline2->lc, FALSE); + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline1->lc)); + LinphoneParticipant *paulineParticipant = linphone_chat_room_find_participant(marie1Cr, paulineAddr); + BC_ASSERT_PTR_NOT_NULL(paulineParticipant); + linphone_chat_room_remove_participant(marie1Cr, paulineParticipant); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie1->stat.number_of_participants_removed, initialMarie1Stats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participants_removed, initialLaureStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline1->stat.number_of_LinphoneChatRoomStateTerminated, initialPauline1Stats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + + // Marie2 comes online, check that pauline is not notified as still being in the chat room + linphone_core_set_network_reachable(marie2->lc, TRUE); + LinphoneChatRoom *marie2Cr = check_creation_chat_room_client_side(coresList, marie2, &initialMarie2Stats, confAddr, initialSubject, 1, TRUE); + + // Marie2 adds Pauline back to the chat room + initialPauline1Stats = pauline1->stat; + participantsAddresses = bctbx_list_append(participantsAddresses, paulineAddr); + linphone_chat_room_add_participants(marie2Cr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + BC_ASSERT_TRUE(wait_for_list(coresList, &marie1->stat.number_of_participants_added, initialMarie1Stats.number_of_participants_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_participants_added, initialMarie2Stats.number_of_participants_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participants_added, initialLaureStats.number_of_participants_added + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marie1Cr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marie2Cr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(laureCr), 2, int, "%d"); + LinphoneChatRoom *newPauline1Cr = check_creation_chat_room_client_side(coresList, pauline1, &initialPauline1Stats, confAddr, initialSubject, 2, FALSE); + BC_ASSERT_PTR_EQUAL(newPauline1Cr, pauline1Cr); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(newPauline1Cr), 2, int, "%d"); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(newPauline1Cr), initialSubject); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie1, marie1Cr, coresList); + linphone_core_delete_chat_room(marie2->lc, marie2Cr); + linphone_core_manager_delete_chat_room(pauline1, newPauline1Cr, coresList); + linphone_core_delete_chat_room(pauline2->lc, pauline2Cr); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie1); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(pauline1); + linphone_core_manager_destroy(pauline2); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_notify_after_disconnection (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + int dummy = 0; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie now changes the subject + const char *newSubject = "New subject"; + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); + + linphone_core_set_network_reachable(pauline->lc, FALSE); + wait_for_list(coresList, &dummy, 1, 1000); + + // Marie now changes the subject + newSubject = "Let's go drink a beer"; + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 2, 3000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 2, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 2, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_NOT_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); + + linphone_core_set_network_reachable(pauline->lc, TRUE); + wait_for_list(coresList, &dummy, 1, 1000); + + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 2, 3000)); + + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + + // Test with more than one missed notify + linphone_core_set_network_reachable(pauline->lc, FALSE); + wait_for_list(coresList, &dummy, 1, 1000); + + // Marie now changes the subject + newSubject = "Let's go drink a mineral water !"; + linphone_chat_room_set_subject(marieCr, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 3, 3000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 3, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 3, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr), newSubject); + BC_ASSERT_STRING_NOT_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr), newSubject); + + // Marie designates Laure as admin + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(marieCr, laureAddr); + LinphoneParticipant *laureParticipantFromPauline = linphone_chat_room_find_participant(paulineCr, laureAddr); + linphone_address_unref(laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + BC_ASSERT_PTR_NOT_NULL(laureParticipantFromPauline); + linphone_chat_room_set_participant_admin_status(marieCr, laureParticipant, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(laureParticipant)); + BC_ASSERT_FALSE(linphone_participant_is_admin(laureParticipantFromPauline)); + + linphone_core_set_network_reachable(pauline->lc, TRUE); + wait_for_list(coresList, &dummy, 1, 1000); + + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 3, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr), newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(laureParticipantFromPauline)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_send_refer_to_all_devices (void) { + LinphoneCoreManager *marie1 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline1 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *pauline2 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie1); + coresManagerList = bctbx_list_append(coresManagerList, marie2); + coresManagerList = bctbx_list_append(coresManagerList, pauline1); + coresManagerList = bctbx_list_append(coresManagerList, pauline2); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline1->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarie1Stats = marie1->stat; + stats initialMarie2Stats = marie2->stat; + stats initialPauline1Stats = pauline1->stat; + stats initialPauline2Stats = pauline2->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie1, &initialMarie1Stats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on second Marie's device + LinphoneChatRoom *marieCr2 = check_creation_chat_room_client_side(coresList, marie2, &initialMarie2Stats, confAddr, initialSubject, 2, TRUE); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline1, &initialPauline1Stats, confAddr, initialSubject, 2, FALSE); + LinphoneChatRoom *paulineCr2 = check_creation_chat_room_client_side(coresList, pauline2, &initialPauline2Stats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Check that added Marie's device didn't change her admin status + LinphoneAddress *marieAddr = linphone_address_new(linphone_core_get_identity(marie1->lc)); + LinphoneParticipant *marieParticipant = linphone_chat_room_get_me(marieCr); + if(BC_ASSERT_PTR_NOT_NULL(marieParticipant)) + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + + marieParticipant = linphone_chat_room_get_me(marieCr2); + if(BC_ASSERT_PTR_NOT_NULL(marieParticipant)) + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + + marieParticipant = linphone_chat_room_find_participant(paulineCr, marieAddr); + if(BC_ASSERT_PTR_NOT_NULL(marieParticipant)) + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + + marieParticipant = linphone_chat_room_find_participant(paulineCr2, marieAddr); + if(BC_ASSERT_PTR_NOT_NULL(marieParticipant)) + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + + marieParticipant = linphone_chat_room_find_participant(laureCr, marieAddr); + if(BC_ASSERT_PTR_NOT_NULL(marieParticipant)) + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + + linphone_address_unref(marieAddr); + + // Marie removes Laure from the chat room + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(marieCr, laureAddr); + linphone_address_unref(laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + linphone_chat_room_remove_participant(marieCr, laureParticipant); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie1->stat.number_of_participants_removed, initialMarie1Stats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_participants_removed, initialMarie2Stats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline1->stat.number_of_participants_removed, initialPauline1Stats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_participants_removed, initialPauline2Stats.number_of_participants_removed + 1, 1000)); + + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr2), 1, int, "%d"); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie1, marieCr, coresList); + linphone_core_delete_chat_room(marie2->lc, marieCr2); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline1, paulineCr, coresList); + linphone_core_delete_chat_room(pauline2->lc, paulineCr2); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie1); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(pauline1); + linphone_core_manager_destroy(pauline2); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_add_device (void) { + LinphoneCoreManager *marie1 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline1 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *pauline2 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie1); + coresManagerList = bctbx_list_append(coresManagerList, pauline1); + coresManagerList = bctbx_list_append(coresManagerList, pauline2); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline1->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarie1Stats = marie1->stat; + stats initialPauline1Stats = pauline1->stat; + stats initialPauline2Stats = pauline2->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie1, &initialMarie1Stats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline1, &initialPauline1Stats, confAddr, initialSubject, 2, FALSE); + LinphoneChatRoom *paulineCr2 = check_creation_chat_room_client_side(coresList, pauline2, &initialPauline2Stats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie adds a new device + LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc"); + coresManagerList = bctbx_list_append(coresManagerList, marie2); + LinphoneAddress *factoryAddr = linphone_address_new(sFactoryUri); + _configure_core_for_conference(marie2, factoryAddr); + linphone_address_unref(factoryAddr); + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_chat_room_state_changed(cbs, core_chat_room_state_changed); + _configure_core_for_callbacks(marie2, cbs); + linphone_core_cbs_unref(cbs); + coresList = bctbx_list_append(coresList, marie2->lc); + _start_core(marie2); + stats initialMarie2Stats = marie2->stat; + // Check that the chat room is correctly created on second Marie's device + LinphoneChatRoom *marieCr2 = check_creation_chat_room_client_side(coresList, marie2, &initialMarie2Stats, confAddr, initialSubject, 2, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie1->stat.number_of_participant_devices_added, initialMarie1Stats.number_of_participant_devices_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline1->stat.number_of_participant_devices_added, initialMarie1Stats.number_of_participant_devices_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_participant_devices_added, initialMarie1Stats.number_of_participant_devices_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_devices_added, initialMarie1Stats.number_of_participant_devices_added + 1, 1000)); + + // Check that adding Marie's device didn't change her admin status + LinphoneParticipant *marieParticipant = linphone_chat_room_get_me(marieCr); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + marieParticipant = linphone_chat_room_get_me(marieCr2); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + LinphoneAddress *marieAddr = linphone_address_new(linphone_core_get_identity(marie1->lc)); + marieParticipant = linphone_chat_room_find_participant(paulineCr, marieAddr); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + marieParticipant = linphone_chat_room_find_participant(paulineCr2, marieAddr); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + marieParticipant = linphone_chat_room_find_participant(laureCr, marieAddr); + BC_ASSERT_PTR_NOT_NULL(marieParticipant); + BC_ASSERT_TRUE(linphone_participant_is_admin(marieParticipant)); + linphone_address_unref(marieAddr); + + // Marie removes Laure from the chat room + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(marieCr, laureAddr); + linphone_address_unref(laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + linphone_chat_room_remove_participant(marieCr, laureParticipant); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie1->stat.number_of_participants_removed, initialMarie1Stats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_participants_removed, initialMarie2Stats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline1->stat.number_of_participants_removed, initialPauline1Stats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_participants_removed, initialPauline2Stats.number_of_participants_removed + 1, 1000)); + + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr2), 1, int, "%d"); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie1, marieCr, coresList); + linphone_core_delete_chat_room(marie2->lc, marieCr2); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline1, paulineCr, coresList); + linphone_core_delete_chat_room(pauline2->lc, paulineCr2); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie1); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(pauline1); + linphone_core_manager_destroy(pauline2); + linphone_core_manager_destroy(laure); +} + +static void multiple_is_composing_notification(void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + const bctbx_list_t *composing_addresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Only one is composing + linphone_chat_room_compose(paulineCr); + + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneIsComposingActiveReceived, 1, 1000)); + + // Laure side + composing_addresses = linphone_chat_room_get_composing_addresses(laureCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 1, int, "%i"); + if (bctbx_list_size(composing_addresses) == 1) { + LinphoneAddress *addr = (LinphoneAddress *)bctbx_list_get_data(composing_addresses); + BC_ASSERT_STRING_EQUAL(linphone_address_get_username(addr), linphone_address_get_username(pauline->identity)); + } + + // Marie side + composing_addresses = linphone_chat_room_get_composing_addresses(marieCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 1, int, "%i"); + if (bctbx_list_size(composing_addresses) == 1) { + LinphoneAddress *addr = (LinphoneAddress *)bctbx_list_get_data(composing_addresses); + BC_ASSERT_STRING_EQUAL(linphone_address_get_username(addr), linphone_address_get_username(pauline->identity)); + } + + // Pauline side + composing_addresses = linphone_chat_room_get_composing_addresses(paulineCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 0, int, "%i"); + + wait_for_list(coresList,0, 1, 1500); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingIdleReceived, 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneIsComposingIdleReceived, 1, 1000)); + + composing_addresses = linphone_chat_room_get_composing_addresses(marieCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 0, int, "%i"); + composing_addresses = linphone_chat_room_get_composing_addresses(laureCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 0, int, "%i"); + + // multiple is composing + linphone_chat_room_compose(paulineCr); + linphone_chat_room_compose(marieCr); + + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneIsComposingActiveReceived, 3, 1000)); // + 2 + // Laure side + composing_addresses = linphone_chat_room_get_composing_addresses(laureCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 2, int, "%i"); + if (bctbx_list_size(composing_addresses) == 2) { + while (composing_addresses) { + LinphoneAddress *addr = (LinphoneAddress *)bctbx_list_get_data(composing_addresses); + bool_t equal = strcmp(linphone_address_get_username(addr), linphone_address_get_username(pauline->identity)) == 0 + || strcmp(linphone_address_get_username(addr), linphone_address_get_username(marie->identity)) == 0; + BC_ASSERT_TRUE(equal); + composing_addresses = bctbx_list_next(composing_addresses); + } + } + + // Marie side + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 2, 1000)); // + 1 + composing_addresses = linphone_chat_room_get_composing_addresses(marieCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 1, int, "%i"); + if (bctbx_list_size(composing_addresses) == 1) { + LinphoneAddress *addr = (LinphoneAddress *)bctbx_list_get_data(composing_addresses); + BC_ASSERT_STRING_EQUAL(linphone_address_get_username(addr), linphone_address_get_username(pauline->identity)); + } + + // Pauline side + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, 1, 2000)); + composing_addresses = linphone_chat_room_get_composing_addresses(paulineCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 1, int, "%i"); + if (bctbx_list_size(composing_addresses) == 1) { + LinphoneAddress *addr = (LinphoneAddress *)bctbx_list_get_data(composing_addresses); + BC_ASSERT_STRING_EQUAL(linphone_address_get_username(addr), linphone_address_get_username(marie->identity)); + } + + wait_for_list(coresList,0, 1, 1500); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneIsComposingIdleReceived, 2, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneIsComposingIdleReceived, 3, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingIdleReceived, 1, 1000)); + + composing_addresses = linphone_chat_room_get_composing_addresses(marieCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 0, int, "%i"); + composing_addresses = linphone_chat_room_get_composing_addresses(laureCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 0, int, "%i"); + composing_addresses = linphone_chat_room_get_composing_addresses(paulineCr); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 0, int, "%i"); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_fallback_to_basic_chat_room (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + linphone_core_set_linphone_specs(pauline->lc, NULL); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + + // Marie creates a new group chat room + LinphoneChatRoom *marieCr = linphone_core_create_client_group_chat_room(marie->lc, "Fallback", TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateInstantiated, initialMarieStats.number_of_LinphoneChatRoomStateInstantiated + 1, 100)); + + // Add participants + linphone_chat_room_add_participants(marieCr, participantsAddresses); + + // Check that the group chat room creation fails and that a fallback to a basic chat room is done + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneChatRoomStateCreationFailed, initialMarieStats.number_of_LinphoneChatRoomStateCreationFailed, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesBasic); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + + // Send a message and check that a basic chat room is created on Pauline's side + LinphoneChatMessage *msg = linphone_chat_room_create_message(marieCr, "Hey Pauline!"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); + if (pauline->stat.last_received_chat_message) + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "text/plain"); + LinphoneChatRoom *paulineCr = linphone_core_get_chat_room(pauline->lc, linphone_chat_room_get_local_address(marieCr)); + BC_ASSERT_PTR_NOT_NULL(paulineCr); + if (paulineCr) + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesBasic); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void group_chat_room_creation_fails_if_invited_participants_dont_support_it (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + linphone_core_set_linphone_specs(pauline->lc, NULL); + linphone_core_set_linphone_specs(laure->lc, NULL); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + + // Marie creates a new group chat room + LinphoneChatRoom *marieCr = linphone_core_create_client_group_chat_room(marie->lc, "Hello there", FALSE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateInstantiated, initialMarieStats.number_of_LinphoneChatRoomStateInstantiated + 1, 100)); + + // Add participants + linphone_chat_room_add_participants(marieCr, participantsAddresses); + + // Check that the group chat room creation fails + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationFailed, initialMarieStats.number_of_LinphoneChatRoomStateCreationFailed + 1, 3000)); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + BC_ASSERT_EQUAL(linphone_chat_room_get_state(marieCr), LinphoneChatRoomStateCreationFailed, int, "%d"); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_creation_successful_if_at_least_one_invited_participant_supports_it (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + linphone_core_set_linphone_specs(laure->lc, NULL); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, 1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE); + + // Check that the chat room has not been created on Laure's side + BC_ASSERT_EQUAL(initialLaureStats.number_of_LinphoneChatRoomStateCreated, laure->stat.number_of_LinphoneChatRoomStateCreated, int, "%d"); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_migrate_from_basic_chat_room (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + + // Create a basic chat room + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + LinphoneChatRoom *marieCr = linphone_core_get_chat_room(marie->lc, paulineAddr); + + // Send a message and check that a basic chat room is created on Pauline's side + LinphoneChatMessage *msg = linphone_chat_room_create_message(marieCr, "Hey Pauline!"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); + if (pauline->stat.last_received_chat_message) + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "text/plain"); + LinphoneChatRoom *paulineCr = linphone_core_get_chat_room(pauline->lc, linphone_chat_room_get_local_address(marieCr)); + BC_ASSERT_PTR_NOT_NULL(paulineCr); + if (paulineCr) + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesBasic); + + // Enable chat room migration and restart core for Marie + _linphone_chat_room_enable_migration(marieCr, TRUE); + coresList = bctbx_list_remove(coresList, marie->lc); + linphone_core_manager_reinit(marie); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, marie); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(marie, TRUE); + + // Send a new message to initiate chat room migration + marieCr = linphone_core_get_chat_room(marie->lc, paulineAddr); + BC_ASSERT_PTR_NOT_NULL(marieCr); + if (marieCr) { + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + BC_ASSERT_EQUAL(linphone_chat_room_get_capabilities(marieCr), LinphoneChatRoomCapabilitiesBasic | LinphoneChatRoomCapabilitiesProxy | LinphoneChatRoomCapabilitiesMigratable | LinphoneChatRoomCapabilitiesOneToOne, int, "%d"); + msg = linphone_chat_room_create_message(marieCr, "Did you migrate?"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomConferenceJoined, initialMarieStats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesConference); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 2, int, "%d"); + + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreationPending, initialPaulineStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, initialPaulineStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomConferenceJoined, initialPaulineStats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesConference); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 1, int, "%d"); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 2, int, "%d"); + + msg = linphone_chat_room_create_message(marieCr, "Let's go drink a beer"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 2, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 3, int, "%d"); + + msg = linphone_chat_room_create_message(paulineCr, "Let's go drink mineral water instead"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 4, int, "%d"); + + BC_ASSERT_EQUAL((int)bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)), 1, int, "%d"); + BC_ASSERT_EQUAL((int)bctbx_list_size(linphone_core_get_chat_rooms(pauline->lc)), 1, int, "%d"); + } + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + linphone_address_unref(paulineAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void group_chat_room_migrate_from_basic_to_client_fail (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + int dummy = 0; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + linphone_core_set_linphone_specs(pauline->lc, NULL); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + + // Marie creates a new group chat room + LinphoneChatRoom *marieCr = linphone_core_create_client_group_chat_room(marie->lc, "Fallback", TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateInstantiated, initialMarieStats.number_of_LinphoneChatRoomStateInstantiated + 1, 100)); + + // Add participants + linphone_chat_room_add_participants(marieCr, participantsAddresses); + + // Check that the group chat room creation fails and that a fallback to a basic chat room is done + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneChatRoomStateCreationFailed, initialMarieStats.number_of_LinphoneChatRoomStateCreationFailed, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesBasic); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + + // Send a message and check that a basic chat room is created on Pauline's side + LinphoneChatMessage *msg = linphone_chat_room_create_message(marieCr, "Hey Pauline!"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); + if (pauline->stat.last_received_chat_message) + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "text/plain"); + LinphoneChatRoom *paulineCr = linphone_core_get_chat_room(pauline->lc, linphone_chat_room_get_local_address(marieCr)); + BC_ASSERT_PTR_NOT_NULL(paulineCr); + if (paulineCr) + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesBasic); + + // Enable chat room migration and restart core for Marie + _linphone_chat_room_enable_migration(marieCr, TRUE); + linphone_chat_room_unref(marieCr); + coresList = bctbx_list_remove(coresList, marie->lc); + linphone_core_manager_reinit(marie); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, marie); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(marie, TRUE); + + // Send a new message to initiate chat room migration + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + marieCr = linphone_core_get_chat_room(marie->lc, paulineAddr); + linphone_address_unref(paulineAddr); + BC_ASSERT_PTR_NOT_NULL(marieCr); + if (marieCr) { + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + BC_ASSERT_EQUAL(linphone_chat_room_get_capabilities(marieCr), LinphoneChatRoomCapabilitiesBasic | LinphoneChatRoomCapabilitiesProxy | LinphoneChatRoomCapabilitiesMigratable | LinphoneChatRoomCapabilitiesOneToOne, int, "%d"); + msg = linphone_chat_room_create_message(marieCr, "Did you migrate?"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesBasic); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 2, int, "%d"); + + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreationPending, initialPaulineStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, initialPaulineStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesBasic); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 1, int, "%d"); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 2, int, "%d"); + + msg = linphone_chat_room_create_message(marieCr, "Let's go drink a beer"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 2, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 3, int, "%d"); + + msg = linphone_chat_room_create_message(paulineCr, "Let's go drink mineral water instead"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 4, int, "%d"); + + // Activate groupchat on Pauline's side and wait for 5 seconds, the migration should now be done on next message sending + lp_config_set_int(linphone_core_get_config(marie->lc), "misc", "basic_to_client_group_chat_room_migration_timer", 5); + linphone_core_set_linphone_specs(pauline->lc, "groupchat"); + linphone_core_set_network_reachable(pauline->lc, FALSE); + wait_for_list(coresList, &dummy, 1, 1000); + linphone_core_set_network_reachable(pauline->lc, TRUE); + wait_for_list(coresList, &dummy, 1, 5000); + msg = linphone_chat_room_create_message(marieCr, "And now, did you migrate?"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 2, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomConferenceJoined, initialMarieStats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesConference); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 5, int, "%d"); + + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreationPending, initialPaulineStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, initialPaulineStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomConferenceJoined, initialPaulineStats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesConference); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 1, int, "%d"); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 3, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 5, int, "%d"); + } + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void group_chat_donot_room_migrate_from_basic_chat_room (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + + // Create a basic chat room + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + LinphoneChatRoom *marieCr = linphone_core_get_chat_room(marie->lc, paulineAddr); + + // Send a message and check that a basic chat room is created on Pauline's side + LinphoneChatMessage *msg = linphone_chat_room_create_message(marieCr, "Hey Pauline!"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); + if (pauline->stat.last_received_chat_message) + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(pauline->stat.last_received_chat_message), "text/plain"); + LinphoneChatRoom *paulineCr = linphone_core_get_chat_room(pauline->lc, linphone_chat_room_get_local_address(marieCr)); + BC_ASSERT_PTR_NOT_NULL(paulineCr); + if (paulineCr) + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesBasic); + + // Enable chat room migration and restart core for Marie + coresList = bctbx_list_remove(coresList, marie->lc); + linphone_core_manager_restart(marie, TRUE); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, marie); + init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_append(coresList, marie->lc); + + // Send a new message to initiate chat room migration + marieCr = linphone_core_get_chat_room(marie->lc, paulineAddr); + BC_ASSERT_PTR_NOT_NULL(marieCr); + if (marieCr) { + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + BC_ASSERT_EQUAL(linphone_chat_room_get_capabilities(marieCr), LinphoneChatRoomCapabilitiesBasic | LinphoneChatRoomCapabilitiesOneToOne, int, "%d"); + msg = linphone_chat_room_create_message(marieCr, "Did you migrate?"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarieStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, initialMarieStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesBasic); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 1, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 2, int, "%d"); + + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreationPending, initialPaulineStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, initialPaulineStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesBasic); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 1, int, "%d"); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 2, int, "%d"); + + msg = linphone_chat_room_create_message(marieCr, "Let's go drink a beer"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 2, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 3, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 3, int, "%d"); + + msg = linphone_chat_room_create_message(paulineCr, "Let's go drink mineral water instead"); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(marieCr), 4, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(paulineCr), 4, int, "%d"); + } + + // Clean db from chat room + linphone_core_delete_chat_room(marie->lc, marieCr); + linphone_core_delete_chat_room(pauline->lc, paulineCr); + + linphone_address_unref(paulineAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void group_chat_room_send_file_with_or_without_text (bool_t with_text) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + int dummy = 0; + char *sendFilepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); + char *receivePaulineFilepath = bc_tester_file("receive_file_pauline.dump"); + char *receiveChloeFilepath = bc_tester_file("receive_file_chloe.dump"); + const char *text = "Hello Group !"; + + /* Globally configure an http file transfer server. */ + linphone_core_set_file_transfer_server(marie->lc, "https://www.linphone.org:444/lft.php"); + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialChloeStats = chloe->stat; + + /* Remove any previously downloaded file */ + remove(receivePaulineFilepath); + remove(receiveChloeFilepath); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Chloe's side and that the participants are added + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, initialSubject, 2, FALSE); + + // Sending file + if (with_text) { + _send_file_plus_text(marieCr, sendFilepath, text); + } else { + _send_file(marieCr, sendFilepath); + } + + wait_for_list(coresList, &dummy, 1, 10000); + + // Check that chat rooms have received the file + if (with_text) { + _receive_file_plus_text(coresList, pauline, &initialPaulineStats, receivePaulineFilepath, sendFilepath, text); + _receive_file_plus_text(coresList, chloe, &initialChloeStats, receiveChloeFilepath, sendFilepath, text); + } else { + _receive_file(coresList, pauline, &initialPaulineStats, receivePaulineFilepath, sendFilepath); + _receive_file(coresList, chloe, &initialChloeStats, receiveChloeFilepath, sendFilepath); + } + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + remove(receivePaulineFilepath); + remove(receiveChloeFilepath); + bc_free(sendFilepath); + bc_free(receivePaulineFilepath); + bc_free(receiveChloeFilepath); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(chloe); +} + +static void group_chat_room_send_file (void) { + group_chat_room_send_file_with_or_without_text(FALSE); +} + +static void group_chat_room_send_file_plus_text (void) { + group_chat_room_send_file_with_or_without_text(TRUE); +} + +static void group_chat_room_unique_one_to_one_chat_room (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Pauline"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesOneToOne); + + LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marieCr)); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne); + + // Marie sends a message + const char *textMessage = "Hello"; + LinphoneChatMessage *message = _send_message(marieCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, initialMarieStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Marie deletes the chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + wait_for_list(coresList, 0, 1, 2000); + BC_ASSERT_EQUAL(pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed, int, "%d"); + + // Marie creates the chat room again + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + participantsAddresses = bctbx_list_append(NULL, linphone_address_new(linphone_core_get_identity(pauline->lc))); + marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + // Marie sends a new message + textMessage = "Hey again"; + message = _send_message(marieCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, initialMarieStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Check that the created address is the same as before + const LinphoneAddress *newConfAddr = linphone_chat_room_get_conference_address(marieCr); + BC_ASSERT_TRUE(linphone_address_weak_equal(confAddr, newConfAddr)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + linphone_address_unref(confAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void group_chat_room_unique_one_to_one_chat_room_recreated_from_message_base (bool_t with_app_restart) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Pauline"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesOneToOne); + + LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marieCr)); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne); + + // Marie sends a message + const char *textMessage = "Hello"; + LinphoneChatMessage *message = _send_message(marieCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, initialMarieStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + if (with_app_restart) { + // To simulate dialog removal + LinphoneAddress *marieAddr = linphone_address_clone(linphone_chat_room_get_peer_address(marieCr)); + linphone_core_set_network_reachable(marie->lc, FALSE); + coresList = bctbx_list_remove(coresList, marie->lc); + linphone_core_manager_reinit(marie); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, marie); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(marie, TRUE); + marieCr = linphone_core_get_chat_room(marie->lc, marieAddr); + linphone_address_unref(marieAddr); + } + + // Marie deletes the chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + wait_for_list(coresList, 0, 1, 2000); + BC_ASSERT_EQUAL(pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed, int, "%d"); + + // Pauline sends a new message + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + + // Pauline sends a new message + textMessage = "Hey you"; + message = _send_message(paulineCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDelivered, initialPaulineStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Check that the chat room has been correctly recreated on Marie's side + marieCr = check_creation_chat_room_client_side(coresList, marie, &initialMarieStats, confAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + wait_for_list(coresList, 0, 1, 2000); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(marie->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(pauline->lc), 0, int,"%i"); + BC_ASSERT_PTR_NULL(linphone_core_get_call_logs(marie->lc)); + BC_ASSERT_PTR_NULL(linphone_core_get_call_logs(pauline->lc)); + + linphone_address_unref(confAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void group_chat_room_unique_one_to_one_chat_room_recreated_from_message(void) { + group_chat_room_unique_one_to_one_chat_room_recreated_from_message_base(FALSE); +} + +static void group_chat_room_unique_one_to_one_chat_room_recreated_from_message_with_app_restart(void) { + group_chat_room_unique_one_to_one_chat_room_recreated_from_message_base(TRUE); +} + +static void group_chat_room_unique_one_to_one_chat_room_recreated_from_message_2 (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + // Create a second device for Marie, but it is inactive after registration in this test + LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc"); + // Create a second device for Pauline, but again inactivate it after registration + LinphoneCoreManager *pauline2 = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, marie2); + coresManagerList = bctbx_list_append(coresManagerList, pauline2); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialMarie2Stats = marie2->stat; + stats initialPauline2Stats = pauline2->stat; + + linphone_core_set_network_reachable(marie2->lc, FALSE); + linphone_core_set_network_reachable(pauline2->lc, FALSE); + + // Marie creates a new group chat room + const char *initialSubject = "Pauline"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesOneToOne); + + LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marieCr)); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne); + + // Marie sends a message + const char *textMessage = "Hello"; + LinphoneChatMessage *message = _send_message(marieCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, initialMarieStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Marie deletes the chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + wait_for_list(coresList, 0, 1, 2000); + BC_ASSERT_EQUAL(pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed, int, "%d"); + + // Marie sends a new message + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + + // Check that the chat room has been correctly recreated on Marie's side + marieCr = check_creation_chat_room_client_side(coresList, marie, &initialMarieStats, confAddr, initialSubject, 1, FALSE); + if (BC_ASSERT_PTR_NOT_NULL(marieCr)){ + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesOneToOne); + textMessage = "Hey you"; + message = _send_message(marieCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, initialMarieStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + } + + // Clean db from chat room + linphone_core_set_network_reachable(marie2->lc, TRUE); + linphone_core_set_network_reachable(pauline2->lc, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneChatRoomStateCreationPending, initialMarie2Stats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneChatRoomStateCreated, initialMarie2Stats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneChatRoomConferenceJoined, initialMarie2Stats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_LinphoneChatRoomStateCreationPending, initialPauline2Stats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_LinphoneChatRoomStateCreated, initialPauline2Stats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_LinphoneChatRoomConferenceJoined, initialPauline2Stats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_LinphoneMessageReceived, initialPauline2Stats.number_of_LinphoneMessageReceived + 1, 3000)); + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateTerminated, initialMarieStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateTerminated, initialPaulineStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneChatRoomStateTerminated, initialMarie2Stats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline2->stat.number_of_LinphoneChatRoomStateTerminated, initialPauline2Stats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(marie->lc), 0, int,"%i"); + BC_ASSERT_EQUAL(linphone_core_get_call_history_size(pauline->lc), 0, int,"%i"); + BC_ASSERT_PTR_NULL(linphone_core_get_call_logs(marie->lc)); + BC_ASSERT_PTR_NULL(linphone_core_get_call_logs(pauline->lc)); + + linphone_address_unref(confAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(pauline2); +} + +static void group_chat_room_join_one_to_one_chat_room_with_a_new_device (void) { + LinphoneCoreManager *marie1 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie1); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_new(linphone_core_get_identity(pauline->lc))); + stats initialMarie1Stats = marie1->stat; + stats initialPaulineStats = pauline->stat; + + // Marie1 creates a new one-to-one chat room with Pauline + const char *initialSubject = "Pauline"; + LinphoneChatRoom *marie1Cr = create_chat_room_client_side(coresList, marie1, &initialMarie1Stats, participantsAddresses, initialSubject, -1); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marie1Cr) & LinphoneChatRoomCapabilitiesOneToOne); + + LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marie1Cr)); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne); + + // Marie1 sends a message + const char *textMessage = "Hello"; + LinphoneChatMessage *message = _send_message(marie1Cr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie1->stat.number_of_LinphoneMessageDelivered, initialMarie1Stats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Pauline answers to the previous message + textMessage = "Hey. How are you?"; + message = _send_message(paulineCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDelivered, initialPaulineStats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie1->stat.number_of_LinphoneMessageReceived, initialMarie1Stats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie1->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Simulate an uninstall of the application on Marie's side + linphone_core_set_network_reachable(marie1->lc, FALSE); + coresManagerList = bctbx_list_remove(coresManagerList, marie1); + coresList = bctbx_list_remove(coresList, marie1->lc); + LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc"); + stats initialMarie2Stats = marie2->stat; + bctbx_list_t *newCoresManagerList = bctbx_list_append(NULL, marie2); + bctbx_list_t *newCoresList = init_core_for_conference(newCoresManagerList); + start_core_for_conference(newCoresManagerList); + coresManagerList = bctbx_list_concat(coresManagerList, newCoresManagerList); + coresList = bctbx_list_concat(coresList, newCoresList); + + // Marie2 gets the one-to-one chat room with Pauline + LinphoneChatRoom *marie2Cr = check_creation_chat_room_client_side(coresList, marie2, &initialMarie2Stats, confAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marie2Cr) & LinphoneChatRoomCapabilitiesOneToOne); + + // Marie2 sends a new message + textMessage = "Fine and you?"; + message = _send_message(marie2Cr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneMessageDelivered, initialMarie2Stats.number_of_LinphoneMessageDelivered + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 2, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Pauline answers to the previous message + textMessage = "Perfect!"; + message = _send_message(paulineCr, textMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDelivered, initialPaulineStats.number_of_LinphoneMessageDelivered + 2, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneMessageReceived, initialMarie2Stats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie2->stat.last_received_chat_message), textMessage); + linphone_chat_message_unref(message); + + // Clean db from chat room + int previousNbRegistrationOk = marie1->stat.number_of_LinphoneRegistrationOk; + linphone_core_set_network_reachable(marie1->lc, TRUE); + wait_for_until(marie1->lc, NULL, &marie1->stat.number_of_LinphoneRegistrationOk, previousNbRegistrationOk + 1, 2000); + linphone_core_manager_delete_chat_room(marie2, marie2Cr, coresList); + linphone_core_delete_chat_room(marie1->lc, marie1Cr); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + linphone_address_unref(confAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(marie1); + linphone_core_manager_destroy(pauline); +} + +static void group_chat_room_new_unique_one_to_one_chat_room_after_both_participants_left (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Pauline"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesOneToOne); + + LinphoneAddress *firstConfAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marieCr)); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, firstConfAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne); + + // Both participants delete the chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + wait_for_list(coresList, 0, 1, 3000); + + // Marie re-creates a chat room with Pauline + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marieCr) & LinphoneChatRoomCapabilitiesOneToOne); + + LinphoneAddress *secondConfAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marieCr)); + + // Check that the chat room has been correctly recreated on Marie's side + paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, secondConfAddr, initialSubject, 1, FALSE); + BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne); + + BC_ASSERT_FALSE(linphone_address_equal(firstConfAddr, secondConfAddr)); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + linphone_address_unref(firstConfAddr); + linphone_address_unref(secondConfAddr); + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void imdn_for_group_chat_room (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialChloeStats = chloe->stat; + time_t initialTime = ms_time(NULL); + + // Enable IMDN + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(chloe->lc)); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Chloe's side and that the participants are added + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, initialSubject, 2, FALSE); + + // Chloe begins composing a message + const char *chloeTextMessage = "Hello"; + LinphoneChatMessage *chloeMessage = _send_message(chloeCr, chloeTextMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + LinphoneChatMessage *marieLastMsg = marie->stat.last_received_chat_message; + if (!BC_ASSERT_PTR_NOT_NULL(marieLastMsg)) + goto end; + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marieLastMsg), chloeTextMessage); + LinphoneAddress *chloeAddr = linphone_address_new(linphone_core_get_identity(chloe->lc)); + BC_ASSERT_TRUE(linphone_address_weak_equal(chloeAddr, linphone_chat_message_get_from_address(marieLastMsg))); + linphone_address_unref(chloeAddr); + + // Check that the message has been delivered to Marie and Pauline + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDeliveredToUser, initialChloeStats.number_of_LinphoneMessageDeliveredToUser + 1, 3000)); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed)); + bctbx_list_t *participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser); + if (BC_ASSERT_PTR_NOT_NULL(participantsThatReceivedChloeMessage)) { + BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatReceivedChloeMessage), 2, int, "%d"); + for (bctbx_list_t *item = participantsThatReceivedChloeMessage; item; item = bctbx_list_next(item)) { + LinphoneParticipantImdnState *state = (LinphoneParticipantImdnState *)bctbx_list_get_data(item); + BC_ASSERT_GREATER((int)linphone_participant_imdn_state_get_state_change_time(state), (int)initialTime, int, "%d"); + BC_ASSERT_EQUAL(linphone_participant_imdn_state_get_state(state), LinphoneChatMessageStateDeliveredToUser, int, "%d"); + BC_ASSERT_PTR_NOT_NULL(linphone_participant_imdn_state_get_participant(state)); + } + bctbx_list_free_with_data(participantsThatReceivedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref); + } + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered)); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered)); + + // Marie marks the message as read, check that the state is not yet displayed on Chloe's side + linphone_chat_room_mark_as_read(marieCr); + BC_ASSERT_FALSE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDisplayed, initialChloeStats.number_of_LinphoneMessageDisplayed + 1, 3000)); + bctbx_list_t *participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed); + if (BC_ASSERT_PTR_NOT_NULL(participantsThatDisplayedChloeMessage)) { + BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatDisplayedChloeMessage), 1, int, "%d"); + bctbx_list_free_with_data(participantsThatDisplayedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref); + } + participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser); + if (BC_ASSERT_PTR_NOT_NULL(participantsThatReceivedChloeMessage)) { + BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatReceivedChloeMessage), 1, int, "%d"); + bctbx_list_free_with_data(participantsThatReceivedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref); + } + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered)); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered)); + + // Pauline also marks the message as read, check that the state is now displayed on Chloe's side + linphone_chat_room_mark_as_read(paulineCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDisplayed, initialChloeStats.number_of_LinphoneMessageDisplayed + 1, 3000)); + participantsThatDisplayedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed); + if (BC_ASSERT_PTR_NOT_NULL(participantsThatDisplayedChloeMessage)) { + BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatDisplayedChloeMessage), 2, int, "%d"); + bctbx_list_free_with_data(participantsThatDisplayedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref); + } + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser)); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered)); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered)); + + linphone_chat_message_unref(chloeMessage); + +end: + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(chloe); +} + +static void aggregated_imdn_for_group_chat_room_base (bool_t read_while_offline) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialChloeStats = chloe->stat; + + // Enable IMDN + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(chloe->lc)); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Chloe's side and that the participants are added + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, initialSubject, 2, FALSE); + + // Chloe begins composing a message + const char *chloeTextMessage = "Hello"; + const char *chloeTextMessage2 = "Long time no talk"; + const char *chloeTextMessage3 = "How are you?"; + LinphoneChatMessage *chloeMessage = _send_message(chloeCr, chloeTextMessage); + LinphoneChatMessage *chloeMessage2 = _send_message(chloeCr, chloeTextMessage2); + LinphoneChatMessage *chloeMessage3 = _send_message(chloeCr, chloeTextMessage3); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 3, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 3, 3000)); + LinphoneChatMessage *marieLastMsg = marie->stat.last_received_chat_message; + if (!BC_ASSERT_PTR_NOT_NULL(marieLastMsg)) + goto end; + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marieLastMsg), chloeTextMessage3); + LinphoneAddress *chloeAddr = linphone_address_new(linphone_core_get_identity(chloe->lc)); + BC_ASSERT_TRUE(linphone_address_weak_equal(chloeAddr, linphone_chat_message_get_from_address(marieLastMsg))); + linphone_address_unref(chloeAddr); + + // Mark the messages as read on Marie's and Pauline's sides + linphone_chat_room_mark_as_read(marieCr); + if (read_while_offline) { + linphone_core_set_network_reachable(pauline->lc, FALSE); + linphone_chat_room_mark_as_read(paulineCr); + wait_for_list(coresList, 0, 1, 2000); + linphone_core_set_network_reachable(pauline->lc, TRUE); + } else { + linphone_chat_room_mark_as_read(paulineCr); + } + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDisplayed, initialChloeStats.number_of_LinphoneMessageDisplayed + 1, 3000)); + BC_ASSERT_EQUAL(chloe->stat.number_of_LinphoneMessageDeliveredToUser, 0, int, "%d"); + if (read_while_offline) { + wait_for_list(coresList, 0, 1, 2000); // To prevent memory leak + } + + linphone_chat_message_unref(chloeMessage3); + linphone_chat_message_unref(chloeMessage2); + linphone_chat_message_unref(chloeMessage); + +end: + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(chloe); +} + +static void aggregated_imdn_for_group_chat_room (void) { + aggregated_imdn_for_group_chat_room_base(FALSE); +} + +static void aggregated_imdn_for_group_chat_room_read_while_offline (void) { + aggregated_imdn_for_group_chat_room_base(TRUE); +} + +static void imdn_sent_from_db_state (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialChloeStats = chloe->stat; + time_t initialTime = ms_time(NULL); + + // Enable IMDN except for Marie + linphone_im_notif_policy_clear(linphone_core_get_im_notif_policy(marie->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(chloe->lc)); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marieCr)); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Chloe's side and that the participants are added + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, initialSubject, 2, FALSE); + + // Chloe begins composing a message + const char *chloeTextMessage = "Hello"; + LinphoneChatMessage *chloeMessage = _send_message(chloeCr, chloeTextMessage); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, initialMarieStats.number_of_LinphoneMessageReceived + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000)); + LinphoneChatMessage *marieLastMsg = marie->stat.last_received_chat_message; + if (!BC_ASSERT_PTR_NOT_NULL(marieLastMsg)) + goto end; + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marieLastMsg), chloeTextMessage); + LinphoneAddress *chloeAddr = linphone_address_new(linphone_core_get_identity(chloe->lc)); + BC_ASSERT_TRUE(linphone_address_weak_equal(chloeAddr, linphone_chat_message_get_from_address(marieLastMsg))); + linphone_address_unref(chloeAddr); + + // Check that the message is not globally marked as delivered to user since Marie do not notify its delivery + BC_ASSERT_FALSE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDeliveredToUser, initialChloeStats.number_of_LinphoneMessageDeliveredToUser + 1, 3000)); + + // Restart Marie's core with IMDN enabled so that delivery notification is sent when chat room is loaded from DB + coresList = bctbx_list_remove(coresList, marie->lc); + linphone_core_manager_reinit(marie); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, marie); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); + linphone_core_manager_start(marie, TRUE); + char *marieIdentity = linphone_core_get_device_identity(marie->lc); + LinphoneAddress *marieAddr = linphone_address_new(marieIdentity); + bctbx_free(marieIdentity); + marieCr = linphone_core_find_chat_room(marie->lc, confAddr, marieAddr); + linphone_address_unref(marieAddr); + linphone_address_unref(confAddr); + + // Check that the message has been delivered to Marie and Pauline + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneMessageDeliveredToUser, initialChloeStats.number_of_LinphoneMessageDeliveredToUser + 1, 3000)); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDisplayed)); + bctbx_list_t *participantsThatReceivedChloeMessage = linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDeliveredToUser); + if (BC_ASSERT_PTR_NOT_NULL(participantsThatReceivedChloeMessage)) { + BC_ASSERT_EQUAL((int)bctbx_list_size(participantsThatReceivedChloeMessage), 2, int, "%d"); + for (bctbx_list_t *item = participantsThatReceivedChloeMessage; item; item = bctbx_list_next(item)) { + LinphoneParticipantImdnState *state = (LinphoneParticipantImdnState *)bctbx_list_get_data(item); + BC_ASSERT_GREATER((int)linphone_participant_imdn_state_get_state_change_time(state), (int)initialTime, int, "%d"); + BC_ASSERT_EQUAL(linphone_participant_imdn_state_get_state(state), LinphoneChatMessageStateDeliveredToUser, int, "%d"); + BC_ASSERT_PTR_NOT_NULL(linphone_participant_imdn_state_get_participant(state)); + } + bctbx_list_free_with_data(participantsThatReceivedChloeMessage, (bctbx_list_free_func)linphone_participant_imdn_state_unref); + } + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateDelivered)); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_participants_by_imdn_state(chloeMessage, LinphoneChatMessageStateNotDelivered)); + + linphone_chat_message_unref(chloeMessage); + +end: + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(chloe); +} + +static void find_one_to_one_chat_room (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *chloe = linphone_core_manager_create("chloe_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, chloe); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(chloe->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialChloeStats = chloe->stat; + // Only to be used in linphone_core_find_one_to_one_chatroom(...); + const LinphoneAddress *marieAddr = linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(marie->lc)); + const LinphoneAddress *paulineAddr = linphone_proxy_config_get_identity_address(linphone_core_get_default_proxy_config(pauline->lc)); + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Chloe's side and that the participants are added + LinphoneChatRoom *chloeCr = check_creation_chat_room_client_side(coresList, chloe, &initialChloeStats, confAddr, initialSubject, 2, FALSE); + + // Chloe leave the chat room + linphone_chat_room_leave(chloeCr); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneChatRoomStateTerminationPending, initialChloeStats.number_of_LinphoneChatRoomStateTerminationPending + 1, 100)); + BC_ASSERT_TRUE(wait_for_list(coresList, &chloe->stat.number_of_LinphoneChatRoomStateTerminated, initialChloeStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_removed, initialMarieStats.number_of_participants_removed + 1, 1000)); + + LinphoneChatRoom *oneToOneChatRoom = linphone_core_find_one_to_one_chat_room(marie->lc, marieAddr, paulineAddr); + BC_ASSERT_PTR_NULL(oneToOneChatRoom); + + // Marie create a one to one chat room with Pauline + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + LinphoneChatRoom *marieOneToOneCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, "one to one", -1); + confAddr = linphone_chat_room_get_conference_address(marieOneToOneCr); + LinphoneChatRoom *paulineOneToOneCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, "one to one", 1, FALSE); + + // Check it's the same chat room + oneToOneChatRoom = linphone_core_find_one_to_one_chat_room(marie->lc, marieAddr, paulineAddr); + BC_ASSERT_PTR_NOT_NULL(oneToOneChatRoom); + BC_ASSERT_PTR_EQUAL(oneToOneChatRoom, marieOneToOneCr); + + // Clean the db + linphone_core_manager_delete_chat_room(marie, marieOneToOneCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineOneToOneCr, coresList); + + // Check cleaning went well + oneToOneChatRoom = linphone_core_find_one_to_one_chat_room(marie->lc, marieAddr, paulineAddr); + BC_ASSERT_PTR_NULL(oneToOneChatRoom); + + // Create a basic chat room + marieOneToOneCr = linphone_core_get_chat_room(marie->lc, paulineAddr); + + // Check it's the same chat room + oneToOneChatRoom = linphone_core_find_one_to_one_chat_room(marie->lc, marieAddr, paulineAddr); + BC_ASSERT_PTR_NOT_NULL(oneToOneChatRoom); + BC_ASSERT_PTR_EQUAL(oneToOneChatRoom, marieOneToOneCr); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieOneToOneCr, coresList); + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(chloe, chloeCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(chloe); +} + +static void group_chat_room_new_device_after_creation (void) { + LinphoneCoreManager *marie1 = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline1 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *pauline2 = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie1); + coresManagerList = bctbx_list_append(coresManagerList, pauline1); + coresManagerList = bctbx_list_append(coresManagerList, pauline2); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline1->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarie1Stats = marie1->stat; + stats initialPauline1Stats = pauline1->stat; + stats initialPauline2Stats = pauline2->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marie1Cr = create_chat_room_client_side(coresList, marie1, &initialMarie1Stats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marie1Cr); + + // Check that the chat room is correctly created on Pauline1 and Pauline2's sides and that the participants are added + LinphoneChatRoom *pauline1Cr = check_creation_chat_room_client_side(coresList, pauline1, &initialPauline1Stats, confAddr, initialSubject, 2, FALSE); + LinphoneChatRoom *pauline2Cr = check_creation_chat_room_client_side(coresList, pauline2, &initialPauline2Stats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + LinphoneChatRoom *laureCr = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Marie adds a new device + LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc"); + stats initialMarie2Stats = marie2->stat; + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, marie2); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + start_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + LinphoneChatRoom *marie2Cr = check_creation_chat_room_client_side(coresList, marie2, &initialMarie2Stats, confAddr, initialSubject, 2, TRUE); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie1, marie1Cr, coresList); + linphone_core_delete_chat_room(marie2->lc, marie2Cr); + linphone_core_manager_delete_chat_room(pauline1, pauline1Cr, coresList); + linphone_core_delete_chat_room(pauline2->lc, pauline2Cr); + linphone_core_manager_delete_chat_room(laure, laureCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie1); + linphone_core_manager_destroy(marie2); + linphone_core_manager_destroy(pauline1); + linphone_core_manager_destroy(pauline2); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_list_subscription (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + int dummy = 0; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr1 = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr1 = linphone_chat_room_get_conference_address(marieCr1); + // Check that the chat room is correctly created on Pauline1 and Pauline2's sides and that the participants are added + LinphoneChatRoom *paulineCr1 = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr1, initialSubject, 2, FALSE); + LinphoneChatRoom *laureCr1 = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr1, initialSubject, 2, FALSE); + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + initialLaureStats = laure->stat; + + // Marie creates a new group chat room + initialSubject = "Friends"; + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + LinphoneChatRoom *marieCr2 = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr2 = linphone_chat_room_get_conference_address(marieCr2); + // Check that the chat room is correctly created on Pauline1 and Pauline2's sides and that the participants are added + LinphoneChatRoom *paulineCr2 = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr2, initialSubject, 2, FALSE); + LinphoneChatRoom *laureCr2 = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr2, initialSubject, 2, FALSE); + initialMarieStats = marie->stat; + initialPaulineStats = pauline->stat; + initialLaureStats = laure->stat; + + // Marie creates a new group chat room + initialSubject = "Bros"; + participantsAddresses = NULL; + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + LinphoneChatRoom *marieCr3 = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + const LinphoneAddress *confAddr3 = linphone_chat_room_get_conference_address(marieCr3); + // Check that the chat room is correctly created on Pauline1 and Pauline2's sides and that the participants are added + LinphoneChatRoom *paulineCr3 = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr3, initialSubject, 2, FALSE); + LinphoneChatRoom *laureCr3 = check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr3, initialSubject, 2, FALSE); + + participantsAddresses = NULL; + + // Marie designates Pauline as admin in chat room 1 + LinphoneAddress *paulineAddr = linphone_address_new(linphone_core_get_identity(pauline->lc)); + LinphoneParticipant *paulineParticipant = linphone_chat_room_find_participant(marieCr1, paulineAddr); + linphone_address_unref(paulineAddr); + BC_ASSERT_PTR_NOT_NULL(paulineParticipant); + linphone_chat_room_set_participant_admin_status(marieCr1, paulineParticipant, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 1, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(paulineParticipant)); + + // Pauline's device goes off + paulineAddr = linphone_address_clone(linphone_chat_room_get_local_address(paulineCr1)); + coresList = bctbx_list_remove(coresList, pauline->lc); + linphone_core_set_network_reachable(pauline->lc, FALSE); + wait_for_list(coresList, &dummy, 1, 1000); + + // Marie designates Laure as admin in chat rooms 1 & 3 + LinphoneAddress *laureAddr = linphone_address_new(linphone_core_get_identity(laure->lc)); + LinphoneParticipant *laureParticipant1 = linphone_chat_room_find_participant(marieCr1, laureAddr); + LinphoneParticipant *laureParticipant2 = linphone_chat_room_find_participant(marieCr2, laureAddr); + LinphoneParticipant *laureParticipant3 = linphone_chat_room_find_participant(marieCr3, laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant1); + BC_ASSERT_PTR_NOT_NULL(laureParticipant2); + BC_ASSERT_PTR_NOT_NULL(laureParticipant3); + linphone_chat_room_set_participant_admin_status(marieCr1, laureParticipant1, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 2, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 2, 1000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 2, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(laureParticipant1)); + linphone_chat_room_set_participant_admin_status(marieCr3, laureParticipant3, TRUE); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participant_admin_statuses_changed, initialMarieStats.number_of_participant_admin_statuses_changed + 3, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_participant_admin_statuses_changed, initialLaureStats.number_of_participant_admin_statuses_changed + 3, 1000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 3, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(laureParticipant3)); + + // Marie now changes the subject or chat room 1 + const char *newSubject = "New subject"; + linphone_chat_room_set_subject(marieCr1, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 1, 10000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 1, 10000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 1, 10000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr1), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr1), newSubject); + + // Pauline is back + linphone_core_manager_reinit(pauline); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, pauline); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(pauline, TRUE); + paulineCr1 = linphone_core_find_chat_room(pauline->lc, confAddr1, paulineAddr); + paulineCr2 = linphone_core_find_chat_room(pauline->lc, confAddr2, paulineAddr); + paulineCr3 = linphone_core_find_chat_room(pauline->lc, confAddr3, paulineAddr); + BC_ASSERT_PTR_NOT_NULL(paulineCr1); + BC_ASSERT_PTR_NOT_NULL(paulineCr2); + BC_ASSERT_PTR_NOT_NULL(paulineCr3); + linphone_address_unref(paulineAddr); + LinphoneParticipant *laureParticipantOfPauline1 = linphone_chat_room_find_participant(paulineCr1, laureAddr); + LinphoneParticipant *laureParticipantOfPauline2 = linphone_chat_room_find_participant(paulineCr2, laureAddr); + LinphoneParticipant *laureParticipantOfPauline3 = linphone_chat_room_find_participant(paulineCr3, laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipantOfPauline1); + BC_ASSERT_PTR_NOT_NULL(laureParticipantOfPauline2); + BC_ASSERT_PTR_NOT_NULL(laureParticipantOfPauline3); + linphone_address_unref(laureAddr); + wait_for_list(coresList, &dummy, 1, 5000); + + // Check that Pauline receive the missing info and not more + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_admin_statuses_changed, initialPaulineStats.number_of_participant_admin_statuses_changed + 2, 1000)); + BC_ASSERT_TRUE(linphone_participant_is_admin(laureParticipantOfPauline1)); + BC_ASSERT_TRUE(linphone_participant_is_admin(laureParticipantOfPauline3)); + BC_ASSERT_FALSE(linphone_participant_is_admin(laureParticipantOfPauline2)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 1, 10000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr1), newSubject); + + // Check that Pauline can still receive info once back + // Marie now changes the subject or chat room 1 + newSubject = "New New subject"; + linphone_chat_room_set_subject(marieCr1, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 2, 10000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 2, 10000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 2, 10000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr1), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr1), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr1), newSubject); + // Marie now changes the subject or chat room 2 + newSubject = "Newer subject"; + linphone_chat_room_set_subject(marieCr2, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 3, 10000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 3, 10000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 3, 10000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr2), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr2), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr2), newSubject); + // Marie now changes the subject or chat room 3 + newSubject = "Newest subject"; + linphone_chat_room_set_subject(marieCr3, newSubject); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_subject_changed, initialMarieStats.number_of_subject_changed + 4, 10000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_subject_changed, initialLaureStats.number_of_subject_changed + 4, 10000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_subject_changed, initialPaulineStats.number_of_subject_changed + 4, 10000)); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(marieCr3), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(laureCr3), newSubject); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(paulineCr3), newSubject); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr1, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr1, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr1, coresList); + linphone_core_manager_delete_chat_room(marie, marieCr2, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr2, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr2, coresList); + linphone_core_manager_delete_chat_room(marie, marieCr3, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr3, coresList); + linphone_core_manager_delete_chat_room(laure, laureCr3, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +static void group_chat_room_complex_participant_removal_scenario (void) { + LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc"); + LinphoneCoreManager *laure = linphone_core_manager_create("laure_tcp_rc"); + bctbx_list_t *coresManagerList = NULL; + bctbx_list_t *participantsAddresses = NULL; + coresManagerList = bctbx_list_append(coresManagerList, marie); + coresManagerList = bctbx_list_append(coresManagerList, pauline); + coresManagerList = bctbx_list_append(coresManagerList, laure); + bctbx_list_t *coresList = init_core_for_conference(coresManagerList); + start_core_for_conference(coresManagerList); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(pauline->lc))); + participantsAddresses = bctbx_list_append(participantsAddresses, linphone_address_new(linphone_core_get_identity(laure->lc))); + stats initialMarieStats = marie->stat; + stats initialPaulineStats = pauline->stat; + stats initialLaureStats = laure->stat; + + // Marie creates a new group chat room + const char *initialSubject = "Colleagues"; + LinphoneChatRoom *marieCr = create_chat_room_client_side(coresList, marie, &initialMarieStats, participantsAddresses, initialSubject, -1); + participantsAddresses = NULL; + const LinphoneAddress *confAddr = linphone_chat_room_get_conference_address(marieCr); + + // Check that the chat room is correctly created on Pauline's side and that the participants are added + LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 2, FALSE); + + // Check that the chat room is correctly created on Laure's side and that the participants are added + check_creation_chat_room_client_side(coresList, laure, &initialLaureStats, confAddr, initialSubject, 2, FALSE); + + // Restart Laure core + linphone_core_set_network_reachable(laure->lc, FALSE); + char *laureIdentity = linphone_core_get_device_identity(laure->lc); + LinphoneAddress *laureAddr = linphone_address_new(laureIdentity); + bctbx_free(laureIdentity); + coresList = bctbx_list_remove(coresList, laure->lc); + linphone_core_manager_reinit(laure); + bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, laure); + bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList); + bctbx_list_free(tmpCoresManagerList); + coresList = bctbx_list_concat(coresList, tmpCoresList); + linphone_core_manager_start(laure, TRUE); + initialLaureStats = laure->stat; + + // Marie removes Laure from the chat room + LinphoneParticipant *laureParticipant = linphone_chat_room_find_participant(marieCr, laureAddr); + BC_ASSERT_PTR_NOT_NULL(laureParticipant); + linphone_chat_room_remove_participant(marieCr, laureParticipant); + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_removed, initialMarieStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_removed, initialPaulineStats.number_of_participants_removed + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + + wait_for_list(coresList,0, 1, 2000); + initialLaureStats = laure->stat; + + linphone_proxy_config_refresh_register(linphone_core_get_default_proxy_config(laure->lc)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneRegistrationOk, initialLaureStats.number_of_LinphoneRegistrationOk + 1, 1000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + + // Marie adds Laure to the chat room + participantsAddresses = bctbx_list_append(participantsAddresses, laureAddr); + linphone_chat_room_add_participants(marieCr, participantsAddresses); + bctbx_list_free_with_data(participantsAddresses, (bctbx_list_free_func)linphone_address_unref); + participantsAddresses = NULL; + BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_participants_added, initialMarieStats.number_of_participants_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participants_added, initialPaulineStats.number_of_participants_added + 1, 1000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateCreationPending, initialLaureStats.number_of_LinphoneChatRoomStateCreationPending + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateCreated, initialLaureStats.number_of_LinphoneChatRoomStateCreated + 1, 3000)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomConferenceJoined, initialLaureStats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 2, int, "%d"); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 2, int, "%d"); + laureIdentity = linphone_core_get_device_identity(laure->lc); + laureAddr = linphone_address_new(laureIdentity); + bctbx_free(laureIdentity); + LinphoneChatRoom *newLaureCr = linphone_core_find_chat_room(laure->lc, confAddr, laureAddr); + linphone_address_unref(laureAddr); + BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(newLaureCr), 2, int, "%d"); + BC_ASSERT_STRING_EQUAL(linphone_chat_room_get_subject(newLaureCr), initialSubject); + BC_ASSERT_FALSE(linphone_chat_room_has_been_left(newLaureCr)); + + unsigned int nbLaureConferenceCreatedEventsBeforeRestart = 0; + bctbx_list_t *laureHistory = linphone_chat_room_get_history_events(newLaureCr, 0); + for (bctbx_list_t *item = laureHistory; item; item = bctbx_list_next(item)) { + LinphoneEventLog *event = (LinphoneEventLog *)bctbx_list_get_data(item); + if (linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceCreated) + nbLaureConferenceCreatedEventsBeforeRestart++; + } + bctbx_list_free_with_data(laureHistory, (bctbx_list_free_func)linphone_event_log_unref); + BC_ASSERT_EQUAL(nbLaureConferenceCreatedEventsBeforeRestart, 2, unsigned int, "%u"); + + initialLaureStats = laure->stat; + linphone_proxy_config_refresh_register(linphone_core_get_default_proxy_config(laure->lc)); + BC_ASSERT_TRUE(wait_for_list(coresList, &laure->stat.number_of_LinphoneRegistrationOk, initialLaureStats.number_of_LinphoneRegistrationOk + 1, 1000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomConferenceJoined, initialLaureStats.number_of_LinphoneChatRoomConferenceJoined + 1, 3000)); + BC_ASSERT_FALSE(wait_for_list(coresList, &laure->stat.number_of_LinphoneChatRoomStateTerminated, initialLaureStats.number_of_LinphoneChatRoomStateTerminated + 1, 3000)); + + unsigned int nbLaureConferenceCreatedEventsAfterRestart = 0; + laureHistory = linphone_chat_room_get_history_events(newLaureCr, 0); + for (bctbx_list_t *item = laureHistory; item; item = bctbx_list_next(item)) { + LinphoneEventLog *event = (LinphoneEventLog *)bctbx_list_get_data(item); + if (linphone_event_log_get_type(event) == LinphoneEventLogTypeConferenceCreated) + nbLaureConferenceCreatedEventsAfterRestart++; + } + bctbx_list_free_with_data(laureHistory, (bctbx_list_free_func)linphone_event_log_unref); + BC_ASSERT_EQUAL(nbLaureConferenceCreatedEventsAfterRestart, nbLaureConferenceCreatedEventsBeforeRestart, unsigned int, "%u"); + + // Clean db from chat room + linphone_core_manager_delete_chat_room(marie, marieCr, coresList); + linphone_core_manager_delete_chat_room(laure, newLaureCr, coresList); + linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList); + + bctbx_list_free(coresList); + bctbx_list_free(coresManagerList); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(laure); +} + +test_t group_chat_tests[] = { + TEST_NO_TAG("Group chat room creation server", group_chat_room_creation_server), + TEST_ONE_TAG("Add participant", group_chat_room_add_participant, "LeaksMemory"), + TEST_NO_TAG("Send message", group_chat_room_send_message), + TEST_NO_TAG("Send encrypted message", group_chat_room_send_message_encrypted), + TEST_NO_TAG("Send invite on a multi register account", group_chat_room_invite_multi_register_account), + TEST_NO_TAG("Add admin", group_chat_room_add_admin), + TEST_NO_TAG("Add admin lately notified", group_chat_room_add_admin_lately_notified), + TEST_NO_TAG("Add admin with a non admin", group_chat_room_add_admin_non_admin), + TEST_NO_TAG("Remove admin", group_chat_room_remove_admin), + TEST_NO_TAG("Admin creator leaves the room", group_chat_room_admin_creator_leaves_the_room), + TEST_NO_TAG("Change subject", group_chat_room_change_subject), + TEST_NO_TAG("Change subject with a non admin", group_chat_room_change_subject_non_admin), + TEST_NO_TAG("Remove participant", group_chat_room_remove_participant), + TEST_NO_TAG("Send message with a participant removed", group_chat_room_send_message_with_participant_removed), + TEST_NO_TAG("Leave group chat room", group_chat_room_leave), + TEST_NO_TAG("Come back on a group chat room after a disconnection", group_chat_room_come_back_after_disconnection), + TEST_ONE_TAG("Create chat room with disconnected friends", group_chat_room_create_room_with_disconnected_friends, "LeaksMemory"), + TEST_ONE_TAG("Create chat room with disconnected friends and initial message", group_chat_room_create_room_with_disconnected_friends_and_initial_message, "LeaksMemory"), + TEST_NO_TAG("Reinvited after removed from group chat room", group_chat_room_reinvited_after_removed), + TEST_ONE_TAG("Reinvited after removed from group chat room 2", group_chat_room_reinvited_after_removed_2, "LeaksMemory"), + TEST_ONE_TAG("Reinvited after removed from group chat room while offline", group_chat_room_reinvited_after_removed_while_offline, "LeaksMemory"), + TEST_ONE_TAG("Reinvited after removed from group chat room while offline 2", group_chat_room_reinvited_after_removed_while_offline_2, "LeaksMemory"), + TEST_NO_TAG("Reinvited after removed from group chat room with several devices", group_chat_room_reinvited_after_removed_with_several_devices), + TEST_NO_TAG("Notify after disconnection", group_chat_room_notify_after_disconnection), + TEST_NO_TAG("Send refer to all participants devices", group_chat_room_send_refer_to_all_devices), + TEST_NO_TAG("Admin add device and doesn't lose admin status", group_chat_room_add_device), + TEST_NO_TAG("Send multiple is composing", multiple_is_composing_notification), + TEST_ONE_TAG("Fallback to basic chat room", group_chat_room_fallback_to_basic_chat_room, "LeaksMemory"), + TEST_NO_TAG("Group chat room creation fails if invited participants don't support it", group_chat_room_creation_fails_if_invited_participants_dont_support_it), + TEST_NO_TAG("Group chat room creation successful if at least one invited participant supports it", group_chat_room_creation_successful_if_at_least_one_invited_participant_supports_it), + TEST_ONE_TAG("Migrate basic chat room to client group chat room", group_chat_room_migrate_from_basic_chat_room, "LeaksMemory"), + TEST_ONE_TAG("Migrate basic chat room to client group chat room failure", group_chat_room_migrate_from_basic_to_client_fail, "LeaksMemory"), + TEST_NO_TAG("Migrate basic chat room to client group chat room not needed", group_chat_donot_room_migrate_from_basic_chat_room), + TEST_NO_TAG("Send file", group_chat_room_send_file), + TEST_NO_TAG("Send file + text", group_chat_room_send_file_plus_text), + TEST_NO_TAG("Unique one-to-one chatroom", group_chat_room_unique_one_to_one_chat_room), + TEST_NO_TAG("Unique one-to-one chatroom recreated from message", group_chat_room_unique_one_to_one_chat_room_recreated_from_message), + TEST_ONE_TAG("Unique one-to-one chatroom recreated from message with app restart", group_chat_room_unique_one_to_one_chat_room_recreated_from_message_with_app_restart, "LeaksMemory"), + TEST_NO_TAG("Join one-to-one chat room with a new device", group_chat_room_join_one_to_one_chat_room_with_a_new_device), + TEST_NO_TAG("New unique one-to-one chatroom after both participants left", group_chat_room_new_unique_one_to_one_chat_room_after_both_participants_left), + TEST_ONE_TAG("Unique one-to-one chatroom re-created from the party that deleted it, with inactive devices", group_chat_room_unique_one_to_one_chat_room_recreated_from_message_2, "LeaksMemory"), + TEST_NO_TAG("IMDN for group chat room", imdn_for_group_chat_room), + TEST_NO_TAG("Aggregated IMDN for group chat room", aggregated_imdn_for_group_chat_room), + TEST_NO_TAG("Aggregated IMDN for group chat room read while offline", aggregated_imdn_for_group_chat_room_read_while_offline), + TEST_ONE_TAG("IMDN sent from DB state", imdn_sent_from_db_state, "LeaksMemory"), + TEST_NO_TAG("Find one to one chat room", find_one_to_one_chat_room), + TEST_NO_TAG("New device after group chat room creation", group_chat_room_new_device_after_creation), + TEST_ONE_TAG("Chat room list subscription", group_chat_room_list_subscription, "LeaksMemory"), + TEST_ONE_TAG("Complex participant removal scenario", group_chat_room_complex_participant_removal_scenario, "LeaksMemory") +}; + +test_suite_t group_chat_test_suite = { + "Group Chat", + NULL, + NULL, + liblinphone_tester_before_each, + liblinphone_tester_after_each, + sizeof(group_chat_tests) / sizeof(group_chat_tests[0]), group_chat_tests +}; + +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic pop +#endif diff --git a/tester/images/linphonesiteqr.jpg b/tester/images/linphonesiteqr.jpg new file mode 100644 index 000000000..21768642c Binary files /dev/null and b/tester/images/linphonesiteqr.jpg differ diff --git a/tester/images/linphonesiteqr_captured.jpg b/tester/images/linphonesiteqr_captured.jpg new file mode 100644 index 000000000..5abe984e4 Binary files /dev/null and b/tester/images/linphonesiteqr_captured.jpg differ diff --git a/tester/images/qrcodesite_captured.jpg b/tester/images/qrcodesite_captured.jpg new file mode 100644 index 000000000..d588bfc15 Binary files /dev/null and b/tester/images/qrcodesite_captured.jpg differ diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 2d22231ab..1a67a2be9 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -18,27 +18,8 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#ifdef _MSC_VER -#pragma warning(disable : 4996) -#else -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#endif - -#ifdef HAVE_GTK -#include -#endif - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif - +#include "tester_utils.h" static FILE * log_file = NULL; @@ -50,6 +31,7 @@ static FILE * log_file = NULL; static JNIEnv *current_env = NULL; static jobject current_obj = 0; +jobject system_context = 0; // Application context static const char* LogDomain = "liblinphone_tester"; int main(int argc, char** argv); @@ -117,6 +99,17 @@ void bcunit_android_trace_handler(int level, const char *fmt, va_list args) { (*env)->DeleteLocalRef(env,cls); } +JNIEXPORT void JNICALL Java_org_linphone_tester_Tester_setApplicationContext(JNIEnv *env, jclass obj, jobject context) { + system_context = (jobject)(*env)->NewGlobalRef(env, context); +} + +JNIEXPORT void JNICALL Java_org_linphone_tester_Tester_removeApplicationContext(JNIEnv *env, jclass obj) { + if (system_context) { + (*env)->DeleteGlobalRef(env, system_context); + system_context = 0; + } +} + JNIEXPORT jint JNICALL Java_org_linphone_tester_Tester_run(JNIEnv *env, jobject obj, jobjectArray stringArray) { int i, ret; int argc = (*env)->GetArrayLength(env, stringArray); @@ -194,7 +187,7 @@ int liblinphone_tester_set_log_file(const char *filename) { return -1; } ms_message("Redirecting traces to file [%s]", filename); - linphone_core_set_log_file(log_file); + linphone_core_set_log_file(log_file); return 0; } @@ -220,14 +213,6 @@ int main (int argc, char *argv[]) int i; int ret; -#ifdef HAVE_GTK - gtk_init(&argc, &argv); -#if !GLIB_CHECK_VERSION(2,32,0) // backward compatibility with Debian 6 and CentOS 6 - g_thread_init(NULL); -#endif - gdk_threads_init(); -#endif - liblinphone_tester_init(NULL); linphone_core_set_log_level(ORTP_ERROR); diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index 61bf51b3a..e13d40a5a 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -39,23 +39,39 @@ extern "C" { #endif +#ifdef __ANDROID__ +extern jobject system_context; +#else +extern void *system_context; +#endif + extern test_suite_t account_creator_test_suite; extern test_suite_t call_test_suite; -#ifdef VIDEO_ENABLED + +#if VIDEO_ENABLED extern test_suite_t call_video_test_suite; -#endif // ifdef VIDEO_ENABLED +#endif // if VIDEO_ENABLED + +extern test_suite_t clonable_object_test_suite; +extern test_suite_t conference_event_test_suite; +extern test_suite_t conference_test_suite; +extern test_suite_t contents_test_suite; extern test_suite_t cpim_test_suite; extern test_suite_t dtmf_test_suite; extern test_suite_t event_test_suite; +extern test_suite_t main_db_test_suite; extern test_suite_t flexisip_test_suite; +extern test_suite_t group_chat_test_suite; extern test_suite_t log_collection_test_suite; extern test_suite_t message_test_suite; extern test_suite_t multi_call_test_suite; extern test_suite_t multicast_call_test_suite; +extern test_suite_t multipart_test_suite; extern test_suite_t offeranswer_test_suite; extern test_suite_t player_test_suite; extern test_suite_t presence_server_test_suite; extern test_suite_t presence_test_suite; +extern test_suite_t property_container_test_suite; extern test_suite_t proxy_config_test_suite; extern test_suite_t quality_reporting_test_suite; extern test_suite_t register_test_suite; @@ -67,12 +83,12 @@ extern test_suite_t upnp_test_suite; extern test_suite_t video_test_suite; #ifdef VCARD_ENABLED -extern test_suite_t vcard_test_suite; + extern test_suite_t vcard_test_suite; #endif extern test_suite_t audio_bypass_suite; #if HAVE_SIPP -extern test_suite_t complex_sip_call_test_suite; + extern test_suite_t complex_sip_call_test_suite; #endif extern int manager_count; @@ -114,6 +130,7 @@ extern void liblinphone_tester_clear_accounts(void); extern const char* test_domain; extern const char* auth_domain; extern const char* test_username; +extern const char* test_sha_username; extern const char* test_password; extern const char* test_route; extern const char* userhostsfile; @@ -121,6 +138,7 @@ extern bool_t liblinphone_tester_keep_uuid; extern bool_t liblinphone_tester_tls_support_disabled; extern const MSAudioDiffParams audio_cmp_params; extern const char *liblinphone_tester_mire_id; +extern const char *liblinphone_tester_static_image_id; extern bool_t liblinphonetester_ipv6; extern bool_t liblinphonetester_show_account_manager_logs; @@ -132,7 +150,6 @@ typedef struct _stats { int number_of_LinphoneRegistrationFailed ; int number_of_auth_info_requested ; - int number_of_LinphoneCallIncomingReceived; int number_of_LinphoneCallOutgoingInit; int number_of_LinphoneCallOutgoingProgress; @@ -164,7 +181,6 @@ typedef struct _stats { int number_of_LinphoneMessageReceived; int number_of_LinphoneMessageReceivedWithFile; - int number_of_LinphoneMessageReceivedLegacy; int number_of_LinphoneMessageExtBodyReceived; int number_of_LinphoneMessageInProgress; int number_of_LinphoneMessageDelivered; @@ -177,6 +193,16 @@ typedef struct _stats { int number_of_LinphoneIsComposingIdleReceived; int progress_of_LinphoneFileTransfer; + int number_of_LinphoneChatRoomConferenceJoined; + int number_of_LinphoneChatRoomStateInstantiated; + int number_of_LinphoneChatRoomStateCreationPending; + int number_of_LinphoneChatRoomStateCreated; + int number_of_LinphoneChatRoomStateCreationFailed; + int number_of_LinphoneChatRoomStateTerminationPending; + int number_of_LinphoneChatRoomStateTerminated; + int number_of_LinphoneChatRoomStateTerminationFailed; + int number_of_LinphoneChatRoomStateDeleted; + int number_of_IframeDecoded; int number_of_NewSubscriptionRequest; @@ -271,19 +297,27 @@ typedef struct _stats { int last_tmmbr_value_received; int tmmbr_received_from_cb; + int number_of_participants_added; + int number_of_participant_admin_statuses_changed; + int number_of_participants_removed; + int number_of_subject_changed; + int number_of_participant_devices_added; + int number_of_snapshot_taken; }stats; typedef struct _LinphoneCoreManager { - LinphoneCoreVTable v_table; - LinphoneCore* lc; + LinphoneCoreCbs *cbs; + LinphoneCore *lc; stats stat; - LinphoneAddress* identity; + LinphoneAddress *identity; LinphoneEvent *lev; bool_t decline_subscribe; int number_of_bcunit_error_at_creation; - char* phone_alias; + char *phone_alias; + char *rc_path; + char *database_path; } LinphoneCoreManager; typedef struct _LinphoneConferenceServer { @@ -303,15 +337,21 @@ typedef struct _LinphoneCallTestParams { void liblinphone_tester_add_suites(void); void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, const char* phone_alias); -void linphone_core_manager_start(LinphoneCoreManager *mgr, int check_for_proxies); +void linphone_core_manager_configure (LinphoneCoreManager *mgr); +void linphone_core_manager_start(LinphoneCoreManager *mgr, bool_t check_for_proxies); +LinphoneCoreManager* linphone_core_manager_create2(const char* rc_file, const char* phone_alias); +LinphoneCoreManager* linphone_core_manager_create(const char* rc_file); LinphoneCoreManager* linphone_core_manager_new4(const char* rc_file, int check_for_proxies, const char* phone_aliasconst, const char* contact_params, int expires); -LinphoneCoreManager* linphone_core_manager_new3(const char* rc_file, int check_for_proxies, const char* phone_alias); -LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_for_proxies); +LinphoneCoreManager* linphone_core_manager_new3(const char* rc_file, bool_t check_for_proxies, const char* phone_alias); +LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, bool_t check_for_proxies); LinphoneCoreManager* linphone_core_manager_new(const char* rc_file); void linphone_core_manager_stop(LinphoneCoreManager *mgr); +void linphone_core_manager_reinit(LinphoneCoreManager *mgr); +void linphone_core_manager_restart(LinphoneCoreManager *mgr, bool_t check_for_proxies); void linphone_core_manager_uninit(LinphoneCoreManager *mgr); void linphone_core_manager_wait_for_stun_resolution(LinphoneCoreManager *mgr); void linphone_core_manager_destroy(LinphoneCoreManager* mgr); +void linphone_core_manager_delete_chat_room (LinphoneCoreManager *mgr, LinphoneChatRoom *cr, bctbx_list_t *coresList); void reset_counters( stats* counters); @@ -320,7 +360,6 @@ void call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState void linphone_transfer_state_changed(LinphoneCore *lc, LinphoneCall *transfered, LinphoneCallState new_call_state); void notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf); void notify_presence_received_for_uri_or_tel(LinphoneCore *lc, LinphoneFriend *lf, const char *uri_or_tel, const LinphonePresenceModel *presence); -void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *message); void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* message); void file_transfer_received(LinphoneChatMessage *message, const LinphoneContent* content, const LinphoneBuffer *buffer); LinphoneBuffer * tester_file_transfer_send(LinphoneChatMessage *message, const LinphoneContent* content, size_t offset, size_t size); @@ -332,13 +371,14 @@ void new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char void linphone_subscription_state_change(LinphoneCore *lc, LinphoneEvent *ev, LinphoneSubscriptionState state); void linphone_publish_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state); void linphone_notify_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content); +void linphone_subscribe_received(LinphoneCore *lc, LinphoneEvent *lev, const char *eventname, const LinphoneContent *content); void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message); void linphone_call_encryption_changed(LinphoneCore *lc, LinphoneCall *call, bool_t on, const char *authentication_token); void dtmf_received(LinphoneCore *lc, LinphoneCall *call, int dtmf); void call_stats_updated(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallStats *stats); LinphoneAddress * create_linphone_address(const char * domain); -LinphoneAddress * create_linphone_address_with_username(const char * domain, const char * username); +LinphoneAddress * create_linphone_address_for_algo(const char * domain, const char * username); bool_t wait_for(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value); bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms); bool_t wait_for_until(LinphoneCore* lc_1, LinphoneCore* lc_2,int* counter,int value,int timout_ms); @@ -375,9 +415,10 @@ void liblinphone_tester_clock_start(MSTimeSpec *start); bool_t liblinphone_tester_clock_elapsed(const MSTimeSpec *start, int value_ms); void linphone_core_manager_check_accounts(LinphoneCoreManager *m); void account_manager_destroy(void); -LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data); +LinphoneAddress *account_manager_get_identity_with_modified_identity(const LinphoneAddress *modified_identity); +LinphoneCore *configure_lc_from(LinphoneCoreCbs *cbs, const char *path, const char *file, void *user_data); -void linphone_call_set_first_video_frame_decoded_cb(LinphoneCall *call); +void liblinphone_tester_set_next_video_frame_decoded_cb(LinphoneCall *call); void call_paused_resumed_base(bool_t multicast,bool_t with_losses); void simple_call_base(bool_t enable_multicast_recv_side); void call_base_with_configfile(LinphoneMediaEncryption mode, bool_t enable_video,bool_t enable_relay,LinphoneFirewallPolicy policy,bool_t enable_tunnel, const char *marie_rc, const char *pauline_rc); @@ -414,7 +455,7 @@ LinphoneAddress * linphone_core_manager_resolve(LinphoneCoreManager *mgr, const FILE *sip_start(const char *senario, const char* dest_username, const char *passwd, LinphoneAddress* dest_addres); void early_media_without_sdp_in_200_base( bool_t use_video, bool_t use_ice ); - +void linphone_conf_event_notify(LinphoneEvent *lev); #ifdef __cplusplus }; diff --git a/tester/liblinphone_tester_ios.m b/tester/liblinphone_tester_ios.m index 6f3e54495..36dfd5237 100644 --- a/tester/liblinphone_tester_ios.m +++ b/tester/liblinphone_tester_ios.m @@ -25,6 +25,7 @@ #include #include #include "liblinphone_tester.h" +#include "tester_utils.h" int g_argc; char** g_argv; @@ -64,5 +65,4 @@ int main(int argc, char * argv[]) { return 0; } - #endif // target IPHONE diff --git a/tester/liblinphone_tester_windows.cpp b/tester/liblinphone_tester_windows.cpp index 03ae5912a..ebb814d2c 100644 --- a/tester/liblinphone_tester_windows.cpp +++ b/tester/liblinphone_tester_windows.cpp @@ -1,6 +1,7 @@ #include #include "liblinphone_tester_windows.h" +#include "tester_utils.h" using namespace BelledonneCommunications::Linphone::Tester; using namespace Platform; diff --git a/tester/local_tester_hosts b/tester/local_tester_hosts index 5966c32bb..94fbdce4d 100644 --- a/tester/local_tester_hosts +++ b/tester/local_tester_hosts @@ -1,4 +1,4 @@ -127.0.0.1 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org sipv4.example.org +127.0.0.1 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org sipv4.example.org conf.example.org ::1 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org 188.165.46.90 tunnel.wildcard2.linphone.org -64:ff9b::94.23.19.176 sipv4-nat64.example.org +64:ff9b::94.23.19.176 sipv4-nat64.example.org diff --git a/tester/log_collection_tester.c b/tester/log_collection_tester.c index 7f607ec6b..b81d43449 100644 --- a/tester/log_collection_tester.c +++ b/tester/log_collection_tester.c @@ -21,8 +21,8 @@ #endif #include #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" #ifdef HAVE_ZLIB #include diff --git a/tester/main-db-tester.cpp b/tester/main-db-tester.cpp new file mode 100644 index 000000000..f27b60e26 --- /dev/null +++ b/tester/main-db-tester.cpp @@ -0,0 +1,196 @@ +/* + * main-db-tester.cpp + * Copyright (C) 2017 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "address/address.h" +#include "core/core-p.h" +#include "db/main-db.h" +#include "event-log/events.h" + +// TODO: Remove me. <3 +#include "private.h" + +#include "liblinphone_tester.h" +#include "tools/tester.h" + +// ============================================================================= + +using namespace std; + +using namespace LinphonePrivate; + +// ----------------------------------------------------------------------------- + +class MainDbProvider { +public: + MainDbProvider () { + mCoreManager = linphone_core_manager_create("marie_rc"); + char *dbPath = bc_tester_res("db/linphone.db"); + linphone_config_set_string(linphone_core_get_config(mCoreManager->lc), "storage", "uri", dbPath); + bctbx_free(dbPath); + linphone_core_manager_start(mCoreManager, false); + } + + ~MainDbProvider () { + linphone_core_manager_destroy(mCoreManager); + } + + const MainDb &getMainDb () { + return *L_GET_PRIVATE(mCoreManager->lc->cppPtr)->mainDb; + } + +private: + LinphoneCoreManager *mCoreManager; +}; + +// ----------------------------------------------------------------------------- + +static void get_events_count () { + MainDbProvider provider; + const MainDb &mainDb = provider.getMainDb(); + BC_ASSERT_EQUAL(mainDb.getEventCount(), 5175, int, "%d"); + BC_ASSERT_EQUAL(mainDb.getEventCount(MainDb::ConferenceCallFilter), 0, int, "%d"); + BC_ASSERT_EQUAL(mainDb.getEventCount(MainDb::ConferenceInfoFilter), 18, int, "%d"); + BC_ASSERT_EQUAL(mainDb.getEventCount(MainDb::ConferenceChatMessageFilter), 5157, int, "%d"); + BC_ASSERT_EQUAL(mainDb.getEventCount(MainDb::NoFilter), 5175, int, "%d"); +} + +static void get_messages_count () { + MainDbProvider provider; + const MainDb &mainDb = provider.getMainDb(); + BC_ASSERT_EQUAL(mainDb.getChatMessageCount(), 5157, int, "%d"); + BC_ASSERT_EQUAL( + mainDb.getChatMessageCount( + ChatRoomId(IdentityAddress("sip:test-3@sip.linphone.org"), IdentityAddress("sip:test-1@sip.linphone.org")) + ), + 861, int, "%d" + ); +} + +static void get_unread_messages_count () { + MainDbProvider provider; + const MainDb &mainDb = provider.getMainDb(); + BC_ASSERT_EQUAL(mainDb.getUnreadChatMessageCount(), 2, int, "%d"); + BC_ASSERT_EQUAL( + mainDb.getUnreadChatMessageCount( + ChatRoomId(IdentityAddress("sip:test-3@sip.linphone.org"), IdentityAddress("sip:test-1@sip.linphone.org")) + ), + 0, int, "%d" + ); +} + +static void get_history () { + MainDbProvider provider; + const MainDb &mainDb = provider.getMainDb(); + BC_ASSERT_EQUAL( + mainDb.getHistoryRange( + ChatRoomId(IdentityAddress("sip:test-4@sip.linphone.org"), IdentityAddress("sip:test-1@sip.linphone.org")), + 0, -1, MainDb::Filter::ConferenceChatMessageFilter + ).size(), + 54, + int, + "%d" + ); + BC_ASSERT_EQUAL( + mainDb.getHistoryRange( + ChatRoomId(IdentityAddress("sip:test-7@sip.linphone.org"), IdentityAddress("sip:test-7@sip.linphone.org")), + 0, -1, MainDb::Filter::ConferenceCallFilter + ).size(), + 0, + int, + "%d" + ); + BC_ASSERT_EQUAL( + mainDb.getHistoryRange( + ChatRoomId(IdentityAddress("sip:test-1@sip.linphone.org"), IdentityAddress("sip:test-1@sip.linphone.org")), + 0, -1, MainDb::Filter::ConferenceChatMessageFilter + ).size(), + 804, + int, + "%d" + ); + BC_ASSERT_EQUAL( + mainDb.getHistory( + ChatRoomId(IdentityAddress("sip:test-1@sip.linphone.org"), IdentityAddress("sip:test-1@sip.linphone.org")), + 100, MainDb::Filter::ConferenceChatMessageFilter + ).size(), + 100, + int, + "%d" + ); +} + +static void get_conference_notified_events () { + MainDbProvider provider; + const MainDb &mainDb = provider.getMainDb(); + list> events = mainDb.getConferenceNotifiedEvents( + ChatRoomId(IdentityAddress("sip:test-44@sip.linphone.org"), IdentityAddress("sip:test-1@sip.linphone.org")), + 1 + ); + BC_ASSERT_EQUAL(events.size(), 3, int, "%d"); + if (events.size() != 3) + return; + + shared_ptr event; + auto it = events.cbegin(); + + event = *it; + if (!BC_ASSERT_TRUE(event->getType() == EventLog::Type::ConferenceParticipantRemoved)) return; + { + shared_ptr participantEvent = static_pointer_cast(event); + BC_ASSERT_TRUE(participantEvent->getChatRoomId().getPeerAddress().asString() == "sip:test-44@sip.linphone.org"); + BC_ASSERT_TRUE(participantEvent->getParticipantAddress().asString() == "sip:test-11@sip.linphone.org"); + BC_ASSERT_TRUE(participantEvent->getNotifyId() == 2); + } + + event = *++it; + if (!BC_ASSERT_TRUE(event->getType() == EventLog::Type::ConferenceParticipantDeviceAdded)) return; + { + shared_ptr deviceEvent = static_pointer_cast< + ConferenceParticipantDeviceEvent + >(event); + BC_ASSERT_TRUE(deviceEvent->getChatRoomId().getPeerAddress().asString() == "sip:test-44@sip.linphone.org"); + BC_ASSERT_TRUE(deviceEvent->getParticipantAddress().asString() == "sip:test-11@sip.linphone.org"); + BC_ASSERT_TRUE(deviceEvent->getNotifyId() == 3); + BC_ASSERT_TRUE(deviceEvent->getDeviceAddress().asString() == "sip:test-47@sip.linphone.org"); + } + + event = *++it; + if (!BC_ASSERT_TRUE(event->getType() == EventLog::Type::ConferenceParticipantDeviceRemoved)) return; + { + shared_ptr deviceEvent = static_pointer_cast< + ConferenceParticipantDeviceEvent + >(event); + BC_ASSERT_TRUE(deviceEvent->getChatRoomId().getPeerAddress().asString() == "sip:test-44@sip.linphone.org"); + BC_ASSERT_TRUE(deviceEvent->getParticipantAddress().asString() == "sip:test-11@sip.linphone.org"); + BC_ASSERT_TRUE(deviceEvent->getNotifyId() == 4); + BC_ASSERT_TRUE(deviceEvent->getDeviceAddress().asString() == "sip:test-47@sip.linphone.org"); + } +} + +test_t main_db_tests[] = { + TEST_NO_TAG("Get events count", get_events_count), + TEST_NO_TAG("Get messages count", get_messages_count), + TEST_NO_TAG("Get unread messages count", get_unread_messages_count), + TEST_NO_TAG("Get history", get_history), + TEST_NO_TAG("Get conference events", get_conference_notified_events) +}; + +test_suite_t main_db_test_suite = { + "MainDb", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + sizeof(main_db_tests) / sizeof(main_db_tests[0]), main_db_tests +}; diff --git a/tester/message_tester.c b/tester/message_tester.c index e859c091d..8768a476e 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -19,18 +19,18 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" #include "lime.h" #include "bctoolbox/crypto.h" +#include +#include "linphone/core_utils.h" +#include #ifdef SQLITE_STORAGE_ENABLED #include #endif -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif #ifdef _MSC_VER #pragma warning(disable : 4996) #endif @@ -47,13 +47,8 @@ static const char *pauline_zid_sqlcache = "BEGIN TRANSACTION; CREATE TABLE IF NO static const char *xmlCacheMigration = "\n00112233445566778899aabb99887766554433221100ffeec4274f13a2b6fa05c15ec93158f930e7264b0a893393376dbc80c6eb1cccdc5asip:bob@sip.linphone.org219d9e445d10d4ed64083c7ccbb83a23bc17a97df0af5de4261f3fe026b05b0b747e72a5cc996413cb9fa6e3d18d8b370436e274cd6ba4efc1a4580340af57cadf2bf38e719fa89e17332cf8d5e774ee70d347baa74d16dee01f306c54789869928ce78b0bfc30427a02b1b668b2b3b0496d5664d7e89b75ed292ee97e3fc850496bcc8959337abe5dda11f388384b349d210612f30824268a3753a7afa52ef6df5866dca76315c4sip:bob2@sip.linphone.orgffeeddccbbaa987654321012858b495dfad483af3c088f26d68c4beebc638bd44feae45aea726a771727235esip:bob@sip.linphone.orgb6aac945057bc4466bfe9a23771c6a1b3b8d72ec3e7d8f30ed63cbc5a9479a25bea5ac3225edd0545b816f061a8190370e3ee5160e75404846a34d1580e0c26317ce70fdf12e500294bcb5f2ffef53096761bb1c912b21e972ae03a5a9f05c477e13a20e15a517700f0be0921f74b96d4b4a0c539d5e14d5cdd8706441874ac075e18caa2cfbbf061533dee20c8116dc2c282cae9adfea689b87bc4c6a4e18a846f12e3e7fea39590987654321fedcba5a5a5a5acb6ecc87d1dd87b23f225eec53a26fc541384917623e0c46abab8c0350c6929e92bb03988e8f0ccfefa37a55fd7c5893bea3bfbb27312f49dd9b10d0e3c15fc72315705a5830b98f68458fcd49623144cb34a667512c4d44686aee125bb8b62294c56eea0dd829379263b6da3f6ac0a95388090f168a3568736ca0bd9f8d595fc319ae0d41183fec90afc412d42253c5b456580f7a463c111c7293623b8631f4sip:bob@sip.linphone.org2c46ddcc15f5779e0000000058f095bf01"; #endif // SQLITE_STORAGE_ENABLED -void text_message_received(LinphoneCore *lc, LinphoneChatRoom *room, const LinphoneAddress *from_address, const char *msg) { - stats* counters = get_stats(lc); - counters->number_of_LinphoneMessageReceivedLegacy++; -} - void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* msg) { - char* from=linphone_address_as_string(linphone_chat_message_get_from(msg)); + char* from=linphone_address_as_string(linphone_chat_message_get_from_address(msg)); stats* counters; const char *text=linphone_chat_message_get_text(msg); const char *external_body_url=linphone_chat_message_get_external_body_url(msg); @@ -63,11 +58,14 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess ms_free(from); counters = get_stats(lc); counters->number_of_LinphoneMessageReceived++; - if (counters->last_received_chat_message) linphone_chat_message_unref(counters->last_received_chat_message); + if (counters->last_received_chat_message) { + linphone_chat_message_unref(counters->last_received_chat_message); + } counters->last_received_chat_message=linphone_chat_message_ref(msg); - if (linphone_chat_message_get_file_transfer_information(msg)) { + LinphoneContent * content = linphone_chat_message_get_file_transfer_information(msg); + if (content) counters->number_of_LinphoneMessageReceivedWithFile++; - } else if (linphone_chat_message_get_external_body_url(msg)) { + else if (linphone_chat_message_get_external_body_url(msg)) { counters->number_of_LinphoneMessageExtBodyReceived++; if (message_external_body_url) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_external_body_url(msg),message_external_body_url); @@ -82,10 +80,10 @@ void message_received(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMess void file_transfer_received(LinphoneChatMessage *msg, const LinphoneContent* content, const LinphoneBuffer *buffer){ FILE* file=NULL; char *receive_file = NULL; - + // If a file path is set, we should NOT call the on_recv callback ! - BC_ASSERT_PTR_NULL(msg->file_transfer_filepath); - + BC_ASSERT_PTR_NULL(linphone_chat_message_get_file_transfer_filepath(msg)); + receive_file = bc_tester_file("receive_file.dump"); if (!linphone_chat_message_get_user_data(msg)) { /*first chunk, creating file*/ @@ -114,9 +112,9 @@ LinphoneBuffer * tester_file_transfer_send(LinphoneChatMessage *msg, const Linph size_t size_to_send; uint8_t *buf; FILE *file_to_send = linphone_chat_message_get_user_data(msg); - + // If a file path is set, we should NOT call the on_send callback ! - BC_ASSERT_PTR_NULL(msg->file_transfer_filepath); + BC_ASSERT_PTR_NULL(linphone_chat_message_get_file_transfer_filepath(msg)); BC_ASSERT_PTR_NOT_NULL(file_to_send); if (file_to_send == NULL){ @@ -143,8 +141,8 @@ LinphoneBuffer * tester_file_transfer_send(LinphoneChatMessage *msg, const Linph void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneContent* content, size_t offset, size_t total) { LinphoneChatRoom *cr = linphone_chat_message_get_chat_room(msg); LinphoneCore *lc = linphone_chat_room_get_core(cr); - const LinphoneAddress* from_address = linphone_chat_message_get_from(msg); - const LinphoneAddress* to_address = linphone_chat_message_get_to(msg); + const LinphoneAddress* from_address = linphone_chat_message_get_from_address(msg); + const LinphoneAddress* to_address = linphone_chat_message_get_to_address(msg); char *address = linphone_chat_message_is_outgoing(msg)?linphone_address_as_string(to_address):linphone_address_as_string(from_address); stats* counters = get_stats(lc); int progress = (int)((offset * 100)/total); @@ -163,7 +161,7 @@ void file_transfer_progress_indication(LinphoneChatMessage *msg, const LinphoneC void is_composing_received(LinphoneCore *lc, LinphoneChatRoom *room) { stats *counters = get_stats(lc); - if (room->remote_is_composing == LinphoneIsComposingActive) { + if (linphone_chat_room_is_remote_composing(room)) { counters->number_of_LinphoneIsComposingActiveReceived++; } else { counters->number_of_LinphoneIsComposingIdleReceived++; @@ -221,7 +219,7 @@ void compare_files(const char *path1, const char *path2) { BC_ASSERT_EQUAL(memcmp(buf1, buf2, size1), 0, int, "%d"); } BC_ASSERT_EQUAL((uint8_t)size2, (uint8_t)size1, uint8_t, "%u"); - + if (buf1) ms_free(buf1); if (buf2) ms_free(buf2); } @@ -238,8 +236,8 @@ LinphoneChatMessage* create_message_from_sintel_trailer(LinphoneChatRoom *chat_r file_size = ftell(file_to_send); fseek(file_to_send, 0, SEEK_SET); - content = linphone_core_create_content(chat_room->lc); - belle_sip_object_set_name(&content->base, "sintel trailer content"); + content = linphone_core_create_content(linphone_chat_room_get_core(chat_room)); + belle_sip_object_set_name(BELLE_SIP_OBJECT(content), "sintel trailer content"); linphone_content_set_type(content,"video"); linphone_content_set_subtype(content,"mkv"); linphone_content_set_size(content,file_size); /*total size to be transfered*/ @@ -264,8 +262,8 @@ LinphoneChatMessage* create_file_transfer_message_from_sintel_trailer(LinphoneCh LinphoneChatMessage* msg; char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); - content = linphone_core_create_content(chat_room->lc); - belle_sip_object_set_name(&content->base, "sintel trailer content"); + content = linphone_core_create_content(linphone_chat_room_get_core(chat_room)); + belle_sip_object_set_name(BELLE_SIP_OBJECT(content), "sintel trailer content"); linphone_content_set_type(content,"video"); linphone_content_set_subtype(content,"mkv"); linphone_content_set_name(content,"sintel_trailer_opus_h264.mkv"); @@ -283,10 +281,11 @@ LinphoneChatMessage* create_file_transfer_message_from_sintel_trailer(LinphoneCh } void text_message_base(LinphoneCoreManager* marie, LinphoneCoreManager* pauline) { - LinphoneChatMessage* msg = linphone_chat_room_create_message(linphone_core_get_chat_room(pauline->lc,marie->identity),"Bli bli bli \n blu"); + LinphoneChatRoom *room = linphone_core_get_chat_room(pauline->lc,marie->identity); + LinphoneChatMessage* msg = linphone_chat_room_create_message(room,"Bli bli bli \n blu"); LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(msg->chat_room,msg); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); @@ -296,6 +295,7 @@ void text_message_base(LinphoneCoreManager* marie, LinphoneCoreManager* pauline) } BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); + linphone_chat_message_unref(msg); } /****************************** Tests starting below ******************************/ @@ -304,8 +304,7 @@ static void text_message(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc,marie->identity), "hello"); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,1)); + text_message_base(marie, pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); @@ -314,16 +313,17 @@ static void text_message(void) { static void text_message_within_call_dialog(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - lp_config_set_int(pauline->lc->config,"sip","chat_use_call_dialogs",1); + lp_config_set_int(linphone_core_get_config(pauline->lc),"sip","chat_use_call_dialogs",1); - BC_ASSERT_TRUE(call(marie,pauline)); - linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bla bla bla bla"); + if (BC_ASSERT_TRUE(call(marie,pauline))){ + linphone_chat_room_send_message(linphone_core_get_chat_room(pauline->lc, marie->identity),"Bla bla bla bla"); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); - // when using call dialogs, we will never receive delivered status - BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,0,int,"%d"); + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); + // when using call dialogs, we will never receive delivered status + BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,0,int,"%d"); - end_call(marie, pauline); + end_call(marie, pauline); + } linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -338,19 +338,20 @@ static void text_message_with_credential_from_auth_cb_auth_info_requested(Linpho static void text_message_with_credential_from_auth_callback(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCoreVTable* vtable = linphone_core_v_table_new(); + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); /*to force cb to be called*/ text_message_with_credential_from_auth_cb_auth_info=linphone_auth_info_clone((LinphoneAuthInfo*)(linphone_core_get_auth_info_list(pauline->lc)->data)); linphone_core_clear_all_auth_info(pauline->lc); - vtable->auth_info_requested=text_message_with_credential_from_auth_cb_auth_info_requested; - linphone_core_add_listener(pauline->lc, vtable); + linphone_core_cbs_set_auth_info_requested(cbs, text_message_with_credential_from_auth_cb_auth_info_requested); + linphone_core_add_callbacks(pauline->lc, cbs); + linphone_core_cbs_unref(cbs); text_message_base(marie, pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); - linphone_auth_info_destroy(text_message_with_credential_from_auth_cb_auth_info); + linphone_auth_info_unref(text_message_with_credential_from_auth_cb_auth_info); text_message_with_credential_from_auth_cb_auth_info = NULL; } @@ -360,7 +361,6 @@ static void text_message_with_privacy(void) { linphone_proxy_config_set_privacy(linphone_core_get_default_proxy_config(pauline->lc),LinphonePrivacyId); text_message_base(marie, pauline); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy,1, int, "%d"); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); @@ -410,60 +410,33 @@ static void text_message_with_send_error(void) { LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); /*simulate a network error*/ - sal_set_send_error(marie->lc->sal, -1); + sal_set_send_error(linphone_core_get_sal(marie->lc), -1); linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room,msg); + linphone_chat_message_send(msg); /* check transient msg list: the msg should be in it, and should be the only one */ - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u"); - BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg); + BC_ASSERT_EQUAL(_linphone_chat_room_get_transient_message_count(chat_room), 1, int, "%d"); + BC_ASSERT_PTR_EQUAL(_linphone_chat_room_get_first_transient_message(chat_room), msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1)); /*BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageInProgress,1, int, "%d");*/ BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d"); /* the msg should have been discarded from transient list after an error */ - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL(_linphone_chat_room_get_transient_message_count(chat_room), 0, int, "%d"); - sal_set_send_error(marie->lc->sal, 0); + sal_set_send_error(linphone_core_get_sal(marie->lc), 0); /*give a chance to register again to allow linphone_core_manager_destroy to properly unregister*/ linphone_core_refresh_registers(marie->lc); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneRegistrationOk,marie->stat.number_of_LinphoneRegistrationOk + 1)); + linphone_chat_message_unref(msg); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -static void text_message_with_external_body(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneChatRoom* chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); - LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room,"Bli bli bli \n blu"); - LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); - - message_external_body_url="http://www.linphone.org"; - linphone_chat_message_set_external_body_url(msg,message_external_body_url); - linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room,msg); - - /* check transient msg list: the msg should be in it, and should be the only one */ - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 1, unsigned int, "%u"); - BC_ASSERT_PTR_EQUAL(bctbx_list_nth_data(chat_room->transient_messages,0), msg); - - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); - - BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,1, int, "%d"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageExtBodyReceived,1, int, "%d"); - - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(chat_room->transient_messages), 0, unsigned int, "%u"); - - linphone_core_manager_destroy(marie); - linphone_core_manager_destroy(pauline); -} - -void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pauline, bool_t upload_error, bool_t download_error, +void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pauline, bool_t upload_error, bool_t download_error, bool_t use_file_body_handler_in_upload, bool_t use_file_body_handler_in_download, bool_t download_from_history) { char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); char *receive_filepath = bc_tester_file("receive_file.dump"); @@ -474,7 +447,7 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau /* Remove any previously downloaded file */ remove(receive_filepath); - + /* Globally configure an http file transfer server. */ linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php"); @@ -487,8 +460,8 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau } else { msg = create_message_from_sintel_trailer(chat_room); } - - linphone_chat_room_send_chat_message(chat_room,msg); + + linphone_chat_message_send(msg); if (upload_error) { int chat_room_size = 0; @@ -505,14 +478,14 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateInProgress, int, "%d"); bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref); } - sal_set_send_error(pauline->lc->sal, -1); + sal_set_send_error(linphone_core_get_sal(pauline->lc), -1); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1)); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d"); - sal_set_send_error(pauline->lc->sal, 0); + sal_set_send_error(linphone_core_get_sal(pauline->lc), 0); linphone_core_refresh_registers(pauline->lc); /*to make sure registration is back in registered and so it can be later unregistered*/ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneRegistrationOk,pauline->stat.number_of_LinphoneRegistrationOk+1)); @@ -529,9 +502,13 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau } else { BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000)); if (marie->stat.last_received_chat_message) { + LinphoneChatRoom *marie_room = linphone_core_get_chat_room(marie->lc, pauline->identity); + linphone_chat_room_mark_as_read(marie_room); + // We shoudln't get displayed IMDN until file has been downloaded + BC_ASSERT_FALSE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDisplayed,1, 5000)); + LinphoneChatMessage *recv_msg; if (download_from_history) { - LinphoneChatRoom *marie_room = linphone_core_get_chat_room(marie->lc, pauline->identity); msg_list = linphone_chat_room_get_history(marie_room,1); BC_ASSERT_PTR_NOT_NULL(msg_list); if (!msg_list) goto end; @@ -552,62 +529,74 @@ void transfer_message_base2(LinphoneCoreManager* marie, LinphoneCoreManager* pau /* wait for file to be 50% downloaded */ BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.progress_of_LinphoneFileTransfer, 50)); /* and simulate network error */ - belle_http_provider_set_recv_error(marie->lc->http_provider, -1); + belle_http_provider_set_recv_error(linphone_core_get_http_provider(marie->lc), -1); BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneMessageNotDelivered,1, 10000)); - belle_http_provider_set_recv_error(marie->lc->http_provider, 0); + belle_http_provider_set_recv_error(linphone_core_get_http_provider(marie->lc), 0); + BC_ASSERT_FALSE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDisplayed,1, 5000)); } else { /* wait for a long time in case the DNS SRV resolution takes times - it should be immediate though */ if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1,55000))) { compare_files(send_filepath, receive_filepath); } + BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDisplayed,1, 5000)); } } BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); //sent twice because of file transfer BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d"); } end: + linphone_chat_message_unref(msg); bctbx_list_free_with_data(msg_list, (bctbx_list_free_func)linphone_chat_message_unref); remove(receive_filepath); bc_free(send_filepath); bc_free(receive_filepath); } -void transfer_message_base(bool_t upload_error, bool_t download_error, bool_t use_file_body_handler_in_upload, - bool_t use_file_body_handler_in_download, bool_t download_from_history) { +void transfer_message_base( + bool_t upload_error, bool_t download_error, bool_t use_file_body_handler_in_upload, + bool_t use_file_body_handler_in_download, bool_t download_from_history, bool_t enable_imdn +) { if (transport_supported(LinphoneTransportTls)) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + + if (enable_imdn) { + lp_config_set_int(linphone_core_get_config(pauline->lc), "sip", "deliver_imdn", 1); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "deliver_imdn", 1); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); + } transfer_message_base2(marie,pauline,upload_error,download_error, use_file_body_handler_in_upload, use_file_body_handler_in_download, download_from_history); linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); } } static void transfer_message(void) { - transfer_message_base(FALSE, FALSE, FALSE, FALSE, FALSE); + transfer_message_base(FALSE, FALSE, FALSE, FALSE, FALSE, TRUE); } static void transfer_message_2(void) { - transfer_message_base(FALSE, FALSE, TRUE, FALSE, FALSE); + transfer_message_base(FALSE, FALSE, TRUE, FALSE, FALSE, TRUE); } static void transfer_message_3(void) { - transfer_message_base(FALSE, FALSE, FALSE, TRUE, FALSE); + transfer_message_base(FALSE, FALSE, FALSE, TRUE, FALSE, TRUE); } static void transfer_message_4(void) { - transfer_message_base(FALSE, FALSE, TRUE, TRUE, FALSE); + transfer_message_base(FALSE, FALSE, TRUE, TRUE, FALSE, TRUE); } static void transfer_message_from_history(void) { - transfer_message_base(FALSE, FALSE, TRUE, TRUE, TRUE); + transfer_message_base(FALSE, FALSE, TRUE, TRUE, TRUE, TRUE); } static void transfer_message_with_upload_io_error(void) { - transfer_message_base(TRUE, FALSE, FALSE, FALSE, FALSE); + transfer_message_base(TRUE, FALSE, FALSE, FALSE, FALSE, TRUE); } static void transfer_message_with_download_io_error(void) { - transfer_message_base(FALSE, TRUE, FALSE, FALSE, FALSE); + transfer_message_base(FALSE, TRUE, FALSE, FALSE, FALSE, TRUE); } static void transfer_message_upload_cancelled(void) { @@ -624,7 +613,7 @@ static void transfer_message_upload_cancelled(void) { chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); msg = create_message_from_sintel_trailer(chat_room); - linphone_chat_room_send_chat_message(chat_room,msg); + linphone_chat_message_send(msg); /*wait for file to be 25% uploaded and cancel the transfer */ BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&pauline->stat.progress_of_LinphoneFileTransfer, 25, 60000)); @@ -635,6 +624,7 @@ static void transfer_message_upload_cancelled(void) { BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d"); + linphone_chat_message_unref(msg); linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); } @@ -652,7 +642,7 @@ static void transfer_message_download_cancelled(void) { /* create a chatroom on pauline's side */ chat_room = linphone_core_get_chat_room(pauline->lc,marie->identity); msg = create_message_from_sintel_trailer(chat_room); - linphone_chat_room_send_chat_message(chat_room,msg); + linphone_chat_message_send(msg); /* wait for marie to receive pauline's msg */ BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000)); @@ -672,47 +662,11 @@ static void transfer_message_download_cancelled(void) { BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,0, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageNotDelivered,1, int, "%d"); + linphone_chat_message_unref(msg); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -static void file_transfer_using_external_body_url(void) { - if (transport_supported(LinphoneTransportTls)) { - LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); - LinphoneChatRoom *chat_room; - LinphoneChatMessage *msg; - LinphoneChatMessageCbs *cbs; - LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); - - /* make sure lime is disabled */ - linphone_core_enable_lime(marie->lc, LinphoneLimeDisabled); - linphone_core_enable_lime(pauline->lc, LinphoneLimeDisabled); - - /* create a chatroom on pauline's side */ - chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); - - msg = linphone_chat_room_create_message(chat_room, NULL); - - cbs = linphone_chat_message_get_callbacks(msg); - linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - - linphone_chat_message_set_external_body_url(msg, "https://www.linphone.org:444//tmp/54ec58280ace9_c30709218df8eaba61d1.jpg"); - linphone_chat_room_send_chat_message(chat_room, msg); - - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - if (marie->stat.last_received_chat_message) { - cbs = linphone_chat_message_get_callbacks(marie->stat.last_received_chat_message); - linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_message_download_file(marie->stat.last_received_chat_message); - } - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageExtBodyReceived, 1)); - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDelivered, 1)); - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageFileTransferError, 1)); - linphone_core_manager_destroy(pauline); - linphone_core_manager_destroy(marie); - } -} - static void file_transfer_2_messages_simultaneously(void) { if (transport_supported(LinphoneTransportTls)) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); @@ -726,7 +680,7 @@ static void file_transfer_2_messages_simultaneously(void) { /* Remove any previously downloaded file */ remove(receive_filepath); - + /* Globally configure an http file transfer server. */ linphone_core_set_file_transfer_server(pauline->lc,"https://www.linphone.org:444/lft.php"); @@ -740,12 +694,12 @@ static void file_transfer_2_messages_simultaneously(void) { BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)), 0, unsigned int, "%u"); if (bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)) == 0) { - linphone_chat_room_send_chat_message(pauline_room,msg); - linphone_chat_room_send_chat_message(pauline_room,msg2); + linphone_chat_message_send(msg); + linphone_chat_message_send(msg2); if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000))) { - msg = linphone_chat_message_clone(marie->stat.last_received_chat_message); + LinphoneChatMessage *recvMsg = linphone_chat_message_ref(marie->stat.last_received_chat_message); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,2, 60000)); - msg2 = marie->stat.last_received_chat_message; + LinphoneChatMessage *recvMsg2 = marie->stat.last_received_chat_message; BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)), 1, unsigned int, "%u"); if (bctbx_list_size(linphone_core_get_chat_rooms(marie->lc)) != 1) { char * buf = ms_strdup_printf("Found %d rooms instead of 1: ", bctbx_list_size(linphone_core_get_chat_rooms(marie->lc))); @@ -758,17 +712,17 @@ static void file_transfer_2_messages_simultaneously(void) { ms_error("%s", buf); } - cbs = linphone_chat_message_get_callbacks(msg); + cbs = linphone_chat_message_get_callbacks(recvMsg); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received); linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); - linphone_chat_message_download_file(msg); + linphone_chat_message_download_file(recvMsg); - cbs = linphone_chat_message_get_callbacks(msg2); + cbs = linphone_chat_message_get_callbacks(recvMsg2); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received); linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); - linphone_chat_message_download_file(msg2); + linphone_chat_message_download_file(recvMsg2); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,2,50000)); @@ -776,9 +730,11 @@ static void file_transfer_2_messages_simultaneously(void) { BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,2, int, "%d"); compare_files(send_filepath, receive_filepath); - linphone_chat_message_unref(msg); + linphone_chat_message_unref(recvMsg); } } + linphone_chat_message_unref(msg); + linphone_chat_message_unref(msg2); linphone_core_manager_destroy(pauline); remove(receive_filepath); bc_free(send_filepath); @@ -787,6 +743,52 @@ static void file_transfer_2_messages_simultaneously(void) { } } +static void file_transfer_external_body_url(bool_t use_file_body_handler_in_download) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + LinphoneChatRoom* chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity); + LinphoneChatMessage* msg = linphone_chat_room_create_message(chat_room, NULL); + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); + char *receive_filepath = bc_tester_file("receive_file.dump"); + + linphone_chat_message_set_external_body_url(msg, "https://www.linphone.org/img/linphone-open-source-voip-projectX2.png"); + linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_send(msg); + linphone_chat_message_unref(msg); + + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceivedWithFile, 1, 60000)); + + if (pauline->stat.last_received_chat_message) { + LinphoneChatMessage *recv_msg = pauline->stat.last_received_chat_message; + cbs = linphone_chat_message_get_callbacks(recv_msg); + linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received); + linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); + if (use_file_body_handler_in_download) { + /* Remove any previously downloaded file */ + remove(receive_filepath); + linphone_chat_message_set_file_transfer_filepath(recv_msg, receive_filepath); + } + linphone_chat_message_download_file(recv_msg); + + /* wait for a long time in case the DNS SRV resolution takes times - it should be immediate though */ + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneFileTransferDownloadSuccessful, 1, 55000)); + } + + remove(receive_filepath); + bc_free(receive_filepath); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void file_transfer_using_external_body_url(void) { + file_transfer_external_body_url(FALSE); +} + +static void file_transfer_using_external_body_url_2(void) { + file_transfer_external_body_url(TRUE); +} + static void text_message_denied(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); @@ -797,10 +799,11 @@ static void text_message_denied(void) { /*pauline doesn't want to be disturbed*/ linphone_core_disable_chat(pauline->lc,LinphoneReasonDoNotDisturb); linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room,msg); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageNotDelivered,1)); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageReceived,0, int, "%d"); + linphone_chat_message_unref(msg); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -825,44 +828,45 @@ void info_message_base(bool_t with_content) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - BC_ASSERT_TRUE(call(pauline,marie)); + if (BC_ASSERT_TRUE(call(pauline,marie))){ - info=linphone_core_create_info_message(marie->lc); - linphone_info_message_add_header(info,"Weather","still bad"); - if (with_content) { - LinphoneContent* ct=linphone_core_create_content(marie->lc); - linphone_content_set_type(ct,"application"); - linphone_content_set_subtype(ct,"somexml"); - linphone_content_set_buffer(ct,info_content,strlen(info_content)); - linphone_info_message_set_content(info,ct); - linphone_content_unref(ct); - } - linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info); - linphone_info_message_unref(info); - - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1)); - - BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_info_message); - hvalue=linphone_info_message_get_header(pauline->stat.last_received_info_message, "Weather"); - content=linphone_info_message_get_content(pauline->stat.last_received_info_message); - - BC_ASSERT_PTR_NOT_NULL(hvalue); - if (hvalue) - BC_ASSERT_STRING_EQUAL(hvalue, "still bad"); - - if (with_content){ - BC_ASSERT_PTR_NOT_NULL(content); - if (content) { - BC_ASSERT_PTR_NOT_NULL(linphone_content_get_buffer(content)); - BC_ASSERT_PTR_NOT_NULL(linphone_content_get_type(content)); - BC_ASSERT_PTR_NOT_NULL(linphone_content_get_subtype(content)); - if (linphone_content_get_type(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content),"application"); - if (linphone_content_get_subtype(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content),"somexml"); - if (linphone_content_get_buffer(content))BC_ASSERT_STRING_EQUAL((const char*)linphone_content_get_buffer(content),info_content); - BC_ASSERT_EQUAL((int)linphone_content_get_size(content),(int)strlen(info_content), int, "%d"); + info=linphone_core_create_info_message(marie->lc); + linphone_info_message_add_header(info,"Weather","still bad"); + if (with_content) { + LinphoneContent* content = linphone_core_create_content(marie->lc); + linphone_content_set_type(content, "application"); + linphone_content_set_subtype(content, "somexml"); + linphone_content_set_buffer(content, (const uint8_t *)info_content, strlen(info_content)); + linphone_info_message_set_content(info, content); + linphone_content_unref(content); } + linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info); + linphone_info_message_unref(info); + + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1)); + + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_info_message); + hvalue=linphone_info_message_get_header(pauline->stat.last_received_info_message, "Weather"); + content=linphone_info_message_get_content(pauline->stat.last_received_info_message); + + BC_ASSERT_PTR_NOT_NULL(hvalue); + if (hvalue) + BC_ASSERT_STRING_EQUAL(hvalue, "still bad"); + + if (with_content){ + BC_ASSERT_PTR_NOT_NULL(content); + if (content) { + BC_ASSERT_PTR_NOT_NULL(linphone_content_get_buffer(content)); + BC_ASSERT_PTR_NOT_NULL(linphone_content_get_type(content)); + BC_ASSERT_PTR_NOT_NULL(linphone_content_get_subtype(content)); + if (linphone_content_get_type(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content),"application"); + if (linphone_content_get_subtype(content)) BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content),"somexml"); + if (linphone_content_get_buffer(content))BC_ASSERT_STRING_EQUAL(linphone_content_get_string_buffer(content),info_content); + BC_ASSERT_EQUAL((int)linphone_content_get_size(content),(int)strlen(info_content), int, "%d"); + } + } + end_call(marie, pauline); } - end_call(marie, pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -894,8 +898,8 @@ static int enable_lime_for_message_test(LinphoneCoreManager *marie, LinphoneCore linphone_core_enable_lime(pauline->lc, LinphoneLimeMandatory); /* make sure to not trigger the cache migration function */ - lp_config_set_int(marie->lc->config, "sip", "zrtp_cache_migration_done", TRUE); - lp_config_set_int(pauline->lc->config, "sip", "zrtp_cache_migration_done", TRUE); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "zrtp_cache_migration_done", TRUE); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sip", "zrtp_cache_migration_done", TRUE); /* create temporary cache files: setting the database_path will create and initialise the files */ tmp = bc_tester_file("tmpZIDCacheMarie.sqlite"); @@ -941,23 +945,62 @@ static int enable_lime_for_message_test(LinphoneCoreManager *marie, LinphoneCore } static void _is_composing_notification(bool_t lime_enabled) { - LinphoneChatRoom* chat_room; + LinphoneChatRoom* pauline_chat_room; + LinphoneChatRoom* marie_chat_room; int dummy = 0; + const bctbx_list_t *composing_addresses = NULL; LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "deliver_imdn", 1); if (lime_enabled) { if (enable_lime_for_message_test(marie, pauline) < 0) goto end; } - chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); + pauline_chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); + marie_chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity); linphone_core_get_chat_room(marie->lc, pauline->identity); /*make marie create the chatroom with pauline, which is necessary for receiving the is-composing*/ - 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 msg"); + linphone_chat_room_compose(pauline_chat_room); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, 1)); + composing_addresses = linphone_chat_room_get_composing_addresses(marie_chat_room); + BC_ASSERT_GREATER(bctbx_list_size(composing_addresses), 0, int, "%i"); + if (bctbx_list_size(composing_addresses) > 0) { + LinphoneAddress *addr = (LinphoneAddress *)bctbx_list_get_data(composing_addresses); + char *address_string = linphone_address_as_string(addr); + char *pauline_address = linphone_address_as_string(pauline->identity); + BC_ASSERT_STRING_EQUAL(address_string, pauline_address); + bctbx_free(address_string); + bctbx_free(pauline_address); + } + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + LinphoneChatMessage *is_composing_msg = marie->stat.last_received_chat_message; + if (BC_ASSERT_PTR_NOT_NULL(is_composing_msg)) { + const char *expires = linphone_chat_message_get_custom_header(is_composing_msg, "Expires"); + if (BC_ASSERT_PTR_NOT_NULL(expires)) + BC_ASSERT_STRING_EQUAL(expires, "0"); + + const char *priority = linphone_chat_message_get_custom_header(is_composing_msg, "Priority"); + if (BC_ASSERT_PTR_NOT_NULL(priority)) + BC_ASSERT_STRING_EQUAL(priority, "non-urgent"); + } + wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /*just to sleep while iterating*/ + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingIdleReceived, 1)); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2)); + is_composing_msg = marie->stat.last_received_chat_message; + if (BC_ASSERT_PTR_NOT_NULL(is_composing_msg)) { + const char *expires = linphone_chat_message_get_custom_header(is_composing_msg, "Expires"); + if (BC_ASSERT_PTR_NOT_NULL(expires)) + BC_ASSERT_STRING_EQUAL(expires, "0"); + + const char *priority = linphone_chat_message_get_custom_header(is_composing_msg, "Priority"); + if (BC_ASSERT_PTR_NOT_NULL(priority)) + BC_ASSERT_STRING_EQUAL(priority, "non-urgent"); + } + linphone_chat_room_send_message(pauline_chat_room, "Composing a msg"); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingIdleReceived, 2)); + composing_addresses = linphone_chat_room_get_composing_addresses(marie_chat_room); + BC_ASSERT_EQUAL(bctbx_list_size(composing_addresses), 0, int, "%i"); end: linphone_core_manager_destroy(marie); @@ -979,6 +1022,7 @@ static void is_composing_notification_with_lime(void) { static void _imdn_notifications(bool_t with_lime) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sip", "deliver_imdn", 1); LinphoneChatRoom *pauline_chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); LinphoneChatRoom *marie_chat_room; LinphoneChatMessage *sent_cm; @@ -993,23 +1037,37 @@ static void _imdn_notifications(bool_t with_lime) { linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); sent_cm = linphone_chat_room_create_message(pauline_chat_room, "Tell me if you get my message"); - linphone_chat_message_ref(sent_cm); cbs = linphone_chat_message_get_callbacks(sent_cm); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(pauline_chat_room, sent_cm); + linphone_chat_message_send(sent_cm); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); marie_chat_room = linphone_core_get_chat_room(marie->lc, pauline->identity); history = linphone_chat_room_get_history(marie_chat_room, 1); BC_ASSERT_EQUAL((int)bctbx_list_size(history), 1, int, "%d"); - received_cm = (LinphoneChatMessage *)bctbx_list_nth_data(history, 0); - BC_ASSERT_PTR_NOT_NULL(received_cm); - if (received_cm != NULL) { - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1)); - linphone_chat_room_mark_as_read(marie_chat_room); /* This sends the display notification */ - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDisplayed, 1)); - bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref); + if (bctbx_list_size(history) > 0) { + received_cm = (LinphoneChatMessage *)bctbx_list_nth_data(history, 0); + BC_ASSERT_PTR_NOT_NULL(received_cm); + if (received_cm != NULL) { + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1)); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); + LinphoneChatMessage *imdn_message = pauline->stat.last_received_chat_message; + if (BC_ASSERT_PTR_NOT_NULL(imdn_message)) { + const char *priority = linphone_chat_message_get_custom_header(imdn_message, "Priority"); + if (BC_ASSERT_PTR_NOT_NULL(priority)) + BC_ASSERT_STRING_EQUAL(priority, "non-urgent"); + } + linphone_chat_room_mark_as_read(marie_chat_room); /* This sends the display notification */ + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDisplayed, 1)); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 2)); + imdn_message = pauline->stat.last_received_chat_message; + if (BC_ASSERT_PTR_NOT_NULL(imdn_message)) { + const char *priority = linphone_chat_message_get_custom_header(imdn_message, "Priority"); + if (BC_ASSERT_PTR_NOT_NULL(priority)) + BC_ASSERT_STRING_EQUAL(priority, "non-urgent"); + } + bctbx_list_free_with_data(history, (bctbx_list_free_func)linphone_chat_message_unref); + } } - linphone_chat_message_unref(sent_cm); end: @@ -1059,35 +1117,31 @@ static void _im_notification_policy(bool_t with_lime) { /* Test imdn delivered */ msg1 = linphone_chat_room_create_message(pauline_chat_room, "Happy new year!"); - linphone_chat_message_ref(msg1); cbs = linphone_chat_message_get_callbacks(msg1); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(pauline_chat_room, msg1); + linphone_chat_message_send(msg1); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */ BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDeliveredToUser, 0, int, "%d"); linphone_im_notif_policy_set_recv_imdn_delivered(pauline_policy, TRUE); msg2 = linphone_chat_room_create_message(pauline_chat_room, "I said: Happy new year!"); - linphone_chat_message_ref(msg2); cbs = linphone_chat_message_get_callbacks(msg2); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(pauline_chat_room, msg2); + linphone_chat_message_send(msg2); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2)); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1)); msg3 = linphone_chat_room_create_message(marie_chat_room, "Thank you! Happy easter to you!"); - linphone_chat_message_ref(msg3); cbs = linphone_chat_message_get_callbacks(msg3); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(marie_chat_room, msg3); + linphone_chat_message_send(msg3); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); wait_for_until(pauline->lc, marie->lc, &dummy, 1, 1500); /* Just to sleep while iterating */ BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageDeliveredToUser, 0, int, "%d"); linphone_im_notif_policy_set_send_imdn_delivered(pauline_policy, TRUE); msg4 = linphone_chat_room_create_message(marie_chat_room, "Yeah, yeah, I heard that..."); - linphone_chat_message_ref(msg4); cbs = linphone_chat_message_get_callbacks(msg4); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(marie_chat_room, msg4); + linphone_chat_message_send(msg4); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 2)); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageDeliveredToUser, 1)); @@ -1149,7 +1203,6 @@ static void _im_error_delivery_notification(bool_t online) { linphone_chat_room_send_message(chat_room, "Bla bla bla bla"); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceivedLegacy, 1)); BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message); if (marie->stat.last_received_chat_message) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla bla bla"); @@ -1158,16 +1211,15 @@ static void _im_error_delivery_notification(bool_t online) { BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc, pauline->identity)); /* Temporary disabling receiver cache and enable all IM notifications */ - zrtp_cache_db_holder = marie->lc->zrtp_cache_db; - marie->lc->zrtp_cache_db = NULL; + zrtp_cache_db_holder = linphone_core_get_zrtp_cache_db(marie->lc); + linphone_core_set_zrtp_cache_db(marie->lc, NULL); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); msg = linphone_chat_room_create_message(chat_room, "Happy new year!"); - linphone_chat_message_ref(msg); cbs = linphone_chat_message_get_callbacks(msg); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room, msg); + linphone_chat_message_send(msg); if (!online) { linphone_core_set_network_reachable(marie->lc, FALSE); BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDelivered, 1, 60000)); @@ -1180,9 +1232,8 @@ static void _im_error_delivery_notification(bool_t online) { BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageNotDelivered, 1)); /* Restore the ZID cache of the receiver and resend the chat message */ - marie->lc->zrtp_cache_db = zrtp_cache_db_holder; - linphone_chat_message_ref(msg); - linphone_chat_message_resend(msg); + linphone_core_set_zrtp_cache_db(marie->lc, zrtp_cache_db_holder); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 2)); /* Check the new message is now received */ BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDeliveredToUser, 1)); linphone_chat_message_unref(msg); @@ -1218,7 +1269,6 @@ static void lime_text_message(void) { linphone_chat_room_send_message(chat_room,"Bla bla bla bla"); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,1)); BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message); if (marie->stat.last_received_chat_message) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla bla bla"); @@ -1249,8 +1299,8 @@ static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t /* enable lime for both parts */ if (enable_lime_for_message_test(marie, pauline) < 0) goto end; /* but then disable marie */ - sqlite3_close(marie->lc->zrtp_cache_db); - marie->lc->zrtp_cache_db = NULL; + sqlite3_close(linphone_core_get_zrtp_cache_db(marie->lc)); + linphone_core_set_zrtp_cache_db(marie->lc, NULL); } chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); @@ -1261,7 +1311,6 @@ static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t int chat_room_size = 0; BC_ASSERT_FALSE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); BC_ASSERT_FALSE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageNotDelivered,1)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy, 0, int, "%d"); chat_room_size = linphone_chat_room_get_history_size(chat_room); BC_ASSERT_EQUAL(chat_room_size, 1, int, "%d"); if (chat_room_size == 1) { @@ -1276,7 +1325,6 @@ static void lime_text_message_to_non_lime(bool_t sender_policy_mandatory, bool_t } } else { BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneMessageReceivedLegacy, 1, int, "%d"); } BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); @@ -1322,7 +1370,6 @@ static void lime_multiple_messages_while_network_unreachable(void) { linphone_core_set_network_reachable(pauline->lc, TRUE); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,2)); - BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedLegacy,2)); BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message); if (marie->stat.last_received_chat_message) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla 2"); @@ -1343,7 +1390,7 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); char *receive_filepath = bc_tester_file("receive_file.dump"); MSList * msg_list = NULL; - + /* Remove any previously downloaded file */ remove(receive_filepath); @@ -1371,11 +1418,11 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st msg = create_message_from_sintel_trailer(linphone_core_get_chat_room(pauline->lc, marie->identity)); } - linphone_chat_room_send_chat_message(msg->chat_room, msg); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000)); if (marie->stat.last_received_chat_message ) { LinphoneChatMessage *recv_msg; - const LinphoneContent* content; + LinphoneContent* content; if (download_file_from_stored_msg) { LinphoneChatRoom *marie_room = linphone_core_get_chat_room(marie->lc, pauline->identity); msg_list = linphone_chat_room_get_history(marie_room,1); @@ -1395,12 +1442,12 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st BC_ASSERT_PTR_NOT_NULL(linphone_content_get_key(content)); else BC_ASSERT_PTR_NULL(linphone_content_get_key(content)); - + if (use_file_body_handler_in_download) { linphone_chat_message_set_file_transfer_filepath(recv_msg, receive_filepath); } linphone_chat_message_download_file(recv_msg); - + if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1,55000))) { compare_files(send_filepath, receive_filepath); } @@ -1410,6 +1457,8 @@ void lime_transfer_message_base(bool_t encrypt_file,bool_t download_file_from_st BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageInProgress,2, int, "%d"); // file transfer BC_ASSERT_EQUAL(pauline->stat.number_of_LinphoneMessageDelivered,1, int, "%d"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1, int, "%d"); + linphone_chat_message_unref(msg); + end: remove("tmpZIDCacheMarie.sqlite"); remove("tmpZIDCachePauline.sqlite"); @@ -1456,7 +1505,7 @@ static void lime_cache_migration(void) { if ((xmlCacheFD = fopen(xmlCache_filepath, "w") ) == NULL) { BC_ASSERT_PTR_NOT_NULL(xmlCacheFD); ms_error("Unable to create temporary XML ZID cache file to test cache migration"); - return; + goto end2; } fprintf(xmlCacheFD, "%s", xmlCacheMigration); fclose(xmlCacheFD); @@ -1467,37 +1516,43 @@ static void lime_cache_migration(void) { linphone_proxy_config_edit(cfg); linphone_address_set_display_name(new_identity,"what about if we have a display name ?"); linphone_proxy_config_set_identity_address(cfg, new_identity); - + linphone_proxy_config_done(cfg); + BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneRegistrationOk, 2, 5000)); + if (!linphone_core_lime_available(marie->lc)) { ms_warning("Lime not available, skiping"); - return; + goto end1; } /* make sure lime is enabled */ linphone_core_enable_lime(marie->lc, LinphoneLimeMandatory); /* make sure to trigger the cache migration function */ - lp_config_set_int(marie->lc->config, "sip", "zrtp_cache_migration_done", FALSE); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "zrtp_cache_migration_done", FALSE); /* set the cache path, it will trigger the migration function */ linphone_core_set_zrtp_secrets_file(marie->lc, xmlCache_filepath); /*short check*/ limeKey_t associatedKey={0}; - + char * selfURI = linphone_address_as_string_uri_only(new_identity); linphone_address_unref(new_identity); bctbx_str_to_uint8(associatedKey.peerZID, (const uint8_t *)"0987654321fedcba5a5a5a5a", (uint16_t)strlen("0987654321fedcba5a5a5a5a")); /* 0987654321fedcba5a5a5a5a is the only one with pvs=1*/ - BC_ASSERT_FALSE(lime_getCachedRcvKeyByZid(marie->lc->zrtp_cache_db, &associatedKey, selfURI, "sip:bob@sip.linphone.org")); + BC_ASSERT_FALSE(lime_getCachedRcvKeyByZid(linphone_core_get_zrtp_cache_db(marie->lc), &associatedKey, selfURI, "sip:bob@sip.linphone.org")); ms_free(selfURI); /* perform checks on the new cache, simple check is ok as deeper ones are performed in the bzrtp migration tester */ /* TODO */ /* free memory */ + + end1: linphone_core_manager_destroy(marie); + end2: remove(xmlCache_filepath); + bc_free(xmlCache_filepath); } } @@ -1519,7 +1574,7 @@ static void lime_unit(void) { * Destination file is truncated if existing. * Return 0 on success, positive value on error. */ -int message_tester_copy_file(const char *from, const char *to) +static int message_tester_copy_file(const char *from, const char *to) { FILE *in, *out; char buf[256]; @@ -1573,190 +1628,32 @@ void history_message_count_helper(LinphoneChatRoom* chatroom, int x, int y, unsi bctbx_list_free_with_data(messages, (void (*)(void *))linphone_chat_message_unref); } -static void database_migration(void) { - LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); - char *src_db = bc_tester_res("messages.db"); - char *tmp_db = bc_tester_file("tmp.db"); - const bctbx_list_t* chatrooms; - LinphoneChatRoom *cr; - - BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d"); - - // enable to test the performances of the migration step - //linphone_core_message_storage_set_debug(marie->lc, TRUE); - - // the messages.db has 10000 dummy messages with the very first DB scheme. - // This will test the migration procedure - linphone_core_set_chat_database_path(marie->lc, tmp_db); - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - if (!marie->lc->db) goto end; - - chatrooms = linphone_core_get_chat_rooms(marie->lc); - BC_ASSERT(bctbx_list_size(chatrooms) > 0); - - // check that all messages have been migrated to the UTC time storage - BC_ASSERT(sqlite3_exec(marie->lc->db, "SELECT COUNT(*) FROM history WHERE time != '-1';", check_no_strange_time, NULL, NULL) == SQLITE_OK); - - // check that the read messages (field read=1) has been migrated to the LinphoneChatMessageStateDisplayed state - cr = linphone_core_get_chat_room_from_uri(marie->lc, "sip:Marielle@sip.linphone.org"); - BC_ASSERT_EQUAL(linphone_chat_room_get_unread_messages_count(cr), 8, int, "%i"); - -end: - linphone_core_manager_destroy(marie); - remove(tmp_db); - bc_free(src_db); - bc_free(tmp_db); -} - -static void history_range(void){ - LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); - LinphoneAddress *jehan_addr = linphone_address_new(""); - LinphoneChatRoom *chatroom; - char *src_db = bc_tester_res("messages.db"); - char *tmp_db = bc_tester_file("tmp.db"); - - BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d"); - - linphone_core_set_chat_database_path(marie->lc, tmp_db); - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - if (!marie->lc->db) goto end; - - chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr); - BC_ASSERT_PTR_NOT_NULL(chatroom); - if (chatroom){ - // We have 20 tests to perform to fully qualify the function, here they are: - history_message_count_helper(chatroom, 0, 0, 1); - history_message_count_helper(chatroom, -1, 0, 1); - history_message_count_helper(chatroom, 0, -1, 1270); - history_message_count_helper(chatroom, 1, 3, 3); - history_message_count_helper(chatroom, 3, 1, 1270-3); - history_message_count_helper(chatroom, 10, 10, 1); - history_message_count_helper(chatroom, -1, -1, 1270); - history_message_count_helper(chatroom, -1, -2, 1270); - history_message_count_helper(chatroom, -2, -1, 1270); - history_message_count_helper(chatroom, 3, -1, 1270-3); - history_message_count_helper(chatroom, 1, -3, 1270-1); - history_message_count_helper(chatroom, 2, -2, 1270-2); - history_message_count_helper(chatroom, 2, 0, 1270-2); - history_message_count_helper(chatroom, 0, 2, 3); - history_message_count_helper(chatroom, -1, 3, 4); - history_message_count_helper(chatroom, -2, 2, 3); - history_message_count_helper(chatroom, -3, 1, 2); - } - -end: - linphone_core_manager_destroy(marie); - linphone_address_unref(jehan_addr); - remove(tmp_db); - bc_free(src_db); - bc_free(tmp_db); -} - -static void history_count(void) { - LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); - LinphoneAddress *jehan_addr = linphone_address_new(""); - LinphoneChatRoom *chatroom; - bctbx_list_t *messages; - char *src_db = bc_tester_res("messages.db"); - char *tmp_db = bc_tester_file("tmp.db"); - - BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d"); - - linphone_core_set_chat_database_path(marie->lc, tmp_db); - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - if (!marie->lc->db) goto end; - - chatroom = linphone_core_get_chat_room(marie->lc, jehan_addr); - BC_ASSERT_PTR_NOT_NULL(chatroom); - if (chatroom){ - messages=linphone_chat_room_get_history(chatroom,10); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 10, unsigned int, "%u"); - bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref); - - messages=linphone_chat_room_get_history(chatroom,1); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1, unsigned int, "%u"); - bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref); - - messages=linphone_chat_room_get_history(chatroom,0); - BC_ASSERT_EQUAL(linphone_chat_room_get_history_size(chatroom), 1270, int, "%d"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1270, unsigned int, "%u"); - - /*check the second most recent msg*/ - BC_ASSERT_PTR_NOT_NULL(messages); - if (messages){ - BC_ASSERT_PTR_NOT_NULL(messages->next->data); - if (messages->next->data){ - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text((LinphoneChatMessage *)messages->next->data), "Fore and aft follow each other."); - } - } - - bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref); - - /*test offset+limit: retrieve the 42th latest msg only and check its content*/ - messages=linphone_chat_room_get_history_range(chatroom, 42, 42); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1, unsigned int, "%u"); - BC_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."); - bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref); - - /*test offset without limit*/ - messages = linphone_chat_room_get_history_range(chatroom, 1265, -1); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1270-1265, unsigned int, "%u"); - bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref); - - /*test limit without offset*/ - messages = linphone_chat_room_get_history_range(chatroom, 0, 5); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 6, unsigned int, "%u"); - bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref); - - /*test invalid start*/ - messages = linphone_chat_room_get_history_range(chatroom, 1265, 1260); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(messages), 1270-1265, unsigned int, "%u"); - bctbx_list_free_with_data(messages, (void (*)(void*))linphone_chat_message_unref); - } - -end: - linphone_core_manager_destroy(marie); - linphone_address_unref(jehan_addr); - remove(tmp_db); - bc_free(src_db); - bc_free(tmp_db); -} - - void crash_during_file_transfer(void) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); - char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); - char *initial_db = bc_tester_file("initial.db"); - char *saved_db = bc_tester_file("saved.db"); LinphoneChatRoom *chat_room; LinphoneChatMessage *msg; int chat_room_size = 0; bctbx_list_t *msg_list = NULL; - /* Remove any previous files */ - remove(initial_db); - remove(saved_db); - /* Globally configure an http file transfer server. */ linphone_core_set_file_transfer_server(pauline->lc, "https://www.linphone.org:444/lft.php"); - linphone_core_set_chat_database_path(pauline->lc, initial_db); /* Create a chatroom and a file transfer message on pauline's side */ chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); msg = create_file_transfer_message_from_sintel_trailer(chat_room); - linphone_chat_room_send_chat_message(chat_room, msg); + linphone_chat_message_send(msg); /* Wait for 25% of the file to be uploaded and crash by stopping the iteration, saving the chat database and destroying the core */ BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.progress_of_LinphoneFileTransfer, 25, 60000)); - BC_ASSERT_EQUAL(message_tester_copy_file(initial_db, saved_db), 0, int, "%d"); linphone_chat_message_unref(msg); - linphone_core_manager_destroy(pauline); + linphone_core_manager_stop(pauline); /* Create a new core and check that the message stored in the saved database is in the not delivered state */ - pauline = linphone_core_manager_new("pauline_tcp_rc"); - linphone_core_set_chat_database_path(pauline->lc, saved_db); - BC_ASSERT_TRUE(wait_for(pauline->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); + linphone_core_manager_restart(pauline, TRUE); + linphone_core_set_file_transfer_server(pauline->lc, "https://www.linphone.org:444/lft.php"); + + //BC_ASSERT_TRUE(wait_for(pauline->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); chat_room_size = linphone_chat_room_get_history_size(chat_room); @@ -1765,12 +1662,36 @@ void crash_during_file_transfer(void) { msg_list = linphone_chat_room_get_history(chat_room, 0); LinphoneChatMessage *sent_msg = (LinphoneChatMessage *)bctbx_list_get_data(msg_list); BC_ASSERT_EQUAL((int)linphone_chat_message_get_state(sent_msg), (int)LinphoneChatMessageStateNotDelivered, int, "%d"); + //resend + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(sent_msg); + linphone_chat_message_cbs_set_file_transfer_send(cbs, tester_file_transfer_send); + linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); + linphone_chat_message_send(sent_msg); + if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceivedWithFile,1, 60000))) { + linphone_core_manager_stop(marie); + /* Create a new core and check that the message stored in the saved database is in the not delivered state */ + linphone_core_manager_restart(marie, TRUE); + LinphoneChatRoom *marie_room = linphone_core_get_chat_room(marie->lc, pauline->identity); + bctbx_list_t *msg_list_2 = linphone_chat_room_get_history(marie_room,1); + BC_ASSERT_PTR_NOT_NULL(msg_list_2); + LinphoneChatMessage *recv_msg = (LinphoneChatMessage *)msg_list_2->data; + LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(recv_msg); + linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); + linphone_chat_message_cbs_set_file_transfer_recv(cbs, file_transfer_received); + linphone_chat_message_cbs_set_file_transfer_progress_indication(cbs, file_transfer_progress_indication); + linphone_chat_message_download_file(recv_msg); + /* wait for a long time in case the DNS SRV resolution takes times - it should be immediate though */ + if (BC_ASSERT_TRUE(wait_for_until(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneFileTransferDownloadSuccessful,1,55000))) { + BC_ASSERT_PTR_NULL(linphone_chat_message_get_external_body_url(recv_msg)); + } + bctbx_list_free_with_data(msg_list_2, (bctbx_list_free_func)linphone_chat_message_unref); + } } + bctbx_list_free_with_data(msg_list, (bctbx_list_free_func)linphone_chat_message_unref); - bc_free(send_filepath); - bc_free(initial_db); - bc_free(saved_db); + linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); @@ -1782,10 +1703,11 @@ static void text_status_after_destroying_chat_room(void) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); LinphoneChatRoom *chatroom = linphone_core_get_chat_room_from_uri(marie->lc, ""); LinphoneChatMessage *msg = linphone_chat_room_create_message(chatroom, "hello"); - linphone_chat_room_send_chat_message(chatroom, msg); + linphone_chat_message_send(msg); linphone_core_delete_chat_room(marie->lc, chatroom); //since message is orphan, we do not expect to be notified of state change BC_ASSERT_FALSE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 1000)); + linphone_chat_message_unref(msg); linphone_core_manager_destroy(marie); } @@ -1797,8 +1719,9 @@ static void file_transfer_not_sent_if_invalid_url(void) { LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); linphone_core_set_file_transfer_server(marie->lc, "INVALID URL"); - linphone_chat_room_send_chat_message(chatroom, msg); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 1000)); + linphone_chat_message_unref(msg); linphone_core_manager_destroy(marie); } @@ -1809,7 +1732,7 @@ void file_transfer_io_error_base(char *server_url, bool_t destroy_room) { LinphoneChatMessageCbs *cbs = linphone_chat_message_get_callbacks(msg); linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); linphone_core_set_file_transfer_server(marie->lc, server_url); - linphone_chat_room_send_chat_message(chatroom, msg); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageInProgress, 1, 1000)); if (destroy_room) { linphone_core_delete_chat_room(marie->lc, chatroom); @@ -1817,6 +1740,7 @@ void file_transfer_io_error_base(char *server_url, bool_t destroy_room) { } else { BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphoneMessageNotDelivered, 1, 3000)); } + linphone_chat_message_unref(msg); linphone_core_manager_destroy(marie); } @@ -1832,8 +1756,11 @@ static void file_transfer_io_error_after_destroying_chatroom(void) { file_transfer_io_error_base("https://www.linphone.org:444/lft.php", TRUE); } -static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, bool_t mess_with_marie_payload_number, bool_t mess_with_pauline_payload_number, - bool_t ice_enabled, bool_t sql_storage, bool_t do_not_store_rtt_messages_in_sql_storage) { +static void real_time_text( + bool_t audio_stream_enabled, bool_t srtp_enabled, bool_t mess_with_marie_payload_number, + bool_t mess_with_pauline_payload_number, bool_t ice_enabled, bool_t sql_storage, + bool_t do_not_store_rtt_messages_in_sql_storage +) { LinphoneChatRoom *pauline_chat_room; LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); @@ -1845,20 +1772,16 @@ static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, boo if (sql_storage) { linphone_core_set_chat_database_path(marie->lc, marie_db); linphone_core_set_chat_database_path(pauline->lc, pauline_db); -#ifdef SQLITE_STORAGE_ENABLED - BC_ASSERT_PTR_NOT_NULL(marie->lc->db); - BC_ASSERT_PTR_NOT_NULL(pauline->lc->db); -#endif - + if (do_not_store_rtt_messages_in_sql_storage) { - lp_config_set_int(marie->lc->config, "misc", "store_rtt_messages", 0); - lp_config_set_int(pauline->lc->config, "misc", "store_rtt_messages", 0); + lp_config_set_int(linphone_core_get_config(marie->lc), "misc", "store_rtt_messages", 0); + lp_config_set_int(linphone_core_get_config(pauline->lc), "misc", "store_rtt_messages", 0); } } if (mess_with_marie_payload_number) { - bctbx_list_t *elem; - for (elem = marie->lc->codecs_conf.text_codecs; elem != NULL; elem = elem->next) { + const bctbx_list_t *elem; + for (elem = linphone_core_get_text_payload_types(marie->lc); elem != NULL; elem = elem->next) { PayloadType *pt = (PayloadType*)elem->data; if (strcasecmp(pt->mime_type, payload_type_t140.mime_type) == 0) { payload_type_set_number(pt, 99); @@ -1866,8 +1789,8 @@ static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, boo } } } else if (mess_with_pauline_payload_number) { - bctbx_list_t *elem; - for (elem = pauline->lc->codecs_conf.text_codecs; elem != NULL; elem = elem->next) { + const bctbx_list_t *elem; + for (elem = linphone_core_get_text_payload_types(pauline->lc); elem != NULL; elem = elem->next) { PayloadType *pt = (PayloadType*)elem->data; if (strcasecmp(pt->mime_type, payload_type_t140.mime_type) == 0) { payload_type_set_number(pt, 99); @@ -1923,8 +1846,9 @@ static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, boo BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], char, "%c"); } - linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message); + linphone_chat_message_send(rtt_message); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + linphone_chat_message_unref(rtt_message); if (sql_storage) { bctbx_list_t *marie_messages = linphone_chat_room_get_history(marie_chat_room, 0); @@ -1942,8 +1866,8 @@ static void real_time_text(bool_t audio_stream_enabled, bool_t srtp_enabled, boo } marie_msg = (LinphoneChatMessage *)marie_messages->data; pauline_msg = (LinphoneChatMessage *)pauline_messages->data; - BC_ASSERT_STRING_EQUAL(marie_msg->message, message); - BC_ASSERT_STRING_EQUAL(pauline_msg->message, message); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie_msg), message); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline_msg), message); bctbx_list_free_with_data(marie_messages, (void (*)(void *))linphone_chat_message_unref); bctbx_list_free_with_data(pauline_messages, (void (*)(void *))linphone_chat_message_unref); } @@ -1994,92 +1918,97 @@ static void real_time_text_conversation(void) { LinphoneCall *pauline_call, *marie_call; linphone_call_params_enable_realtime_text(marie_params,TRUE); - BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params)); - pauline_call=linphone_core_get_current_call(pauline->lc); - marie_call=linphone_core_get_current_call(marie->lc); - BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call))); + if (BC_ASSERT_TRUE(call_with_caller_params(marie, pauline, marie_params))){ + pauline_call=linphone_core_get_current_call(pauline->lc); + marie_call=linphone_core_get_current_call(marie->lc); + BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(pauline_call))); - pauline_chat_room = linphone_call_get_chat_room(pauline_call); - BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); - marie_chat_room = linphone_call_get_chat_room(marie_call); - BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); - if (pauline_chat_room && marie_chat_room) { - const char* message1_1 = "Lorem"; - const char* message1_2 = "Ipsum"; - const char* message2_1 = "Be lle Com"; - const char* message2_2 = "eB ell moC"; - size_t i; - LinphoneChatMessage* pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); - LinphoneChatMessage* marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); + pauline_chat_room = linphone_call_get_chat_room(pauline_call); + BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); + marie_chat_room = linphone_call_get_chat_room(marie_call); + BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); + if (pauline_chat_room && marie_chat_room) { + const char* message1_1 = "Lorem"; + const char* message1_2 = "Ipsum"; + const char* message2_1 = "Be lle Com"; + const char* message2_2 = "eB ell moC"; + size_t i; + LinphoneChatMessage* pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); + LinphoneChatMessage* marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); - for (i = 0; i < strlen(message1_1); i++) { - linphone_chat_message_put_char(pauline_rtt_message, message1_1[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message1_1[i], char, "%c"); + for (i = 0; i < strlen(message1_1); i++) { + linphone_chat_message_put_char(pauline_rtt_message, message1_1[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message1_1[i], char, "%c"); - linphone_chat_message_put_char(marie_rtt_message, message1_2[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message1_2[i], char, "%c"); - } - - /*Commit the message, triggers a NEW LINE in T.140 */ - linphone_chat_room_send_chat_message(pauline_chat_room, pauline_rtt_message); - linphone_chat_room_send_chat_message(marie_chat_room, marie_rtt_message); - - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = marie->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_1); + linphone_chat_message_put_char(marie_rtt_message, message1_2[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message1_2[i], char, "%c"); } - } - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_2); + + /*Commit the message, triggers a NEW LINE in T.140 */ + linphone_chat_message_send(pauline_rtt_message); + linphone_chat_message_send(marie_rtt_message); + + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = marie->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_1); + } } - } - - reset_counters(&pauline->stat); - reset_counters(&marie->stat); - pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); - marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); - - for (i = 0; i < strlen(message2_1); i++) { - linphone_chat_message_put_char(pauline_rtt_message, message2_1[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message2_1[i], char, "%c"); - - linphone_chat_message_put_char(marie_rtt_message, message2_2[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); - BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message2_2[i], char, "%c"); - } - - /*Commit the message, triggers a NEW LINE in T.140 */ - linphone_chat_room_send_chat_message(pauline_chat_room, pauline_rtt_message); - linphone_chat_room_send_chat_message(marie_chat_room, marie_rtt_message); - - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = marie->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_1); + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message1_2); + } } - } - BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); - { - LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; - BC_ASSERT_PTR_NOT_NULL(msg); - if (msg) { - BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_2); + + linphone_chat_message_unref(pauline_rtt_message); + linphone_chat_message_unref(marie_rtt_message); + reset_counters(&pauline->stat); + reset_counters(&marie->stat); + pauline_rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); + marie_rtt_message = linphone_chat_room_create_message(marie_chat_room,NULL); + + for (i = 0; i < strlen(message2_1); i++) { + linphone_chat_message_put_char(pauline_rtt_message, message2_1[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message2_1[i], char, "%c"); + + linphone_chat_message_put_char(marie_rtt_message, message2_2[i]); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_EQUAL(linphone_chat_room_get_char(pauline_chat_room), message2_2[i], char, "%c"); } + + /*Commit the message, triggers a NEW LINE in T.140 */ + linphone_chat_message_send(pauline_rtt_message); + linphone_chat_message_send(marie_rtt_message); + + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = marie->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_1); + } + } + BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageReceived, 1)); + { + LinphoneChatMessage * msg = pauline->stat.last_received_chat_message; + BC_ASSERT_PTR_NOT_NULL(msg); + if (msg) { + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), message2_2); + } + } + linphone_chat_message_unref(pauline_rtt_message); + linphone_chat_message_unref(marie_rtt_message); } + end_call(marie, pauline); } - end_call(marie, pauline); linphone_call_params_unref(marie_params); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); @@ -2192,9 +2121,16 @@ static void real_time_text_message_accented_chars(void) { BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], unsigned long, "%lu"); } - linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message); + linphone_chat_message_send(rtt_message); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); - BC_ASSERT_EQUAL(strcmp(marie->stat.last_received_chat_message->message, "ãæçéîøùÿ"), 0, int, "%i"); + BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message); + if (marie->stat.last_received_chat_message) { + const char *text = linphone_chat_message_get_text(marie->stat.last_received_chat_message); + BC_ASSERT_PTR_NOT_NULL(text); + if (text) + BC_ASSERT_STRING_EQUAL(text, "ãæçéîøùÿ"); + } + linphone_chat_message_unref(rtt_message); } end_call(marie, pauline); } @@ -2245,8 +2181,9 @@ static void real_time_text_copy_paste(void) { } } } - linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message); + linphone_chat_message_send(rtt_message); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); + linphone_chat_message_unref(rtt_message); } end_call(marie, pauline); @@ -2260,6 +2197,10 @@ void file_transfer_with_http_proxy(void) { if (transport_supported(LinphoneTransportTls)) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + lp_config_set_int(linphone_core_get_config(pauline->lc), "sip", "deliver_imdn", 1); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "deliver_imdn", 1); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(marie->lc)); + linphone_im_notif_policy_enable_all(linphone_core_get_im_notif_policy(pauline->lc)); linphone_core_set_http_proxy_host(marie->lc, "sip.linphone.org"); transfer_message_base2(marie,pauline,FALSE,FALSE,FALSE,FALSE,FALSE); linphone_core_manager_destroy(pauline); @@ -2279,19 +2220,20 @@ void chat_message_custom_headers(void) { linphone_chat_message_remove_custom_header(msg, "Test1"); linphone_chat_message_cbs_set_msg_state_changed(cbs,liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room,msg); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageDelivered,1)); - + if (marie->stat.last_received_chat_message) { const char *header = linphone_chat_message_get_custom_header(marie->stat.last_received_chat_message, "Test2"); BC_ASSERT_STRING_EQUAL(header, "Value2"); header = linphone_chat_message_get_custom_header(marie->stat.last_received_chat_message, "Test1"); BC_ASSERT_PTR_NULL(header); - BC_ASSERT_STRING_EQUAL(marie->stat.last_received_chat_message->message, "Lorem Ipsum"); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Lorem Ipsum"); } + linphone_chat_message_unref(msg); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -2308,6 +2250,9 @@ void _text_message_with_custom_content_type(bool_t with_lime) { size_t file_size; char *buf; + linphone_core_add_content_type_support(marie->lc, "image/svg+xml"); + linphone_core_add_content_type_support(pauline->lc, "image/svg+xml"); + if (with_lime) { if (enable_lime_for_message_test(marie, pauline) < 0) goto end; } @@ -2323,21 +2268,23 @@ void _text_message_with_custom_content_type(bool_t with_lime) { msg = linphone_chat_room_create_message(chat_room, buf); linphone_chat_message_set_content_type(msg, "image/svg+xml"); - linphone_core_add_content_type_support(marie->lc, "image/svg+xml"); - linphone_core_add_content_type_support(pauline->lc, "image/svg+xml"); cbs = linphone_chat_message_get_callbacks(msg); linphone_chat_message_cbs_set_msg_state_changed(cbs, liblinphone_tester_chat_message_msg_state_changed); - linphone_chat_room_send_chat_message(chat_room, msg); + linphone_chat_message_send(msg); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1)); BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageDelivered, 1)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(msg), "image/svg+xml"); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), buf); + if (marie->stat.last_received_chat_message) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_content_type(marie->stat.last_received_chat_message), "image/svg+xml"); BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), buf); } bctbx_free(buf); + linphone_chat_message_unref(msg); end: linphone_core_manager_destroy(marie); @@ -2356,15 +2303,19 @@ void text_message_with_custom_content_type_and_lime(void) { static int im_encryption_engine_process_incoming_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { + ms_debug("IM encryption process incoming message with content type %s", linphone_chat_message_get_content_type(msg)); if (linphone_chat_message_get_content_type(msg)) { if (strcmp(linphone_chat_message_get_content_type(msg), "cipher/b64") == 0) { size_t b64Size = 0; unsigned char *output; - bctbx_base64_decode(NULL, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); + const char *data = linphone_chat_message_get_text(msg); + ms_debug("IM encryption process incoming message crypted message is %s", data); + bctbx_base64_decode(NULL, &b64Size, (unsigned char *)data, strlen(data)); output = (unsigned char *)ms_malloc(b64Size+1), - bctbx_base64_decode(output, &b64Size, (unsigned char *)linphone_chat_message_get_text(msg), strlen(linphone_chat_message_get_text(msg))); + bctbx_base64_decode(output, &b64Size, (unsigned char *)data, strlen(data)); output[b64Size] = '\0'; linphone_chat_message_set_text(msg, (char *)output); + ms_debug("IM encryption process incoming message decrypted message is %s", output); ms_free(output); linphone_chat_message_set_content_type(msg, "text/plain"); return 0; @@ -2377,6 +2328,16 @@ static int im_encryption_engine_process_incoming_message_cb(LinphoneImEncryption return 500; } +static bool_t im_encryption_engine_process_incoming_message_async_impl(LinphoneChatMessage** msg) { + if (*msg) { + im_encryption_engine_process_incoming_message_cb(NULL,NULL,*msg); + linphone_chat_room_receive_chat_message(linphone_chat_message_get_chat_room(*msg), *msg); + linphone_chat_message_unref(*msg); + *msg=NULL; + } + return TRUE; +} + static int im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { if (strcmp(linphone_chat_message_get_content_type(msg),"text/plain") == 0) { size_t b64Size = 0; @@ -2393,7 +2354,34 @@ static int im_encryption_engine_process_outgoing_message_cb(LinphoneImEncryption return -1; } -void im_encryption_engine_b64(void) { +static bool_t im_encryption_engine_process_outgoing_message_async_impl(LinphoneChatMessage** msg) { + if (*msg) { + im_encryption_engine_process_outgoing_message_cb(NULL,NULL,*msg); + linphone_chat_message_send(*msg); + linphone_chat_message_unref(*msg); + *msg=NULL; + } + return TRUE; +} + +static LinphoneChatMessage* pending_message=NULL; /*limited to one message at a time */ +static LinphoneChatMessage* incoming_pending_message=NULL; /*limited to one message at a time */ + +static int im_encryption_engine_process_outgoing_message_async(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { + pending_message=msg; + linphone_chat_message_ref(pending_message); + linphone_core_add_iterate_hook(linphone_chat_room_get_core(room), (LinphoneCoreIterateHook)im_encryption_engine_process_outgoing_message_async_impl,&pending_message); + return 1;/*temporaly code to defer message sending*/ +} + +static int im_encryption_engine_process_incoming_message_async(LinphoneImEncryptionEngine *engine, LinphoneChatRoom *room, LinphoneChatMessage *msg) { + incoming_pending_message=msg; + linphone_chat_message_ref(incoming_pending_message); + linphone_core_add_iterate_hook(linphone_chat_room_get_core(room), (LinphoneCoreIterateHook)im_encryption_engine_process_incoming_message_async_impl,&incoming_pending_message); + return 1;/*temporaly code to defer message receiving*/ +} + +void im_encryption_engine_b64_base(bool_t async) { LinphoneChatMessage *chat_msg = NULL; LinphoneChatRoom* chat_room = NULL; LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); @@ -2402,40 +2390,119 @@ void im_encryption_engine_b64(void) { LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); LinphoneImEncryptionEngine *pauline_imee = linphone_im_encryption_engine_new(); LinphoneImEncryptionEngineCbs *pauline_cbs = linphone_im_encryption_engine_get_callbacks(pauline_imee); - - linphone_im_encryption_engine_cbs_set_process_incoming_message(marie_cbs, im_encryption_engine_process_incoming_message_cb); + linphone_im_encryption_engine_cbs_set_process_outgoing_message(marie_cbs, im_encryption_engine_process_outgoing_message_cb); linphone_im_encryption_engine_cbs_set_process_incoming_message(pauline_cbs, im_encryption_engine_process_incoming_message_cb); - linphone_im_encryption_engine_cbs_set_process_outgoing_message(pauline_cbs, im_encryption_engine_process_outgoing_message_cb); - + if (async) { + linphone_im_encryption_engine_cbs_set_process_outgoing_message(pauline_cbs, im_encryption_engine_process_outgoing_message_async); + linphone_im_encryption_engine_cbs_set_process_incoming_message(marie_cbs, im_encryption_engine_process_incoming_message_async); + } else { + linphone_im_encryption_engine_cbs_set_process_outgoing_message(pauline_cbs, im_encryption_engine_process_outgoing_message_cb); + linphone_im_encryption_engine_cbs_set_process_incoming_message(marie_cbs, im_encryption_engine_process_incoming_message_cb); + } + linphone_core_set_im_encryption_engine(marie->lc, marie_imee); linphone_core_set_im_encryption_engine(pauline->lc, pauline_imee); chat_room = linphone_core_get_chat_room(pauline->lc, marie->identity); chat_msg = linphone_chat_room_create_message(chat_room, "Bla bla bla bla"); - linphone_chat_room_send_chat_message(chat_room, chat_msg); + linphone_chat_message_send(chat_msg); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneMessageReceived,1)); + BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(chat_msg), "Bla bla bla bla"); BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message); if (marie->stat.last_received_chat_message) { BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie->stat.last_received_chat_message), "Bla bla bla bla"); } BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room(marie->lc,pauline->identity)); - + + linphone_chat_message_unref(chat_msg); linphone_im_encryption_engine_unref(marie_imee); linphone_im_encryption_engine_unref(pauline_imee); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } +void im_encryption_engine_b64(void) { + im_encryption_engine_b64_base(FALSE); +} + +void im_encryption_engine_b64_async(void) { + im_encryption_engine_b64_base(TRUE); +} + +void unread_message_count(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + + text_message_base(marie, pauline); + + BC_ASSERT_PTR_NOT_NULL(marie->stat.last_received_chat_message); + if (marie->stat.last_received_chat_message != NULL) { + LinphoneChatRoom *marie_room = linphone_chat_message_get_chat_room(marie->stat.last_received_chat_message); + BC_ASSERT_EQUAL(1, linphone_chat_room_get_unread_messages_count(marie_room), int, "%d"); + linphone_chat_room_mark_as_read(marie_room); + BC_ASSERT_EQUAL(0, linphone_chat_room_get_unread_messages_count(marie_room), int, "%d"); + } + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void message_received_callback(LinphoneCore *lc, LinphoneChatRoom *room, LinphoneChatMessage* msg) { + BC_ASSERT_PTR_NOT_NULL(room); + BC_ASSERT_EQUAL(1, linphone_chat_room_get_unread_messages_count(room), int, "%d"); + BC_ASSERT_PTR_NOT_NULL(msg); + if (room != NULL) { + linphone_chat_room_mark_as_read(room); + } + BC_ASSERT_EQUAL(0, linphone_chat_room_get_unread_messages_count(room), int, "%d"); +} + +void unread_message_count_callback(void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); + int dummy = 0; + + LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_message_received(cbs, message_received_callback); + linphone_core_add_callbacks(marie->lc, cbs); + + text_message_base(marie, pauline); + + wait_for_until(pauline->lc, marie->lc, &dummy, 1, 5000); + + linphone_core_cbs_unref(cbs); + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void migration_from_messages_db (void) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + char *src_db = bc_tester_res("db/messages.db"); + char *tmp_db = bc_tester_file("tmp.db"); + + BC_ASSERT_EQUAL(message_tester_copy_file(src_db, tmp_db), 0, int, "%d"); + + // The messages.db has 10000 dummy messages with the very first DB scheme. + // This will test the migration procedure + linphone_core_set_chat_database_path(marie->lc, tmp_db); + + const bctbx_list_t *chatrooms = linphone_core_get_chat_rooms(marie->lc); + BC_ASSERT(bctbx_list_size(chatrooms) > 0); + + linphone_core_manager_destroy(marie); + remove(tmp_db); + bctbx_free(src_db); + bctbx_free(tmp_db); +} + test_t message_tests[] = { TEST_NO_TAG("Text message", text_message), - TEST_NO_TAG("Text message within call dialog", text_message_within_call_dialog), TEST_NO_TAG("Text message with credentials from auth callback", text_message_with_credential_from_auth_callback), TEST_NO_TAG("Text message with privacy", text_message_with_privacy), TEST_NO_TAG("Text message compatibility mode", text_message_compatibility_mode), TEST_NO_TAG("Text message with ack", text_message_with_ack), TEST_NO_TAG("Text message with send error", text_message_with_send_error), - TEST_NO_TAG("Text message with external body", text_message_with_external_body), TEST_NO_TAG("Transfer message", transfer_message), TEST_NO_TAG("Transfer message 2", transfer_message_2), TEST_NO_TAG("Transfer message 3", transfer_message_3), @@ -2446,15 +2513,16 @@ test_t message_tests[] = { TEST_NO_TAG("Transfer message with download io error", transfer_message_with_download_io_error), TEST_NO_TAG("Transfer message upload cancelled", transfer_message_upload_cancelled), TEST_NO_TAG("Transfer message download cancelled", transfer_message_download_cancelled), - TEST_NO_TAG("Transfer message using external body url", file_transfer_using_external_body_url), TEST_NO_TAG("Transfer 2 messages simultaneously", file_transfer_2_messages_simultaneously), + TEST_NO_TAG("Transfer using external body URL", file_transfer_using_external_body_url), + TEST_NO_TAG("Transfer using external body URL 2", file_transfer_using_external_body_url_2), TEST_NO_TAG("Text message denied", text_message_denied), - TEST_NO_TAG("Info message", info_message), - TEST_NO_TAG("Info message with body", info_message_with_body), TEST_NO_TAG("IsComposing notification", is_composing_notification), TEST_NO_TAG("IMDN notifications", imdn_notifications), TEST_NO_TAG("IM notification policy", im_notification_policy), #ifdef SQLITE_STORAGE_ENABLED + TEST_NO_TAG("Unread message count", unread_message_count), + TEST_NO_TAG("Unread message count in callback", unread_message_count_callback), TEST_ONE_TAG("IsComposing notification lime", is_composing_notification_with_lime, "LIME"), TEST_ONE_TAG("IMDN notifications with lime", imdn_notifications_with_lime, "LIME"), TEST_ONE_TAG("IM notification policy with lime", im_notification_policy_with_lime, "LIME"), @@ -2475,16 +2543,10 @@ test_t message_tests[] = { TEST_ONE_TAG("Lime transfer message without encryption 2", lime_transfer_message_without_encryption_2, "LIME"), TEST_ONE_TAG("Lime cache migration", lime_cache_migration, "LIME"), TEST_ONE_TAG("Lime unitary", lime_unit, "LIME"), - TEST_NO_TAG("Database migration", database_migration), - TEST_NO_TAG("History range", history_range), - TEST_NO_TAG("History count", history_count), - TEST_NO_TAG("Crash during file transfer", crash_during_file_transfer), #endif - TEST_NO_TAG("Text status after destroying chat room", text_status_after_destroying_chat_room), TEST_NO_TAG("Transfer not sent if invalid url", file_transfer_not_sent_if_invalid_url), TEST_NO_TAG("Transfer not sent if host not found", file_transfer_not_sent_if_host_not_found), TEST_NO_TAG("Transfer not sent if url moved permanently", file_transfer_not_sent_if_url_moved_permanently), - TEST_ONE_TAG("Transfer io error after destroying chatroom", file_transfer_io_error_after_destroying_chatroom, "LeaksMemory"), TEST_ONE_TAG("Real Time Text message", real_time_text_message, "RTT"), TEST_ONE_TAG("Real Time Text SQL storage", real_time_text_sql_storage, "RTT"), TEST_ONE_TAG("Real Time Text SQL storage with RTT messages not stored", real_time_text_sql_storage_rtt_disabled, "RTT"), @@ -2503,7 +2565,15 @@ test_t message_tests[] = { #ifdef SQLITE_STORAGE_ENABLED TEST_ONE_TAG("Text message with custom content-type and lime", text_message_with_custom_content_type_and_lime, "LIME"), #endif - TEST_NO_TAG("IM Encryption Engine b64", im_encryption_engine_b64) + TEST_NO_TAG("IM Encryption Engine b64", im_encryption_engine_b64), + TEST_NO_TAG("IM Encryption Engine b64 async", im_encryption_engine_b64_async), + TEST_NO_TAG("Text message within call dialog", text_message_within_call_dialog), + TEST_NO_TAG("Info message", info_message), + TEST_NO_TAG("Info message with body", info_message_with_body), + TEST_NO_TAG("Crash during file transfer", crash_during_file_transfer), + TEST_NO_TAG("Text status after destroying chat room", text_status_after_destroying_chat_room), + TEST_NO_TAG("Transfer io error after destroying chatroom", file_transfer_io_error_after_destroying_chatroom), + TEST_NO_TAG("Migration from messages db", migration_from_messages_db) }; static int message_tester_before_suite(void) { @@ -2524,7 +2594,3 @@ test_suite_t message_test_suite = { liblinphone_tester_after_each, sizeof(message_tests) / sizeof(message_tests[0]), message_tests }; - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif diff --git a/tester/messages.db b/tester/messages.db deleted file mode 100644 index 01ad041d3..000000000 Binary files a/tester/messages.db and /dev/null differ diff --git a/tester/multipart-tester.cpp b/tester/multipart-tester.cpp new file mode 100644 index 000000000..663b114f4 --- /dev/null +++ b/tester/multipart-tester.cpp @@ -0,0 +1,141 @@ +/* + * cpim-tester.cpp + * Copyright (C) 2017 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "address/address.h" +#include "chat/chat-message/chat-message.h" +#include "chat/chat-room/basic-chat-room.h" +#include "content/content-type.h" +#include "content/content.h" +#include "content/file-content.h" +#include "core/core.h" + +// TODO: Remove me later. +#include "private.h" + +#include "liblinphone_tester.h" +#include "tester_utils.h" + +// ============================================================================= + +using namespace std; + +using namespace LinphonePrivate; + +static void chat_message_multipart_modifier_base(bool first_file_transfer, bool second_file_transfer, bool use_cpim) { + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new("pauline_tcp_rc"); + + char *paulineUriStr = linphone_address_as_string_uri_only(pauline->identity); + IdentityAddress paulineAddress(paulineUriStr); + bctbx_free(paulineUriStr); + shared_ptr marieRoom = marie->lc->cppPtr->getOrCreateBasicChatRoom(paulineAddress); + marieRoom->allowMultipart(true); + + shared_ptr marieMessage = marieRoom->createChatMessage(); + if (first_file_transfer) { + char *send_filepath = bc_tester_res("sounds/sintel_trailer_opus_h264.mkv"); + FileContent *content = new FileContent(); + content->setContentType(ContentType("video/mkv")); + content->setFilePath(send_filepath); + content->setFileName("sintel_trailer_opus_h264.mkv"); + marieMessage->addContent(content); + bc_free(send_filepath); + } else { + Content *content = new Content(); + content->setContentType(ContentType::PlainText); + content->setBody("Hello part 1"); + marieMessage->addContent(content); + } + + if (second_file_transfer) { + char *send_filepath = bc_tester_res("vcards/vcards.vcf"); + FileContent *content = new FileContent(); + content->setContentType(ContentType("file/vcf")); + content->setFilePath(send_filepath); + content->setFileName("vcards.vcf"); + marieMessage->addContent(content); + bc_free(send_filepath); + } else { + Content *content = new Content(); + content->setContentType(ContentType::PlainText); + content->setBody("Hello part 2"); + marieMessage->addContent(content); + } + + linphone_core_set_file_transfer_server(marie->lc,"https://www.linphone.org:444/lft.php"); + marieMessage->send(); + + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneMessageReceived,1)); + BC_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_chat_message); + + if (first_file_transfer || second_file_transfer) { + LinphoneContent *content = linphone_chat_message_get_file_transfer_information(pauline->stat.last_received_chat_message); + BC_ASSERT_PTR_NOT_NULL(content); + } + if (!first_file_transfer || !second_file_transfer) { + const char *content = linphone_chat_message_get_text_content(pauline->stat.last_received_chat_message); + BC_ASSERT_PTR_NOT_NULL(content); + if (!first_file_transfer) + BC_ASSERT_STRING_EQUAL(content, "Hello part 1"); + else if (!second_file_transfer) + BC_ASSERT_STRING_EQUAL(content, "Hello part 2"); + } + + marieRoom.reset(); // Avoid bad weak ptr when the core is destroyed below this line. + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + +static void multipart_two_text_content(void) { + chat_message_multipart_modifier_base(false, false, false); +} + +static void multipart_two_text_content_with_cpim(void) { + chat_message_multipart_modifier_base(false, false, true); +} + +static void multipart_one_text_and_one_file_content(void) { + chat_message_multipart_modifier_base(true, false, false); +} + +static void multipart_one_text_and_one_file_content_with_cpim(void) { + chat_message_multipart_modifier_base(true, false, true); +} + +static void multipart_two_file_content(void) { + chat_message_multipart_modifier_base(true, true, false); +} + +static void multipart_two_file_content_with_cpim(void) { + chat_message_multipart_modifier_base(true, true, true); +} + +test_t multipart_tests[] = { + TEST_NO_TAG("Chat message multipart 2 text content", multipart_two_text_content), + TEST_NO_TAG("Chat message multipart 2 text content with CPIM", multipart_two_text_content_with_cpim), + TEST_NO_TAG("Chat message multipart 1 file content and 1 text content", multipart_one_text_and_one_file_content), + TEST_NO_TAG("Chat message multipart 1 file content and 1 text content with CPIM", multipart_one_text_and_one_file_content_with_cpim), + TEST_NO_TAG("Chat message multipart 2 file content", multipart_two_file_content), + TEST_NO_TAG("Chat message multipart 2 file content with CPIM", multipart_two_file_content_with_cpim), +}; + +test_suite_t multipart_test_suite = { + "Multipart", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + sizeof(multipart_tests) / sizeof(multipart_tests[0]), multipart_tests +}; diff --git a/tester/offeranswer_tester.c b/tester/offeranswer_tester.c index ee85af984..6e2e3a17f 100644 --- a/tester/offeranswer_tester.c +++ b/tester/offeranswer_tester.c @@ -20,8 +20,8 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" static int get_codec_position(const MSList *l, const char *mime_type, int rate){ const MSList *elem; @@ -35,7 +35,7 @@ static int get_codec_position(const MSList *l, const char *mime_type, int rate){ /*check basic things about codecs at startup: order and enablement*/ static void start_with_no_config(void){ - LinphoneCore *lc=linphone_factory_create_core(linphone_factory_get(), NULL, NULL, NULL); + LinphoneCore *lc=linphone_factory_create_core_2(linphone_factory_get(), NULL, NULL, NULL, NULL, system_context); const MSList *codecs=linphone_core_get_audio_codecs(lc); int opus_codec_pos; int speex_codec_pos=get_codec_position(codecs, "speex", 8000); @@ -461,7 +461,8 @@ static void check_avpf_features(LinphoneCore *lc, unsigned char expected_feature LinphoneCall *lcall = linphone_core_get_current_call(lc); BC_ASSERT_PTR_NOT_NULL(lcall); if (lcall != NULL) { - SalStreamDescription *desc = sal_media_description_find_stream(lcall->resultdesc, SalProtoRtpAvpf, SalVideo); + SalMediaDescription *resultDesc = _linphone_call_get_result_desc(lcall); + SalStreamDescription *desc = sal_media_description_find_stream(resultDesc, SalProtoRtpAvpf, SalVideo); BC_ASSERT_PTR_NOT_NULL(desc); if (desc != NULL) { BC_ASSERT_PTR_NOT_NULL(desc->payloads); @@ -481,7 +482,7 @@ static void compatible_avpf_features(void) { bool_t call_ok; if (configure_core_for_avpf_and_video(marie->lc) == NULL) goto end; - + pt = configure_core_for_avpf_and_video(pauline->lc); BC_ASSERT_TRUE((call_ok=call(marie, pauline))); @@ -506,7 +507,7 @@ static void incompatible_avpf_features(void) { bool_t call_ok; if (configure_core_for_avpf_and_video(marie->lc) == NULL) goto end; - + pt = configure_core_for_avpf_and_video(pauline->lc); pt->avpf.features = PAYLOAD_TYPE_AVPF_NONE; diff --git a/tester/player_tester.c b/tester/player_tester.c index 533ceec09..f4171f6fc 100644 --- a/tester/player_tester.c +++ b/tester/player_tester.c @@ -17,6 +17,7 @@ */ #include "liblinphone_tester.h" +#include "tester_utils.h" #include static bool_t wait_for_eof(bool_t *eof, int *time,int time_refresh, int timeout) { diff --git a/tester/presence_server_tester.c b/tester/presence_server_tester.c index 26802d375..bada13035 100644 --- a/tester/presence_server_tester.c +++ b/tester/presence_server_tester.c @@ -18,8 +18,9 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" +#include "linphone/core_utils.h" static void enable_publish(LinphoneCoreManager *mgr, bool_t enable) { LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc); @@ -34,12 +35,17 @@ const char * get_identity(LinphoneCoreManager *mgr) { return linphone_proxy_config_get_identity(cfg); } +const LinphoneAddress *get_identity_address(LinphoneCoreManager *mgr) { + LinphoneProxyConfig *cfg = linphone_core_get_default_proxy_config(mgr->lc); + return linphone_proxy_config_get_identity_address(cfg); +} + static void enable_deflate_content_encoding(LinphoneCoreManager *mgr, bool_t enable) { LinphoneCore *lc = mgr->lc; if (enable == TRUE) - lp_config_set_string(lc->config, "sip", "handle_content_encoding", "deflate"); + lp_config_set_string(linphone_core_get_config(lc), "sip", "handle_content_encoding", "deflate"); else - lp_config_set_string(lc->config, "sip", "handle_content_encoding", "none"); + lp_config_set_string(linphone_core_get_config(lc), "sip", "handle_content_encoding", "none"); } static void simple(void) { @@ -49,12 +55,12 @@ static void simple(void) { LinphoneFriend* f = linphone_core_create_friend_with_address(marie->lc, get_identity(pauline)); LinphonePresenceActivity *activity = NULL; LinphoneCoreCbs *callbacks = linphone_factory_create_core_cbs(linphone_factory_get()); - + linphone_core_cbs_set_publish_state_changed(callbacks, linphone_publish_state_changed); _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support-bypass", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support-bypass", NULL); enable_publish(pauline, TRUE); @@ -74,7 +80,7 @@ static void simple(void) { } BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphonePublishOk,2)); - + linphone_friend_invalidate_subscription(f); linphone_friend_enable_subscribes(f, FALSE); wait_for_until(marie->lc, NULL, NULL, 0, 5000); @@ -85,7 +91,7 @@ static void simple(void) { linphone_core_manager_stop(marie); linphone_core_manager_destroy(marie); - + linphone_core_manager_stop(pauline); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePublishCleared,1,int,"%i"); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePublishOk,2,int,"%i"); @@ -153,7 +159,7 @@ static void subscriber_no_longer_reachable(void){ lcs = bctbx_list_append(lcs, marie->lc); lcs = bctbx_list_append(lcs, pauline1->lc); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 80); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 80); linphone_core_set_user_agent(marie->lc, "full-presence-support-bypass", NULL); linphone_core_set_user_agent(pauline1->lc, "full-presence-support-bypass", NULL); @@ -423,18 +429,21 @@ static void test_presence_list_base(bool_t enable_compression) { lcs = bctbx_list_append(lcs, marie->lc); lcs = bctbx_list_append(lcs, pauline->lc); - wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 2, 4000); - BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 1, int, "%d"); - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), marie_identity); + wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 4, 4000); // one event by known friend by notify, 4 if test is started independently in + BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); + BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); + BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); + BC_ASSERT_LOWER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 2, int, "%d"); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); + if (!BC_ASSERT_PTR_NOT_NULL(lf)) goto end; BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(pauline)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), "sip:michelle@sip.inexistentdomain.com"); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); - BC_ASSERT_FALSE(lf->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(lf)); lfl = linphone_core_create_friend_list(marie->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -448,10 +457,10 @@ static void test_presence_list_base(bool_t enable_compression) { wait_for_list(lcs, &marie->stat.number_of_NotifyPresenceReceived, 1, 4000); BC_ASSERT_EQUAL(marie->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(marie->lc)->expected_notification_version, 1, int, "%d"); - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(marie->lc), laure_identity); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(marie->lc)), 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(marie->lc), get_identity_address(laure)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnline, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; lfl = linphone_core_create_friend_list(pauline->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -465,27 +474,25 @@ static void test_presence_list_base(bool_t enable_compression) { wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 1, 4000); BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(pauline->lc)->expected_notification_version, 1, int, "%d"); - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), marie_identity); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(pauline->lc)), 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(pauline->lc), get_identity_address(marie)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusBusy, int, "%d"); - if (!BC_ASSERT_TRUE(lf->presence_received)) goto end; + if (!BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf))) goto end; presence = linphone_core_create_presence_model_with_activity(marie->lc, LinphonePresenceActivityOnThePhone, NULL); linphone_core_set_presence_model(marie->lc, presence); linphone_presence_model_unref(presence); - - wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, 4, 4000); - /* The number of PresenceReceived events can be 3 or 4 here. TODO: ideally it should always be 3. */ - BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 3, int, "%d"); - BC_ASSERT_LOWER(laure->stat.number_of_NotifyPresenceReceived, 4, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 2, int, "%d"); - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), marie_identity); + + int previous_laure_number_of_NotifyPresenceReceived = laure->stat.number_of_NotifyPresenceReceived ; + wait_for_list(lcs, &laure->stat.number_of_NotifyPresenceReceived, previous_laure_number_of_NotifyPresenceReceived + 1, 4000); + BC_ASSERT_EQUAL(laure->stat.number_of_NotifyPresenceReceived, previous_laure_number_of_NotifyPresenceReceived + 1, int, "%d"); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); wait_for_list(lcs, &pauline->stat.number_of_NotifyPresenceReceived, 2, 4000); BC_ASSERT_EQUAL(pauline->stat.number_of_NotifyPresenceReceived, 2, int, "%d"); - BC_ASSERT_EQUAL(linphone_core_get_default_friend_list(pauline->lc)->expected_notification_version, 2, int, "%d"); - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), marie_identity); + BC_ASSERT_EQUAL(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(pauline->lc)), 2, int, "%d"); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(pauline->lc), get_identity_address(marie)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOnThePhone, int, "%d"); ms_message("Disabling publish"); @@ -501,26 +508,26 @@ static void test_presence_list_base(bool_t enable_compression) { /*keep in mind long terme presence*/ if (!BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphonePresenceActivityAway, 1, 4000))) goto end; - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), marie_identity); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(pauline->lc), get_identity_address(marie)); /*BC_ASSERT_EQUAL(linphone_presence_activity_get_type(linphone_presence_model_get_activity(linphone_friend_get_presence_model(lf))) , LinphonePresenceActivityOnline, int, "%d"); fixme, should be LinphonePresenceActivityUnknown*/ BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); if (!BC_ASSERT_TRUE(wait_for_list(lcs, &laure->stat.number_of_LinphonePresenceActivityAway, 2, 4000))) goto end; - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(pauline)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); /*BC_ASSERT_EQUAL(linphone_presence_activity_get_type(linphone_presence_model_get_activity(linphone_friend_get_presence_model(lf))) , LinphonePresenceActivityOnline, int, "%d"); fixme, should be LinphonePresenceActivityUnknown*/ - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), marie_identity); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(laure->lc), get_identity_address(marie)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); /*BC_ASSERT_EQUAL(linphone_presence_activity_get_type(linphone_presence_model_get_activity(linphone_friend_get_presence_model(lf))) , LinphonePresenceActivityOnline, int, "%d"); fixme, should be LinphonePresenceActivityUnknown*/ if (!BC_ASSERT_TRUE(wait_for_list(lcs, &marie->stat.number_of_LinphonePresenceActivityAway, 1, 4000))) goto end; - lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(marie->lc), laure_identity); + lf = linphone_friend_list_find_friend_by_address(linphone_core_get_default_friend_list(marie->lc), get_identity_address(laure)); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); /*BC_ASSERT_EQUAL(linphone_presence_activity_get_type(linphone_presence_model_get_activity(linphone_friend_get_presence_model(lf))) , LinphonePresenceActivityOnline, int, "%d"); fixme, should be LinphonePresenceActivityUnknown*/ @@ -605,7 +612,7 @@ static void test_presence_list_subscription_expire_for_unknown(void) { const char *rls_uri = "sip:rls@sip.example.org"; LinphoneFriendList *lfl; LinphoneFriend *lf; - lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 3); + lp_config_set_int(linphone_core_get_config(laure->lc), "sip", "rls_presence_expires", 3); lfl = linphone_core_create_friend_list(laure->lc); linphone_friend_list_set_rls_uri(lfl, rls_uri); @@ -636,7 +643,7 @@ static void test_presence_list_subscribe_with_error(bool_t io_error) { int dummy = 0; LinphonePresenceModel *presence; - lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 5); + lp_config_set_int(linphone_core_get_config(laure->lc), "sip", "rls_presence_expires", 5); pauline_identity = get_identity(pauline); presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); @@ -667,28 +674,28 @@ static void test_presence_list_subscribe_with_error(bool_t io_error) { enable_publish(pauline, TRUE); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 1, 6000)); BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_GREATER(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 1, int, "%d"); + BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); - BC_ASSERT_TRUE(lf->presence_received); + BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), "sip:michelle@sip.inexistentdomain.com"); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); - BC_ASSERT_FALSE(lf->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(lf)); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 2, 6000)); if (io_error) { ms_message("Simulating socket error"); - sal_set_recv_error(laure->lc->sal, -1); + sal_set_recv_error(linphone_core_get_sal(laure->lc), -1); wait_for_list(lcs, &dummy, 1, 500); /* just time for socket to be closed */ } else { ms_message("Simulating in/out packets losses"); - sal_set_send_error(laure->lc->sal,1500); /*make sure no refresh is sent, trash the message without generating error*/ - sal_set_recv_error(laure->lc->sal, 1500); /*make sure server notify to close the dialog is also ignored*/ + sal_set_send_error(linphone_core_get_sal(laure->lc),1500); /*make sure no refresh is sent, trash the message without generating error*/ + sal_set_recv_error(linphone_core_get_sal(laure->lc), 1500); /*make sure server notify to close the dialog is also ignored*/ wait_for_list(lcs, &dummy, 1, 32000); /* Wait a little bit for the subscribe transaction to timeout */ } /*restart normal behavior*/ - sal_set_send_error(laure->lc->sal,0); - sal_set_recv_error(laure->lc->sal, 1); + sal_set_send_error(linphone_core_get_sal(laure->lc),0); + sal_set_recv_error(linphone_core_get_sal(laure->lc), 1); /*a new subscribe should be sent */ BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 3, 9000)); /* give time for subscription to recover to avoid to receive 491 Request pending*/ @@ -726,7 +733,7 @@ static void presence_list_subscribe_network_changes(void) { int dummy = 0; LinphonePresenceModel *presence; - lp_config_set_int(laure->lc->config, "sip", "rls_presence_expires", 5); + lp_config_set_int(linphone_core_get_config(laure->lc), "sip", "rls_presence_expires", 5); pauline_identity = get_identity(pauline); presence = linphone_core_create_presence_model_with_activity(pauline->lc, LinphonePresenceActivityVacation, NULL); @@ -757,16 +764,16 @@ static void presence_list_subscribe_network_changes(void) { enable_publish(pauline, TRUE); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 1, 6000)); BC_ASSERT_GREATER(laure->stat.number_of_NotifyPresenceReceived, 1, int, "%d"); - BC_ASSERT_GREATER(linphone_core_get_default_friend_list(laure->lc)->expected_notification_version, 1, int, "%d"); + BC_ASSERT_GREATER(linphone_friend_list_get_expected_notification_version(linphone_core_get_default_friend_list(laure->lc)), 1, int, "%d"); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusVacation, int, "%d"); - BC_ASSERT_TRUE(lf->presence_received); + BC_ASSERT_TRUE(linphone_friend_is_presence_received(lf)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), "sip:michelle@sip.inexistentdomain.com"); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusOffline, int, "%d"); - BC_ASSERT_FALSE(lf->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(lf)); BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityVacation, 2, 6000)); - + // Simulate network changes linphone_core_set_network_reachable(laure->lc,FALSE); ms_sleep(1); @@ -781,7 +788,7 @@ static void presence_list_subscribe_network_changes(void) { linphone_core_set_presence_model(pauline->lc, presence); linphone_presence_model_unref(presence); - BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityAway, 1, 6000)); + BC_ASSERT_TRUE(wait_for_until(laure->lc, pauline->lc, &laure->stat.number_of_LinphonePresenceActivityAway, 2, 6000)); lf = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(laure->lc), pauline_identity); BC_ASSERT_EQUAL(linphone_friend_get_status(lf), LinphoneStatusAway, int, "%d"); @@ -822,6 +829,31 @@ static void long_term_presence_base(const char* addr, bool_t exist, const char* linphone_friend_unref(friend2); linphone_core_manager_destroy(pauline); } + +static void long_term_presence_large_number_of_subs(void) { +#if 0 /*only work if user are loaded from userdb.conf*/ + int i=0; + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + linphone_core_set_user_agent(pauline->lc, "bypass", NULL); + LinphoneFriendList *friends = linphone_core_create_friend_list(pauline->lc); + linphone_friend_list_set_rls_uri(friends, "sip:rls@sip.example.org"); + for (i = 0 ; i <1000; i++ ) { + char user_id[256]; + snprintf(user_id, sizeof(user_id), "sip:user_%i@sip.example.org",i); + LinphoneFriend* friend2 =linphone_core_create_friend_with_address(pauline->lc, user_id); + linphone_friend_list_add_friend(friends,friend2); + linphone_friend_unref(friend2); + } + linphone_core_add_friend_list(pauline->lc, friends); + linphone_friend_list_unref(friends); + + BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_NotifyPresenceReceived,i)); + + linphone_core_manager_destroy(pauline); + +#endif +} + static void long_term_presence_existing_friend(void) { // this friend is not online, but is known from flexisip to be registered (see flexisip/userdb.conf), // so we expect to get a report that he is currently not online @@ -836,12 +868,13 @@ static void long_term_presence_phone_alias(void) { } static const char* random_phone_number(void) { - static char phone[10]; + static char phone[11]; int i; phone[0] = '+'; for (i = 1; i < 10; i++) { phone[i] = '0' + rand() % 10; } + phone[10] = '\0'; return phone; } @@ -860,14 +893,14 @@ static void long_term_presence_phone_alias2(void) { static void long_term_presence_list(void) { if (linphone_core_vcard_supported()){ - + LinphoneFriend *f1, *f2; LinphoneFriendList* friends; const LinphonePresenceModel *presence; const char *e164_phone_number = "+33" "123456789"; const char *nationnal_phone_number = "0123456789"; LinphoneProxyConfig * pauline_proxy_config; - + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); linphone_core_set_user_agent(pauline->lc, "bypass", NULL); enable_publish(pauline, FALSE); @@ -891,13 +924,13 @@ static void long_term_presence_list(void) { f1 = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), "sip:liblinphone_tester@sip.example.org"); BC_ASSERT_EQUAL(linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(f1)), LinphonePresenceBasicStatusOpen, int, "%d"); - + presence = linphone_friend_get_presence_model_for_uri_or_tel(f1, e164_phone_number); - + if (BC_ASSERT_PTR_NOT_NULL(presence)) { BC_ASSERT_STRING_EQUAL(linphone_presence_model_get_contact(presence), "sip:liblinphone_tester@sip.example.org"); } - BC_ASSERT_TRUE(f1->presence_received); + BC_ASSERT_TRUE(linphone_friend_is_presence_received(f1)); /*now try with nationnal version of phone numer*/ pauline_proxy_config = linphone_core_get_default_proxy_config(pauline->lc); @@ -905,12 +938,12 @@ static void long_term_presence_list(void) { linphone_proxy_config_set_dial_prefix(pauline_proxy_config, "33"); linphone_proxy_config_done(pauline_proxy_config); presence = linphone_friend_get_presence_model_for_uri_or_tel(f1, nationnal_phone_number); - + BC_ASSERT_PTR_NOT_NULL(presence); - + f2 = linphone_friend_list_find_friend_by_uri(linphone_core_get_default_friend_list(pauline->lc), "sip:random_unknown@sip.example.org"); BC_ASSERT_EQUAL(linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(f2)), LinphonePresenceBasicStatusClosed, int, "%d"); - BC_ASSERT_FALSE(f2->presence_received); + BC_ASSERT_FALSE(linphone_friend_is_presence_received(f2)); linphone_core_manager_destroy(pauline); }else ms_warning("Test skipped, no vcard support"); @@ -960,6 +993,8 @@ static void long_term_presence_with_e164_phone_without_sip(void) { static void long_term_presence_with_phone_without_sip(void) { if (linphone_core_vcard_supported()){ const LinphoneDialPlan *dialPlan; + const LinphoneDialPlan *genericDialPlan = linphone_dial_plan_by_ccc(NULL); + char phone[20]; char* e164; size_t i; @@ -968,48 +1003,48 @@ static void long_term_presence_with_phone_without_sip(void) { char *presence_contact; LinphoneCoreManager *marie = NULL; char * identity=NULL; - - while ((dialPlan = linphone_dial_plan_by_ccc_as_int(bctbx_random()%900)) == linphone_dial_plan_by_ccc(NULL)); + + while ((dialPlan = linphone_dial_plan_by_ccc_as_int(bctbx_random()%900)) == genericDialPlan); /*now with have a dialplan*/ - for (i = 0; i < MIN((size_t)dialPlan->nnl,sizeof(phone)-1); i++) { + for (i = 0; i < MIN((size_t)linphone_dial_plan_get_national_number_length(dialPlan),sizeof(phone)-1); i++) { phone[i] = '0' + rand() % 10; } phone[i]='\0'; - - e164=ms_strdup_printf("+%s%s",dialPlan->ccc,phone); - + + e164=ms_strdup_printf("+%s%s",linphone_dial_plan_get_country_calling_code(dialPlan),phone); + ms_message("Phone number is %s, e164 is %s", phone, e164); - + marie = linphone_core_manager_new3("marie_rc", TRUE, e164); linphone_core_set_user_agent(marie->lc, "bypass", NULL); identity = linphone_address_as_string_uri_only(marie->identity); - + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); linphone_core_set_user_agent(pauline->lc, "full-presence-support-bypass", NULL); - + friend2=linphone_core_create_friend(pauline->lc); linphone_friend_add_phone_number(friend2, phone); linphone_core_add_friend(pauline->lc,friend2); - + linphone_friend_list_set_rls_uri(linphone_core_get_default_friend_list(pauline->lc), "sip:rls@sip.example.org"); linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), TRUE); linphone_core_refresh_registers(pauline->lc); - + /*because phone is not normalized*/ BC_ASSERT_FALSE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphonePresenceActivityAway,1,2000)); - + /*know adding ccc to proxy config*/ proxy_config = linphone_core_get_default_proxy_config(pauline->lc); linphone_proxy_config_edit(proxy_config); - linphone_proxy_config_set_dial_prefix(proxy_config, dialPlan->ccc); + linphone_proxy_config_set_dial_prefix(proxy_config, linphone_dial_plan_get_country_calling_code(dialPlan)); linphone_proxy_config_done(proxy_config); /*re-create sub list*/ linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), FALSE); - + wait_for_until(pauline->lc, NULL, NULL, 0,2000); /*wait for unsubscribe*/ linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), TRUE); - + BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphonePresenceActivityAway,1)); BC_ASSERT_EQUAL(pauline->stat.number_of_LinphonePresenceActivityAway, 1, int, "%d"); BC_ASSERT_EQUAL(linphone_presence_model_get_basic_status(linphone_friend_get_presence_model(friend2)), LinphonePresenceBasicStatusOpen, int, "%d"); @@ -1020,7 +1055,10 @@ static void long_term_presence_with_phone_without_sip(void) { ms_free(presence_contact); } } + linphone_friend_unref(friend2); + belle_sip_object_remove_from_leak_detector((void*)dialPlan); //because mostCommon dial plan is a static object freed at the end of the process. This f is only to avoid wrong leak detection. + belle_sip_object_remove_from_leak_detector((void*)genericDialPlan); linphone_core_manager_destroy(pauline); ms_free(e164); ms_free(identity); @@ -1032,12 +1070,12 @@ static char * generate_random_e164_phone_from_dial_plan(const LinphoneDialPlan * char phone[64]; size_t i; /*now with have a dialplan*/ - for (i = 0; i < MIN((size_t)dialPlan->nnl,sizeof(phone)-1); i++) { + for (i = 0; i < MIN((size_t)linphone_dial_plan_get_national_number_length(dialPlan),sizeof(phone)-1); i++) { phone[i] = '0' + rand() % 10; } phone[i]='\0'; - - return ms_strdup_printf("+%s%s",dialPlan->ccc,phone); + + return ms_strdup_printf("+%s%s",linphone_dial_plan_get_country_calling_code(dialPlan),phone); } /* use case: I have a friend, I invite him to use Linphone for the first time. @@ -1051,14 +1089,14 @@ static void long_term_presence_with_crossed_references(void) { const LinphoneDialPlan *dialPlan; char *e164_marie, *e164_pauline, *e164_laure; LinphoneFriend* friend2; - - + + while ((dialPlan = linphone_dial_plan_by_ccc_as_int(bctbx_random()%900)) == linphone_dial_plan_by_ccc(NULL)); - + ms_message("Marie's phone number is %s", e164_marie=generate_random_e164_phone_from_dial_plan(dialPlan)); ms_message("Pauline's phone number is %s", e164_pauline=generate_random_e164_phone_from_dial_plan(dialPlan)); ms_message("Laure's phone number is %s", e164_laure=generate_random_e164_phone_from_dial_plan(dialPlan)); - + /*pauline has marie as friend*/ LinphoneCoreManager *pauline = linphone_core_manager_new3("pauline_tcp_rc",TRUE,e164_pauline); linphone_core_set_user_agent(pauline->lc, "full-presence-support-bypass", NULL); @@ -1069,7 +1107,7 @@ static void long_term_presence_with_crossed_references(void) { linphone_friend_list_set_rls_uri(linphone_core_get_default_friend_list(pauline->lc), "sip:rls@sip.example.org"); linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), TRUE); linphone_core_refresh_registers(pauline->lc); - + //Laure has marie as friend LinphoneCoreManager *laure = linphone_core_manager_new3("laure_tcp_rc",TRUE,e164_laure); linphone_core_set_user_agent(laure->lc, "full-presence-support-bypass", NULL); @@ -1080,11 +1118,11 @@ static void long_term_presence_with_crossed_references(void) { linphone_friend_list_set_rls_uri(linphone_core_get_default_friend_list(laure->lc), "sip:rls@sip.example.org"); linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(laure->lc), TRUE); linphone_core_refresh_registers(laure->lc); - + /*because marie is not registered yet*/ BC_ASSERT_FALSE(wait_for_until(pauline->lc,laure->lc,&pauline->stat.number_of_LinphonePresenceActivityAway,1,2000)); BC_ASSERT_FALSE(wait_for_until(pauline->lc,laure->lc,&laure->stat.number_of_LinphonePresenceActivityAway,1,2000)); - + //Now, marie register to the service LinphoneCoreManager *marie = linphone_core_manager_new3("marie_rc", TRUE, e164_marie); linphone_core_set_user_agent(marie->lc, "bypass", NULL); @@ -1095,21 +1133,22 @@ static void long_term_presence_with_crossed_references(void) { linphone_friend_list_set_rls_uri(linphone_core_get_default_friend_list(marie->lc), "sip:rls@sip.example.org"); linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(marie->lc), TRUE); linphone_core_refresh_registers(marie->lc); - + //Pauline is already registered so I must be notified very rapidely BC_ASSERT_TRUE(wait_for_until(marie->lc,marie->lc,&marie->stat.number_of_LinphonePresenceActivityAway,1,4000)); - + //For Pauline and Laure long term presence check was already performed so they will not be notified until new subscription BC_ASSERT_FALSE(wait_for_until(pauline->lc,laure->lc,&laure->stat.number_of_LinphonePresenceActivityAway,1,4000)); BC_ASSERT_FALSE(wait_for_until(pauline->lc,laure->lc,&pauline->stat.number_of_LinphonePresenceActivityAway,1,4000)); - + //re-subscribe to get notification. linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), FALSE); wait_for_until(pauline->lc, NULL, NULL, 0,2000); /*wait for unsubscribe*/ linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), TRUE); - + BC_ASSERT_TRUE(wait_for_until(pauline->lc,pauline->lc,&pauline->stat.number_of_LinphonePresenceActivityAway,1,4000)); - + + belle_sip_object_remove_from_leak_detector((void*)dialPlan); //because mostCommon dial plan is a static object freed at the end of the process. This f is only to avoid wrong leak detection. linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(laure); @@ -1144,7 +1183,7 @@ static void multiple_publish_aggregation(void) { _linphone_core_add_callbacks(pauline2->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(pauline2->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); @@ -1229,7 +1268,7 @@ static void extended_notify_only_both_side_subscribed(void) { _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); enable_publish(pauline, TRUE); @@ -1251,7 +1290,7 @@ static void extended_notify_only_both_side_subscribed(void) { BC_ASSERT_FALSE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityDinner,1)); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_NotifyPresenceReceived,1)); - + linphone_friend_enable_subscribes(f2, TRUE); linphone_friend_set_inc_subscribe_policy(f2,LinphoneSPAccept); /* Accept incoming subscription request for this friend*/ linphone_core_add_friend(pauline->lc, f2); @@ -1303,7 +1342,7 @@ static void extended_notify_only_both_side_subscribed2(void) { _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); enable_publish(pauline, TRUE); @@ -1323,7 +1362,7 @@ static void extended_notify_only_both_side_subscribed2(void) { BC_ASSERT_FALSE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePresenceActivityDinner,1)); BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_NotifyPresenceReceived,1)); - + linphone_friend_enable_subscribes(f2, TRUE); linphone_friend_set_inc_subscribe_policy(f2,LinphoneSPAccept); /* Accept incoming subscription request for this friend*/ linphone_core_add_friend(pauline->lc, f2); @@ -1349,7 +1388,7 @@ static void extended_notify_only_both_side_subscribed2(void) { linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(marie->lc), FALSE); linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), FALSE); wait_for_list(lcs,NULL, 0, 2000); // wait for unsubscritptions - + linphone_core_manager_stop(marie); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,1,int,"%i"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,2,int,"%i"); @@ -1380,7 +1419,7 @@ static void extended_notify_sub_unsub_sub(void) { _linphone_core_add_callbacks(pauline->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); @@ -1392,7 +1431,7 @@ static void extended_notify_sub_unsub_sub(void) { linphone_friend_enable_subscribes(f, TRUE); linphone_friend_set_inc_subscribe_policy(f,LinphoneSPAccept); /* Accept incoming subscription request for this friend*/ linphone_core_add_friend(marie->lc, f); - + linphone_friend_enable_subscribes(f2, TRUE); linphone_friend_set_inc_subscribe_policy(f2,LinphoneSPAccept); /* Accept incoming subscription request for this friend*/ linphone_core_add_friend(pauline->lc, f2); @@ -1433,7 +1472,7 @@ static void extended_notify_sub_unsub_sub(void) { linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(marie->lc), FALSE); linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), FALSE); wait_for_list(lcs,NULL, 0, 2000); // wait for unsubscritptions - + linphone_core_manager_stop(marie); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,1,int,"%i"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,1,int,"%i"); @@ -1471,7 +1510,7 @@ static void extended_notify_sub_unsub_sub2(void) { _linphone_core_add_callbacks(pauline2->lc, callbacks, TRUE); linphone_core_cbs_unref(callbacks); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 40); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 40); linphone_core_set_user_agent(pauline->lc, "full-presence-support", NULL); linphone_core_set_user_agent(pauline2->lc, "full-presence-support", NULL); linphone_core_set_user_agent(marie->lc, "full-presence-support", NULL); @@ -1482,11 +1521,11 @@ static void extended_notify_sub_unsub_sub2(void) { linphone_presence_model_unref(pauline_presence); linphone_presence_model_unref(pauline_presence2); linphone_presence_model_unref(marie_presence); - + linphone_friend_enable_subscribes(f2, TRUE); linphone_friend_set_inc_subscribe_policy(f2,LinphoneSPAccept); /* Accept incoming subscription request for this friend*/ linphone_core_add_friend(pauline->lc, f2); - + linphone_friend_enable_subscribes(f3, TRUE); linphone_friend_set_inc_subscribe_policy(f3,LinphoneSPAccept); /* Accept incoming subscription request for this friend*/ linphone_core_add_friend(pauline2->lc, f3); @@ -1546,7 +1585,7 @@ static void extended_notify_sub_unsub_sub2(void) { linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline->lc), FALSE); linphone_friend_list_enable_subscriptions(linphone_core_get_default_friend_list(pauline2->lc), FALSE); wait_for_list(lcs,NULL, 0, 2000); // wait for unsubscritptions - + linphone_core_manager_stop(marie); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishCleared,1,int,"%i"); BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,1,int,"%i"); @@ -1731,7 +1770,8 @@ test_t presence_server_tests[] = { TEST_ONE_TAG("Long term presence list",long_term_presence_list, "longterm"), TEST_ONE_TAG("Long term presence with +164 phone, without sip",long_term_presence_with_e164_phone_without_sip, "longterm"), TEST_ONE_TAG("Long term presence with phone, without sip",long_term_presence_with_phone_without_sip, "longterm"), - TEST_ONE_TAG("Long term presence with cross references", long_term_presence_with_crossed_references,"longtern"), + TEST_ONE_TAG("Long term presence with cross references", long_term_presence_with_crossed_references,"longterm"), + TEST_ONE_TAG("Long term presence with large number of subs", long_term_presence_large_number_of_subs,"longterm"), TEST_NO_TAG("Subscriber no longer reachable using server",subscriber_no_longer_reachable), TEST_NO_TAG("Subscribe with late publish", subscribe_with_late_publish), TEST_NO_TAG("Multiple publish aggregation", multiple_publish_aggregation), diff --git a/tester/presence_tester.c b/tester/presence_tester.c index 974a6d747..2eb4c931d 100644 --- a/tester/presence_tester.c +++ b/tester/presence_tester.c @@ -18,8 +18,8 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" static LinphoneCoreManager* presence_linphone_core_manager_new_with_rc_name(char* username, char * rc_name) { LinphoneCoreManager* mgr= linphone_core_manager_new2( rc_name, FALSE); @@ -187,11 +187,11 @@ static void subscribe_failure_handle_by_app(void) { BC_ASSERT_TRUE(subscribe_to_callee_presence(marie,pauline)); wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_NewSubscriptionRequest,1); /*just to wait for unsubscription even if not notified*/ - sal_set_recv_error(marie->lc->sal, 0); /*simulate an error*/ + sal_set_recv_error(linphone_core_get_sal(marie->lc), 0); /*simulate an error*/ BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneRegistrationProgress,2)); BC_ASSERT_EQUAL(linphone_proxy_config_get_error(config),LinphoneReasonIOError, int, "%d"); - sal_set_recv_error(marie->lc->sal, 1); + sal_set_recv_error(linphone_core_get_sal(marie->lc), 1); lf = linphone_core_get_friend_by_address(marie->lc,lf_identity); ms_free(lf_identity); @@ -449,7 +449,7 @@ static void subscribe_presence_expired(void){ lcs = bctbx_list_append(lcs, marie->lc); lcs = bctbx_list_append(lcs, pauline1->lc); - lp_config_set_int(marie->lc->config, "sip", "subscribe_expires", 10); + lp_config_set_int(linphone_core_get_config(marie->lc), "sip", "subscribe_expires", 10); lf = linphone_core_create_friend(marie->lc); linphone_friend_set_address(lf, pauline1->identity); @@ -463,13 +463,13 @@ static void subscribe_presence_expired(void){ lf = linphone_core_find_friend(pauline1->lc, marie->identity); BC_ASSERT_PTR_NOT_NULL(lf); if (lf) { - BC_ASSERT_PTR_NOT_NULL(lf->insubs); + BC_ASSERT_PTR_NOT_NULL(linphone_friend_get_insubs(lf)); /*marie comes offline suddenly*/ linphone_core_set_network_reachable(marie->lc, FALSE); /*after a certain time, pauline shall see the incoming SUBSCRIBE expired*/ wait_for_list(lcs,NULL, 0, 11000); - BC_ASSERT_PTR_NULL(lf->insubs); + BC_ASSERT_PTR_NULL(linphone_friend_get_insubs(lf)); /*just make network reachable so that marie can unregister properly*/ linphone_core_set_network_reachable(marie->lc, TRUE); @@ -514,7 +514,7 @@ test_t presence_tests[] = { /*TEST_ONE_TAG("Call with presence", call_with_presence, "LeaksMemory"),*/ TEST_NO_TAG("Unsubscribe while subscribing", unsubscribe_while_subscribing), TEST_NO_TAG("Presence information", presence_information), - TEST_NO_TAG("App managed presence failure", subscribe_failure_handle_by_app), + TEST_ONE_TAG("App managed presence failure", subscribe_failure_handle_by_app,"presence"), TEST_NO_TAG("Presence SUBSCRIBE forked", subscribe_presence_forked), TEST_NO_TAG("Presence SUBSCRIBE expired", subscribe_presence_expired), }; diff --git a/tester/property-container-tester.cpp b/tester/property-container-tester.cpp new file mode 100644 index 000000000..17b4fcc2a --- /dev/null +++ b/tester/property-container-tester.cpp @@ -0,0 +1,62 @@ +/* + * property-container-tester.cpp + * Copyright (C) 2017 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 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "object/property-container.h" + +#include "liblinphone_tester.h" +#include "tester_utils.h" + +// ============================================================================= + +using namespace std; + +using namespace LinphonePrivate; + +static void set_int_property () { + PropertyContainer properties; + properties.setProperty("integer", 42); + BC_ASSERT_EQUAL(properties.getProperty("integer").getValue(), 42, int, "%d"); +} + +static void set_string_property () { + PropertyContainer properties; + const string text = "Hey listen!"; + properties.setProperty("string", text); + + { + string textToCheck = properties.getProperty("string").getValue(); + BC_ASSERT_STRING_EQUAL(textToCheck.c_str(), text.c_str()); + } +} + +static void set_generic_property () { + PropertyContainer properties; + properties.setProperty("generic", reinterpret_cast(0x42)); + BC_ASSERT_EQUAL(properties.getProperty("generic").getValue(), reinterpret_cast(0x42), void *, "%p"); +} + +test_t property_container_tests[] = { + TEST_NO_TAG("Set int property", set_int_property), + TEST_NO_TAG("Set string property", set_string_property), + TEST_NO_TAG("Set generic property", set_generic_property) +}; + +test_suite_t property_container_test_suite = { + "PropertyContainer", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + sizeof(property_container_tests) / sizeof(property_container_tests[0]), property_container_tests +}; diff --git a/tester/proxy_config_tester.c b/tester/proxy_config_tester.c index c11f352db..a07c0217f 100644 --- a/tester/proxy_config_tester.c +++ b/tester/proxy_config_tester.c @@ -17,6 +17,7 @@ */ #include "liblinphone_tester.h" +#include "tester_utils.h" #include @@ -131,15 +132,15 @@ static void phone_normalization_with_proxy(void) { linphone_proxy_config_set_dial_prefix(proxy, "52"); BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "+5217227718184"), "+5217227718184"); /*this is a mobile phone number */ BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "+528127718184"), "+528127718184"); /*this is a landline phone number from Monterrey*/ - + // Phone normalization for myanmar dial plans linphone_proxy_config_set_dial_prefix(proxy, "95"); BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "9965066691"), "+959965066691"); - + // Phone normalization for cameroon dial plans linphone_proxy_config_set_dial_prefix(proxy, "237"); BC_ASSERT_STRING_EQUAL(phone_normalization(proxy, "674788175"), "+237674788175"); - + linphone_proxy_config_unref(proxy); } @@ -220,16 +221,16 @@ static void load_dynamic_proxy_config(void) { ""; BC_ASSERT_FALSE(linphone_config_load_from_xml_string(linphone_core_get_config(lauriane->lc),config)); proxy = linphone_core_create_proxy_config(lauriane->lc); - + read = linphone_address_new(linphone_proxy_config_get_server_addr(proxy)); expected = linphone_address_new("sip:sip.linphone.org;transport=tls"); - + BC_ASSERT_TRUE(linphone_address_equal(read,expected)); linphone_address_unref(read); linphone_address_unref(expected); - + nat_policy = linphone_proxy_config_get_nat_policy(proxy); - + if (BC_ASSERT_PTR_NOT_NULL(nat_policy)) { BC_ASSERT_TRUE(linphone_nat_policy_ice_enabled(nat_policy)); BC_ASSERT_TRUE(linphone_nat_policy_stun_enabled(nat_policy)); @@ -237,9 +238,32 @@ static void load_dynamic_proxy_config(void) { } linphone_proxy_config_unref(proxy); linphone_core_manager_destroy(lauriane); - + //BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get(proxy), "sip:sip.linphone.org;transport=tls"); - + +} + +static void single_route(void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); + LinphoneProxyConfig *marie_cfg = linphone_core_get_default_proxy_config(marie->lc); + BC_ASSERT_PTR_NOT_NULL(marie_cfg); + + const bctbx_list_t *routes = linphone_proxy_config_get_routes(marie_cfg); + BC_ASSERT_PTR_NOT_NULL(routes); + BC_ASSERT_EQUAL(bctbx_list_size(routes), 1, int, "%d"); + const char *route = (const char *)bctbx_list_get_data(routes); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_route(marie_cfg), "sip:sip.example.org;transport=tcp;lr"); + BC_ASSERT_STRING_EQUAL(route, "sip:sip.example.org;transport=tcp;lr"); + + linphone_proxy_config_set_route(marie_cfg, "sip.linphone.org"); + routes = linphone_proxy_config_get_routes(marie_cfg); + BC_ASSERT_PTR_NOT_NULL(routes); + BC_ASSERT_EQUAL(bctbx_list_size(routes), 1, int, "%d"); + route = (const char *)bctbx_list_get_data(routes); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_route(marie_cfg), "sip:sip.linphone.org"); + BC_ASSERT_STRING_EQUAL(route, "sip:sip.linphone.org"); + + linphone_core_manager_destroy(marie); } test_t proxy_config_tests[] = { @@ -247,7 +271,8 @@ test_t proxy_config_tests[] = { TEST_NO_TAG("Phone normalization with proxy", phone_normalization_with_proxy), TEST_NO_TAG("Phone normalization with dial escape plus", phone_normalization_with_dial_escape_plus), TEST_NO_TAG("SIP URI normalization", sip_uri_normalization), - TEST_NO_TAG("Load new default value for proxy config", load_dynamic_proxy_config) + TEST_NO_TAG("Load new default value for proxy config", load_dynamic_proxy_config), + TEST_NO_TAG("Single route", single_route) }; test_suite_t proxy_config_test_suite = {"Proxy config", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/quality_reporting_tester.c b/tester/quality_reporting_tester.c index d466e8462..ef00ace9d 100644 --- a/tester/quality_reporting_tester.c +++ b/tester/quality_reporting_tester.c @@ -16,45 +16,44 @@ along with this program. If not, see . */ -#include #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" +#include "quality_reporting.h" -/*avoid crash if x is NULL on libc versions <4.5.26 */ +/* Avoid crash if x is NULL on libc versions <4.5.26 */ #define __strstr(x, y) ((x==NULL)?NULL:strstr(x,y)) -void on_report_send_mandatory(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){ - char * body = (char *)linphone_content_get_buffer(content); - char * remote_metrics_start = __strstr(body, "RemoteMetrics:"); - BC_ASSERT_TRUE( - __strstr(body, "VQIntervalReport\r\n") == body || - __strstr(body, "VQSessionReport\r\n") == body || - __strstr(body, "VQSessionReport: CallTerm\r\n") == body +static void on_report_send_mandatory (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) { + const char *body = linphone_content_get_string_buffer(content); + char *remote_metrics_start = __strstr(body, "RemoteMetrics:"); + BC_ASSERT_TRUE((__strstr(body, "VQIntervalReport\r\n") == body) + || (__strstr(body, "VQSessionReport\r\n") == body) + || (__strstr(body, "VQSessionReport: CallTerm\r\n") == body) ); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "CallID:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalID:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteID:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "OrigID:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalGroup:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteGroup:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalAddr:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "IP=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PORT=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SSRC=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteAddr:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "IP=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PORT=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SSRC=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalMetrics:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Timestamps:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "START=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "STOP=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "CallID:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalID:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteID:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "OrigID:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalGroup:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteGroup:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalAddr:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "IP=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PORT=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SSRC=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteAddr:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "IP=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PORT=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SSRC=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalMetrics:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "Timestamps:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "START=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "STOP=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SessionDesc:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PT=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PD=")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SR=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SessionDesc:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PT=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PD=")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SR=")); /* We should have not reached RemoteMetrics section yet */ BC_ASSERT_TRUE(!remote_metrics_start || body < remote_metrics_start); @@ -62,57 +61,60 @@ void on_report_send_mandatory(const LinphoneCall *call, SalStreamType stream_typ BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "DialogID:")); } -char * on_report_send_verify_metrics(const reporting_content_metrics_t *metrics, char * body){ - if (metrics->rtcp_xr_count){ - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "SessionDesc:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "JitterBuffer:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "PacketLoss:")); - } - if (metrics->rtcp_sr_count+metrics->rtcp_xr_count>0){ - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Delay:")); - } - if (metrics->rtcp_xr_count){ - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "QualityEst:")); +static const char *on_report_send_verify_metrics (const reporting_content_metrics_t *metrics, const char *body) { + if (metrics->rtcp_xr_count) { + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "SessionDesc:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "JitterBuffer:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "PacketLoss:")); } + if (metrics->rtcp_sr_count + metrics->rtcp_xr_count > 0) + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "Delay:")); + if (metrics->rtcp_xr_count) + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "QualityEst:")); return body; } -void on_report_send_with_rtcp_xr_local(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){ - char * body = (char*)linphone_content_get_buffer(content); - char * remote_metrics_start = __strstr(body, "RemoteMetrics:"); - reporting_session_report_t * report = call->log->reporting.reports[stream_type]; - on_report_send_mandatory(call,stream_type,content); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "LocalMetrics:")); - BC_ASSERT_TRUE(!remote_metrics_start || on_report_send_verify_metrics(&report->local_metrics,body) < remote_metrics_start); -} -void on_report_send_with_rtcp_xr_remote(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){ - char * body = (char*)linphone_content_get_buffer(content); - reporting_session_report_t * report = call->log->reporting.reports[stream_type]; +#if VIDEO_ENABLED +static void on_report_send_with_rtcp_xr_local (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) { + char *remote_metrics_start = __strstr(linphone_content_get_string_buffer(content), "RemoteMetrics:"); + reporting_session_report_t *report = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call)))[stream_type]; + on_report_send_mandatory(call, stream_type, content); - on_report_send_mandatory(call,stream_type,content); - if (report->remote_metrics.rtcp_sr_count+report->remote_metrics.rtcp_xr_count>0){ - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "RemoteMetrics:")); - BC_ASSERT_PTR_NOT_NULL(body=__strstr(body, "Timestamps:")); - on_report_send_verify_metrics(&report->remote_metrics,body); + const char *body = linphone_content_get_string_buffer(content); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "LocalMetrics:")); + BC_ASSERT_TRUE(!remote_metrics_start || on_report_send_verify_metrics(&report->local_metrics, body) < remote_metrics_start); +} +#endif + +static void on_report_send_with_rtcp_xr_remote (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) { + char *body = (char *)linphone_content_get_buffer(content); + reporting_session_report_t *report = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call)))[stream_type]; + + on_report_send_mandatory(call, stream_type, content); + if ((report->remote_metrics.rtcp_sr_count + report->remote_metrics.rtcp_xr_count) > 0) { + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "RemoteMetrics:")); + BC_ASSERT_PTR_NOT_NULL(body = __strstr(body, "Timestamps:")); + on_report_send_verify_metrics(&report->remote_metrics, body); } } -void on_report_send_with_rtcp_xr_both(const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content){ - on_report_send_with_rtcp_xr_local(call,stream_type,content); - on_report_send_with_rtcp_xr_remote(call,stream_type,content); + +/* +static void on_report_send_with_rtcp_xr_both (const LinphoneCall *call, SalStreamType stream_type, const LinphoneContent *content) { + on_report_send_with_rtcp_xr_local(call, stream_type, content); + on_report_send_with_rtcp_xr_remote(call, stream_type, content); } +*/ -bool_t create_call_for_quality_reporting_tests( - LinphoneCoreManager* marie, - LinphoneCoreManager* pauline, - LinphoneCall** call_marie, - LinphoneCall** call_pauline, - LinphoneCallParams * params_marie, - LinphoneCallParams * params_pauline - ) { - - - bool_t call_succeeded = call_with_params(marie,pauline,params_marie,params_pauline); +static bool_t create_call_for_quality_reporting_tests ( + LinphoneCoreManager *marie, + LinphoneCoreManager *pauline, + LinphoneCall **call_marie, + LinphoneCall **call_pauline, + LinphoneCallParams *params_marie, + LinphoneCallParams *params_pauline +) { + bool_t call_succeeded = call_with_params(marie, pauline, params_marie, params_pauline); BC_ASSERT_TRUE(call_succeeded); if (call_succeeded) { if (call_marie) { @@ -127,22 +129,24 @@ bool_t create_call_for_quality_reporting_tests( return call_succeeded; } -static void quality_reporting_not_used_without_config(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCall* call_marie = NULL; - LinphoneCall* call_pauline = NULL; +static void quality_reporting_not_used_without_config (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphoneCall *call_marie = NULL; + LinphoneCall *call_pauline = NULL; + reporting_session_report_t **quality_reports = NULL; - if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { - // marie has stats collection enabled but pauline has not - BC_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(call_marie->dest_proxy)); - BC_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(call_pauline->dest_proxy)); + if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + // Marie has stats collection enabled but Pauline has not + BC_ASSERT_TRUE(linphone_proxy_config_quality_reporting_enabled(linphone_call_get_dest_proxy(call_marie))); + BC_ASSERT_FALSE(linphone_proxy_config_quality_reporting_enabled(linphone_call_get_dest_proxy(call_pauline))); - // this field should be already filled - BC_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->info.local_addr.ip); + // This field should be already filled + quality_reports = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call_marie))); + BC_ASSERT_PTR_NOT_NULL(quality_reports[0]->info.local_addr.ip); - // but not this one since it is updated at the end of call - BC_ASSERT_PTR_NULL(call_marie->log->reporting.reports[0]->dialog_id); + // But not this one since it is updated at the end of call + BC_ASSERT_PTR_NULL(quality_reports[0]->dialog_id); end_call(marie, pauline); } @@ -150,52 +154,52 @@ static void quality_reporting_not_used_without_config(void) { linphone_core_manager_destroy(pauline); } -static void quality_reporting_not_sent_if_call_not_started(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCallLog* out_call_log; - LinphoneCall* out_call; +static void quality_reporting_not_sent_if_call_not_started (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphoneCallLog *out_call_log; + LinphoneCall *out_call; - linphone_core_set_max_calls(pauline->lc,0); - out_call = linphone_core_invite(marie->lc,"pauline"); + linphone_core_set_max_calls(pauline->lc, 0); + out_call = linphone_core_invite(marie->lc, "pauline"); BC_ASSERT_PTR_NOT_NULL(out_call); - if(out_call == NULL) goto end; + if (!out_call) + goto end; linphone_call_ref(out_call); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallError,1, 10000)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError,1, int, "%d"); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallError, 1, 10000)); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallError, 1, int, "%d"); - if (bctbx_list_size(linphone_core_get_call_logs(marie->lc))>0) { - out_call_log=(LinphoneCallLog*)(linphone_core_get_call_logs(marie->lc)->data); + if (bctbx_list_size(linphone_core_get_call_logs(marie->lc)) > 0) { + out_call_log = (LinphoneCallLog *)(linphone_core_get_call_logs(marie->lc)->data); BC_ASSERT_PTR_NOT_NULL(out_call_log); - BC_ASSERT_EQUAL(linphone_call_log_get_status(out_call_log),LinphoneCallAborted, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_log_get_status(out_call_log), LinphoneCallAborted, int, "%d"); } linphone_call_unref(out_call); - // wait a few time... - wait_for_until(marie->lc,NULL,NULL,0,1000); + // Wait a few time... + wait_for_until(marie->lc, NULL, NULL, 0, 1000); + + // Since the callee was busy, there should be no publish to do + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 0, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d"); - // since the callee was busy, there should be no publish to do - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0, int, "%d"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d"); end: linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -static void quality_reporting_not_sent_if_low_bandwidth(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCallParams* marie_params; - - marie_params=linphone_core_create_call_params(marie->lc, NULL); - linphone_call_params_enable_low_bandwidth(marie_params,TRUE); +static void quality_reporting_not_sent_if_low_bandwidth (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphoneCallParams *marie_params = linphone_core_create_call_params(marie->lc, NULL); + linphone_call_params_enable_low_bandwidth(marie_params, TRUE); if (create_call_for_quality_reporting_tests(marie, pauline, NULL, NULL, marie_params, NULL)) { end_call(marie, pauline); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0, int, "%d"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 0, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d"); } linphone_call_params_unref(marie_params); linphone_core_manager_destroy(marie); @@ -212,188 +216,195 @@ static void on_report_send_remove_fields (const LinphoneCall *call, SalStreamTyp bctbx_free(body); } -static void quality_reporting_invalid_report(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCall* call_marie = NULL; - LinphoneCall* call_pauline = NULL; +static void quality_reporting_invalid_report (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphoneCall *call_marie = NULL; + LinphoneCall *call_pauline = NULL; 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); end_call(marie, pauline); - BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1)); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishError,1,3000)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError,1, int, "%d"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d"); + BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishError, 1, 3000)); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishError, 1, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d"); } + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -static void quality_reporting_at_call_termination(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc_rtcp_xr"); - LinphoneCall* call_marie = NULL; - LinphoneCall* call_pauline = NULL; +static void quality_reporting_at_call_termination (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc_rtcp_xr"); + LinphoneCall *call_marie = NULL; + LinphoneCall *call_pauline = NULL; + reporting_session_report_t **quality_reports = NULL; 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); - // now dialog id should be filled - BC_ASSERT_PTR_NOT_NULL(call_marie->log->reporting.reports[0]->dialog_id); + // Now dialog id should be filled + quality_reports = linphone_quality_reporting_get_reports(linphone_call_log_get_quality_reporting(linphone_call_get_log(call_marie))); + BC_ASSERT_PTR_NOT_NULL(quality_reports[0]->dialog_id); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallReleased,1, 10000)); - BC_ASSERT_TRUE(wait_for_until(pauline->lc,NULL,&pauline->stat.number_of_LinphoneCallReleased,1, 10000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1, 10000)); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, NULL, &pauline->stat.number_of_LinphoneCallReleased, 1, 10000)); BC_ASSERT_PTR_NULL(linphone_core_get_current_call(marie->lc)); BC_ASSERT_PTR_NULL(linphone_core_get_current_call(pauline->lc)); // PUBLISH submission to the collector should be ok - BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,1, int, "%d"); - BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishOk,1)); + BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphonePublishProgress, 1)); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 1, int, "%d"); + BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphonePublishOk, 1)); } + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -static void quality_reporting_interval_report(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc_rtcp_xr"); - LinphoneCall* call_marie = NULL; - LinphoneCall* call_pauline = NULL; +static void quality_reporting_interval_report (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc_rtcp_xr"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc_rtcp_xr"); + LinphoneCall *call_marie = NULL; + LinphoneCall *call_pauline = NULL; - if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { + 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, 1); + linphone_proxy_config_set_quality_reporting_interval(linphone_call_get_dest_proxy(call_marie), 1); BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(marie->lc)); BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc)); // PUBLISH submission to the collector should be ok - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,60000)); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,60000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1, 60000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 1, 60000)); end_call(marie, pauline); } + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } #ifdef VIDEO_ENABLED -static void quality_reporting_session_report_if_video_stopped(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCall* call_pauline = NULL; - LinphoneCall* call_marie = NULL; - LinphoneCallParams* pauline_params; - LinphoneCallParams* marie_params; +static void quality_reporting_session_report_if_video_stopped (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc_rtcp_xr"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphoneCall *call_pauline = NULL; + LinphoneCall *call_marie = NULL; + LinphoneCallParams *pauline_params; + LinphoneCallParams *marie_params; linphone_core_enable_video_capture(marie->lc, TRUE); linphone_core_enable_video_display(marie->lc, FALSE); linphone_core_enable_video_capture(pauline->lc, TRUE); linphone_core_enable_video_display(pauline->lc, FALSE); - marie_params=linphone_core_create_call_params(marie->lc, NULL); - linphone_call_params_enable_video(marie_params,TRUE); - pauline_params=linphone_core_create_call_params(pauline->lc, NULL); - linphone_call_params_enable_video(pauline_params,TRUE); + marie_params = linphone_core_create_call_params(marie->lc, NULL); + linphone_call_params_enable_video(marie_params, TRUE); + pauline_params = linphone_core_create_call_params(pauline->lc, NULL); + linphone_call_params_enable_video(pauline_params, TRUE); 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); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,0, int, "%d"); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 0, int, "%d"); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d"); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, NULL, 0, 3000)); BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); - /*remove video*/ + /* Remove video */ linphone_call_params_unref(pauline_params); - pauline_params=linphone_core_create_call_params(pauline->lc, call_pauline); - linphone_call_params_enable_video(pauline_params,FALSE); - linphone_call_update(call_pauline,pauline_params); + pauline_params = linphone_core_create_call_params(pauline->lc, call_pauline); + linphone_call_params_enable_video(pauline_params, FALSE); + linphone_call_update(call_pauline, pauline_params); linphone_call_params_unref(pauline_params); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,10000)); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,10000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1, 10000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 1, 10000)); BC_ASSERT_FALSE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); end_call(marie, pauline); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,2,5000)); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,2,5000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 2, 5000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 2, 5000)); } linphone_call_params_unref(marie_params); - linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } #endif -void publish_report_with_route_state_changed(LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state){ +static void publish_report_with_route_state_changed (LinphoneCore *lc, LinphoneEvent *ev, LinphonePublishState state) { if (state == LinphonePublishProgress) { - BC_ASSERT_STRING_EQUAL(linphone_address_as_string(linphone_event_get_resource(ev)), linphone_proxy_config_get_quality_reporting_collector(linphone_core_get_default_proxy_config(lc))); + char *uri = linphone_address_as_string(linphone_event_get_resource(ev)); + BC_ASSERT_STRING_EQUAL(uri, linphone_proxy_config_get_quality_reporting_collector(linphone_core_get_default_proxy_config(lc))); + bctbx_free(uri); } } static void quality_reporting_sent_using_custom_route(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_quality_reporting_rc"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); - LinphoneCall* call_marie = NULL; - LinphoneCall* call_pauline = NULL; + LinphoneCoreManager *marie = linphone_core_manager_new("marie_quality_reporting_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); + LinphoneCall *call_marie = NULL; + LinphoneCall *call_pauline = NULL; LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); linphone_core_cbs_set_publish_state_changed(cbs, publish_report_with_route_state_changed); linphone_core_add_callbacks(marie->lc, cbs); linphone_core_cbs_unref(cbs); - //INVALID collector: sip.linphone.org do not collect reports, so it will throw a 404 Not Found error + // INVALID collector: sip.linphone.org do not collect reports, so it will throw a 404 Not Found error linphone_proxy_config_set_quality_reporting_collector(linphone_core_get_default_proxy_config(marie->lc), "sip:sip.linphone.org"); if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, NULL, NULL)) { end_call(marie, pauline); // PUBLISH submission to the collector should be ERROR since route is not valid - BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphonePublishProgress,1)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress,1, int, "%d"); - BC_ASSERT_TRUE(wait_for_until(marie->lc,NULL,&marie->stat.number_of_LinphonePublishError,1,10000)); - BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk,0,int, "%d"); + BC_ASSERT_TRUE(wait_for(marie->lc, NULL, &marie->stat.number_of_LinphonePublishProgress, 1)); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishProgress, 1, int, "%d"); + BC_ASSERT_TRUE(wait_for_until(marie->lc, NULL, &marie->stat.number_of_LinphonePublishError, 1, 10000)); + BC_ASSERT_EQUAL(marie->stat.number_of_LinphonePublishOk, 0, int, "%d"); } + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } #ifdef VIDEO_ENABLED -static void quality_reporting_interval_report_video_and_rtt(void) { - LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc_rtcp_xr"); - LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc_rtcp_xr"); - LinphoneCall* call_marie = NULL; - LinphoneCall* call_pauline = NULL; - LinphoneCallParams* pauline_params; - LinphoneCallParams* marie_params; - LinphoneChatRoom *pauline_chat_room; +static void quality_reporting_interval_report_video_and_rtt (void) { + LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc_rtcp_xr"); + LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc_rtcp_xr"); + LinphoneCall *call_marie = NULL; + LinphoneCall *call_pauline = NULL; + LinphoneCallParams *pauline_params; + LinphoneCallParams *marie_params; + LinphoneChatRoom *pauline_chat_room; linphone_core_enable_video_capture(marie->lc, TRUE); linphone_core_enable_video_display(marie->lc, FALSE); linphone_core_enable_video_capture(pauline->lc, TRUE); linphone_core_enable_video_display(pauline->lc, FALSE); - marie_params=linphone_core_create_call_params(marie->lc, NULL); - linphone_call_params_enable_video(marie_params,TRUE); - linphone_call_params_enable_realtime_text(marie_params,TRUE); - pauline_params=linphone_core_create_call_params(pauline->lc, NULL); - linphone_call_params_enable_video(pauline_params,TRUE); - linphone_call_params_enable_realtime_text(pauline_params,TRUE); + marie_params = linphone_core_create_call_params(marie->lc, NULL); + linphone_call_params_enable_video(marie_params, TRUE); + linphone_call_params_enable_realtime_text(marie_params, TRUE); + pauline_params = linphone_core_create_call_params(pauline->lc, NULL); + linphone_call_params_enable_video(pauline_params, TRUE); + linphone_call_params_enable_realtime_text(pauline_params, TRUE); - if (create_call_for_quality_reporting_tests(marie, pauline, &call_marie, &call_pauline, marie_params, pauline_params)) { + 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_mandatory); - linphone_proxy_config_set_quality_reporting_interval(call_marie->dest_proxy, 3); + linphone_proxy_config_set_quality_reporting_interval(linphone_call_get_dest_proxy(call_marie), 3); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,NULL,0,3000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, NULL, 0, 3000)); BC_ASSERT_TRUE(linphone_call_params_video_enabled(linphone_call_get_current_params(call_pauline))); BC_ASSERT_TRUE(linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(call_pauline))); @@ -401,28 +412,32 @@ static void quality_reporting_interval_report_video_and_rtt(void) { BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(pauline->lc)); // PUBLISH submission to the collector should be ok - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishProgress,1,5000)); - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,1,10000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishProgress, 1, 5000)); + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, 1, 10000)); pauline_chat_room = linphone_call_get_chat_room(call_pauline); BC_ASSERT_PTR_NOT_NULL(pauline_chat_room); + LinphoneChatMessage *rtt_message = NULL; if (pauline_chat_room) { - const char* message = "Lorem Ipsum Belledonnum Communicatum"; + const char *message = "Lorem Ipsum Belledonnum Communicatum"; size_t i; - LinphoneChatMessage* rtt_message = linphone_chat_room_create_message(pauline_chat_room,NULL); + rtt_message = linphone_chat_room_create_message(pauline_chat_room, NULL); LinphoneChatRoom *marie_chat_room = linphone_call_get_chat_room(call_marie); for (i = 0; i < strlen(message); i++) { linphone_chat_message_put_char(rtt_message, message[i]); - BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)i+1, 1000)); + BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneIsComposingActiveReceived, (int)(i + 1), 1000)); BC_ASSERT_EQUAL(linphone_chat_room_get_char(marie_chat_room), message[i], char, "%c"); } - linphone_chat_room_send_chat_message(pauline_chat_room, rtt_message); + linphone_chat_message_send(rtt_message); } end_call(marie, pauline); - /*wait that all publish complete*/ - BC_ASSERT_TRUE(wait_for_until(marie->lc,pauline->lc,&marie->stat.number_of_LinphonePublishOk,marie->stat.number_of_LinphonePublishProgress,60000)); + /* Wait that all publish complete */ + BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_LinphonePublishOk, marie->stat.number_of_LinphonePublishProgress, 60000)); + + if (rtt_message) + linphone_chat_message_unref(rtt_message); } linphone_call_params_unref(marie_params); @@ -433,10 +448,10 @@ static void quality_reporting_interval_report_video_and_rtt(void) { } #endif -static void video_bandwidth_estimation(void){ +static void video_bandwidth_estimation (void) { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_rc"); - LinphoneVideoPolicy pol = {0}; + LinphoneVideoPolicy pol = { 0 }; OrtpNetworkSimulatorParams simparams = { 0 }; linphone_core_set_video_device(marie->lc, "Mire: Mire (synthetic moving picture)"); @@ -456,14 +471,15 @@ static void video_bandwidth_estimation(void){ simparams.max_bandwidth = 300000; linphone_core_set_network_simulator_params(marie->lc, &simparams); - if (BC_ASSERT_TRUE(call(marie, pauline))){ - /*wait for the first TMMBR*/ + if (BC_ASSERT_TRUE(call(marie, pauline))) { + /* Wait for the first TMMBR */ BC_ASSERT_TRUE(wait_for_until(marie->lc, pauline->lc, &marie->stat.number_of_tmmbr_received, 1, 50000)); BC_ASSERT_GREATER((float)marie->stat.last_tmmbr_value_received, 270000.f, float, "%f"); BC_ASSERT_LOWER((float)marie->stat.last_tmmbr_value_received, 330000.f, float, "%f"); end_call(marie, pauline); } + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } @@ -476,13 +492,15 @@ test_t quality_reporting_tests[] = { TEST_NO_TAG("Call term session report sent if call ended normally", quality_reporting_at_call_termination), TEST_NO_TAG("Interval report if interval is configured", quality_reporting_interval_report), #ifdef VIDEO_ENABLED - TEST_NO_TAG("Interval report if interval is configured with video and realtime text", quality_reporting_interval_report_video_and_rtt), - TEST_NO_TAG("Session report sent if video stopped during call", quality_reporting_session_report_if_video_stopped), - #endif + TEST_NO_TAG("Interval report if interval is configured with video and realtime text", quality_reporting_interval_report_video_and_rtt), + TEST_NO_TAG("Session report sent if video stopped during call", quality_reporting_session_report_if_video_stopped), + #endif // ifdef VIDEO_ENABLED TEST_NO_TAG("Sent using custom route", quality_reporting_sent_using_custom_route), TEST_NO_TAG("Video bandwidth estimation", video_bandwidth_estimation) }; -test_suite_t quality_reporting_test_suite = {"QualityReporting", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(quality_reporting_tests) / sizeof(quality_reporting_tests[0]), - quality_reporting_tests}; +test_suite_t quality_reporting_test_suite = { + "QualityReporting", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + sizeof(quality_reporting_tests) / sizeof(quality_reporting_tests[0]), + quality_reporting_tests +}; diff --git a/tester/rcfiles/chloe_rc b/tester/rcfiles/chloe_rc new file mode 100644 index 000000000..6fdd750f4 --- /dev/null +++ b/tester/rcfiles/chloe_rc @@ -0,0 +1,45 @@ +[sip] +sip_port=-1 +sip_tcp_port=-1 +sip_tls_port=-1 +default_proxy=0 +ping_with_options=0 +composing_idle_timeout=1 + +[auth_info_0] +username=chloe +userid=chloe +passwd=secret +realm=sip.example.org + +[proxy_0] +realm=sip.example.org +reg_proxy=sip2.linphone.org;transport=tls +reg_route=sip2.linphone.org;transport=tls +reg_identity=sip:chloe@sip.example.org +reg_expires=3600 +reg_sendregister=1 +publish=0 +dial_escape_plus=0 + +[rtp] +audio_rtp_port=18070-28000 +video_rtp_port=39072-49000 + +[video] +display=0 +capture=0 +show_local=0 +size=qcif +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 + +[net] +dns_srv_enabled=0 #no srv needed in general +stun_server=stun.linphone.org diff --git a/tester/rcfiles/laure_tcp_rc b/tester/rcfiles/laure_tcp_rc index 4c66553ea..912db8271 100644 --- a/tester/rcfiles/laure_tcp_rc +++ b/tester/rcfiles/laure_tcp_rc @@ -5,23 +5,21 @@ sip_tls_port=-1 default_proxy=0 ping_with_options=0 - [auth_info_0] username=laure userid=laure passwd=secret realm="sip.example.org" - [proxy_0] reg_proxy=sip.example.org;transport=tcp +reg_route=sip.example.org;transport=tcp reg_identity=sip:laure@sip.example.org reg_expires=3600 reg_sendregister=1 publish=0 dial_escape_plus=0 - [rtp] audio_rtp_port=9010-9390 video_rtp_port=9410-9910 diff --git a/tester/rcfiles/marie_rc b/tester/rcfiles/marie_rc index 64c454bb1..7c511b311 100644 --- a/tester/rcfiles/marie_rc +++ b/tester/rcfiles/marie_rc @@ -4,7 +4,6 @@ sip_tcp_port=-1 sip_tls_port=-1 default_proxy=0 ping_with_options=0 - composing_idle_timeout=1 store_ha1_passwd=0 #used for sipp @@ -14,7 +13,6 @@ 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 @@ -29,6 +27,9 @@ url="Paupoche" pol=accept subscribe=0 +[misc] +enable_basic_to_client_group_chat_room_migration=1 +basic_to_client_group_chat_room_migration_timer=180 [rtp] audio_rtp_port=18070-28000 diff --git a/tester/rcfiles/pauline_rc b/tester/rcfiles/pauline_rc index c5f1fed4d..6d1be2b7f 100644 --- a/tester/rcfiles/pauline_rc +++ b/tester/rcfiles/pauline_rc @@ -4,7 +4,6 @@ sip_tcp_port=-1 sip_tls_port=-1 default_proxy=0 ping_with_options=0 - composing_idle_timeout=1 [auth_info_0] @@ -13,7 +12,6 @@ userid=pauline passwd=secret realm=sip.example.org - [proxy_0] realm=sip.example.org reg_proxy=sip2.linphone.org;transport=tls diff --git a/tester/rcfiles/upnp_rc b/tester/rcfiles/upnp_rc deleted file mode 100644 index 3b04fd077..000000000 --- a/tester/rcfiles/upnp_rc +++ /dev/null @@ -1,2 +0,0 @@ - [net] - firewall_policy=4 diff --git a/tester/register_tester.c b/tester/register_tester.c index 873c9fcc8..9865b5845 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -18,8 +18,8 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" static void authentication_requested(LinphoneCore *lc, LinphoneAuthInfo *auth_info, LinphoneAuthMethod method) { @@ -64,13 +64,16 @@ void registration_state_changed(struct _LinphoneCore *lc, LinphoneProxyConfig *c } } -static void register_with_refresh_base_3(LinphoneCore* lc - , bool_t refresh - ,const char* domain - ,const char* route - ,bool_t late_auth_info - ,LinphoneTransports *transport - ,LinphoneRegistrationState expected_final_state) { +static void register_with_refresh_base_3_for_algo( + LinphoneCore* lc, + bool_t refresh, + const char* domain, + const char* route, + bool_t late_auth_info, + LinphoneTransports *transport, + LinphoneRegistrationState expected_final_state, + const char* username +) { int retry=0; char* addr; LinphoneProxyConfig* proxy_cfg; @@ -86,9 +89,9 @@ static void register_with_refresh_base_3(LinphoneCore* lc reset_counters(counters); linphone_core_set_transports(lc, transport); - proxy_cfg = linphone_proxy_config_new(); + proxy_cfg = linphone_core_create_proxy_config(lc); - from = create_linphone_address(domain); + from = create_linphone_address_for_algo(domain, username); linphone_proxy_config_set_identity(proxy_cfg,addr=linphone_address_as_string(from)); ms_free(addr); @@ -136,31 +139,54 @@ static void register_with_refresh_base_3(LinphoneCore* lc linphone_proxy_config_unref(proxy_cfg); } -static void register_with_refresh_base_2(LinphoneCore* lc - , bool_t refresh - ,const char* domain - ,const char* route - ,bool_t late_auth_info - ,LinphoneTransports *transport) { - register_with_refresh_base_3(lc, refresh, domain, route, late_auth_info, transport,LinphoneRegistrationOk ); +static void register_with_refresh_base_3( + LinphoneCore* lc, + bool_t refresh, + const char *domain, + const char *route, + bool_t late_auth_info, + LinphoneTransports *transport, + LinphoneRegistrationState expected_final_state +) { + register_with_refresh_base_3_for_algo(lc, refresh, domain, route, late_auth_info, transport, expected_final_state, NULL); } -static void register_with_refresh_base(LinphoneCore* lc, bool_t refresh,const char* domain,const char* route) { - LinphoneTransports *transport = linphone_transports_new(); + +static void register_with_refresh_base_2( + LinphoneCore* lc, + bool_t refresh, + const char *domain, + const char *route, + bool_t late_auth_info, + LinphoneTransports *transport +) { + register_with_refresh_base_3(lc, refresh, domain, route, late_auth_info, transport,LinphoneRegistrationOk); +} + +static void register_with_refresh_base_for_algo(LinphoneCore* lc, bool_t refresh, const char *domain,const char *route, const char *username) { + LinphoneTransports *transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, 5070); linphone_transports_set_tcp_port(transport, 5070); linphone_transports_set_tls_port(transport, 5071); linphone_transports_set_dtls_port(transport, 0); - register_with_refresh_base_2(lc,refresh,domain,route,FALSE,transport); + register_with_refresh_base_3_for_algo(lc,refresh,domain,route,FALSE,transport,LinphoneRegistrationOk,username); linphone_transports_unref(transport); } -static void register_with_refresh(LinphoneCoreManager* lcm, bool_t refresh,const char* domain,const char* route) { +static void register_with_refresh_base(LinphoneCore *lc, bool_t refresh, const char *domain, const char *route) { + register_with_refresh_base_for_algo(lc, refresh, domain, route, NULL); +} + +static void register_with_refresh_for_algo(LinphoneCoreManager *lcm, bool_t refresh, const char *domain, const char*route, const char *username) { stats* counters = &lcm->stat; - register_with_refresh_base(lcm->lc,refresh,domain,route); + register_with_refresh_base_for_algo(lcm->lc,refresh,domain,route,username); linphone_core_manager_stop(lcm); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationCleared,1, int, "%d"); } +static void register_with_refresh(LinphoneCoreManager* lcm, bool_t refresh,const char* domain,const char* route) { + register_with_refresh_for_algo(lcm, refresh, domain, route, NULL); +} + static void register_with_refresh_with_send_error(void) { int retry=0; LinphoneCoreManager* lcm = create_lcm_with_auth(1); @@ -172,7 +198,7 @@ static void register_with_refresh_with_send_error(void) { linphone_auth_info_unref(info); register_with_refresh_base(lcm->lc,TRUE,auth_domain,route); /*simultate a network error*/ - sal_set_send_error(lcm->lc->sal, -1); + sal_set_send_error(linphone_core_get_sal(lcm->lc), -1); while (counters->number_of_LinphoneRegistrationProgress<2 && retry++ <200) { linphone_core_iterate(lcm->lc); ms_usleep(10000); @@ -289,7 +315,7 @@ static void simple_tcp_register_compatibility_mode(void){ LinphoneTransports *transport = NULL; sprintf(route,"sip:%s",test_route); lcm = create_lcm(); - transport = linphone_transports_new(); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_tcp_port(transport, 5070); register_with_refresh_base_2(lcm->lc,FALSE,test_domain,route,FALSE,transport); linphone_transports_unref(transport); @@ -310,7 +336,7 @@ static void simple_tls_register(void){ static void simple_authenticated_register(void){ stats* counters; LinphoneCoreManager* lcm = create_lcm(); - LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/ + LinphoneAuthInfo *info=linphone_auth_info_new_for_algorithm(test_username,NULL,test_password,NULL,auth_domain,NULL,NULL); /*create authentication structure from identity*/ char route[256]; sprintf(route,"sip:%s",test_route); linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/ @@ -321,6 +347,20 @@ static void simple_authenticated_register(void){ linphone_core_manager_destroy(lcm); } +static void simple_authenticated_register_for_algorithm(void){ + stats* counters; + LinphoneCoreManager* lcm = create_lcm(); + LinphoneAuthInfo *info=linphone_auth_info_new_for_algorithm(test_sha_username,NULL,test_password,NULL,auth_domain,NULL,"SHA-256"); /*create authentication structure from identity*/ + char route[256]; + sprintf(route,"sip:%s",test_route); + linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/ + linphone_auth_info_unref(info); + counters = &lcm->stat; + register_with_refresh_for_algo(lcm,FALSE,auth_domain,route,test_sha_username); + BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,0, int, "%d"); + linphone_core_manager_destroy(lcm); +} + static void ha1_authenticated_register(void){ stats* counters; LinphoneCoreManager* lcm = create_lcm(); @@ -328,7 +368,7 @@ static void ha1_authenticated_register(void){ LinphoneAuthInfo *info; char route[256]; sal_auth_compute_ha1(test_username,auth_domain,test_password,ha1); - info=linphone_auth_info_new(test_username,NULL,NULL,ha1,auth_domain,NULL); /*create authentication structure from identity*/ + info=linphone_auth_info_new_for_algorithm(test_username,NULL,NULL,ha1,auth_domain,NULL,NULL); /*create authentication structure from identity*/ sprintf(route,"sip:%s",test_route); linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/ linphone_auth_info_unref(info); @@ -338,6 +378,23 @@ static void ha1_authenticated_register(void){ linphone_core_manager_destroy(lcm); } +static void ha1_authenticated_register_for_algorithm(void){ + stats* counters; + LinphoneCoreManager* lcm = create_lcm(); + char ha1[65]; + LinphoneAuthInfo *info; + char route[256]; + sal_auth_compute_ha1_for_algorithm(test_sha_username,auth_domain,test_password,ha1,65,"SHA-256"); + info=linphone_auth_info_new_for_algorithm(test_sha_username,NULL,NULL,ha1,auth_domain,NULL,"SHA-256"); /*create authentication structure from identity*/ + sprintf(route,"sip:%s",test_route); + linphone_core_add_auth_info(lcm->lc,info); /*add authentication info to LinphoneCore*/ + linphone_auth_info_unref(info); + counters = &lcm->stat; + register_with_refresh_for_algo(lcm,FALSE,auth_domain,route,test_sha_username); + BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,0, int, "%d"); + linphone_core_manager_destroy(lcm); +} + static void authenticated_register_with_no_initial_credentials(void){ LinphoneCoreManager *lcm; LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); @@ -368,8 +425,8 @@ static void authenticated_register_with_late_credentials(void){ sprintf(route,"sip:%s",test_route); - lcm = linphone_core_manager_new(NULL); - transport = linphone_transports_new(); + lcm = linphone_core_manager_new(NULL); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, 5070); linphone_transports_set_tcp_port(transport, 5070); linphone_transports_set_dtls_port(transport, 5071); @@ -392,7 +449,7 @@ static void authenticated_register_with_provided_credentials(void){ sprintf(route,"sip:%s",test_route); - lcm = linphone_core_manager_new(NULL); + lcm = linphone_core_manager_new(NULL); counters = get_stats(lcm->lc); cfg = linphone_core_create_proxy_config(lcm->lc); @@ -415,53 +472,45 @@ static void authenticated_register_with_provided_credentials(void){ BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,1)); BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,0, int, "%d"); - BC_ASSERT_PTR_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "passwd", NULL)); - BC_ASSERT_PTR_NOT_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "ha1", NULL)); + BC_ASSERT_PTR_NULL(lp_config_get_string(linphone_core_get_config(lcm->lc), "auth_info_0", "passwd", NULL)); + BC_ASSERT_PTR_NOT_NULL(lp_config_get_string(linphone_core_get_config(lcm->lc), "auth_info_0", "ha1", NULL)); - linphone_proxy_config_destroy(cfg); + linphone_proxy_config_unref(cfg); linphone_core_manager_destroy(lcm); } -static void authenticated_register_with_provided_credentials_and_username_with_espace(void){ - LinphoneCoreManager *lcm; - stats* counters; - LinphoneProxyConfig *cfg; - char route[256]; - LinphoneAddress *from; - char *addr; - LinphoneAuthInfo *ai; - const char* username = "test username"; - sprintf(route,"sip:%s",test_route); - - lcm = linphone_core_manager_new(NULL); - - counters = get_stats(lcm->lc); - cfg = linphone_core_create_proxy_config(lcm->lc); - from = create_linphone_address_with_username(auth_domain,username); - - linphone_proxy_config_set_identity(cfg, addr=linphone_address_as_string(from)); +static void authenticated_register_with_provided_credentials_and_username_with_space(void) { + LinphoneCoreManager *lcm = linphone_core_manager_new(NULL); + stats *counters = get_stats(lcm->lc); + LinphoneProxyConfig *cfg = linphone_core_create_proxy_config(lcm->lc); + const char *username = "test username"; + LinphoneAddress *from = create_linphone_address_for_algo(auth_domain, username); + + char *addr = linphone_address_as_string(from); + linphone_proxy_config_set_identity(cfg, addr); ms_free(addr); - - linphone_proxy_config_enable_register(cfg,TRUE); - linphone_proxy_config_set_expires(cfg,1); + + linphone_proxy_config_enable_register(cfg, TRUE); + linphone_proxy_config_set_expires(cfg, 1); linphone_proxy_config_set_route(cfg, test_route); - linphone_proxy_config_set_server_addr(cfg,test_route); + linphone_proxy_config_set_server_addr(cfg, test_route); linphone_address_unref(from); - - ai = linphone_auth_info_new(username, NULL, test_password, NULL, NULL, NULL); + + LinphoneAuthInfo *ai = linphone_auth_info_new(username, NULL, test_password, NULL, NULL, test_route); linphone_core_add_auth_info(lcm->lc, ai); linphone_auth_info_unref(ai); linphone_core_add_proxy_config(lcm->lc, cfg); - - BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,1)); - BC_ASSERT_EQUAL(counters->number_of_auth_info_requested,0, int, "%d"); - - BC_ASSERT_PTR_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "passwd", NULL)); - BC_ASSERT_PTR_NOT_NULL(lp_config_get_string(lcm->lc->config, "auth_info_0", "ha1", NULL)); - - linphone_proxy_config_destroy(cfg); + + BC_ASSERT_TRUE(wait_for(lcm->lc, lcm->lc, &counters->number_of_LinphoneRegistrationOk, 1)); + BC_ASSERT_EQUAL(counters->number_of_auth_info_requested, 0, int, "%d"); + + BC_ASSERT_PTR_NULL(lp_config_get_string(linphone_core_get_config(lcm->lc), "auth_info_0", "passwd", NULL)); + BC_ASSERT_PTR_NOT_NULL(lp_config_get_string(linphone_core_get_config(lcm->lc), "auth_info_0", "ha1", NULL)); + + linphone_proxy_config_unref(cfg); linphone_core_manager_destroy(lcm); } + static void authenticated_register_with_wrong_late_credentials(void){ LinphoneCoreManager *lcm; stats* counters; @@ -474,8 +523,8 @@ static void authenticated_register_with_wrong_late_credentials(void){ sprintf(route,"sip:%s",test_route); - lcm = linphone_core_manager_new(NULL); - transport = linphone_transports_new(); + lcm = linphone_core_manager_new(NULL); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, 5070); linphone_transports_set_tcp_port(transport, 5070); linphone_transports_set_tls_port(transport, 5071); @@ -494,7 +543,7 @@ static void authenticated_register_with_wrong_late_credentials(void){ static void authenticated_register_with_wrong_credentials_with_params_base(const char* user_agent,LinphoneCoreManager *lcm) { stats* counters; - LinphoneTransports *transport = linphone_transports_new(); + LinphoneTransports *transport = linphone_factory_create_transports(linphone_factory_get()); LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,"wrong passwd",NULL,auth_domain,NULL); /*create authentication structure from identity*/ char route[256]; @@ -504,7 +553,7 @@ static void authenticated_register_with_wrong_credentials_with_params_base(const linphone_transports_set_tls_port(transport, 5071); linphone_transports_set_dtls_port(transport, 0); - sal_set_refresher_retry_after(lcm->lc->sal,500); + sal_set_refresher_retry_after(linphone_core_get_sal(lcm->lc),500); if (user_agent) { linphone_core_set_user_agent(lcm->lc,user_agent,NULL); } @@ -625,7 +674,7 @@ static void transport_change(void){ lcm=configure_lcm(); if (lcm) { lc=lcm->lc; - sip_tr = linphone_transports_new(); + sip_tr = linphone_factory_create_transports(linphone_factory_get()); counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; @@ -633,7 +682,7 @@ static void transport_change(void){ total_number_of_proxies=(int)bctbx_list_size(linphone_core_get_proxy_config_list(lc)); sip_tr_orig = linphone_core_get_transports(lc); - sip_tr->udp_port = sip_tr_orig->udp_port; + linphone_transports_set_udp_port(sip_tr, linphone_transports_get_udp_port(sip_tr_orig)); /*keep only udp*/ linphone_core_set_transports(lc, sip_tr); @@ -650,17 +699,17 @@ static void transport_change(void){ static void transport_dont_bind(void){ LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); stats* counters = &pauline->stat; - LinphoneTransports *tr = linphone_transports_new(); + LinphoneTransports *tr = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_tcp_port(tr, LC_SIP_TRANSPORT_DONTBIND); linphone_transports_set_tls_port(tr, LC_SIP_TRANSPORT_DONTBIND); - + linphone_core_set_transports(pauline->lc, tr); BC_ASSERT_TRUE(wait_for_until(pauline->lc,pauline->lc,&counters->number_of_LinphoneRegistrationOk,2,15000)); linphone_transports_unref(tr); tr = linphone_core_get_transports_used(pauline->lc); - BC_ASSERT_EQUAL(tr->udp_port, 0, int, "%i"); - BC_ASSERT_EQUAL(tr->tcp_port, LC_SIP_TRANSPORT_DONTBIND, int, "%i"); - BC_ASSERT_EQUAL(tr->tls_port, LC_SIP_TRANSPORT_DONTBIND, int, "%i"); + BC_ASSERT_EQUAL(linphone_transports_get_udp_port(tr), 0, int, "%i"); + BC_ASSERT_EQUAL(linphone_transports_get_tcp_port(tr), LC_SIP_TRANSPORT_DONTBIND, int, "%i"); + BC_ASSERT_EQUAL(linphone_transports_get_tls_port(tr), LC_SIP_TRANSPORT_DONTBIND, int, "%i"); linphone_transports_unref(tr); linphone_core_manager_destroy(pauline); } @@ -668,14 +717,14 @@ static void transport_dont_bind(void){ static void transport_busy(void){ LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); LCSipTransports tr; - + memset(&tr, 0, sizeof(tr)); tr.udp_port = 5070; tr.tcp_port = 5070; tr.tls_port = 5071; - + linphone_core_set_sip_transports(pauline->lc, &tr); - + { LinphoneCoreManager *marie = linphone_core_manager_new("marie_rc"); linphone_core_set_sip_transports(marie->lc, &tr); @@ -686,7 +735,7 @@ static void transport_busy(void){ BC_ASSERT_EQUAL(tr.tls_port, 0, int, "%i");*/ linphone_core_manager_destroy(marie); } - + linphone_core_manager_destroy(pauline); } @@ -727,8 +776,8 @@ static void proxy_transport_change(void){ } /* * On ios, some firewal require to disable flow label (livebox with default firewall level). - * sudo sysctl net.inet6.ip6.auto_flowlabel=0 - * It might be possible to found a sockopt for such purpose. + * sudo sysctl net.inet6.ip6.auto_flowlabel=0 + * It might be possible to found a sockopt for such purpose. */ static void proxy_transport_change_with_wrong_port(void) { LinphoneCoreManager* lcm = create_lcm(); @@ -736,7 +785,7 @@ static void proxy_transport_change_with_wrong_port(void) { LinphoneProxyConfig* proxy_config; LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/ char route[256]; - LinphoneTransports *transport= linphone_transports_new(); + LinphoneTransports *transport= linphone_factory_create_transports(linphone_factory_get()); sprintf(route,"sip:%s",test_route); linphone_transports_set_udp_port(transport, LC_SIP_TRANSPORT_RANDOM); linphone_transports_set_tcp_port(transport, LC_SIP_TRANSPORT_RANDOM); @@ -772,7 +821,7 @@ static void proxy_transport_change_with_wrong_port_givin_up(void) { LinphoneProxyConfig* proxy_config; LinphoneAuthInfo *info=linphone_auth_info_new(test_username,NULL,test_password,NULL,auth_domain,NULL); /*create authentication structure from identity*/ char route[256]; - LinphoneTransports *transport = linphone_transports_new(); + LinphoneTransports *transport = linphone_factory_create_transports(linphone_factory_get()); sprintf(route,"sip:%s",test_route); linphone_transports_set_udp_port(transport, LC_SIP_TRANSPORT_RANDOM); linphone_transports_set_tcp_port(transport, LC_SIP_TRANSPORT_RANDOM); @@ -814,12 +863,12 @@ static void io_recv_error(void){ counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); - sal_set_recv_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 0); BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationProgress,2*(register_ok-number_of_udp_proxy) /*because 1 udp*/)); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - sal_set_recv_error(lc->sal, 1); /*reset*/ + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ linphone_core_manager_destroy(lcm); } @@ -838,11 +887,11 @@ static void io_recv_error_retry_immediatly(void){ counters = get_stats(lc); register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); - sal_set_recv_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 0); BC_ASSERT_TRUE(wait_for(lc,NULL,&counters->number_of_LinphoneRegistrationProgress,(register_ok-number_of_udp_proxy)+register_ok /*because 1 udp*/)); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - sal_set_recv_error(lc->sal, 1); /*reset*/ + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ BC_ASSERT_TRUE(wait_for_until(lc,lc,&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy+register_ok,30000)); @@ -860,7 +909,7 @@ static void io_recv_error_late_recovery(void){ bctbx_list_t* lcs; lcm=linphone_core_manager_new2( "multi_account_rc",FALSE); /*to make sure iterates are not call yet*/ lc=lcm->lc; - sal_set_refresher_retry_after(lc->sal,1000); + sal_set_refresher_retry_after(linphone_core_get_sal(lc),1000); counters=&lcm->stat; BC_ASSERT_TRUE(wait_for(lcm->lc,lcm->lc,&counters->number_of_LinphoneRegistrationOk,(int)bctbx_list_size(linphone_core_get_proxy_config_list(lcm->lc)))); @@ -869,18 +918,18 @@ static void io_recv_error_late_recovery(void){ register_ok=counters->number_of_LinphoneRegistrationOk; number_of_udp_proxy=get_number_of_udp_proxy(lc); /*simulate a general socket error*/ - sal_set_recv_error(lc->sal, 0); - sal_set_send_error(lc->sal, -1); + sal_set_recv_error(linphone_core_get_sal(lc), 0); + sal_set_send_error(linphone_core_get_sal(lc), -1); BC_ASSERT_TRUE(wait_for(lc,NULL,&counters->number_of_LinphoneRegistrationProgress,(register_ok-number_of_udp_proxy)+register_ok /*because 1 udp*/)); BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationFailed,(register_ok-number_of_udp_proxy),sal_get_refresher_retry_after(lc->sal)+3000)); + BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationFailed,(register_ok-number_of_udp_proxy),sal_get_refresher_retry_after(linphone_core_get_sal(lc))+3000)); - sal_set_recv_error(lc->sal, 1); /*reset*/ - sal_set_send_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ + sal_set_send_error(linphone_core_get_sal(lc), 0); - BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy +register_ok,sal_get_refresher_retry_after(lc->sal)+3000)); + BC_ASSERT_TRUE(wait_for_list(lcs=bctbx_list_append(NULL,lc),&counters->number_of_LinphoneRegistrationOk,register_ok-number_of_udp_proxy +register_ok,sal_get_refresher_retry_after(linphone_core_get_sal(lc))+3000)); linphone_core_manager_destroy(lcm); } } @@ -910,7 +959,7 @@ static void io_recv_error_without_active_register(void){ /*wait for unregistrations*/ BC_ASSERT_TRUE(wait_for(lc,lc,&counters->number_of_LinphoneRegistrationCleared,register_ok /*because 1 udp*/)); - sal_set_recv_error(lc->sal, 0); + sal_set_recv_error(linphone_core_get_sal(lc), 0); /*nothing should happen because no active registration*/ wait_for_until(lc,lc, &dummy, 1, 3000); @@ -918,7 +967,7 @@ static void io_recv_error_without_active_register(void){ BC_ASSERT_EQUAL(counters->number_of_LinphoneRegistrationFailed,0,int,"%d"); - sal_set_recv_error(lc->sal, 1); /*reset*/ + sal_set_recv_error(linphone_core_get_sal(lc), 1); /*reset*/ linphone_core_manager_destroy(lcm); } @@ -981,11 +1030,11 @@ static void tls_certificate_subject_check(void){ } char *read_file(const char *path) { - long numbytes = 0; + long numbytes = 0; size_t readbytes; char *buffer = NULL; FILE *infile = fopen(path, "rb"); - + BC_ASSERT_PTR_NOT_NULL(infile); if (infile) { fseek(infile, 0L, SEEK_END); @@ -1039,7 +1088,7 @@ static void tls_with_non_tls_server(void){ lcm=linphone_core_manager_new2( "marie_rc", 0); lc=lcm->lc; - sal_set_transport_timeout(lc->sal,3000); + sal_set_transport_timeout(linphone_core_get_sal(lc),3000); proxy_cfg = linphone_core_get_default_proxy_config(lc); linphone_proxy_config_edit(proxy_cfg); addr=linphone_address_new(linphone_proxy_config_get_addr(proxy_cfg)); @@ -1094,7 +1143,7 @@ static void redirect(void){ sprintf(route,"sip:%s:5064",test_route); lcm = create_lcm(); if (lcm) { - transport = linphone_transports_new(); + transport = linphone_factory_create_transports(linphone_factory_get()); linphone_transports_set_udp_port(transport, -1); linphone_core_set_user_agent(lcm->lc,"redirect",NULL); register_with_refresh_base_2(lcm->lc,FALSE,test_domain,route,FALSE,transport); @@ -1110,7 +1159,7 @@ static void tls_auth_global_client_cert(void) { char *cert_path = bc_tester_res("certificates/client/cert.pem"); char *key_path = bc_tester_res("certificates/client/key.pem"); linphone_core_manager_init(manager, "pauline_tls_client_rc", NULL); - lpc = manager->lc->config; + lpc = linphone_core_get_config(manager->lc); lp_config_set_string(lpc, "sip", "client_cert_chain", cert_path); lp_config_set_string(lpc, "sip", "client_cert_key", key_path); linphone_core_manager_start(manager, TRUE); @@ -1162,7 +1211,7 @@ static void tls_auth_info_client_cert_api(void) { char *cert = read_file(cert_path); char *key = read_file(key_path); LinphoneCore *lc = pauline->lc; - LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)lc->auth_info->data; + LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)bctbx_list_get_data(linphone_core_get_auth_info_list(lc)); linphone_auth_info_set_tls_cert(authInfo, cert); linphone_auth_info_set_tls_key(authInfo, key); BC_ASSERT_TRUE(wait_for(lc, lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); @@ -1180,7 +1229,7 @@ static void tls_auth_info_client_cert_api_path(void) { char *cert = bc_tester_res("certificates/client/cert.pem"); char *key = bc_tester_res("certificates/client/key.pem"); LinphoneCore *lc = pauline->lc; - LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)lc->auth_info->data; + LinphoneAuthInfo *authInfo = (LinphoneAuthInfo *)bctbx_list_get_data(linphone_core_get_auth_info_list(lc)); linphone_auth_info_set_tls_cert_path(authInfo, cert); linphone_auth_info_set_tls_key_path(authInfo, key); BC_ASSERT_TRUE(wait_for(lc, lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); @@ -1265,7 +1314,9 @@ static void register_get_gruu(void) { if(cfg) { const LinphoneAddress *addr = linphone_proxy_config_get_contact(cfg); BC_ASSERT_PTR_NOT_NULL(addr); - BC_ASSERT_PTR_NOT_NULL(strstr(linphone_address_as_string_uri_only(addr), "gr")); + char *addrStr = linphone_address_as_string_uri_only(addr); + BC_ASSERT_PTR_NOT_NULL(strstr(addrStr, "gr")); + bctbx_free(addrStr); } linphone_core_manager_destroy(marie); } @@ -1287,10 +1338,7 @@ static void multi_devices_register_with_gruu(void) { linphone_core_set_network_reachable(marie->lc,FALSE); /*to make sure first instance is not unregistered*/ linphone_core_manager_destroy(marie); - marie = ms_new0(LinphoneCoreManager, 1); - linphone_core_manager_init(marie, "marie_rc", NULL); - linphone_core_add_supported_tag(marie->lc,"gruu"); - linphone_core_manager_start(marie,TRUE); + marie=linphone_core_manager_new("marie_rc"); cfg=linphone_core_get_default_proxy_config(marie->lc); if(cfg) { const LinphoneAddress *addr = linphone_proxy_config_get_contact(cfg); @@ -1317,7 +1365,9 @@ test_t register_tests[] = { TEST_NO_TAG("TLS certificate given by string instead of file",tls_certificate_data), TEST_NO_TAG("TLS with non tls server",tls_with_non_tls_server), TEST_NO_TAG("Simple authenticated register", simple_authenticated_register), + TEST_NO_TAG("Simple authenticated register SHA-256", simple_authenticated_register_for_algorithm), TEST_NO_TAG("Ha1 authenticated register", ha1_authenticated_register), + TEST_NO_TAG("Ha1 authenticated register SHA-256", ha1_authenticated_register_for_algorithm), TEST_NO_TAG("Digest auth without initial credentials", authenticated_register_with_no_initial_credentials), TEST_NO_TAG("Digest auth with wrong credentials", authenticated_register_with_wrong_credentials), TEST_NO_TAG("Digest auth with wrong credentials, check if registration attempts are stopped", authenticated_register_with_wrong_credentials_2), @@ -1325,7 +1375,7 @@ test_t register_tests[] = { TEST_NO_TAG("Authenticated register with wrong late credentials", authenticated_register_with_wrong_late_credentials), TEST_NO_TAG("Authenticated register with late credentials", authenticated_register_with_late_credentials), TEST_NO_TAG("Authenticated register with provided credentials", authenticated_register_with_provided_credentials), - TEST_NO_TAG("Authenticated register with provided credentials, username with espace", authenticated_register_with_provided_credentials_and_username_with_espace), + TEST_NO_TAG("Authenticated register with provided credentials, username with space", authenticated_register_with_provided_credentials_and_username_with_space), TEST_NO_TAG("Register with refresh", simple_register_with_refresh), TEST_NO_TAG("Authenticated register with refresh", simple_auth_register_with_refresh), TEST_NO_TAG("Register with refresh and send error", register_with_refresh_with_send_error), diff --git a/tester/remote_provisioning_tester.c b/tester/remote_provisioning_tester.c index 967533780..8aba68be2 100644 --- a/tester/remote_provisioning_tester.c +++ b/tester/remote_provisioning_tester.c @@ -18,8 +18,8 @@ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" void linphone_configuration_status(LinphoneCore *lc, LinphoneConfiguringState status, const char *message) { stats* counters; @@ -89,11 +89,11 @@ static void remote_provisioning_default_values(void) { LinphoneCoreManager* marie = linphone_core_manager_new2("marie_remote_default_values_rc", FALSE); BC_ASSERT_TRUE(wait_for(marie->lc,NULL,&marie->stat.number_of_LinphoneConfiguringSuccessful,1)); lpc = linphone_core_create_proxy_config(marie->lc); - BC_ASSERT_TRUE(lpc->reg_sendregister); - BC_ASSERT_EQUAL(lpc->expires, 604800, int, "%d"); - BC_ASSERT_STRING_EQUAL(lpc->reg_proxy, ""); - BC_ASSERT_STRING_EQUAL(lpc->reg_route, ""); - BC_ASSERT_STRING_EQUAL(lpc->reg_identity, "sip:?@sip.linphone.org"); + BC_ASSERT_TRUE(linphone_proxy_config_register_enabled(lpc)); + BC_ASSERT_EQUAL(linphone_proxy_config_get_expires(lpc), 604800, int, "%d"); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_server_addr(lpc), ""); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_route(lpc), ""); + BC_ASSERT_STRING_EQUAL(linphone_proxy_config_get_identity(lpc), "sip:?@sip.linphone.org"); { LpConfig* lp = linphone_core_get_config(marie->lc); BC_ASSERT_STRING_EQUAL(lp_config_get_string(lp,"app","toto","empty"),"titi"); @@ -119,7 +119,7 @@ static void remote_provisioning_file(void) { { char* path = bc_tester_res("rcfiles/marie_remote_localfile2_rc"); char* abspath = ms_strdup_printf("file://%s", path); - lp_config_set_string(marie->lc->config, "misc", "config-uri", abspath); + lp_config_set_string(linphone_core_get_config(marie->lc), "misc", "config-uri", abspath); linphone_core_manager_start(marie, 1); ms_free(path); ms_free(abspath); diff --git a/tester/setup_tester.c b/tester/setup_tester.c index b1259cb0d..994e24e98 100644 --- a/tester/setup_tester.c +++ b/tester/setup_tester.c @@ -17,10 +17,104 @@ */ -#include "linphone/core.h" #include "liblinphone_tester.h" +#include "linphone/core.h" +#include "linphone/friend.h" +#include "linphone/friendlist.h" #include "linphone/lpconfig.h" -#include "private.h" +#include "linphone/api/c-magic-search.h" +#include "tester_utils.h" + +#ifdef __APPLE__ +#include "TargetConditionals.h" +#endif + +#define S_SIZE_FRIEND 12 +static const unsigned int sSizeFriend = S_SIZE_FRIEND; +static const char *sFriends[S_SIZE_FRIEND] = { + "sip:charu@sip.test.org",//0 + "sip:charette@sip.example.org",//1 + "sip:allo@sip.example.org",//2 + "sip:hello@sip.example.org",//3 + "sip:hello@sip.test.org",//4 + "sip:marie@sip.example.org",//5 + "sip:laura@sip.example.org",//6 + "sip:loic@sip.example.org",//7 + "sip:laure@sip.test.org",//8 + "sip:loic@sip.test.org",//9 + "sip:+111223344@sip.example.org",//10 + "sip:+33655667788@sip.example.org"//11 +}; + +static void _create_friends_from_tab(LinphoneCore *lc, LinphoneFriendList *list, const char *friends[], const unsigned int size) { + unsigned int i; + for (i = 0 ; i < size ; i++) { + LinphoneFriend *fr = linphone_core_create_friend_with_address(lc, friends[i]); + linphone_friend_list_add_friend(list, fr); + } +} + +static void _remove_friends_from_list(LinphoneFriendList *list, const char *friends[], const unsigned int size) { + unsigned int i; + for (i = 0 ; i < size ; i++) { + LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(list, friends[i]); + if (fr) { + linphone_friend_list_remove_friend(list, fr); + linphone_friend_unref(fr); + } + } +} + +static void _check_friend_result_list(LinphoneCore *lc, const bctbx_list_t *resultList, const unsigned int index, const char* uri, const char* phone) { + if (index >= bctbx_list_size(resultList)) { + ms_error("Attempt to access result to an outbound index"); + return; + } + const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, index); + const LinphoneFriend *lf = linphone_search_result_get_friend(sr); + if (lf || linphone_search_result_get_address(sr)) { + const LinphoneAddress *la = (linphone_search_result_get_address(sr)) ? + linphone_search_result_get_address(sr) : linphone_friend_get_address(lf); + if (la) { + char* fa = linphone_address_as_string(la); + BC_ASSERT_STRING_EQUAL(fa , uri); + free(fa); + return; + } else if (phone) { + const LinphonePresenceModel *presence = linphone_friend_get_presence_model_for_uri_or_tel(lf, phone); + if (BC_ASSERT_PTR_NOT_NULL(presence)) { + char *contact = linphone_presence_model_get_contact(presence); + BC_ASSERT_STRING_EQUAL(contact, uri); + free(contact); + return; + } + } + } else { + const bctbx_list_t *callLog = linphone_core_get_call_logs(lc); + const bctbx_list_t *f; + for (f = callLog ; f != NULL ; f = bctbx_list_next(f)) { + LinphoneCallLog *log = (LinphoneCallLog*)(f->data); + const LinphoneAddress *addr = (linphone_call_log_get_dir(log) == LinphoneCallIncoming) ? + linphone_call_log_get_from_address(log) : linphone_call_log_get_to_address(log); + if (addr) { + char *addrUri = linphone_address_as_string_uri_only(addr); + if (addrUri && strcmp(addrUri, uri) == 0) { + bctbx_free(addrUri); + return; + } + if (addrUri) bctbx_free(addrUri); + } + } + } + BC_ASSERT(FALSE); + ms_error("Address NULL and Presence NULL"); +} + +static void _create_call_log(LinphoneCore *lc, LinphoneAddress *addrFrom, LinphoneAddress *addrTo) { + linphone_call_log_unref( + linphone_core_create_call_log(lc, addrFrom, addrTo, LinphoneCallOutgoing, 100, time(NULL), time(NULL), LinphoneCallSuccess, FALSE, 1.0) + ); +} static void linphone_version_test(void){ const char *version=linphone_core_get_version(); @@ -31,7 +125,8 @@ static void linphone_version_test(void){ static void core_init_test(void) { LinphoneCore* lc; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); + /* until we have good certificates on our test server... */ linphone_core_verify_server_certificates(lc,FALSE); if (BC_ASSERT_PTR_NOT_NULL(lc)) { @@ -57,7 +152,7 @@ static void linphone_address_test(void) { static void core_sip_transport_test(void) { LinphoneCore* lc; LCSipTransports tr; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); if (!BC_ASSERT_PTR_NOT_NULL(lc)) return; linphone_core_get_sip_transports(lc,&tr); BC_ASSERT_EQUAL(tr.udp_port,5060, int, "%d"); /*default config*/ @@ -86,7 +181,7 @@ static void linphone_interpret_url_test(void) { LinphoneAddress* address; LinphoneProxyConfig *proxy_config; char *tmp; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); if (!BC_ASSERT_PTR_NOT_NULL( lc )) return; proxy_config =linphone_core_create_proxy_config(lc); @@ -197,7 +292,7 @@ static void linphone_lpconfig_from_xml_zerolen_value(void){ BC_ASSERT_EQUAL(linphone_remote_provisioning_load_file(mgr->lc, xml_path), 0, int, "%d"); - conf = mgr->lc->config; + conf = linphone_core_get_config(mgr->lc); BC_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","zero_len","LOL"),"LOL"); BC_ASSERT_STRING_EQUAL(lp_config_get_string(conf,"test","non_zero_len",""),"test"); @@ -279,7 +374,7 @@ void linphone_proxy_config_is_server_config_changed_test(void) { static void chat_room_test(void) { LinphoneCore* lc; - lc = linphone_factory_create_core(linphone_factory_get(),NULL,NULL,NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(),NULL,NULL,NULL, NULL, system_context); if (!BC_ASSERT_PTR_NOT_NULL(lc)) return; BC_ASSERT_PTR_NOT_NULL(linphone_core_get_chat_room_from_uri(lc,"sip:toto@titi.com")); linphone_core_unref(lc); @@ -402,6 +497,913 @@ static void custom_tones_setup(void){ linphone_core_manager_destroy(mgr); } +static void search_friend_in_alphabetical_order(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + const char *name1SipUri = {"sip:toto@sip.example.org"}; + const char *name2SipUri = {"sip:stephanie@sip.example.org"}; + const char *name3SipUri = {"sip:alber@sip.example.org"}; + const char *name4SipUri = {"sip:gauthier@sip.example.org"}; + const char *name5SipUri = {"sip:gal@sip.example.org"}; + + LinphoneFriend *friend1 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend2 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend3 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend4 = linphone_core_create_friend(manager->lc); + LinphoneFriend *friend5 = linphone_core_create_friend(manager->lc); + + LinphoneVcard *vcard1 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard2 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard3 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard4 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *vcard5 = linphone_factory_create_vcard(linphone_factory_get()); + + const char *name1 = {"STEPHANIE delarue"}; + const char *name2 = {"alias delarue"}; + const char *name3 = {"Alber josh"}; + const char *name4 = {"gauthier wei"}; + const char *name5 = {"gal tcho"}; + + linphone_vcard_set_full_name(vcard1, name1); // STEPHANIE delarue + linphone_vcard_set_url(vcard1, name1SipUri); //sip:toto@sip.example.org + linphone_vcard_add_sip_address(vcard1, name1SipUri); + linphone_friend_set_vcard(friend1, vcard1); + linphone_core_add_friend(manager->lc, friend1); + + linphone_vcard_set_full_name(vcard2, name2); // alias delarue + linphone_vcard_set_url(vcard2, name2SipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(vcard2, name2SipUri); + linphone_friend_set_vcard(friend2, vcard2); + linphone_core_add_friend(manager->lc, friend2); + + linphone_vcard_set_full_name(vcard3, name3); // Alber josh + linphone_vcard_set_url(vcard3, name3SipUri); //sip:alber@sip.example.org + linphone_vcard_add_sip_address(vcard3, name3SipUri); + linphone_friend_set_vcard(friend3, vcard3); + linphone_core_add_friend(manager->lc, friend3); + + linphone_vcard_set_full_name(vcard4, name4); // gauthier wei + linphone_vcard_set_url(vcard4, name4SipUri); //sip:gauthier@sip.example.org + linphone_vcard_add_sip_address(vcard4, name4SipUri); + linphone_friend_set_vcard(friend4, vcard4); + linphone_core_add_friend(manager->lc, friend4); + + linphone_vcard_set_full_name(vcard5, name5); // gal tcho + linphone_vcard_set_url(vcard5, name5SipUri); //sip:gal@sip.example.org + linphone_vcard_add_sip_address(vcard5, name5SipUri); + linphone_friend_set_vcard(friend5, vcard5); + linphone_core_add_friend(manager->lc, friend5); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, name3SipUri, NULL);//"sip:stephanie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, name2SipUri, NULL);//"sip:alber@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, name5SipUri, NULL);//"sip:gal@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, name4SipUri, NULL);//"sip:gauthier@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 4, name1SipUri, NULL);//"sip:toto@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + linphone_friend_list_remove_friend(lfl, friend1); + linphone_friend_list_remove_friend(lfl, friend2); + linphone_friend_list_remove_friend(lfl, friend3); + linphone_friend_list_remove_friend(lfl, friend4); + linphone_friend_list_remove_friend(lfl, friend5); + + if (friend1) linphone_friend_unref(friend1); + if (friend2) linphone_friend_unref(friend2); + if (friend3) linphone_friend_unref(friend3); + if (friend4) linphone_friend_unref(friend4); + if (friend5) linphone_friend_unref(friend5); + + if (vcard1) linphone_vcard_unref(vcard1); + if (vcard2) linphone_vcard_unref(vcard2); + if (vcard3) linphone_vcard_unref(vcard3); + if (vcard4) linphone_vcard_unref(vcard4); + if (vcard5) linphone_vcard_unref(vcard5); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); + +} + +static void search_friend_without_filter(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), S_SIZE_FRIEND, int, "%d"); + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_with_domain_without_filter(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("marie_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *chloeName = "chloe zaya"; + const char *chloeSipUri = "sip:ch@sip.test.org"; + const char *chloePhoneNumber = "0633556644"; + LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc); + LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc); + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(manager->lc); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_set_dial_prefix(proxy, "33"); + linphone_proxy_config_done(proxy); + linphone_core_set_default_proxy(manager->lc, proxy); + + linphone_presence_model_set_contact(chloePresence, chloeSipUri); + linphone_friend_set_name(chloeFriend, chloeName); + linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber); + linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence); + linphone_friend_list_add_friend(lfl, chloeFriend); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "sip.test.org"); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[4], NULL);//"sip:hello@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 3, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 4, sFriends[9], NULL);//"sip:loic@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(lfl, chloeSipUri); + linphone_friend_list_remove_friend(lfl, fr); + + if (chloeFriend) linphone_friend_unref(chloeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_all_domains(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "llo", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 3, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[3], NULL);//"sip:hello@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[4], NULL);//"sip:hello@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_one_domain(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "llo", "sip.example.org"); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[3], NULL);//"sip:hello@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_research_estate(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "l", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 7, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[7], NULL);//"sip:loic@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 3, sFriends[9], NULL);//"sip:loic@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 4, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 5, sFriends[3], NULL);//"sip:hello@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 6, sFriends[4], NULL);//"sip:hello@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "la", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[6], NULL);//"sip:laura@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_research_estate_reset(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "la", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[8], NULL);//"sip:laure@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "l", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 7, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[6], NULL);//"sip:laura@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[7], NULL);//"sip:loic@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[8], NULL);//"sip:laure@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 3, sFriends[9], NULL);//"sip:loic@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 4, sFriends[2], NULL);//"sip:allo@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 5, sFriends[3], NULL);//"sip:hello@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 6, sFriends[4], NULL);//"sip:hello@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_with_phone_number(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + LinphoneFriend *stephanieFriend = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanieVcard = linphone_factory_create_vcard(linphone_factory_get()); + const char* stephanieName = {"stephanie de monaco"}; + const char* mariePhoneNumber = {"0633556644"}; + const char* stephaniePhoneNumber = {"0633889977"}; + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + linphone_vcard_set_full_name(stephanieVcard, stephanieName); // stephanie de monaco + linphone_vcard_add_phone_number(stephanieVcard, stephaniePhoneNumber); + linphone_friend_set_vcard(stephanieFriend, stephanieVcard); + linphone_core_add_friend(manager->lc, stephanieFriend); + + linphone_friend_add_phone_number(linphone_friend_list_find_friend_by_uri(lfl, sFriends[5]), mariePhoneNumber); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", "*"); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 3, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[10], NULL);//"sip:+111223344@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[5], NULL);//"sip:marie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "5", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[5], NULL);//"sip:marie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "55", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[5], NULL);//"sip:marie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "556", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[5], NULL);//"sip:marie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "5566", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[5], NULL);//"sip:marie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "55667", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "55667", "sip.test.org"); + + BC_ASSERT_PTR_NULL(resultList); + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_friend_list_remove_friend(lfl, stephanieFriend); + if (stephanieFriend) linphone_friend_unref(stephanieFriend); + if (stephanieVcard) linphone_vcard_unref(stephanieVcard); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_with_presence(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_create("marie_rc"); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *chloeName = "chloe zaya"; + const char *chloeSipUri = "sip:ch@sip.example.org"; + const char *chloePhoneNumber = "0633556644"; + LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc); + LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc); + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(manager->lc); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_set_dial_prefix(proxy, "33"); + linphone_proxy_config_done(proxy); + linphone_core_set_default_proxy(manager->lc, proxy); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + linphone_presence_model_set_contact(chloePresence, chloeSipUri); + linphone_friend_set_name(chloeFriend, chloeName); + linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber); + linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence); + linphone_friend_list_add_friend(lfl, chloeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "33", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[11], NULL);//"sip:+33655667788@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[10], NULL);//"sip:+111223344@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, "sip:33@sip.example.org", NULL);//"sip:33@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "chloe", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, chloePhoneNumber);//"sip:ch@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, "sip:chloe@sip.example.org", NULL);//"sip:chloe@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(lfl, chloeSipUri); + linphone_friend_list_remove_friend(lfl, fr); + + if (chloeFriend) linphone_friend_unref(chloeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_in_call_log(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *chloeSipUri = {"sip:chloe@sip.example.org"}; + const char *benjaminSipUri = {"sip:benjamin@sip.example.org"}; + const char *charlesSipUri = {"sip:charles@sip.test.org"}; + const char *ronanSipUri = {"sip:ronan@sip.example.org"}; + LinphoneAddress *chloeAddress = linphone_address_new(chloeSipUri); + LinphoneAddress *benjaminAddress = linphone_address_new(benjaminSipUri); + LinphoneAddress *charlesAddress = linphone_address_new(charlesSipUri); + LinphoneAddress *ronanAddress = linphone_address_new(ronanSipUri); + + _create_call_log(manager->lc, ronanAddress, chloeAddress); + _create_call_log(manager->lc, ronanAddress, charlesAddress); + _create_call_log(manager->lc, ronanAddress, benjaminAddress); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "ch", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 4, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[1], NULL);//"sip:charette@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 2, chloeSipUri, NULL);//"sip:chloe@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, charlesSipUri, NULL);//"sip:charles@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "ch", "sip.test.org"); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 1, charlesSipUri, NULL);//"sip:charles@sip.test.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + if (chloeAddress) linphone_address_unref(chloeAddress); + if (benjaminAddress) linphone_address_unref(benjaminAddress); + if (charlesAddress) linphone_address_unref(charlesAddress); + if (ronanAddress) linphone_address_unref(ronanAddress); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_in_call_log_already_exist(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("marie_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *ronanSipUri = {"sip:ronan@sip.example.org"}; + const char *chloeName = "chloe zaya"; + const char *chloeSipUri = "sip:chloe@sip.example.org"; + const char *chloePhoneNumber = "0633556644"; + LinphoneFriend *chloeFriend = linphone_core_create_friend(manager->lc); + LinphonePresenceModel *chloePresence = linphone_core_create_presence_model(manager->lc); + LinphoneProxyConfig *proxy = linphone_core_get_default_proxy_config(manager->lc); + LinphoneAddress *ronanAddress = linphone_address_new(ronanSipUri); + LinphoneAddress *chloeAddress = linphone_address_new(chloeSipUri); + + linphone_proxy_config_edit(proxy); + linphone_proxy_config_set_dial_prefix(proxy, "33"); + linphone_proxy_config_done(proxy); + linphone_core_set_default_proxy(manager->lc, proxy); + + linphone_presence_model_set_contact(chloePresence, chloeSipUri); + linphone_friend_set_name(chloeFriend, chloeName); + linphone_friend_set_address(chloeFriend, chloeAddress); + linphone_friend_add_phone_number(chloeFriend, chloePhoneNumber); + linphone_friend_set_presence_model_for_uri_or_tel(chloeFriend, chloePhoneNumber, chloePresence); + linphone_friend_list_add_friend(lfl, chloeFriend); + + _create_call_log(manager->lc, ronanAddress, chloeAddress); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "ch", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 5, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, chloeSipUri, NULL);//"sip:chloe@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, sFriends[0], NULL);//"sip:charu@sip.test.org" + _check_friend_result_list(manager->lc, resultList, 2, sFriends[1], NULL);//"sip:charette@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 3, "sip:pauline@sip.example.org", NULL);//In the linphonerc "sip:pauline@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 4,"sip:ch@sip.example.org", NULL);//"sip:ch@sip.example.org" + const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, 0); + if (BC_ASSERT_PTR_NOT_NULL(sr)) { + const LinphoneFriend *lf = linphone_search_result_get_friend(sr); + BC_ASSERT_PTR_NOT_NULL(lf); + } + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + LinphoneFriend *fr = linphone_friend_list_find_friend_by_uri(lfl, chloeSipUri); + linphone_friend_list_remove_friend(lfl, fr); + + if (chloeFriend) linphone_friend_unref(chloeFriend); + + if (chloeAddress) linphone_address_unref(chloeAddress); + if (ronanAddress) linphone_address_unref(ronanAddress); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_last_item_is_filter(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_create("marie_rc"); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "newaddress", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d"); + const LinphoneSearchResult *sr = bctbx_list_nth_data(resultList, 0); + if (BC_ASSERT_PTR_NOT_NULL(sr)) { + const LinphoneAddress *srAddress = linphone_search_result_get_address(sr); + if (BC_ASSERT_PTR_NOT_NULL(srAddress)) { + BC_ASSERT_STRING_EQUAL(linphone_address_get_username(srAddress), "newaddress"); + } + } + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_with_name(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *stephanie1SipUri = {"sip:toto@sip.example.org"}; + const char *stephanie2SipUri = {"sip:stephanie@sip.example.org"}; + LinphoneFriend *stephanie1Friend = linphone_core_create_friend(manager->lc); + LinphoneFriend *stephanie2Friend = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanie1Vcard = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *stephanie2Vcard = linphone_factory_create_vcard(linphone_factory_get()); + const char *stephanie1Name = {"stephanie delarue"}; + const char *stephanie2Name = {"alias delarue"}; + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + linphone_vcard_set_full_name(stephanie1Vcard, stephanie1Name); // stephanie delarue + linphone_vcard_set_url(stephanie1Vcard, stephanie1SipUri); //sip:toto@sip.example.org + linphone_vcard_add_sip_address(stephanie1Vcard, stephanie1SipUri); + linphone_friend_set_vcard(stephanie1Friend, stephanie1Vcard); + linphone_core_add_friend(manager->lc, stephanie1Friend); + + linphone_vcard_set_full_name(stephanie2Vcard, stephanie2Name); // alias delarue + linphone_vcard_set_url(stephanie2Vcard, stephanie2SipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(stephanie2Vcard, stephanie2SipUri); + linphone_friend_set_vcard(stephanie2Friend, stephanie2Vcard); + linphone_core_add_friend(manager->lc, stephanie2Friend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "stephanie", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanie1SipUri, NULL);//"sip:toto@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, stephanie2SipUri, NULL);//"sip:stephanie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "delarue", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanie2SipUri, NULL);//"sip:stephanie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, stephanie1SipUri, NULL);//"sip:toto@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + linphone_friend_list_remove_friend(lfl, stephanie1Friend); + linphone_friend_list_remove_friend(lfl, stephanie2Friend); + if (stephanie1Friend) linphone_friend_unref(stephanie1Friend); + if (stephanie2Friend) linphone_friend_unref(stephanie2Friend); + if (stephanie1Vcard) linphone_vcard_unref(stephanie1Vcard); + if (stephanie2Vcard) linphone_vcard_unref(stephanie2Vcard); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_with_name_with_uppercase(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *stephanie1SipUri = {"sip:toto@sip.example.org"}; + const char *stephanie2SipUri = {"sip:stephanie@sip.example.org"}; + LinphoneFriend *stephanie1Friend = linphone_core_create_friend(manager->lc); + LinphoneFriend *stephanie2Friend = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanie1Vcard = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *stephanie2Vcard = linphone_factory_create_vcard(linphone_factory_get()); + const char *stephanie1Name = {"STEPHANIE delarue"}; + const char *stephanie2Name = {"alias delarue"}; + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + linphone_vcard_set_full_name(stephanie1Vcard, stephanie1Name); // STEPHANIE delarue + linphone_vcard_set_url(stephanie1Vcard, stephanie1SipUri); //sip:toto@sip.example.org + linphone_vcard_add_sip_address(stephanie1Vcard, stephanie1SipUri); + linphone_friend_set_vcard(stephanie1Friend, stephanie1Vcard); + linphone_core_add_friend(manager->lc, stephanie1Friend); + + linphone_vcard_set_full_name(stephanie2Vcard, stephanie2Name); // alias delarue + linphone_vcard_set_url(stephanie2Vcard, stephanie2SipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(stephanie2Vcard, stephanie2SipUri); + linphone_friend_set_vcard(stephanie2Friend, stephanie2Vcard); + linphone_core_add_friend(manager->lc, stephanie2Friend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "stephanie", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanie1SipUri, NULL);//"sip:toto@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, stephanie2SipUri, NULL);//"sip:stephanie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + linphone_friend_list_remove_friend(lfl, stephanie1Friend); + linphone_friend_list_remove_friend(lfl, stephanie2Friend); + if (stephanie1Friend) linphone_friend_unref(stephanie1Friend); + if (stephanie2Friend) linphone_friend_unref(stephanie2Friend); + if (stephanie1Vcard) linphone_vcard_unref(stephanie1Vcard); + if (stephanie2Vcard) linphone_vcard_unref(stephanie2Vcard); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_with_multiple_sip_address(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *stephanieSipUri1 = {"sip:toto@sip.example.org"}; + const char *stephanieSipUri2 = {"sip:stephanie@sip.example.org"}; + LinphoneFriend *stephanieFriend = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanieVcard = linphone_factory_create_vcard(linphone_factory_get()); + const char *stephanieName = {"stephanie delarue"}; + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + linphone_vcard_set_full_name(stephanieVcard, stephanieName); // stephanie delarue + linphone_vcard_set_url(stephanieVcard, stephanieSipUri1); //sip:toto@sip.example.org + linphone_vcard_add_sip_address(stephanieVcard, stephanieSipUri1); + linphone_vcard_add_sip_address(stephanieVcard, stephanieSipUri2); + linphone_friend_set_vcard(stephanieFriend, stephanieVcard); + linphone_core_add_friend(manager->lc, stephanieFriend); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "stephanie", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri2, NULL);//"sip:stephanie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, stephanieSipUri1, NULL);//"sip:toto@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "delarue", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 2, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri2, NULL);//"sip:stephanie@sip.example.org" + _check_friend_result_list(manager->lc, resultList, 1, stephanieSipUri1, NULL);//"sip:toto@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + linphone_friend_list_remove_friend(lfl, stephanieFriend); + if (stephanieFriend) linphone_friend_unref(stephanieFriend); + if (stephanieVcard) linphone_vcard_unref(stephanieVcard); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_with_same_address(void) { + LinphoneMagicSearch *magicSearch = NULL; + bctbx_list_t *resultList = NULL; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); + const char *stephanieSipUri = {"sip:stephanie@sip.example.org"}; + LinphoneFriend *stephanieFriend1 = linphone_core_create_friend(manager->lc); + LinphoneFriend *stephanieFriend2 = linphone_core_create_friend(manager->lc); + LinphoneVcard *stephanieVcard1 = linphone_factory_create_vcard(linphone_factory_get()); + LinphoneVcard *stephanieVcard2 = linphone_factory_create_vcard(linphone_factory_get()); + const char *stephanieName = {"stephanie delarue"}; + + _create_friends_from_tab(manager->lc, lfl, sFriends, sSizeFriend); + + linphone_vcard_set_full_name(stephanieVcard1, stephanieName); // stephanie delarue + linphone_vcard_set_url(stephanieVcard1, stephanieSipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(stephanieVcard1, stephanieSipUri); + linphone_friend_set_vcard(stephanieFriend1, stephanieVcard1); + linphone_core_add_friend(manager->lc, stephanieFriend1); + + linphone_vcard_set_full_name(stephanieVcard2, stephanieName); // stephanie delarue + linphone_vcard_set_url(stephanieVcard2, stephanieSipUri); //sip:stephanie@sip.example.org + linphone_vcard_add_sip_address(stephanieVcard2, stephanieSipUri); + linphone_friend_set_vcard(stephanieFriend2, stephanieVcard2); + linphone_core_add_friend(manager->lc, stephanieFriend2); + + magicSearch = linphone_magic_search_new(manager->lc); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "stephanie", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri, NULL);//"sip:stephanie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "delarue", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), 1, int, "%d"); + _check_friend_result_list(manager->lc, resultList, 0, stephanieSipUri, NULL);//"sip:stephanie@sip.example.org" + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", ""); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), S_SIZE_FRIEND+1, int, "%d"); + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + linphone_magic_search_reset_search_cache(magicSearch); + + resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, "", "*"); + + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + BC_ASSERT_EQUAL(bctbx_list_size(resultList), S_SIZE_FRIEND+1, int, "%d"); + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + + _remove_friends_from_list(lfl, sFriends, sSizeFriend); + linphone_friend_list_remove_friend(lfl, stephanieFriend1); + linphone_friend_list_remove_friend(lfl, stephanieFriend2); + if (stephanieFriend1) linphone_friend_unref(stephanieFriend1); + if (stephanieFriend2) linphone_friend_unref(stephanieFriend2); + if (stephanieVcard1) linphone_vcard_unref(stephanieVcard1); + if (stephanieVcard2) linphone_vcard_unref(stephanieVcard2); + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); +} + +static void search_friend_large_database(void) { + char *dbPath = bc_tester_res("db/friends.db"); + char *searchedFriend = "6295103032641994169"; + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + linphone_core_set_friends_database_path(manager->lc, dbPath); + LinphoneMagicSearch *magicSearch = linphone_magic_search_new(manager->lc); + + for (size_t i = 1; i < strlen(searchedFriend) ; i++) { + MSTimeSpec start, current; + char subBuff[20]; + memcpy(subBuff, searchedFriend, i); + subBuff[i] = '\0'; + liblinphone_tester_clock_start(&start); + bctbx_list_t *resultList = linphone_magic_search_get_contact_list_from_filter(magicSearch, subBuff, ""); + if (BC_ASSERT_PTR_NOT_NULL(resultList)) { + long long time; + ms_get_cur_time(¤t); + time = ((current.tv_sec - start.tv_sec) * 1000LL) + ((current.tv_nsec - start.tv_nsec) / 1000000LL); + ms_message("Searching time: %lld ms", time); + BC_ASSERT_LOWER(time, 10000, long long, "%lld"); + ms_message("List size: %zu", bctbx_list_size(resultList)); + bctbx_list_free_with_data(resultList, (bctbx_list_free_func)linphone_magic_search_unref); + } + } + + linphone_magic_search_unref(magicSearch); + linphone_core_manager_destroy(manager); + free(dbPath); +} + + +/*the webrtc AEC implementation is brought to mediastreamer2 by a plugin. + * We finally check here that if the plugin is correctly loaded and the right choice of echo canceller implementation is made*/ +static void echo_canceller_check(void){ + LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); + MSFactory *factory = linphone_core_get_ms_factory(manager->lc); + const char *expected_filter = "MSSpeexEC"; + AudioStream *as = audio_stream_new2(factory, NULL, 43000, 43001); + const char *ec_filter = NULL; + + BC_ASSERT_PTR_NOT_NULL(as); + if (as){ + MSFilter *ecf = as->ec; + BC_ASSERT_PTR_NOT_NULL(ecf); + if (ecf){ + ec_filter = ecf->desc->name; + } + } + BC_ASSERT_PTR_NOT_NULL(ec_filter); + +#if defined(__linux) || (defined(__APPLE__) && !TARGET_OS_IPHONE) || defined(_WIN32) + expected_filter = "MSWebRTCAEC"; +#elif defined(__ANDROID__) + expected_filter = "MSWebRTCAECM"; +#endif + if (ec_filter){ + BC_ASSERT_STRING_EQUAL(ec_filter, expected_filter); + } + audio_stream_stop(as); + linphone_core_manager_destroy(manager); +} + test_t setup_tests[] = { TEST_NO_TAG("Version check", linphone_version_test), TEST_NO_TAG("Linphone Address", linphone_address_test), @@ -413,12 +1415,30 @@ test_t setup_tests[] = { TEST_NO_TAG("LPConfig from buffer", linphone_lpconfig_from_buffer), TEST_NO_TAG("LPConfig zero_len value from buffer", linphone_lpconfig_from_buffer_zerolen_value), TEST_NO_TAG("LPConfig zero_len value from file", linphone_lpconfig_from_file_zerolen_value), - TEST_ONE_TAG("LPConfig zero_len value from XML", linphone_lpconfig_from_xml_zerolen_value, "LeaksMemory"), + TEST_NO_TAG("LPConfig zero_len value from XML", linphone_lpconfig_from_xml_zerolen_value), TEST_NO_TAG("Chat room", chat_room_test), TEST_NO_TAG("Devices reload", devices_reload_test), TEST_NO_TAG("Codec usability", codec_usability_test), TEST_NO_TAG("Codec setup", codec_setup), - TEST_NO_TAG("Custom tones setup", custom_tones_setup) + TEST_NO_TAG("Custom tones setup", custom_tones_setup), + TEST_NO_TAG("Appropriate software echo canceller check", echo_canceller_check), + TEST_ONE_TAG("Return friend list in alphabetical order", search_friend_in_alphabetical_order, "MagicSearch"), + TEST_ONE_TAG("Search friend without filter and domain", search_friend_without_filter, "MagicSearch"), + TEST_ONE_TAG("Search friend with domain and without filter", search_friend_with_domain_without_filter, "MagicSearch"), + TEST_ONE_TAG("Search friend from all domains", search_friend_all_domains, "MagicSearch"), + TEST_ONE_TAG("Search friend from one domain", search_friend_one_domain, "MagicSearch"), + TEST_ONE_TAG("Multiple looking for friends with the same cache", search_friend_research_estate, "MagicSearch"), + TEST_ONE_TAG("Multiple looking for friends with cache resetting", search_friend_research_estate_reset, "MagicSearch"), + TEST_ONE_TAG("Search friend with phone number", search_friend_with_phone_number, "MagicSearch"), + TEST_ONE_TAG("Search friend and find it with its presence", search_friend_with_presence, "MagicSearch"), + TEST_ONE_TAG("Search friend in call log", search_friend_in_call_log, "MagicSearch"), + TEST_ONE_TAG("Search friend in call log but don't add address which already exist", search_friend_in_call_log_already_exist, "MagicSearch"), + TEST_ONE_TAG("Search friend last item is the filter", search_friend_last_item_is_filter, "MagicSearch"), + TEST_ONE_TAG("Search friend with name", search_friend_with_name, "MagicSearch"), + TEST_ONE_TAG("Search friend with uppercase name", search_friend_with_name_with_uppercase, "MagicSearch"), + TEST_ONE_TAG("Search friend with multiple sip address", search_friend_with_multiple_sip_address, "MagicSearch"), + TEST_ONE_TAG("Search friend with same address", search_friend_with_same_address, "MagicSearch"), + TEST_ONE_TAG("Search friend in large friends database", search_friend_large_database, "MagicSearch") }; test_suite_t setup_test_suite = {"Setup", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, diff --git a/tester/stun_tester.c b/tester/stun_tester.c index 4ef4a7726..a4e8ceb07 100644 --- a/tester/stun_tester.c +++ b/tester/stun_tester.c @@ -17,8 +17,8 @@ */ #include "linphone/core.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" #include "mediastreamer2/stun.h" #include "ortp/port.h" @@ -45,53 +45,46 @@ static void linphone_stun_test_encode(void) ms_message("STUN message encoded in %i bytes", (int)len); } -static void linphone_stun_test_grab_ip(void) -{ - +static void linphone_stun_test_grab_ip(void) { LinphoneCoreManager* lc_stun = linphone_core_manager_new2("stun_rc", FALSE); - LinphoneCall dummy_call; int ping_time; int tmp = 0; + char audio_addr[LINPHONE_IPADDR_SIZE] = { 0 }; + char video_addr[LINPHONE_IPADDR_SIZE] = { 0 }; + char text_addr[LINPHONE_IPADDR_SIZE] = { 0 }; + int audio_port = 0; + int video_port = 0; + int text_port = 0; - /*this test verifies the very basic STUN support of liblinphone, which is deprecated. - * It works only in IPv4 mode and there is no plan to make it work over ipv6.*/ - if (liblinphone_tester_ipv4_available()){ + /* This test verifies the very basic STUN support of liblinphone, which is deprecated. + * It works only in IPv4 mode and there is no plan to make it work over ipv6. */ + if (liblinphone_tester_ipv4_available()) goto end; - } linphone_core_enable_ipv6(lc_stun->lc, FALSE); - - memset(&dummy_call, 0, sizeof(LinphoneCall)); - dummy_call.main_audio_stream_index = 0; - dummy_call.main_video_stream_index = 1; - dummy_call.main_text_stream_index = 2; - dummy_call.media_ports[dummy_call.main_audio_stream_index].rtp_port = 7078; - dummy_call.media_ports[dummy_call.main_video_stream_index].rtp_port = 9078; - dummy_call.media_ports[dummy_call.main_text_stream_index].rtp_port = 11078; - + linphone_core_enable_realtime_text(lc_stun->lc, TRUE); linphone_core_set_stun_server(lc_stun->lc, stun_address); BC_ASSERT_STRING_EQUAL(stun_address, linphone_core_get_stun_server(lc_stun->lc)); - wait_for(lc_stun->lc, lc_stun->lc, &tmp, 1); - ping_time = linphone_core_run_stun_tests(lc_stun->lc, &dummy_call); + ping_time = linphone_run_stun_tests(lc_stun->lc, 7078, 9078, 11078, audio_addr, &audio_port, video_addr, &video_port, text_addr, &text_port); BC_ASSERT(ping_time != -1); ms_message("Round trip to STUN: %d ms", ping_time); - BC_ASSERT(dummy_call.ac.addr[0] != '\0'); - BC_ASSERT(dummy_call.ac.port != 0); + BC_ASSERT(audio_addr[0] != '\0'); + BC_ASSERT(audio_port != 0); #ifdef VIDEO_ENABLED - BC_ASSERT(dummy_call.vc.addr[0] != '\0'); - BC_ASSERT(dummy_call.vc.port != 0); + BC_ASSERT(video_addr[0] != '\0'); + BC_ASSERT(video_port != 0); #endif - BC_ASSERT(dummy_call.tc.addr[0] != '\0'); - BC_ASSERT(dummy_call.tc.port != 0); + BC_ASSERT(text_addr[0] != '\0'); + BC_ASSERT(text_port != 0); - ms_message("STUN test result: local audio port maps to %s:%i", dummy_call.ac.addr, dummy_call.ac.port); + ms_message("STUN test result: local audio port maps to %s:%i", audio_addr, audio_port); #ifdef VIDEO_ENABLED - ms_message("STUN test result: local video port maps to %s:%i", dummy_call.vc.addr, dummy_call.vc.port); + ms_message("STUN test result: local video port maps to %s:%i", video_addr, video_port); #endif - ms_message("STUN test result: local text port maps to %s:%i", dummy_call.tc.addr, dummy_call.tc.port); + ms_message("STUN test result: local text port maps to %s:%i", text_addr, text_port); end: linphone_core_manager_destroy(lc_stun); @@ -138,9 +131,9 @@ static void ice_turn_call_base(bool_t video_enabled, bool_t forced_relay, bool_t LinphoneMediaDirection expected_video_dir = LinphoneMediaDirectionInactive; bctbx_list_t *lcs = NULL; - marie = linphone_core_manager_new2("marie_rc", FALSE); + marie = linphone_core_manager_create("marie_rc"); lcs = bctbx_list_append(lcs, marie->lc); - pauline = linphone_core_manager_new2(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc", FALSE); + pauline = linphone_core_manager_create(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); lcs = bctbx_list_append(lcs, pauline->lc); if (ipv6) { @@ -190,9 +183,10 @@ static void ice_turn_call_base(bool_t video_enabled, bool_t forced_relay, bool_t lcall = linphone_core_get_current_call(marie->lc); BC_ASSERT_PTR_NOT_NULL(lcall); if (lcall != NULL) { - BC_ASSERT_PTR_NOT_NULL(lcall->ice_session); - if (lcall->ice_session != NULL) { - IceCheckList *cl = ice_session_check_list(lcall->ice_session, 0); + IceSession *ice_session = linphone_call_get_ice_session(lcall); + BC_ASSERT_PTR_NOT_NULL(ice_session); + if (ice_session != NULL) { + IceCheckList *cl = ice_session_check_list(ice_session, 0); BC_ASSERT_PTR_NOT_NULL(cl); if (cl != NULL) { check_turn_context_statistics(cl->rtp_turn_context, forced_relay); diff --git a/tester/tester.c b/tester/tester.c index b5e906755..86a4d71c9 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -20,30 +20,20 @@ #include #include "linphone/core.h" #include "linphone/logging.h" -#include "private.h" #include "logging-private.h" #include "liblinphone_tester.h" #include - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#ifndef _MSC_VER -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#endif - -#ifdef HAVE_GTK -#include -#endif - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif +#include "tester_utils.h" #if _WIN32 #define unlink _unlink #endif +#ifdef __ANDROID__ +extern jobject system_context; +#else +void *system_context=0; +#endif static int liblinphone_tester_keep_accounts_flag = 0; static bool_t liblinphone_tester_keep_record_files = FALSE; @@ -57,6 +47,7 @@ const MSAudioDiffParams audio_cmp_params = {10,2000}; const char* test_domain="sipopen.example.org"; const char* auth_domain="sip.example.org"; const char* test_username="liblinphone_tester"; +const char* test_sha_username="liblinphone_sha_tester"; const char* test_password="secret"; const char* test_route="sip2.linphone.org"; const char *userhostsfile = "tester_hosts"; @@ -67,6 +58,7 @@ int liblinphonetester_transport_timeout = 9000; /*milliseconds. it is set to suc Thanks to the timeout, it will fallback to IPv4*/ const char *liblinphone_tester_mire_id="Mire: Mire (synthetic moving picture)"; +const char *liblinphone_tester_static_image_id="StaticImage: Static picture"; static void network_reachable(LinphoneCore *lc, bool_t reachable) { stats* counters; @@ -91,31 +83,29 @@ bool_t liblinphone_tester_clock_elapsed(const MSTimeSpec *start, int value_ms){ LinphoneAddress * create_linphone_address(const char * domain) { - return create_linphone_address_with_username(domain,NULL); + return create_linphone_address_for_algo(domain,NULL); } -LinphoneAddress * create_linphone_address_with_username(const char * domain, const char* username) { +LinphoneAddress * create_linphone_address_for_algo(const char * domain, const char* username) { LinphoneAddress *addr = linphone_address_new(NULL); if (!BC_ASSERT_PTR_NOT_NULL(addr)) return NULL; - /* For test purpose, we might use different username */ - if(username) linphone_address_set_username(addr,username); + /* For clients who support different algorithms, their usernames must be differnet for having diffrent forms of password */ + if (username) linphone_address_set_username(addr,username); else linphone_address_set_username(addr,test_username); - if(username) BC_ASSERT_STRING_EQUAL(username,linphone_address_get_username(addr)); - else BC_ASSERT_STRING_EQUAL(test_username,linphone_address_get_username(addr)); - if (!domain) domain= test_route; + if (username) BC_ASSERT_STRING_EQUAL(username, linphone_address_get_username(addr)); + else BC_ASSERT_STRING_EQUAL(test_username, linphone_address_get_username(addr)); + if (!domain) domain = test_route; linphone_address_set_domain(addr,domain); - BC_ASSERT_STRING_EQUAL(domain,linphone_address_get_domain(addr)); + BC_ASSERT_STRING_EQUAL(domain, linphone_address_get_domain(addr)); linphone_address_set_display_name(addr, NULL); linphone_address_set_display_name(addr, "Mr Tester"); - BC_ASSERT_STRING_EQUAL("Mr Tester",linphone_address_get_display_name(addr)); + BC_ASSERT_STRING_EQUAL("Mr Tester", linphone_address_get_display_name(addr)); return addr; } static void auth_info_requested(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); + 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++; } @@ -123,31 +113,32 @@ static void auth_info_requested(LinphoneCore *lc, const char *realm, const char void reset_counters( stats* counters) { if (counters->last_received_chat_message) linphone_chat_message_unref(counters->last_received_chat_message); if (counters->last_received_info_message) linphone_info_message_unref(counters->last_received_info_message); + if (counters->dtmf_list_received) bctbx_free(counters->dtmf_list_received); + memset(counters,0,sizeof(stats)); } -LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, const char* file, void* user_data) { - LinphoneCore* lc; - LpConfig* config = NULL; +LinphoneCore *configure_lc_from(LinphoneCoreCbs *cbs, const char *path, const char *file, void *user_data) { + LinphoneCore *lc; + LinphoneConfig *config = NULL; char *filepath = NULL; char *ringpath = NULL; char *ringbackpath = NULL; char *rootcapath = NULL; char *dnsuserhostspath = NULL; char *nowebcampath = NULL; - char *chatdb = NULL; - if (path==NULL) path="."; + if (!path) + path = "."; if (file){ - filepath = ms_strdup_printf("%s/%s", path, file); - if (ortp_file_exist(filepath) != 0) { + filepath = bctbx_strdup_printf("%s/%s", path, file); + if (bctbx_file_exist(filepath) != 0) { ms_fatal("Could not find file %s in path %s, did you configured resources directory correctly?", file, path); } - config = lp_config_new_with_factory(NULL,filepath); + config = lp_config_new_with_factory(NULL, filepath); } - // setup dynamic-path assets ringpath = ms_strdup_printf("%s/sounds/oldphone.wav",path); ringbackpath = ms_strdup_printf("%s/sounds/ringback.wav", path); @@ -155,43 +146,41 @@ LinphoneCore* configure_lc_from(LinphoneCoreVTable* v_table, const char* path, c rootcapath = ms_strdup_printf("%s/certificates/cn/cafile.pem", path); dnsuserhostspath = userhostsfile[0]=='/' ? ms_strdup(userhostsfile) : ms_strdup_printf("%s/%s", path, userhostsfile); - - if( config != NULL ) { + if (config) { lp_config_set_string(config, "sound", "remote_ring", ringbackpath); lp_config_set_string(config, "sound", "local_ring" , ringpath); lp_config_set_string(config, "sip", "root_ca" , rootcapath); - lc = linphone_core_new_with_config(v_table, config, user_data); + lc = linphone_factory_create_core_with_config_3(linphone_factory_get(), config, system_context); } else { - lc = linphone_core_new(v_table,NULL,(filepath!=NULL&&filepath[0]!='\0') ? filepath : NULL, user_data); - + lc = linphone_factory_create_core_3(linphone_factory_get(), NULL, (filepath && (filepath[0] != '\0')) ? filepath : NULL, system_context); linphone_core_set_ring(lc, ringpath); linphone_core_set_ringback(lc, ringbackpath); linphone_core_set_root_ca(lc,rootcapath); } - chatdb = ms_strdup_printf("%s/messages-%p.db",bc_tester_get_writable_dir_prefix(),lc); + linphone_core_set_user_data(lc, user_data); + if (cbs) + linphone_core_add_callbacks(lc, cbs); linphone_core_enable_ipv6(lc, liblinphonetester_ipv6); linphone_core_set_sip_transport_timeout(lc, liblinphonetester_transport_timeout); - sal_enable_test_features(lc->sal,TRUE); - sal_set_dns_user_hosts_file(lc->sal, dnsuserhostspath); + sal_enable_test_features(linphone_core_get_sal(lc),TRUE); + sal_set_dns_user_hosts_file(linphone_core_get_sal(lc), dnsuserhostspath); #ifdef VIDEO_ENABLED linphone_core_set_static_picture(lc,nowebcampath); #endif - linphone_core_set_chat_database_path(lc, chatdb); - ms_free(ringpath); ms_free(ringbackpath); ms_free(nowebcampath); ms_free(rootcapath); ms_free(dnsuserhostspath); - remove(chatdb); - ms_free(chatdb); - if( filepath ) ms_free(filepath); + if (filepath) + bctbx_free(filepath); - if( config ) lp_config_unref(config); + if (config) + linphone_config_unref(config); return lc; } @@ -220,11 +209,6 @@ bool_t wait_for_list(bctbx_list_t* lcs,int* counter,int value,int timeout_ms) { liblinphone_tester_clock_start(&start); while ((counter==NULL || *counternext) { -#ifdef HAVE_GTK - gdk_threads_enter(); - gtk_main_iteration_do(FALSE); - gdk_threads_leave(); -#endif linphone_core_iterate((LinphoneCore*)(iterator->data)); } #ifdef LINPHONE_WINDOWS_DESKTOP @@ -291,45 +275,11 @@ bool_t transport_supported(LinphoneTransportType transport) { } } -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#ifdef _MSC_VER -#pragma warning(disable : 4996) -#else -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif -void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, const char* phone_alias) { +void linphone_core_manager_configure (LinphoneCoreManager *mgr) { LinphoneImNotifPolicy *im_notif_policy; - char *rc_path = NULL; char *hellopath = bc_tester_res("sounds/hello8000.wav"); - mgr->number_of_bcunit_error_at_creation = bc_get_number_of_failures(); - mgr->v_table.registration_state_changed=registration_state_changed; - mgr->v_table.auth_info_requested=auth_info_requested; - mgr->v_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.is_composing_received=is_composing_received; - mgr->v_table.new_subscription_requested=new_subscription_requested; - mgr->v_table.notify_presence_received=notify_presence_received; - mgr->v_table.notify_presence_received_for_uri_or_tel=notify_presence_received_for_uri_or_tel; - mgr->v_table.transfer_state_changed=linphone_transfer_state_changed; - mgr->v_table.info_received=info_message_received; - mgr->v_table.subscription_state_changed=linphone_subscription_state_change; - mgr->v_table.notify_received=linphone_notify_received; - 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; - mgr->v_table.dtmf_received=dtmf_received; - mgr->v_table.call_stats_updated=call_stats_updated; - - mgr->phone_alias = phone_alias ? ms_strdup(phone_alias) : NULL; - - reset_counters(&mgr->stat); - if (rc_file) rc_path = ms_strdup_printf("rcfiles/%s", rc_file); - mgr->lc=configure_lc_from(&mgr->v_table, bc_tester_get_resource_dir_prefix(), rc_path, mgr); + mgr->lc = configure_lc_from(mgr->cbs, bc_tester_get_resource_dir_prefix(), mgr->rc_path, mgr); linphone_core_manager_check_accounts(mgr); im_notif_policy = linphone_core_get_im_notif_policy(mgr->lc); if (im_notif_policy != NULL) { @@ -339,8 +289,6 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, c linphone_im_notif_policy_set_recv_is_composing(im_notif_policy, TRUE); } - manager_count++; - #if TARGET_OS_IPHONE linphone_core_set_ringer_device( mgr->lc, "AQ: Audio Queue Device"); linphone_core_set_ringback(mgr->lc, NULL); @@ -352,13 +300,13 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, c { MSWebCam *cam; - cam = ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(mgr->lc->factory), "Mire: Mire (synthetic moving picture)"); + cam = ms_web_cam_manager_get_cam(ms_factory_get_web_cam_manager(linphone_core_get_ms_factory(mgr->lc)), "Mire: Mire (synthetic moving picture)"); if (cam == NULL) { MSWebCamDesc *desc = ms_mire_webcam_desc_get(); if (desc){ cam=ms_web_cam_new(desc); - ms_web_cam_manager_add_cam(ms_factory_get_web_cam_manager(mgr->lc->factory), cam); + ms_web_cam_manager_add_cam(ms_factory_get_web_cam_manager(linphone_core_get_ms_factory(mgr->lc)), cam); } } } @@ -370,7 +318,7 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, c if( manager_count >= 2){ char *recordpath = ms_strdup_printf("%s/record_for_lc_%p.wav",bc_tester_get_writable_dir_prefix(),mgr->lc); - ms_message("Manager for '%s' using files", rc_file ? rc_file : "--"); + ms_message("Manager for '%s' using files", mgr->rc_path ? mgr->rc_path : "--"); linphone_core_set_use_files(mgr->lc, TRUE); linphone_core_set_record_file(mgr->lc,recordpath); ms_free(recordpath); @@ -378,18 +326,72 @@ void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, c linphone_core_set_user_certificates_path(mgr->lc,bc_tester_get_writable_dir_prefix()); /*for now, we need the periodical updates facility to compute bandwidth measurements correctly during tests*/ - lp_config_set_int(linphone_core_get_config(mgr->lc), "misc", "send_call_stats_periodical_updates", 1); + linphone_core_enable_send_call_stats_periodical_updates(mgr->lc, TRUE); - if (rc_path) ms_free(rc_path); + LinphoneConfig *config = linphone_core_get_config(mgr->lc); + linphone_config_set_string(config, "storage", "backend", "sqlite3"); + linphone_config_set_string(config, "storage", "uri", mgr->database_path); +} + +static void generate_random_database_path (LinphoneCoreManager *mgr) { + char random_id[32]; + belle_sip_random_token(random_id, sizeof random_id); + char *database_path_format = bctbx_strdup_printf("linphone_%s.db", random_id); + mgr->database_path = bc_tester_file(database_path_format); + bctbx_free(database_path_format); +} + +#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) +#pragma GCC diagnostic push +#endif +#ifdef _MSC_VER +#pragma warning(disable : 4996) +#else +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif +void linphone_core_manager_init(LinphoneCoreManager *mgr, const char* rc_file, const char* phone_alias) { + mgr->number_of_bcunit_error_at_creation = bc_get_number_of_failures(); + mgr->cbs = linphone_factory_create_core_cbs(linphone_factory_get()); + linphone_core_cbs_set_registration_state_changed(mgr->cbs, registration_state_changed); + linphone_core_cbs_set_auth_info_requested(mgr->cbs, auth_info_requested); + linphone_core_cbs_set_call_state_changed(mgr->cbs, call_state_changed); + linphone_core_cbs_set_message_received(mgr->cbs, message_received); + linphone_core_cbs_set_is_composing_received(mgr->cbs, is_composing_received); + linphone_core_cbs_set_new_subscription_requested(mgr->cbs, new_subscription_requested); + linphone_core_cbs_set_notify_presence_received(mgr->cbs, notify_presence_received); + linphone_core_cbs_set_notify_presence_received_for_uri_or_tel(mgr->cbs, notify_presence_received_for_uri_or_tel); + linphone_core_cbs_set_transfer_state_changed(mgr->cbs, linphone_transfer_state_changed); + linphone_core_cbs_set_info_received(mgr->cbs, info_message_received); + linphone_core_cbs_set_subscription_state_changed(mgr->cbs, linphone_subscription_state_change); + linphone_core_cbs_set_notify_received(mgr->cbs, linphone_notify_received); + linphone_core_cbs_set_subscribe_received(mgr->cbs, linphone_subscribe_received); + linphone_core_cbs_set_publish_state_changed(mgr->cbs, linphone_publish_state_changed); + linphone_core_cbs_set_configuring_status(mgr->cbs, linphone_configuration_status); + linphone_core_cbs_set_call_encryption_changed(mgr->cbs, linphone_call_encryption_changed); + linphone_core_cbs_set_network_reachable(mgr->cbs, network_reachable); + linphone_core_cbs_set_dtmf_received(mgr->cbs, dtmf_received); + linphone_core_cbs_set_call_stats_updated(mgr->cbs, call_stats_updated); + + mgr->phone_alias = phone_alias ? ms_strdup(phone_alias) : NULL; + + reset_counters(&mgr->stat); + if (rc_file) mgr->rc_path = ms_strdup_printf("rcfiles/%s", rc_file); + + manager_count++; + + generate_random_database_path(mgr); + linphone_core_manager_configure(mgr); } #if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) #pragma GCC diagnostic pop #endif -void linphone_core_manager_start(LinphoneCoreManager *mgr, int check_for_proxies) { +void linphone_core_manager_start(LinphoneCoreManager *mgr, bool_t check_for_proxies) { LinphoneProxyConfig* proxy; int proxy_count; + linphone_core_start(mgr->lc); + /*BC_ASSERT_EQUAL(bctbx_list_size(linphone_core_get_proxy_config_list(lc)),proxy_count, int, "%d");*/ if (check_for_proxies){ /**/ proxy_count=(int)bctbx_list_size(linphone_core_get_proxy_config_list(mgr->lc)); @@ -427,6 +429,16 @@ void linphone_core_manager_start(LinphoneCoreManager *mgr, int check_for_proxies } +LinphoneCoreManager* linphone_core_manager_create2(const char* rc_file, const char* phone_alias) { + LinphoneCoreManager *manager = ms_new0(LinphoneCoreManager, 1); + linphone_core_manager_init(manager, rc_file, phone_alias); + return manager; +} + +LinphoneCoreManager* linphone_core_manager_create(const char* rc_file) { + return linphone_core_manager_create2(rc_file, NULL); +} + LinphoneCoreManager* linphone_core_manager_new4(const char* rc_file, int check_for_proxies, const char* phone_alias, const char* contact_params, int expires) { /* This function is for testing purposes. */ LinphoneCoreManager *manager = ms_new0(LinphoneCoreManager, 1); @@ -438,15 +450,13 @@ LinphoneCoreManager* linphone_core_manager_new4(const char* rc_file, int check_f return manager; } -LinphoneCoreManager* linphone_core_manager_new3(const char* rc_file, int check_for_proxies, const char* phone_alias) { - LinphoneCoreManager *manager = ms_new0(LinphoneCoreManager, 1); - - linphone_core_manager_init(manager, rc_file, phone_alias); +LinphoneCoreManager* linphone_core_manager_new3(const char* rc_file, bool_t check_for_proxies, const char* phone_alias) { + LinphoneCoreManager *manager = linphone_core_manager_create2(rc_file, phone_alias); linphone_core_manager_start(manager, check_for_proxies); return manager; } -LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, int check_for_proxies) { +LinphoneCoreManager* linphone_core_manager_new2(const char* rc_file, bool_t check_for_proxies) { return linphone_core_manager_new3(rc_file, check_for_proxies, NULL); } @@ -458,7 +468,6 @@ LinphoneCoreManager* linphone_core_manager_new( const char* rc_file) { void linphone_core_manager_stop(LinphoneCoreManager *mgr){ if (mgr->lc) { const char *record_file = linphone_core_get_record_file(mgr->lc); - char *chatdb = ms_strdup(linphone_core_get_chat_database_path(mgr->lc)); if (!liblinphone_tester_keep_record_files && record_file && ortp_file_exist(record_file)==0) { if ((bc_get_number_of_failures() - mgr->number_of_bcunit_error_at_creation)>0) { ms_error("Test has failed, keeping recorded file [%s]", record_file); @@ -468,31 +477,50 @@ void linphone_core_manager_stop(LinphoneCoreManager *mgr){ } } linphone_core_unref(mgr->lc); - if (chatdb) { - if (ortp_file_exist(chatdb)==0) { - if (unlink(chatdb) != 0){ - ms_error("Could not delete %s: %s", chatdb, strerror(errno)); - } - } - ms_free(chatdb); - } mgr->lc = NULL; } } +void linphone_core_manager_reinit(LinphoneCoreManager *mgr) { + char *uuid = NULL; + if (mgr->lc) { + if (lp_config_get_string(linphone_core_get_config(mgr->lc), "misc", "uuid", NULL)) + uuid = bctbx_strdup(lp_config_get_string(linphone_core_get_config(mgr->lc), "misc", "uuid", NULL)); + linphone_core_unref(mgr->lc); + } + linphone_core_manager_configure(mgr); + reset_counters(&mgr->stat); + // Make sure gruu is preserved + lp_config_set_string(linphone_core_get_config(mgr->lc), "misc", "uuid", uuid); + if (uuid) + bctbx_free(uuid); +} + +void linphone_core_manager_restart(LinphoneCoreManager *mgr, bool_t check_for_proxies) { + linphone_core_manager_reinit(mgr); + linphone_core_manager_start(mgr, check_for_proxies); +} + void linphone_core_manager_uninit(LinphoneCoreManager *mgr) { int old_log_level = linphone_core_get_log_level_mask(); linphone_core_set_log_level(ORTP_ERROR); if (mgr->phone_alias) { ms_free(mgr->phone_alias); } - if (mgr->stat.last_received_chat_message) { - linphone_chat_message_unref(mgr->stat.last_received_chat_message); - } - if (mgr->stat.last_received_info_message) linphone_info_message_unref(mgr->stat.last_received_info_message); if (mgr->identity) { linphone_address_unref(mgr->identity); } + if (mgr->rc_path) + bctbx_free(mgr->rc_path); + if (mgr->database_path) { + unlink(mgr->database_path); + bctbx_free(mgr->database_path); + } + + if (mgr->cbs) + linphone_core_cbs_unref(mgr->cbs); + + reset_counters(&mgr->stat); manager_count--; linphone_core_set_log_level_mask(old_log_level); @@ -509,11 +537,22 @@ void linphone_core_manager_wait_for_stun_resolution(LinphoneCoreManager *mgr) { } void linphone_core_manager_destroy(LinphoneCoreManager* mgr) { + if (mgr->lc && !linphone_core_is_network_reachable(mgr->lc)) { + int previousNbRegistrationOk = mgr->stat.number_of_LinphoneRegistrationOk; + linphone_core_set_network_reachable(mgr->lc, TRUE); + wait_for_until(mgr->lc, NULL, &mgr->stat.number_of_LinphoneRegistrationOk, previousNbRegistrationOk + 1, 2000); + } linphone_core_manager_stop(mgr); linphone_core_manager_uninit(mgr); ms_free(mgr); } +void linphone_core_manager_delete_chat_room (LinphoneCoreManager *mgr, LinphoneChatRoom *cr, bctbx_list_t *coresList) { + stats mgrStats = mgr->stat; + linphone_core_delete_chat_room(mgr->lc, cr); + BC_ASSERT_TRUE(wait_for_list(coresList, &mgr->stat.number_of_LinphoneChatRoomStateDeleted, mgrStats.number_of_LinphoneChatRoomStateDeleted + 1, 10000)); +} + int liblinphone_tester_ipv6_available(void){ if (liblinphonetester_ipv6) { struct addrinfo *ai=bctbx_ip_address_to_addrinfo(AF_INET6,SOCK_STREAM,"2a01:e00::2",53); @@ -584,11 +623,10 @@ void liblinphone_tester_add_suites() { bc_tester_add_suite(&presence_test_suite); bc_tester_add_suite(&presence_server_test_suite); bc_tester_add_suite(&account_creator_test_suite); -#ifdef UPNP - bc_tester_add_suite(&upnp_test_suite); -#endif bc_tester_add_suite(&stun_test_suite); bc_tester_add_suite(&event_test_suite); + bc_tester_add_suite(&conference_event_test_suite); + bc_tester_add_suite(&contents_test_suite); bc_tester_add_suite(&flexisip_test_suite); bc_tester_add_suite(&remote_provisioning_test_suite); bc_tester_add_suite(&quality_reporting_test_suite); @@ -596,9 +634,13 @@ void liblinphone_tester_add_suites() { bc_tester_add_suite(&player_test_suite); bc_tester_add_suite(&dtmf_test_suite); bc_tester_add_suite(&cpim_test_suite); -#if defined(VIDEO_ENABLED) && defined(HAVE_GTK) - bc_tester_add_suite(&video_test_suite); -#endif + bc_tester_add_suite(&multipart_test_suite); + bc_tester_add_suite(&clonable_object_test_suite); + bc_tester_add_suite(&main_db_test_suite); + bc_tester_add_suite(&property_container_test_suite); + #ifdef VIDEO_ENABLED + bc_tester_add_suite(&video_test_suite); + #endif // ifdef VIDEO_ENABLED bc_tester_add_suite(&multicast_call_test_suite); bc_tester_add_suite(&proxy_config_test_suite); #if HAVE_SIPP @@ -607,6 +649,7 @@ void liblinphone_tester_add_suites() { #ifdef VCARD_ENABLED bc_tester_add_suite(&vcard_test_suite); #endif + bc_tester_add_suite(&group_chat_test_suite); } static int linphone_core_manager_get_max_audio_bw_base(const int array[],int array_size) { @@ -705,13 +748,13 @@ static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStrea LinphoneCallStats *stats; switch (stream_type) { case LinphoneStreamTypeAudio: - ms=&c1->audiostream->ms; + ms=linphone_call_get_stream(c1, LinphoneStreamTypeAudio); break; case LinphoneStreamTypeVideo: - ms=&c1->videostream->ms; + ms=linphone_call_get_stream(c1, LinphoneStreamTypeVideo); break; case LinphoneStreamTypeText: - ms=&c1->textstream->ms; + ms=linphone_call_get_stream(c1, LinphoneStreamTypeText); break; default: ms_error("Unknown stream type [%s]", linphone_stream_type_to_string(stream_type)); @@ -720,25 +763,27 @@ static void check_ice_from_rtp(LinphoneCall *c1, LinphoneCall *c2, LinphoneStrea } stats = linphone_call_get_audio_stats(c1); - if (stats->ice_state == LinphoneIceStateHostConnection && media_stream_started(ms)) { + if (linphone_call_stats_get_ice_state(stats) == LinphoneIceStateHostConnection && media_stream_started(ms)) { struct sockaddr_storage remaddr; socklen_t remaddrlen = sizeof(remaddr); char ip[NI_MAXHOST] = { 0 }; int port = 0; SalMediaDescription *result_desc; char *expected_addr = NULL; + AudioStream *astream; const LinphoneCallParams *cp1 = linphone_call_get_current_params(c1); const LinphoneCallParams *cp2 = linphone_call_get_current_params(c2); - if (cp1->update_call_when_ice_completed && cp2->update_call_when_ice_completed) { + if (linphone_call_params_get_update_call_when_ice_completed(cp1) && linphone_call_params_get_update_call_when_ice_completed(cp2)) { memset(&remaddr, 0, remaddrlen); - result_desc = sal_call_get_final_media_description(c2->op); + result_desc = sal_call_get_final_media_description(linphone_call_get_op_as_sal_op(c2)); expected_addr = result_desc->streams[0].rtp_addr; if (expected_addr[0] == '\0') expected_addr = result_desc->addr; - if ((strchr(expected_addr, ':') == NULL) && (c1->audiostream->ms.sessions.rtp_session->rtp.gs.rem_addr.ss_family == AF_INET6)) { - bctbx_sockaddr_ipv6_to_ipv4((struct sockaddr *)&c1->audiostream->ms.sessions.rtp_session->rtp.gs.rem_addr, (struct sockaddr *)&remaddr, &remaddrlen); + astream = (AudioStream *)linphone_call_get_stream(c1, LinphoneStreamTypeAudio); + if ((strchr(expected_addr, ':') == NULL) && (astream->ms.sessions.rtp_session->rtp.gs.rem_addr.ss_family == AF_INET6)) { + bctbx_sockaddr_ipv6_to_ipv4((struct sockaddr *)&astream->ms.sessions.rtp_session->rtp.gs.rem_addr, (struct sockaddr *)&remaddr, &remaddrlen); } else { - memcpy(&remaddr, &c1->audiostream->ms.sessions.rtp_session->rtp.gs.rem_addr, c1->audiostream->ms.sessions.rtp_session->rtp.gs.rem_addrlen); + memcpy(&remaddr, &astream->ms.sessions.rtp_session->rtp.gs.rem_addr, astream->ms.sessions.rtp_session->rtp.gs.rem_addrlen); } bctbx_sockaddr_to_ip_address((struct sockaddr *)&remaddr, remaddrlen, ip, sizeof(ip), &port); @@ -773,68 +818,89 @@ bool_t check_ice(LinphoneCoreManager* caller, LinphoneCoreManager* callee, Linph realtime_text_enabled=linphone_call_params_realtime_text_enabled(linphone_call_get_current_params(c1)); if (audio_enabled) { liblinphone_tester_clock_start(&ts); - do{ + LinphoneCallStats *stats1 = NULL; + LinphoneCallStats *stats2 = NULL; + do { if ((c1 != NULL) && (c2 != NULL)) { - LinphoneCallStats *stats1 = linphone_call_get_audio_stats(c1); - LinphoneCallStats *stats2 = linphone_call_get_audio_stats(c2); - if (stats1->ice_state==state && - stats2->ice_state==state){ + stats1 = linphone_call_get_audio_stats(c1); + stats2 = linphone_call_get_audio_stats(c2); + if (linphone_call_stats_get_ice_state(stats1)==state && + linphone_call_stats_get_ice_state(stats2)==state){ audio_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeAudio); check_ice_from_rtp(c2,c1,LinphoneStreamTypeAudio); break; } - linphone_call_stats_unref(stats1); - linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); + stats1 = stats2 = NULL; } ms_usleep(20000); - }while(!liblinphone_tester_clock_elapsed(&ts,10000)); + } while (!liblinphone_tester_clock_elapsed(&ts,10000)); + if (stats1) + linphone_call_stats_unref(stats1); + if (stats2) + linphone_call_stats_unref(stats2); } if (video_enabled){ liblinphone_tester_clock_start(&ts); - do{ + LinphoneCallStats *stats1 = NULL; + LinphoneCallStats *stats2 = NULL; + do { if ((c1 != NULL) && (c2 != NULL)) { - LinphoneCallStats *stats1 = linphone_call_get_video_stats(c1); - LinphoneCallStats *stats2 = linphone_call_get_video_stats(c2); - if (stats1->ice_state==state && - stats2->ice_state==state){ + stats1 = linphone_call_get_video_stats(c1); + stats2 = linphone_call_get_video_stats(c2); + if (linphone_call_stats_get_ice_state(stats1)==state && + linphone_call_stats_get_ice_state(stats2)==state){ video_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeVideo); check_ice_from_rtp(c2,c1,LinphoneStreamTypeVideo); break; } - linphone_call_stats_unref(stats1); - linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); + stats1 = stats2 = NULL; } ms_usleep(20000); - }while(!liblinphone_tester_clock_elapsed(&ts,10000)); + } while (!liblinphone_tester_clock_elapsed(&ts,10000)); + if (stats1) + linphone_call_stats_unref(stats1); + if (stats2) + linphone_call_stats_unref(stats2); } if (realtime_text_enabled){ liblinphone_tester_clock_start(&ts); - do{ + LinphoneCallStats *stats1 = NULL; + LinphoneCallStats *stats2 = NULL; + do { if ((c1 != NULL) && (c2 != NULL)) { - LinphoneCallStats *stats1 = linphone_call_get_text_stats(c1); - LinphoneCallStats *stats2 = linphone_call_get_text_stats(c2); - if (stats1->ice_state==state && - stats2->ice_state==state){ + stats1 = linphone_call_get_text_stats(c1); + stats2 = linphone_call_get_text_stats(c2); + if (linphone_call_stats_get_ice_state(stats1)==state && + linphone_call_stats_get_ice_state(stats2)==state){ text_success=TRUE; check_ice_from_rtp(c1,c2,LinphoneStreamTypeText); check_ice_from_rtp(c2,c1,LinphoneStreamTypeText); break; } - linphone_call_stats_unref(stats1); - linphone_call_stats_unref(stats2); linphone_core_iterate(caller->lc); linphone_core_iterate(callee->lc); + linphone_call_stats_unref(stats1); + linphone_call_stats_unref(stats2); + stats1 = stats2 = NULL; } ms_usleep(20000); - }while(!liblinphone_tester_clock_elapsed(&ts,10000)); + } while (!liblinphone_tester_clock_elapsed(&ts,10000)); + if (stats1) + linphone_call_stats_unref(stats1); + if (stats2) + linphone_call_stats_unref(stats2); } /*make sure encryption mode are preserved*/ @@ -902,10 +968,12 @@ static void linphone_conference_server_refer_received(LinphoneCore *core, const linphone_address_unref(refer_to_addr); } -static void linphone_conference_server_registration_state_changed(LinphoneCore *core, - LinphoneProxyConfig *cfg, - LinphoneRegistrationState cstate, - const char *message) { +static void linphone_conference_server_registration_state_changed( + LinphoneCore *core, + LinphoneProxyConfig *cfg, + LinphoneRegistrationState cstate, + const char *message +) { LinphoneCoreCbs *cbs = linphone_core_get_current_callbacks(core); LinphoneConferenceServer *m = (LinphoneConferenceServer *)linphone_core_cbs_get_user_data(cbs); if(cfg == linphone_core_get_default_proxy_config(core)) { diff --git a/tester/tester_hosts b/tester/tester_hosts index 686c42b88..6cbe9b3e2 100644 --- a/tester/tester_hosts +++ b/tester/tester_hosts @@ -1,4 +1,4 @@ -94.23.19.176 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org sipv4.example.org -2001:41d0:2:14b0::1 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org +54.37.202.228 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org sipv4.example.org +2001:41d0:700:789::2010 sip2.linphone.org sip.example.org sipopen.example.org auth.example.org auth1.example.org auth2.example.org altname.linphone.org sip.wildcard1.linphone.org altname.wildcard2.linphone.org 188.165.46.90 tunnel.wildcard2.linphone.org -64:ff9b::94.23.19.176 sipv4-nat64.example.org +64:ff9b::54.37.202.228 sipv4-nat64.example.org diff --git a/tester/tools/private-access.h b/tester/tools/private-access.h new file mode 100644 index 000000000..6f49adc09 --- /dev/null +++ b/tester/tools/private-access.h @@ -0,0 +1,63 @@ +/* + * private-access.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +// ============================================================================= +// Tools to get/set private data of Cpp objects. +// +// See: https://bloglitb.blogspot.fr/2011/12/access-to-private-members-safer.html +// See: http://en.cppreference.com/w/cpp/language/adl +// See: http://en.cppreference.com/w/cpp/language/friend +// ============================================================================= + +#ifndef _L_PRIVATE_ACCESS_H_ +#define _L_PRIVATE_ACCESS_H_ + +#include + +#include "linphone/utils/utils.h" + +#define L_INTERNAL_STRUCT_L_ATTR_GET(CLASS, ATTR_NAME) AttrGet ## _ ## CLASS ## _ ## ATTR_NAME +#define L_INTERNAL_STRUCT_ATTR_SPY(ATTR_NAME) AttrSpy ## _ ## ATTR_NAME + +#define L_ENABLE_ATTR_ACCESS(CLASS, ATTR_TYPE, ATTR_NAME) \ + template \ + struct L_INTERNAL_STRUCT_L_ATTR_GET(CLASS, ATTR_NAME) { \ + friend constexpr ATTR_TYPE CLASS::*get(AttrSpy *) { \ + return Attr; \ + } \ + }; \ + template \ + struct L_INTERNAL_STRUCT_ATTR_SPY(ATTR_NAME); \ + template<> \ + struct L_INTERNAL_STRUCT_ATTR_SPY(ATTR_NAME) { \ + friend constexpr ATTR_TYPE CLASS::*get(L_INTERNAL_STRUCT_ATTR_SPY(ATTR_NAME) *); \ + }; \ + template struct L_INTERNAL_STRUCT_L_ATTR_GET(CLASS, ATTR_NAME)< \ + L_INTERNAL_STRUCT_ATTR_SPY(ATTR_NAME), \ + &CLASS::ATTR_NAME \ + >; + +// Warning: Allow to modify const data. +// Returns a ref to `ATTR_NAME`. +#define L_ATTR_GET(OBJECT, ATTR_NAME) \ + (const_cast::type>::type *>(LinphonePrivate::Utils::getPtr(OBJECT)))->*get( \ + static_cast::type>::type> *>(nullptr) \ + ) + +#endif // ifndef _L_PRIVATE_ACCESS_H_ diff --git a/tester/tools/tester.h b/tester/tools/tester.h new file mode 100644 index 000000000..6c04045af --- /dev/null +++ b/tester/tools/tester.h @@ -0,0 +1,57 @@ +/* + * tester.h + * Copyright (C) 2010-2018 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _L_TESTER_H_ +#define _L_TESTER_H_ + +#include + +#include "linphone/utils/utils.h" + +// ============================================================================= + +// ----------------------------------------------------------------------------- +// Internal. +// ----------------------------------------------------------------------------- + +LINPHONE_BEGIN_NAMESPACE + +class Tester { +public: + Tester () = delete; + + template + static constexpr decltype(std::declval().getPrivate()) getPrivate (T *object) { + return object->getPrivate(); + } + +private: + L_DISABLE_COPY(Tester); +}; + +LINPHONE_END_NAMESPACE + +// ----------------------------------------------------------------------------- +// Public. +// ----------------------------------------------------------------------------- + +#define L_GET_PRIVATE(OBJECT) \ + LinphonePrivate::Tester::getPrivate(LinphonePrivate::Utils::getPtr(OBJECT)) + +#endif // ifndef _L_TESTER_H_ diff --git a/tester/tunnel_tester.c b/tester/tunnel_tester.c index 19cb9f5ed..ac66c4591 100644 --- a/tester/tunnel_tester.c +++ b/tester/tunnel_tester.c @@ -20,8 +20,8 @@ #include #include "linphone/core.h" #include "linphone/lpconfig.h" -#include "private.h" #include "liblinphone_tester.h" +#include "tester_utils.h" /* Retrieve the public IP from a given hostname */ int get_ip_from_hostname(const char * tunnel_hostname, char *ip, size_t ip_size){ @@ -60,7 +60,7 @@ static void call_with_tunnel_base(LinphoneTunnelMode tunnel_mode, bool_t with_si BC_ASSERT_FALSE(get_ip_from_hostname("tunnel.linphone.org",tunnel_ip,sizeof(tunnel_ip))); linphone_core_remove_supported_tag(pauline->lc,"gruu"); /*with gruu, we have no access to the "public IP from contact*/ linphone_core_remove_supported_tag(marie->lc,"gruu"); - + BC_ASSERT_TRUE(wait_for(pauline->lc,NULL,&pauline->stat.number_of_LinphoneRegistrationOk,1)); public_ip = get_public_contact_ip(pauline->lc); BC_ASSERT_STRING_NOT_EQUAL(public_ip, tunnel_ip); @@ -264,7 +264,7 @@ static void register_on_second_tunnel(void) { LinphoneTunnelConfig *config2 = linphone_tunnel_config_new(); char tunnel_ip[64]; char* public_ip; - + BC_ASSERT_FALSE(get_ip_from_hostname("tunnel.linphone.org",tunnel_ip,sizeof(tunnel_ip))); linphone_tunnel_simulate_udp_loss(tunnel, TRUE); diff --git a/tester/upnp_tester.c b/tester/upnp_tester.c deleted file mode 100644 index afae29acf..000000000 --- a/tester/upnp_tester.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - liblinphone_tester - liblinphone test suite - Copyright (C) 2013 Belledonne Communications SARL - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#include "linphone/core.h" -#include "linphone/lpconfig.h" -#include "private.h" -#include "liblinphone_tester.h" - -static void upnp_start_n_stop(void) { - int tmp = 0; - LinphoneCoreManager* lc_upnp = linphone_core_manager_new2( "upnp_rc", FALSE); - wait_for(lc_upnp->lc,lc_upnp->lc,&tmp,1); -#ifdef BUILD_UPNP - BC_ASSERT_PTR_NOT_NULL(lc_upnp->lc->upnp); -#endif - linphone_core_manager_destroy(lc_upnp); -} - -static void upnp_check_state(void) { - int tmp = 0; - LinphoneCoreManager* lc_upnp = linphone_core_manager_new2( "upnp_rc", FALSE); - wait_for(lc_upnp->lc,lc_upnp->lc,&tmp,1); - BC_ASSERT_EQUAL(linphone_core_get_upnp_state(lc_upnp->lc), LinphoneUpnpStateOk, int, "%d"); - linphone_core_manager_destroy(lc_upnp); -} - -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); - addr = linphone_core_get_upnp_external_ipaddress(lc_upnp->lc); - BC_ASSERT_PTR_NOT_NULL(addr); - if (addr!=NULL) { - BC_ASSERT_GREATER((int)strlen(addr),7,int,"%d"); - } - linphone_core_manager_destroy(lc_upnp); -} - -test_t upnp_tests[] = { - TEST_NO_TAG("Start and stop", upnp_start_n_stop), - TEST_NO_TAG("Check state", upnp_check_state), - TEST_NO_TAG("Check ip address", upnp_check_ipaddress) -}; - -test_suite_t upnp_test_suite = {"Upnp", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(upnp_tests) / sizeof(upnp_tests[0]), upnp_tests}; diff --git a/tester/vcard_tester.c b/tester/vcard_tester.c index 5159988be..23a897c13 100644 --- a/tester/vcard_tester.c +++ b/tester/vcard_tester.c @@ -17,13 +17,15 @@ */ #include "linphone/core.h" -#include "private.h" + #ifdef VCARD_ENABLED #include "liblinphone_tester.h" +#include "tester_utils.h" #include "carddav.h" +#include #include #define CARDDAV_SERVER "http://dav.linphone.org/card.php/addressbooks/tester/default" @@ -37,7 +39,7 @@ static void linphone_vcard_import_export_friends_test(void) { char *export_filepath = bc_tester_file("export_vcards.vcf"); int count = 0; BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends), 0, unsigned int, "%u"); - + count = linphone_friend_list_import_friends_from_vcard4_file(lfl, import_filepath); BC_ASSERT_EQUAL(count, 3, int, "%d"); friends = linphone_friend_list_get_friends(lfl); @@ -145,7 +147,7 @@ static void linphone_vcard_update_existing_friends_test(void) { static void linphone_vcard_phone_numbers_and_sip_addresses(void) { LinphoneCoreManager* manager = linphone_core_manager_new2("empty_rc", FALSE); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nIMPP;TYPE=home:sip:sylvain@sip.linphone.org\r\nTEL;TYPE=work:0952636505\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nIMPP;TYPE=home:sip:sylvain@sip.linphone.org\r\nTEL;TYPE=work:0952636505\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); const bctbx_list_t *sip_addresses = linphone_friend_get_addresses(lf); @@ -157,10 +159,10 @@ static void linphone_vcard_phone_numbers_and_sip_addresses(void) { if (phone_numbers) bctbx_list_free(phone_numbers); linphone_friend_unref(lf); - lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nTEL;TYPE=work:0952636505\r\nTEL:0476010203\r\nEND:VCARD\r\n"); + lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nTEL;TYPE=work:0952636505\r\nTEL:0476010203\r\nEND:VCARD\r\n"); lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); - lf->lc = manager->lc; + linphone_friend_set_core(lf, manager->lc); sip_addresses = linphone_friend_get_addresses(lf); phone_numbers = linphone_friend_get_phone_numbers(lf); @@ -225,31 +227,6 @@ static void friends_if_no_db_set(void) { linphone_core_manager_destroy(manager); } -static void friends_migration(void) { - LinphoneCoreManager* manager = linphone_core_manager_new2("friends_rc", FALSE); - LpConfig *lpc = linphone_core_get_config(manager->lc); - LinphoneFriendList *lfl = linphone_core_get_default_friend_list(manager->lc); - const bctbx_list_t *friends = linphone_friend_list_get_friends(lfl); - bctbx_list_t *friends_from_db = NULL; - char *friends_db = bc_tester_file("friends.db"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends), 3, unsigned int, "%u"); - BC_ASSERT_EQUAL(lp_config_get_int(lpc, "misc", "friends_migration_done", 0), 0, int, "%i"); - - unlink(friends_db); - linphone_core_set_friends_database_path(manager->lc, friends_db); - lfl = linphone_core_get_default_friend_list(manager->lc); - friends = linphone_friend_list_get_friends(lfl); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends), 3, unsigned int, "%u"); - friends_from_db = linphone_core_fetch_friends_from_db(manager->lc, lfl); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends_from_db), 3, unsigned int, "%u"); - BC_ASSERT_EQUAL(lp_config_get_int(lpc, "misc", "friends_migration_done", 0), 1, int, "%i"); - - friends_from_db = bctbx_list_free_with_data(friends_from_db, (void (*)(void *))linphone_friend_unref); - linphone_core_manager_destroy(manager); - unlink(friends_db); - bc_free(friends_db); -} - typedef struct _LinphoneFriendListStats { int new_list_count; int removed_list_count; @@ -288,7 +265,7 @@ static void friends_sqlite_storage(void) { cbs = linphone_factory_create_core_cbs(linphone_factory_get()); linphone_core_cbs_set_friend_list_created(cbs, friend_list_created_cb); linphone_core_cbs_set_friend_list_removed(cbs, friend_list_removed_cb); - lc = linphone_factory_create_core(linphone_factory_get(), cbs, NULL, NULL); + lc = linphone_factory_create_core_2(linphone_factory_get(), cbs, NULL, NULL, NULL, system_context); linphone_core_cbs_unref(cbs); friends = linphone_friend_list_get_friends(linphone_core_get_default_friend_list(lc)); lfl = linphone_core_create_friend_list(lc); @@ -314,19 +291,19 @@ static void friends_sqlite_storage(void) { linphone_friend_list_set_display_name(lfl, "Test"); BC_ASSERT_EQUAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%i"); linphone_friend_unref(lf); - BC_ASSERT_EQUAL(lfl->storage_id, 1, unsigned int, "%u"); - BC_ASSERT_EQUAL(lf->storage_id, 1, unsigned int, "%u"); + BC_ASSERT_EQUAL(linphone_friend_list_get_storage_id(lfl), 1, unsigned int, "%u"); + BC_ASSERT_EQUAL(linphone_friend_get_storage_id(lf), 1, unsigned int, "%u"); friends = linphone_friend_list_get_friends(linphone_core_get_default_friend_list(lc)); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends), 0, unsigned int, "%u"); friends_lists_from_db = linphone_core_fetch_friends_lists_from_db(lc); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends_lists_from_db), 1, unsigned int, "%u"); - friends_from_db = ((LinphoneFriendList *)friends_lists_from_db->data)->friends; + friends_from_db = *linphone_friend_list_get_friends_attribute((LinphoneFriendList *)bctbx_list_get_data(friends_lists_from_db)); BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(friends_from_db), 1, unsigned int, "%u"); lf2 = (LinphoneFriend *)friends_from_db->data; - BC_ASSERT_PTR_NOT_NULL(lf2->lc); - BC_ASSERT_PTR_NOT_NULL(lf2->friend_list); + BC_ASSERT_PTR_NOT_NULL(linphone_friend_get_core(lf2)); + BC_ASSERT_PTR_NOT_NULL(linphone_friend_get_friend_list(lf2)); friends_lists_from_db = bctbx_list_free_with_data(friends_lists_from_db, (void (*)(void *))linphone_friend_list_unref); friends_from_db = linphone_core_fetch_friends_from_db(lc, lfl); @@ -336,7 +313,7 @@ static void friends_sqlite_storage(void) { } lf2 = (LinphoneFriend *)friends_from_db->data; BC_ASSERT_STRING_EQUAL(linphone_friend_get_name(lf2), linphone_friend_get_name(lf)); - BC_ASSERT_EQUAL(lf2->storage_id, lf->storage_id, unsigned int, "%u"); + BC_ASSERT_EQUAL(linphone_friend_get_storage_id(lf2), linphone_friend_get_storage_id(lf), unsigned int, "%u"); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_etag(linphone_friend_get_vcard(lf2)), linphone_vcard_get_etag(linphone_friend_get_vcard(lf))); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_url(linphone_friend_get_vcard(lf2)), linphone_vcard_get_url(linphone_friend_get_vcard(lf))); laddress = linphone_friend_get_address(lf); @@ -344,7 +321,7 @@ static void friends_sqlite_storage(void) { laddress2 = linphone_friend_get_address(lf2); address2 = linphone_address_as_string(laddress2); BC_ASSERT_STRING_EQUAL(address2, address); - + ms_free(address); ms_free(address2); @@ -381,22 +358,22 @@ end: } static void friends_sqlite_store_lot_of_friends(void) { - LinphoneCore* lc = linphone_factory_create_core(linphone_factory_get(), NULL, NULL, NULL); + LinphoneCore* lc = linphone_factory_create_core_2(linphone_factory_get(), NULL, NULL, NULL, NULL, system_context); sqlite3 *db; int i; char* errmsg = NULL; int ret; char *buf; char *friends_db = bc_tester_file("friends.db"); - + unlink(friends_db); - ret = sqlite3_open(friends_db, &db); bc_free(friends_db); + BC_ASSERT_TRUE(ret ==SQLITE_OK); ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); - + ret = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS friends (" "id INTEGER PRIMARY KEY AUTOINCREMENT," @@ -434,12 +411,12 @@ static void friends_sqlite_store_lot_of_friends(void) { BC_ASSERT_TRUE(ret ==SQLITE_OK); sqlite3_free(buf); } - + ret = sqlite3_exec(db,"END",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); - + ms_message("End :\n"); - + ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); ret = sqlite3_exec(db, "DELETE FROM friends;",0,0,&errmsg); @@ -451,7 +428,7 @@ static void friends_sqlite_store_lot_of_friends(void) { } static void friends_sqlite_find_friend_in_lot_of_friends(void) { - LinphoneCore* lc = linphone_factory_create_core(linphone_factory_get(), NULL, NULL, NULL); + LinphoneCore* lc = linphone_factory_create_core_2(linphone_factory_get(), NULL, NULL, NULL, NULL, system_context); sqlite3 *db; int i; char* errmsg = NULL; @@ -460,15 +437,15 @@ static void friends_sqlite_find_friend_in_lot_of_friends(void) { bctoolboxTimeSpec t1; bctoolboxTimeSpec t2; char *friends_db = bc_tester_file("friends.db"); - - unlink(friends_db); + unlink(friends_db); ret = sqlite3_open(friends_db, &db); bc_free(friends_db); + BC_ASSERT_TRUE(ret ==SQLITE_OK); ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); - + ret = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS friends (" "id INTEGER PRIMARY KEY AUTOINCREMENT," @@ -485,7 +462,7 @@ static void friends_sqlite_find_friend_in_lot_of_friends(void) { BC_ASSERT_TRUE(ret ==SQLITE_OK); ret = sqlite3_exec(db,"END",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); - + ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); for (i = 0; i < 20000; i++) { @@ -500,30 +477,30 @@ static void friends_sqlite_find_friend_in_lot_of_friends(void) { NULL, 0 ); - + ret = sqlite3_exec(db,buf,0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); sqlite3_free(buf); //ms_message("%i",i); } - + ret = sqlite3_exec(db,"END",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); - + bctbx_get_cur_time(&t1); ms_message("Start : %li : %li\n", (long int)t1.tv_sec, (long int)t1.tv_nsec); for (i = 0; i < 20000; i++) { buf = sqlite3_mprintf("SELECT * FROM friends WHERE ref_key LIKE 'key_%i';", i); - + ret = sqlite3_exec(db,buf,0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); sqlite3_free(buf); } - + bctbx_get_cur_time(&t2); ms_message("End : %li : %li\n", (long int)t2.tv_sec, (long int)t2.tv_nsec); - + ret = sqlite3_exec(db,"BEGIN",0,0,&errmsg); BC_ASSERT_TRUE(ret ==SQLITE_OK); ret = sqlite3_exec(db, "DELETE FROM friends;",0,0,&errmsg); @@ -641,7 +618,7 @@ static void carddav_sync_2(void) { static void carddav_sync_3(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nFN:Sylvain Berfini\r\nIMPP;TYPE=work:sip:sylvain@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nFN:Sylvain Berfini\r\nIMPP;TYPE=work:sip:sylvain@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); char *friends_db = bc_tester_file("friends.db"); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); @@ -682,7 +659,7 @@ static void carddav_sync_3(void) { static void carddav_sync_4(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); LinphoneCardDavContext *c = NULL; @@ -717,23 +694,23 @@ static void carddav_sync_4(void) { } static void carddav_contact_created(LinphoneFriendList *list, LinphoneFriend *lf) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); stats->new_contact_count++; } static void carddav_contact_deleted(LinphoneFriendList *list, LinphoneFriend *lf) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); stats->removed_contact_count++; } static void carddav_contact_updated(LinphoneFriendList *list, LinphoneFriend *new_friend, LinphoneFriend *old_friend) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); BC_ASSERT_STRING_EQUAL(linphone_vcard_get_full_name(linphone_friend_get_vcard(new_friend)), linphone_vcard_get_full_name(linphone_friend_get_vcard(old_friend))); stats->updated_contact_count++; } static void carddav_sync_status_changed(LinphoneFriendList *list, LinphoneFriendListSyncStatus status, const char *msg) { - LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(list->cbs); + LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)linphone_friend_list_cbs_get_user_data(linphone_friend_list_get_callbacks(list)); char *state = status == LinphoneFriendListSyncStarted ? "Sync started" : (status == LinphoneFriendListSyncFailure ? "Sync failure" : "Sync successful"); ms_message("[CardDAV] %s : %s", state, msg); if (status == LinphoneFriendListSyncFailure || status == LinphoneFriendListSyncSuccessful) { @@ -744,7 +721,7 @@ static void carddav_sync_status_changed(LinphoneFriendList *list, LinphoneFriend static void carddav_integration(void) { LinphoneCoreManager *manager = linphone_core_manager_new2("carddav_rc", FALSE); LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); - LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf = linphone_friend_new_from_vcard(lvc); LinphoneVcard *lvc2 = NULL; LinphoneFriend *lf2 = NULL; @@ -765,34 +742,34 @@ static void carddav_integration(void) { linphone_core_add_friend_list(manager->lc, lfl); BC_ASSERT_PTR_NULL(linphone_vcard_get_uid(lvc)); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->dirty_friends_to_update), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(lfl)), 0, unsigned int, "%u"); BC_ASSERT_EQUAL(linphone_friend_list_add_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->dirty_friends_to_update), 1, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(lfl)), 1, unsigned int, "%u"); wait_for_until(manager->lc, NULL, &stats->sync_done_count, 1, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->dirty_friends_to_update), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(lfl)), 0, unsigned int, "%u"); BC_ASSERT_PTR_NOT_NULL(linphone_vcard_get_uid(lvc)); linphone_friend_list_remove_friend(lfl, lf); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->friends), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_friends(lfl)), 0, unsigned int, "%u"); wait_for_until(manager->lc, NULL, &stats->sync_done_count, 2, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->sync_done_count, 2, int, "%i"); linphone_friend_unref(lf); lf = NULL; - lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); + lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf), LinphoneFriendListOK, int, "%d"); linphone_friend_unref(lf); - lvc2 = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); + lvc2 = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sberfini@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); linphone_vcard_set_url(lvc2, "/card.php/addressbooks/tester/default/me.vcf"); lf2 = linphone_friend_new_from_vcard(lvc2); linphone_vcard_unref(lvc2); linphone_friend_set_ref_key(lf2, refkey); BC_ASSERT_EQUAL(linphone_friend_list_add_local_friend(lfl, lf2), LinphoneFriendListOK, int, "%d"); - BC_ASSERT_EQUAL(lfl->revision, 0, int, "%i"); + BC_ASSERT_EQUAL(linphone_friend_list_get_revision(lfl), 0, int, "%i"); linphone_friend_list_synchronize_friends_from_server(lfl); wait_for_until(manager->lc, NULL, &stats->new_contact_count, 0, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->new_contact_count, 0, int, "%i"); @@ -800,14 +777,14 @@ static void carddav_integration(void) { BC_ASSERT_EQUAL(stats->removed_contact_count, 1, int, "%i"); wait_for_until(manager->lc, NULL, &stats->updated_contact_count, 1, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->updated_contact_count, 1, int, "%i"); - BC_ASSERT_NOT_EQUAL(lfl->revision, 0, int, "%i"); + BC_ASSERT_NOT_EQUAL(linphone_friend_list_get_revision(lfl), 0, int, "%i"); wait_for_until(manager->lc, NULL, &stats->sync_done_count, 3, CARDDAV_SYNC_TIMEOUT); BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lfl->friends), 1, unsigned int, "%u"); - lf = (LinphoneFriend *)lfl->friends->data; - BC_ASSERT_STRING_EQUAL(lf->refkey, refkey); - BC_ASSERT_EQUAL(lf->storage_id, lf2->storage_id, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_friends(lfl)), 1, unsigned int, "%u"); + lf = (LinphoneFriend *)bctbx_list_get_data((linphone_friend_list_get_friends(lfl))); + BC_ASSERT_STRING_EQUAL(linphone_friend_get_ref_key(lf), refkey); + BC_ASSERT_EQUAL(linphone_friend_get_storage_id(lf), linphone_friend_get_storage_id(lf2), unsigned int, "%u"); linphone_friend_unref(lf2); addr = linphone_friend_get_address(lf); BC_ASSERT_PTR_NOT_NULL(addr); @@ -818,17 +795,17 @@ static void carddav_integration(void) { linphone_friend_edit(lf); linphone_friend_done(lf); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lf->friend_list->dirty_friends_to_update), 0, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(linphone_friend_get_friend_list(lf))), 0, unsigned int, "%u"); linphone_core_set_network_reachable(manager->lc, FALSE); //To prevent the CardDAV update linphone_friend_edit(lf); linphone_friend_set_name(lf, "François Grisez"); linphone_friend_done(lf); - BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(lf->friend_list->dirty_friends_to_update), 1, unsigned int, "%u"); + BC_ASSERT_EQUAL((unsigned int)bctbx_list_size(linphone_friend_list_get_dirty_friends_to_update(linphone_friend_get_friend_list(lf))), 1, unsigned int, "%u"); - ms_free(stats); linphone_friend_list_unref(lfl); linphone_core_manager_destroy(manager); + ms_free(stats); } static void carddav_clean(void) { // This is to ensure the content of the test addressbook is in the correct state for the following tests @@ -854,7 +831,7 @@ static void carddav_clean(void) { // This is to ensure the content of the test BC_ASSERT_EQUAL(stats->sync_done_count, 1, int, "%i"); stats->sync_done_count = 0; - friends = bctbx_list_copy(lfl->friends); + friends = bctbx_list_copy(linphone_friend_list_get_friends(lfl)); friends_iterator = friends; while (friends_iterator) { LinphoneFriend *lf = (LinphoneFriend *)friends_iterator->data; @@ -867,7 +844,7 @@ static void carddav_clean(void) { // This is to ensure the content of the test } bctbx_list_free(friends); - lvc = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sylvain@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); + lvc = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Sylvain Berfini\r\nIMPP:sip:sylvain@sip.linphone.org\r\nUID:1f08dd48-29ac-4097-8e48-8596d7776283\r\nEND:VCARD\r\n"); linphone_vcard_set_url(lvc, "http://dav.linphone.org/card.php/addressbooks/tester/default/me.vcf"); lf = linphone_friend_new_from_vcard(lvc); linphone_vcard_unref(lvc); @@ -916,9 +893,9 @@ static void carddav_server_to_client_and_client_to_sever_sync(void) { LinphoneFriendList *lfl = linphone_core_create_friend_list(manager->lc); LinphoneFriendListCbs *cbs = linphone_friend_list_get_callbacks(lfl); LinphoneCardDAVStats *stats = (LinphoneCardDAVStats *)ms_new0(LinphoneCardDAVStats, 1); - LinphoneVcard *lvc1 = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc1 = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Margaux Clerc\r\nIMPP;TYPE=work:sip:margaux@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf1 = linphone_friend_new_from_vcard(lvc1); - LinphoneVcard *lvc2 = linphone_vcard_context_get_vcard_from_buffer(manager->lc->vcard_context, "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); + LinphoneVcard *lvc2 = linphone_vcard_context_get_vcard_from_buffer(linphone_core_get_vcard_context(manager->lc), "BEGIN:VCARD\r\nVERSION:4.0\r\nFN:Ghislain Mary\r\nIMPP;TYPE=work:sip:ghislain@sip.linphone.org\r\nEND:VCARD\r\n"); LinphoneFriend *lf2 = linphone_friend_new_from_vcard(lvc2); bctbx_list_t *friends = NULL, *friends_iterator = NULL; @@ -941,7 +918,7 @@ static void carddav_server_to_client_and_client_to_sever_sync(void) { BC_ASSERT_EQUAL(stats->sync_done_count, 3, int, "%i"); stats->sync_done_count = 0; - friends = bctbx_list_copy(lfl->friends); + friends = bctbx_list_copy(linphone_friend_list_get_friends(lfl)); friends_iterator = friends; while (friends_iterator) { LinphoneFriend *lf = (LinphoneFriend *)friends_iterator->data; @@ -974,7 +951,9 @@ static void find_friend_by_ref_key_test(void) { goto end; } addr = linphone_friend_get_address(lf2); - BC_ASSERT_STRING_EQUAL(linphone_address_as_string_uri_only(addr), "sip:toto@sip.linphone.org"); + char *uri_addr = linphone_address_as_string_uri_only(addr); + BC_ASSERT_STRING_EQUAL(uri_addr, "sip:toto@sip.linphone.org"); + bctbx_free(uri_addr); BC_ASSERT_EQUAL(lf2, lf, void*, "%p"); end: linphone_friend_unref(lf); @@ -985,7 +964,7 @@ static void insert_lot_of_friends_map_test(void) { int i; bctbx_map_t *friends_map = bctbx_mmap_cchar_new(); bctbx_pair_cchar_t *pair; - + char key[64]; ms_message("Start\n"); for(i = 0; i < 20000; i++) { @@ -1045,7 +1024,6 @@ test_t vcard_tests[] = { TEST_NO_TAG("vCard phone numbers and SIP addresses", linphone_vcard_phone_numbers_and_sip_addresses), #ifdef SQLITE_STORAGE_ENABLED TEST_NO_TAG("Friends working if no db set", friends_if_no_db_set), - TEST_NO_TAG("Friends storage migration from rc to db", friends_migration), TEST_NO_TAG("Friends storage in sqlite database", friends_sqlite_storage), TEST_NO_TAG("20000 Friends storage in sqlite database", friends_sqlite_store_lot_of_friends), TEST_NO_TAG("Find friend in database of 20000 objects", friends_sqlite_find_friend_in_lot_of_friends), diff --git a/tester/video_tester.c b/tester/video_tester.c index 54fccaea6..da9b7a4be 100644 --- a/tester/video_tester.c +++ b/tester/video_tester.c @@ -15,542 +15,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "private.h" - -#if defined(VIDEO_ENABLED) +#ifdef VIDEO_ENABLED #include "linphone/core.h" #include "liblinphone_tester.h" +#include "tester_utils.h" #include "linphone/lpconfig.h" -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic push -#endif -#ifndef _MSC_VER -#pragma GCC diagnostic ignored "-Wstrict-prototypes" -#endif - -#if HAVE_GTK -#include -#ifdef GDK_WINDOWING_X11 -#include -#elif defined(_WIN32) -#include -#elif defined(__APPLE__) -extern void *gdk_quartz_window_get_nswindow(GdkWindow *window); -extern void *gdk_quartz_window_get_nsview(GdkWindow *window); -#endif - -#include - -#if __clang__ || ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4) -#pragma GCC diagnostic pop -#endif - - -static void *get_native_handle(GdkWindow *gdkw) { -#ifdef GDK_WINDOWING_X11 - return (void *)GDK_WINDOW_XID(gdkw); -#elif defined(_WIN32) - return (void *)GDK_WINDOW_HWND(gdkw); -#elif defined(__APPLE__) - return (void *)gdk_quartz_window_get_nsview(gdkw); -#endif - g_warning("No way to get the native handle from gdk window"); - return 0; -} - -static GtkWidget *create_video_window(LinphoneCall *call, LinphoneCallState cstate) { - GtkWidget *video_window; - GdkDisplay *display; - GdkColor color; - MSVideoSize vsize = { MS_VIDEO_SIZE_CIF_W, MS_VIDEO_SIZE_CIF_H }; - const char *cstate_str; - char *title; - stats* counters = get_stats(call->core); - - cstate_str = linphone_call_state_to_string(cstate); - title = g_strdup_printf("%s", cstate_str); - video_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(video_window), title); - g_free(title); - gtk_window_resize(GTK_WINDOW(video_window), vsize.width, vsize.height); - gdk_color_parse("black", &color); - gtk_widget_modify_bg(video_window, GTK_STATE_NORMAL, &color); - gtk_widget_show(video_window); - g_object_set_data(G_OBJECT(video_window), "call", call); -#if GTK_CHECK_VERSION(2,24,0) - display = gdk_window_get_display(gtk_widget_get_window(video_window)); -#else // backward compatibility with Debian 6 and Centos 6 - display = gdk_drawable_get_display(gtk_widget_get_window(video_window)); -#endif - gdk_display_flush(display); - counters->number_of_video_windows_created++; - return video_window; -} - -static void show_video_window(LinphoneCall *call, LinphoneCallState cstate) { - GtkWidget *video_window = (GtkWidget *)linphone_call_get_user_data(call); - if (video_window == NULL) { - video_window = create_video_window(call, cstate); - linphone_call_set_user_data(call, video_window); - linphone_call_set_native_video_window_id(call, get_native_handle(gtk_widget_get_window(video_window))); - } -} - -static void hide_video_video(LinphoneCall *call) { - GtkWidget *video_window = (GtkWidget *)linphone_call_get_user_data(call); - if (video_window != NULL) { - gtk_widget_destroy(video_window); - linphone_call_set_user_data(call, NULL); - linphone_call_set_native_video_window_id(call, 0); - } -} - -static void video_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) { - switch (cstate) { - case LinphoneCallIncomingEarlyMedia: - case LinphoneCallOutgoingEarlyMedia: - case LinphoneCallConnected: - show_video_window(call, cstate); - break; - case LinphoneCallEnd: - hide_video_video(call); - break; - default: - break; - } -} - -static void early_media_video_call_state_changed(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) { - LinphoneCallParams *params; - - video_call_state_changed(lc, call, cstate, msg); - switch (cstate) { - case LinphoneCallIncomingReceived: - params = linphone_core_create_call_params(lc, call); - linphone_call_params_enable_video(params, TRUE); - linphone_call_params_set_audio_direction(params, LinphoneMediaDirectionSendOnly); - linphone_call_params_set_video_direction(params, LinphoneMediaDirectionRecvOnly); - linphone_call_accept_early_media_with_params(call, params); - linphone_call_params_unref(params); - break; - default: - break; - } -} - -static void early_media_video_call_state_changed_with_inactive_audio(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *msg) { - LinphoneCallParams *params; - - video_call_state_changed(lc, call, cstate, msg); - switch (cstate) { - case LinphoneCallIncomingReceived: - params = linphone_core_create_call_params(lc, call); - linphone_call_params_enable_video(params, TRUE); - linphone_call_params_set_audio_direction(params, LinphoneMediaDirectionInactive); - linphone_call_params_set_video_direction(params, LinphoneMediaDirectionRecvOnly); - linphone_call_accept_early_media_with_params(call, params); - linphone_call_params_unref(params); - break; - default: - break; - } -} - -bool_t wait_for_three_cores(LinphoneCore *lc1, LinphoneCore *lc2, LinphoneCore *lc3, int timeout) { - bctbx_list_t *lcs = NULL; - bool_t result; - int dummy = 0; - if (lc1) lcs = bctbx_list_append(lcs, lc1); - if (lc2) lcs = bctbx_list_append(lcs, lc2); - if (lc3) lcs = bctbx_list_append(lcs, lc3); - result = wait_for_list(lcs, &dummy, 1, timeout); - bctbx_list_free(lcs); - return result; -} - -static bool_t video_call_with_params(LinphoneCoreManager* caller_mgr, LinphoneCoreManager* callee_mgr, const LinphoneCallParams *caller_params, const LinphoneCallParams *callee_params, bool_t automatically_accept) { - int retry = 0; - stats initial_caller = caller_mgr->stat; - stats initial_callee = callee_mgr->stat; - bool_t result = TRUE; - bool_t did_received_call; - - BC_ASSERT_PTR_NOT_NULL(linphone_core_invite_address_with_params(caller_mgr->lc, callee_mgr->identity, caller_params)); - did_received_call = wait_for(callee_mgr->lc, caller_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallIncomingReceived, initial_callee.number_of_LinphoneCallIncomingReceived + 1); - if (!did_received_call) return 0; - - BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress, initial_caller.number_of_LinphoneCallOutgoingProgress + 1, int, "%d"); - - while (caller_mgr->stat.number_of_LinphoneCallOutgoingRinging != (initial_caller.number_of_LinphoneCallOutgoingRinging + 1) - && caller_mgr->stat.number_of_LinphoneCallOutgoingEarlyMedia != (initial_caller.number_of_LinphoneCallOutgoingEarlyMedia + 1) - && retry++ < 200) { - linphone_core_iterate(caller_mgr->lc); - linphone_core_iterate(callee_mgr->lc); - ms_usleep(10000); - } - - BC_ASSERT_TRUE((caller_mgr->stat.number_of_LinphoneCallOutgoingRinging == initial_caller.number_of_LinphoneCallOutgoingRinging + 1) - || (caller_mgr->stat.number_of_LinphoneCallOutgoingEarlyMedia == initial_caller.number_of_LinphoneCallOutgoingEarlyMedia + 1)); - - BC_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call_remote_address(callee_mgr->lc)); - if(!linphone_core_get_current_call(caller_mgr->lc) || !linphone_core_get_current_call(callee_mgr->lc) || !linphone_core_get_current_call_remote_address(callee_mgr->lc)) { - return 0; - } - - if (automatically_accept == TRUE) { - linphone_call_accept_with_params(linphone_core_get_current_call(callee_mgr->lc), callee_params); - - BC_ASSERT_TRUE(wait_for(callee_mgr->lc, caller_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallConnected, initial_callee.number_of_LinphoneCallConnected + 1)); - BC_ASSERT_TRUE(wait_for(callee_mgr->lc, caller_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallConnected, initial_callee.number_of_LinphoneCallConnected + 1)); - result = wait_for(callee_mgr->lc, caller_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallStreamsRunning, initial_caller.number_of_LinphoneCallStreamsRunning + 1) - && wait_for(callee_mgr->lc, caller_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallStreamsRunning, initial_callee.number_of_LinphoneCallStreamsRunning + 1); - } - return result; -} - -static LinphoneCallParams * _configure_for_video(LinphoneCoreManager *manager, LinphoneCoreCbsCallStateChangedCb cb) { - LinphoneCallParams *params; - LinphoneCoreCbs *cbs = linphone_factory_create_core_cbs(linphone_factory_get()); - linphone_core_cbs_set_call_state_changed(cbs, cb); - linphone_core_add_callbacks(manager->lc, cbs); - linphone_core_cbs_unref(cbs); - linphone_core_set_video_device(manager->lc, "StaticImage: Static picture"); - linphone_core_enable_video_capture(manager->lc, TRUE); - linphone_core_enable_video_display(manager->lc, TRUE); - params = linphone_core_create_call_params(manager->lc, NULL); - linphone_call_params_enable_video(params, TRUE); - if (linphone_core_find_payload_type(manager->lc,"VP8", 90000, -1)!=NULL){ - disable_all_video_codecs_except_one(manager->lc, "VP8"); - }else{ - ms_warning("VP8 codec not available, will use MP4V-ES instead"); - disable_all_video_codecs_except_one(manager->lc, "MP4V-ES"); - } - return params; -} - -static LinphoneCallParams * configure_for_video(LinphoneCoreManager *manager) { - return _configure_for_video(manager, video_call_state_changed); -} - -static LinphoneCallParams * configure_for_early_media_video_sending(LinphoneCoreManager *manager) { - LinphoneCallParams *params = _configure_for_video(manager, video_call_state_changed); - linphone_call_params_enable_early_media_sending(params, TRUE); - return params; -} - -static LinphoneCallParams * configure_for_early_media_video_receiving(LinphoneCoreManager *manager) { - return _configure_for_video(manager, early_media_video_call_state_changed); -} - -static LinphoneCallParams * configure_for_early_media_video_receiving_with_inactive_audio(LinphoneCoreManager *manager) { - return _configure_for_video(manager, early_media_video_call_state_changed_with_inactive_audio); -} - - -static void early_media_video_during_video_call_test(void) { - LinphoneCoreManager *marie; - LinphoneCoreManager *pauline; - LinphoneCoreManager *laure; - LinphoneCallParams *marie_params; - LinphoneCallParams *pauline_params; - LinphoneCallParams *laure_params; - - marie = linphone_core_manager_new("marie_rc"); - pauline = linphone_core_manager_new("pauline_tcp_rc"); - laure = linphone_core_manager_new("laure_rc_udp"); - marie_params = configure_for_early_media_video_receiving(marie); - pauline_params = configure_for_video(pauline); - laure_params = configure_for_early_media_video_sending(laure); - - /* Normal automatically accepted video call from marie to pauline. */ - BC_ASSERT_TRUE(video_call_with_params(marie, pauline, marie_params, pauline_params, TRUE)); - - /* Wait for 2s. */ - wait_for_three_cores(marie->lc, pauline->lc, NULL, 2000); - - /* Early media video call from laure to marie. */ - BC_ASSERT_TRUE(video_call_with_params(laure, marie, laure_params, NULL, FALSE)); - - /* Wait for 2s. */ - wait_for_three_cores(marie->lc, pauline->lc, laure->lc, 2000); - - linphone_core_terminate_all_calls(marie->lc); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, laure->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, laure->lc, &laure->stat.number_of_LinphoneCallEnd, 1)); - - BC_ASSERT_EQUAL(marie->stat.number_of_video_windows_created, 2, int, "%d"); - BC_ASSERT_EQUAL(pauline->stat.number_of_video_windows_created, 1, int, "%d"); - BC_ASSERT_EQUAL(laure->stat.number_of_video_windows_created, 1, int, "%d"); - - linphone_call_params_unref(marie_params); - linphone_call_params_unref(pauline_params); - linphone_call_params_unref(laure_params); - linphone_core_manager_destroy(marie); - linphone_core_manager_destroy(pauline); - linphone_core_manager_destroy(laure); -} - -static void two_incoming_early_media_video_calls_test(void) { - char *ringback_path; - LinphoneCoreManager *marie; - LinphoneCoreManager *pauline; - LinphoneCoreManager *laure; - LinphoneCallParams *marie_params; - LinphoneCallParams *pauline_params; - LinphoneCallParams *laure_params; - LinphoneCall *call; - const bctbx_list_t *calls_list; - - marie = linphone_core_manager_new("marie_rc"); - pauline = linphone_core_manager_new("pauline_tcp_rc"); - laure = linphone_core_manager_new("laure_rc_udp"); - marie_params = configure_for_early_media_video_receiving(marie); - pauline_params = configure_for_early_media_video_sending(pauline); - laure_params = configure_for_early_media_video_sending(laure); - - /* Configure early media audio to play ring during early-media and send remote ring back tone. */ - linphone_core_set_ring_during_incoming_early_media(marie->lc, TRUE); - ringback_path = bc_tester_res("sounds/ringback.wav"); - linphone_core_set_remote_ringback_tone(marie->lc, ringback_path); - ms_free(ringback_path); - - /* Early media video call from pauline to marie. */ - BC_ASSERT_TRUE(video_call_with_params(pauline, marie, pauline_params, NULL, FALSE)); - - /* Wait for 2s. */ - wait_for_three_cores(marie->lc, pauline->lc, NULL, 2000); - - /* Early media video call from laure to marie. */ - BC_ASSERT_TRUE(video_call_with_params(laure, marie, laure_params, NULL, FALSE)); - - /* Wait for 2s. */ - wait_for_three_cores(marie->lc, pauline->lc, laure->lc, 2000); - - BC_ASSERT_EQUAL(linphone_core_get_calls_nb(marie->lc), 2, int, "%d"); - if (linphone_core_get_calls_nb(marie->lc) == 2) { - calls_list = linphone_core_get_calls(marie->lc); - call = (LinphoneCall *)bctbx_list_nth_data(calls_list, 0); - BC_ASSERT_PTR_NOT_NULL(call); - if (call != NULL) { - LinphoneCallParams *params = linphone_call_params_copy(linphone_call_get_current_params(call)); - linphone_call_params_set_audio_direction(params, LinphoneMediaDirectionSendRecv); - linphone_call_params_set_video_direction(params, LinphoneMediaDirectionSendRecv); - linphone_call_accept_with_params(call, params); - linphone_call_params_unref(params); - - /* Wait for 5s. */ - wait_for_three_cores(marie->lc, pauline->lc, laure->lc, 5000); - } - } - - linphone_core_terminate_all_calls(marie->lc); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, laure->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, laure->lc, &laure->stat.number_of_LinphoneCallEnd, 1)); - - BC_ASSERT_EQUAL(marie->stat.number_of_video_windows_created, 2, int, "%d"); - BC_ASSERT_EQUAL(pauline->stat.number_of_video_windows_created, 1, int, "%d"); - BC_ASSERT_EQUAL(laure->stat.number_of_video_windows_created, 1, int, "%d"); - - linphone_call_params_unref(marie_params); - linphone_call_params_unref(pauline_params); - linphone_call_params_unref(laure_params); - linphone_core_manager_destroy(marie); - linphone_core_manager_destroy(pauline); - linphone_core_manager_destroy(laure); -} - -static void early_media_video_with_inactive_audio(void) { - LinphoneCoreManager *marie; - LinphoneCoreManager *pauline; - LinphoneCallParams *marie_params; - LinphoneCallParams *pauline_params; - - marie = linphone_core_manager_new("marie_rc"); - pauline = linphone_core_manager_new("pauline_tcp_rc"); - marie_params = configure_for_early_media_video_receiving_with_inactive_audio(marie); - pauline_params = configure_for_early_media_video_sending(pauline); - - /* Early media video call from pauline to marie. */ - BC_ASSERT_TRUE(video_call_with_params(pauline, marie, pauline_params, NULL, FALSE)); - - /* Wait for 2s. */ - wait_for_three_cores(marie->lc, pauline->lc, NULL, 2000); - - /* Check that we are in LinphoneCallOutgoingEarlyMedia state and that the ringstream is present meaning we are playing the ringback tone. */ - BC_ASSERT_EQUAL(linphone_call_get_state(linphone_core_get_current_call(pauline->lc)), LinphoneCallOutgoingEarlyMedia, int, "%d"); - BC_ASSERT_PTR_NOT_NULL(pauline->lc->ringstream); - - linphone_core_terminate_all_calls(marie->lc); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1)); - - BC_ASSERT_EQUAL(marie->stat.number_of_video_windows_created, 1, int, "%d"); - BC_ASSERT_EQUAL(pauline->stat.number_of_video_windows_created, 1, int, "%d"); - - linphone_call_params_unref(marie_params); - linphone_call_params_unref(pauline_params); - linphone_core_manager_destroy(marie); - linphone_core_manager_destroy(pauline); -} - -static void forked_outgoing_early_media_video_call_with_inactive_audio_test(void) { - LinphoneCoreManager *pauline = linphone_core_manager_new("pauline_tcp_rc"); - LinphoneCoreManager *marie1 = linphone_core_manager_new("marie_early_rc"); - LinphoneCoreManager *marie2 = linphone_core_manager_new("marie_early_rc"); - bctbx_list_t *lcs = NULL; - LinphoneCallParams *pauline_params; - LinphoneCallParams *marie1_params; - LinphoneCallParams *marie2_params; - LinphoneVideoActivationPolicy *pol = linphone_video_activation_policy_new(); - LinphoneCall *marie1_call; - LinphoneCall *marie2_call; - LinphoneCall *pauline_call; - LinphoneInfoMessage *info; - int dummy = 0; - pol->automatically_accept = TRUE; - pol->automatically_initiate = TRUE; - LinphoneRange *port_range = NULL; - - linphone_core_enable_video_capture(pauline->lc, TRUE); - linphone_core_enable_video_display(pauline->lc, TRUE); - linphone_core_enable_video_capture(marie1->lc, TRUE); - linphone_core_enable_video_display(marie1->lc, TRUE); - linphone_core_set_video_activation_policy(marie1->lc, pol); - linphone_core_enable_video_capture(marie2->lc, TRUE); - linphone_core_enable_video_display(marie2->lc, TRUE); - linphone_core_set_video_activation_policy(marie2->lc, pol); - linphone_video_activation_policy_unref(pol); - linphone_core_set_audio_port_range(marie2->lc, 40200, 40300); - port_range = linphone_core_get_audio_ports_range(marie2->lc); - BC_ASSERT_EQUAL(port_range->min, 40200, int, "%i"); - BC_ASSERT_EQUAL(port_range->max, 40300, int, "%i"); - linphone_range_unref(port_range); - linphone_core_set_video_port_range(marie2->lc, 40400, 40500); - port_range = linphone_core_get_video_ports_range(marie2->lc); - BC_ASSERT_EQUAL(port_range->min, 40400, int, "%i"); - BC_ASSERT_EQUAL(port_range->max, 40500, int, "%i"); - linphone_range_unref(port_range); - - lcs = bctbx_list_append(lcs,marie1->lc); - lcs = bctbx_list_append(lcs,marie2->lc); - lcs = bctbx_list_append(lcs,pauline->lc); - - pauline_params = linphone_core_create_call_params(pauline->lc, NULL); - linphone_call_params_enable_early_media_sending(pauline_params, TRUE); - linphone_call_params_enable_video(pauline_params, TRUE); - marie1_params = configure_for_early_media_video_receiving_with_inactive_audio(marie1); - marie2_params = configure_for_early_media_video_receiving_with_inactive_audio(marie2); - - linphone_core_invite_address_with_params(pauline->lc, marie1->identity, pauline_params); - linphone_call_params_unref(pauline_params); - - BC_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingReceived, 1, 3000)); - BC_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingReceived, 1, 3000)); - - marie1_call = linphone_core_get_current_call(marie1->lc); - marie2_call = linphone_core_get_current_call(marie2->lc); - - if (marie1_call){ - linphone_call_set_next_video_frame_decoded_callback(marie1_call, linphone_call_iframe_decoded_cb, marie1->lc); - } - if (marie2_call){ - linphone_call_set_next_video_frame_decoded_callback(marie2_call, linphone_call_iframe_decoded_cb, marie2->lc); - } - - BC_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallIncomingEarlyMedia, 1, 3000)); - BC_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallIncomingEarlyMedia, 1, 3000)); - BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallOutgoingEarlyMedia, 1, 3000)); - - pauline_call = linphone_core_get_current_call(pauline->lc); - - BC_ASSERT_PTR_NOT_NULL(pauline_call); - BC_ASSERT_PTR_NOT_NULL(marie1_call); - BC_ASSERT_PTR_NOT_NULL(marie2_call); - - if (pauline_call && marie1_call && marie2_call) { - LinphoneCallStats *pauline_audio_stats, *marie1_audio_stats, *marie2_audio_stats; - LinphoneCallStats *pauline_video_stats, *marie1_video_stats, *marie2_video_stats; - linphone_call_set_next_video_frame_decoded_callback(pauline_call, linphone_call_iframe_decoded_cb, pauline->lc); - - /* wait a bit that streams are established */ - wait_for_list(lcs, &dummy, 1, 3000); - pauline_audio_stats = linphone_call_get_audio_stats(pauline_call); - marie1_audio_stats = linphone_call_get_audio_stats(marie1_call); - marie2_audio_stats = linphone_call_get_audio_stats(marie2_call); - pauline_video_stats = linphone_call_get_video_stats(pauline_call); - marie1_video_stats = linphone_call_get_video_stats(marie1_call); - marie2_video_stats = linphone_call_get_video_stats(marie2_call); - BC_ASSERT_EQUAL(pauline_audio_stats->download_bandwidth, 0, float, "%f"); - BC_ASSERT_EQUAL(marie1_audio_stats->download_bandwidth, 0, float, "%f"); - BC_ASSERT_EQUAL(marie2_audio_stats->download_bandwidth, 0, float, "%f"); - BC_ASSERT_LOWER(pauline_video_stats->download_bandwidth, 11, float, "%f"); /* because of stun packets*/ - BC_ASSERT_GREATER(marie1_video_stats->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(marie2_video_stats->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(marie1->stat.number_of_IframeDecoded, 1, int, "%i"); - BC_ASSERT_GREATER(marie2->stat.number_of_IframeDecoded, 1, int, "%i"); - linphone_call_stats_unref(pauline_audio_stats); - linphone_call_stats_unref(marie1_audio_stats); - linphone_call_stats_unref(marie2_audio_stats); - linphone_call_stats_unref(pauline_video_stats); - linphone_call_stats_unref(marie1_video_stats); - linphone_call_stats_unref(marie2_video_stats); - - linphone_call_params_set_audio_direction(marie1_params, LinphoneMediaDirectionSendRecv); - linphone_call_accept_with_params(linphone_core_get_current_call(marie1->lc), marie1_params); - BC_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallStreamsRunning, 1, 3000)); - BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1, 3000)); - - /* marie2 should get her call terminated */ - BC_ASSERT_TRUE(wait_for_list(lcs, &marie2->stat.number_of_LinphoneCallEnd, 1, 1000)); - - /*wait a bit that streams are established*/ - wait_for_list(lcs, &dummy, 1, 3000); - pauline_audio_stats = linphone_call_get_audio_stats(pauline_call); - marie1_audio_stats = linphone_call_get_audio_stats(marie1_call); - pauline_video_stats = linphone_call_get_video_stats(pauline_call); - marie1_video_stats = linphone_call_get_video_stats(marie1_call); - BC_ASSERT_GREATER(pauline_audio_stats->download_bandwidth, 71, float, "%f"); - BC_ASSERT_GREATER(marie1_audio_stats->download_bandwidth, 71, float, "%f"); - BC_ASSERT_GREATER(pauline_video_stats->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(marie1_video_stats->download_bandwidth, 0, float, "%f"); - BC_ASSERT_GREATER(pauline->stat.number_of_IframeDecoded, 1, int, "%i"); - linphone_call_stats_unref(pauline_audio_stats); - linphone_call_stats_unref(marie1_audio_stats); - linphone_call_stats_unref(pauline_video_stats); - linphone_call_stats_unref(marie1_video_stats); - - /* send an INFO in reverse side to check that dialogs are properly established */ - info = linphone_core_create_info_message(marie1->lc); - linphone_call_send_info_message(marie1_call, info); - linphone_info_message_unref(info); - BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_inforeceived, 1, 3000)); - } - - linphone_core_terminate_all_calls(pauline->lc); - BC_ASSERT_TRUE(wait_for_list(lcs, &pauline->stat.number_of_LinphoneCallEnd, 1, 3000)); - BC_ASSERT_TRUE(wait_for_list(lcs, &marie1->stat.number_of_LinphoneCallEnd, 1, 3000)); - - linphone_call_params_unref(marie1_params); - linphone_call_params_unref(marie2_params); - bctbx_list_free(lcs); - linphone_core_manager_destroy(marie1); - linphone_core_manager_destroy(marie2); - linphone_core_manager_destroy(pauline); -} -#endif /*HAVE_GTK*/ +#include static void enable_disable_camera_after_camera_switches(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); @@ -560,7 +33,6 @@ static void enable_disable_camera_after_camera_switches(void) { const char *newCamId=NULL; int i; - video_call_base_2(marie,pauline,FALSE,LinphoneMediaEncryptionNone,TRUE,TRUE); for (i=0;cameras[i]!=NULL;++i){ @@ -569,6 +41,7 @@ static void enable_disable_camera_after_camera_switches(void) { break; } } + if (newCamId){ LinphoneCall *call = linphone_core_get_current_call(marie->lc); ms_message("Switching from [%s] to [%s]", currentCamId, newCamId); @@ -576,32 +49,113 @@ static void enable_disable_camera_after_camera_switches(void) { if(call != NULL) { linphone_call_update(call, NULL); } - BC_ASSERT_STRING_EQUAL(newCamId,ms_web_cam_get_string_id(linphone_call_get_video_device(call))); + BC_ASSERT_STRING_EQUAL(newCamId,ms_web_cam_get_string_id(_linphone_call_get_video_device(call))); linphone_call_enable_camera(call,FALSE); linphone_core_iterate(marie->lc); linphone_call_enable_camera(call,TRUE); - BC_ASSERT_STRING_EQUAL(newCamId,ms_web_cam_get_string_id(linphone_call_get_video_device(call))); + BC_ASSERT_STRING_EQUAL(newCamId,ms_web_cam_get_string_id(_linphone_call_get_video_device(call))); } - linphone_core_terminate_all_calls(pauline->lc); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1)); linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); } -test_t video_tests[] = { -#if HAVE_GTK - TEST_NO_TAG("Early-media video during video call", early_media_video_during_video_call_test), - TEST_NO_TAG("Two incoming early-media video calls", two_incoming_early_media_video_calls_test), - TEST_NO_TAG("Early-media video with inactive audio", early_media_video_with_inactive_audio), - TEST_NO_TAG("Forked outgoing early-media video call with inactive audio", forked_outgoing_early_media_video_call_with_inactive_audio_test), -#endif /*HAVE_GTK*/ - TEST_NO_TAG("Enable/disable camera after camera switches", enable_disable_camera_after_camera_switches) +typedef struct struct_qrcode_callback_data { + int qrcode_found; + char *text; +}qrcode_callback_data; + + +static void qrcode_found_cb(LinphoneCore *lc, const char *result) { + LinphoneCoreCbs *cbs = linphone_core_get_current_callbacks(lc); + qrcode_callback_data *found = (qrcode_callback_data *)linphone_core_cbs_get_user_data(cbs); + found->qrcode_found = TRUE; + if (result) { + if (found->text) ms_free(found->text); + found->text = ms_strdup(result); + } +} + +typedef struct struct_image_rect { + int x; + int y; + int w; + int h; +}image_rect; + +static void _decode_qrcode(const char* image_path, image_rect *rect) { + qrcode_callback_data qrcode_data; + char *qrcode_image; + LinphoneCoreManager* lcm = NULL; + MSFactory* factory = NULL; + factory = ms_factory_new_with_voip(); + if (!ms_factory_lookup_filter_by_name(factory, "MSQRCodeReader")) { + ms_error("QRCode support is not built-in"); + goto end; + } + + lcm =linphone_core_manager_create("empty_rc"); + LinphoneCoreCbs* cbs = NULL; + qrcode_data.qrcode_found = FALSE; + qrcode_data.text = NULL; + linphone_core_manager_start(lcm, FALSE); + + qrcode_image = bc_tester_res(image_path); + + linphone_core_set_video_device(lcm->lc, liblinphone_tester_static_image_id); + linphone_core_set_static_picture(lcm->lc, qrcode_image); + + linphone_core_enable_qrcode_video_preview(lcm->lc, TRUE); + cbs = linphone_core_get_current_callbacks(lcm->lc); + linphone_core_cbs_set_qrcode_found(cbs, qrcode_found_cb); + linphone_core_cbs_set_user_data(cbs, &qrcode_data); + if (rect) { + linphone_core_set_qrcode_decode_rect(lcm->lc, rect->x, rect->y, rect->w, rect->h); + } + linphone_core_enable_video_preview(lcm->lc, TRUE); + + BC_ASSERT_TRUE(wait_for_until(lcm->lc, NULL, &qrcode_data.qrcode_found, TRUE, 2000)); + if (qrcode_data.qrcode_found) { + if (BC_ASSERT_PTR_NOT_NULL(qrcode_data.text)) { + ms_message("QRCode decode: %s", qrcode_data.text); + BC_ASSERT_STRING_EQUAL(qrcode_data.text, "https://www.linphone.org/"); + } + } + + if (qrcode_data.text) ms_free(qrcode_data.text); + if (qrcode_image) ms_free(qrcode_image); + + linphone_core_enable_video_preview(lcm->lc, FALSE); + linphone_core_manager_destroy(lcm); +end: + ms_factory_destroy(factory); +} + +static void decode_qrcode_from_image(void) { + _decode_qrcode("images/linphonesiteqr.jpg", NULL); +} + +static void decode_qrcode_from_zone(void) { + image_rect rect; + rect.x = 332; + rect.y = 470; + rect.w = 268; + rect.h = 262; + _decode_qrcode("images/linphonesiteqr_captured.jpg", &rect); +} + +test_t video_tests[] = { + TEST_NO_TAG("Enable/disable camera after camera switches", enable_disable_camera_after_camera_switches), + TEST_ONE_TAG("Decode QRCode from image", decode_qrcode_from_image, "QRCode"), + TEST_ONE_TAG("Decode QRCode from zone", decode_qrcode_from_zone, "QRCode") }; -test_suite_t video_test_suite = {"Video", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, - sizeof(video_tests) / sizeof(video_tests[0]), video_tests}; +test_suite_t video_test_suite = { + "Video", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, + sizeof(video_tests) / sizeof(video_tests[0]), video_tests +}; -#endif /* VIDEO_ENABLED */ +#endif // ifdef VIDEO_ENABLED diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index fdc797c02..3c66c9cf2 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -33,31 +33,31 @@ endif() set(LP_AUTO_ANSWER_SOURCE_FILES auto_answer.c) bc_apply_compile_flags(LP_AUTO_ANSWER_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(lp-auto-answer ${USE_BUNDLE} ${LP_AUTO_ANSWER_SOURCE_FILES}) -target_link_libraries(lp-auto-answer ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) +target_link_libraries(lp-auto-answer ${LINPHONE_LIBS_FOR_TOOLS} ${MEDIASTREAMER2_LIBRARIES} ${ORTP_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(lp-auto-answer PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set(LP_SENDMSG_SOURCE_FILES lpsendmsg.c) bc_apply_compile_flags(LP_SENDMSG_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(lp-sendmsg ${USE_BUNDLE} ${LP_SENDMSG_SOURCE_FILES}) -target_link_libraries(lp-sendmsg ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES}) +target_link_libraries(lp-sendmsg ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(lp-sendmsg PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set(LP_LPC2XML_TEST_SOURCE_FILES lpc2xml_test.c) bc_apply_compile_flags(LP_LPC2XML_TEST_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(lpc2xml_test ${USE_BUNDLE} ${LP_LPC2XML_TEST_SOURCE_FILES}) -target_link_libraries(lpc2xml_test ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES}) +target_link_libraries(lpc2xml_test ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(lpc2xml_test PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set(LP_XML2LPC_TEST_SOURCE_FILES xml2lpc_test.c) bc_apply_compile_flags(LP_XML2LPC_TEST_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(xml2lpc_test ${USE_BUNDLE} ${LP_XML2LPC_TEST_SOURCE_FILES}) -target_link_libraries(xml2lpc_test ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES}) +target_link_libraries(xml2lpc_test ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(xml2lpc_test PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") set(LP_TEST_ECC_SOURCE_FILES test_ecc.c) bc_apply_compile_flags(LP_TEST_ECC_SOURCE_FILES STRICT_OPTIONS_CPP STRICT_OPTIONS_C) add_executable(lp-test-ecc ${USE_BUNDLE} ${LP_TEST_ECC_SOURCE_FILES}) -target_link_libraries(lp-test-ecc ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES}) +target_link_libraries(lp-test-ecc ${LINPHONE_LIBS_FOR_TOOLS} ${ORTP_LIBRARIES} ${MEDIASTREAMER2_LIBRARIES} ${BCTOOLBOX_CORE_LIBRARIES} ${XSD_LIBRARIES}) set_target_properties(lp-test-ecc PROPERTIES LINK_FLAGS "${LINPHONE_LDFLAGS}") if (NOT IOS) diff --git a/tools/abstractapi.py b/tools/abstractapi.py index d7a247ca1..e4a464b43 100644 --- a/tools/abstractapi.py +++ b/tools/abstractapi.py @@ -19,13 +19,65 @@ import re import genapixml as CApi import metaname +import logging -class Error(RuntimeError): - pass +logger = logging.getLogger(__name__) -class BlacklistedException(Error): +class Error(Exception): + @property + def reason(self): + return self.args[0] + + def __str__(self): + return str(self.reason) + + @staticmethod + def _name_get_type_as_string(name): + if type(name) is metaname.ClassName: + return 'class' + elif type(name) is metaname.EnumName: + return 'enum' + elif type(name) is metaname.EnumeratorName: + return 'enumerator' + elif type(name) is metaname.MethodName: + return 'function' + else: + raise TypeError('{0} not handled'.format(type(name))) + + +class ParsingError(Error): + @property + def context(self): + return self.args[1] if len(self.args) >= 2 else None + + def __str__(self): + if self.context is None: + return Error.__str__(self) + else: + params = { + 'reason': self.reason, + 'name': self.context.to_c(addBrackets=True), + 'type_': Error._name_get_type_as_string(self.context) + } + return "error while parsing {name} {type_}: {reason}".format(**params) + + +class BlacklistedSymbolError(Error): + @property + def name(self): + return self.args[0] + + def __str__(self): + params = { + 'name': self.name.to_c(addBrackets=True), + 'type_': Error._name_get_type_as_string(self.name) + } + return "{name} {type_} has been blacklisted".format(**params) + + +class TranslationError(Error): pass @@ -58,11 +110,18 @@ class Object(object): def __lt__(self, other): return self.name < other.name - def find_first_ancestor_by_type(self, *types): + def find_first_ancestor_by_type(self, *types, **kargs): + try: + priorAncestor = kargs['priorAncestor'] + except KeyError: + priorAncestor = False + + current = self ancestor = self.parent while ancestor is not None and type(ancestor) not in types: + current = ancestor ancestor = ancestor.parent - return ancestor + return ancestor if not priorAncestor else current class Type(Object): @@ -107,14 +166,14 @@ class ListType(Type): self.containedTypeName = containedTypeName self._containedTypeDesc = None - def _set_contained_type_desc(self, desc): - self._containedTypeDesc = desc - desc.parent = self - - def _get_contained_type_desc(self): + @property + def containedTypeDesc(self): return self._containedTypeDesc - containedTypeDesc = property(fset=_set_contained_type_desc, fget=_get_contained_type_desc) + @containedTypeDesc.setter + def containedTypeDesc(self, desc): + self._containedTypeDesc = desc + desc.parent = self def translate(self, translator, **params): return translator.translate_list_type(self, **params) @@ -125,25 +184,25 @@ class DocumentableObject(Object): Object.__init__(self, name) self._briefDescription = None self._detailedDescription = None - self.deprecated = None - def _get_brief_description(self): + @property + def briefDescription(self): return self._briefDescription - def _set_brief_description(self, description): + @briefDescription.setter + def briefDescription(self, description): self._briefDescription = description description.relatedObject = self - def _get_detailed_description(self): + @property + def detailedDescription(self): return self._detailedDescription - def _set_detailed_description(self, description): + @detailedDescription.setter + def detailedDescription(self, description): self._detailedDescription = description description.relatedObject = self - briefDescription = property(fget=_get_brief_description, fset=_set_brief_description) - detailedDescription = property(fget=_get_detailed_description, fset=_set_detailed_description) - def set_from_c(self, cObject, namespace=None): self.briefDescription = cObject.briefDescription self.detailedDescription = cObject.detailedDescription @@ -154,7 +213,7 @@ class DocumentableObject(Object): if isinstance(self, (Namespace,Enum,Class)): return self elif self.parent is None: - raise Error('{0} is not attached to a namespace object'.format(self)) + return None else: return self.parent.get_namespace_object() @@ -162,11 +221,45 @@ class DocumentableObject(Object): class Namespace(DocumentableObject): def __init__(self, name): DocumentableObject.__init__(self, name) - self.children = [] + self.enums = [] + self.classes = [] + self.interfaces = [] + + def addenum(self, enum): + Namespace._insert_element(self.enums, enum) + enum.parent = self + + def delenum(self, enum): + i = self.enums.index(enum) + del self.enums[i] + enum.parent = None + + def addclass(self, class_): + Namespace._insert_element(self.classes, class_) + class_.parent = self + + def delclass(self, class_): + i = self.classes.index(class_) + del self.classes[i] + class_.parent = None - def add_child(self, child): - self.children.append(child) - child.parent = self + def addinterface(self, interface): + Namespace._insert_element(self.interfaces, interface) + interface.parent = self + + def delinterface(self, interface): + i = self.interfaces.index(interface) + del self.interfaces[i] + interface.parent = None + + @staticmethod + def _insert_element(l, e): + try: + inspoint = next(x for x in l if e.name < x.name) + index = l.index(inspoint) + l.insert(index, e) + except StopIteration: + l.append(e) GlobalNs = Namespace('') @@ -228,14 +321,14 @@ class Argument(DocumentableObject): self.optional = optional self.default = default - def _set_type(self, _type): - self._type = _type - _type.parent = self - - def _get_type(self): + @property + def type(self): return self._type - type = property(fset=_set_type, fget=_get_type) + @type.setter + def type(self, _type): + self._type = _type + _type.parent = self def translate(self, translator, **params): return translator.translate_argument(self, **params) @@ -257,14 +350,14 @@ class Method(DocumentableObject): self.args.append(arg) arg.parent = self - def _set_return_type(self, returnType): - self._returnType = returnType - returnType.parent = self - - def _get_return_type(self): + @property + def returnType(self): return self._returnType - returnType = property(fset=_set_return_type, fget=_get_return_type) + @returnType.setter + def returnType(self, returnType): + self._returnType = returnType + returnType.parent = self def translate_as_prototype(self, translator, **params): return translator.translate_method_as_prototype(self, **params) @@ -277,56 +370,57 @@ class Property(DocumentableObject): self._getter = None self._type = None - def set_setter(self, setter): + @property + def setter(self): + return self._setter + + @setter.setter + def setter(self, setter): self._setter = setter setter.parent = self - def get_setter(self): - return self._setter + @property + def getter(self): + return self._getter - def set_getter(self, getter): + @getter.setter + def getter(self, getter): self._getter = getter if self._type is None: self._type = getter.returnType getter.parent = self - - def get_getter(self): - return self._getter - - setter = property(fset=set_setter, fget=get_setter) - getter = property(fset=set_getter, fget=get_getter) -class Class(DocumentableObject): +class Class(Namespace): def __init__(self, name): - DocumentableObject.__init__(self, name) + Namespace.__init__(self, name) self.properties = [] self.instanceMethods = [] self.classMethods = [] self._listenerInterface = None self.multilistener = False self.refcountable = False - + def add_property(self, property): - self.properties.append(property) + Namespace._insert_element(self.properties, property) property.parent = self def add_instance_method(self, method): - self.instanceMethods.append(method) + Namespace._insert_element(self.instanceMethods, method) method.parent = self def add_class_method(self, method): - self.classMethods.append(method) + Namespace._insert_element(self.classMethods, method) method.parent = self - def set_listener_interface(self, interface): - self._listenerInterface = interface - interface._listenedClass = self - - def get_listener_interface(self): + @property + def listenerInterface(self): return self._listenerInterface - listenerInterface = property(fget=get_listener_interface, fset=set_listener_interface) + @listenerInterface.setter + def listenerInterface(self, interface): + self._listenerInterface = interface + interface._listenedClass = self def sort(self): self.properties.sort() @@ -334,27 +428,36 @@ class Class(DocumentableObject): self.classMethods.sort() -class Interface(DocumentableObject): +class Interface(Namespace): def __init__(self, name): - DocumentableObject.__init__(self, name) - self.methods = [] + Namespace.__init__(self, name) + self.instanceMethods = [] + self.classMethods = [] self._listenedClass = None - - def add_method(self, method): - self.methods.append(method) + + def add_instance_methods(self, method): + self.instanceMethods.append(method) method.parent = self - - def get_listened_class(self): + + def add_class_methods(self, method): + self.classMethods.append(method) + method.parent = self + + @property + def listenedClass(self): return self._listenedClass - - listenedClass = property(fget=get_listened_class) - + + @listenedClass.setter + def listenedClass(self, method): + self.instanceMethods.append(method) + method.parent = self + def sort(self): - self.methods.sort() + self.instanceMethods.sort() class CParser(object): - def __init__(self, cProject): + def __init__(self, cProject, classBlAppend=[]): self.cBaseType = ['void', 'bool_t', 'char', 'short', 'int', 'long', 'size_t', 'time_t', 'float', 'double', 'LinphoneStatus'] self.cListType = 'bctbx_list_t' self.regexFixedSizeInteger = '^(u?)int(\d?\d)_t$' @@ -367,15 +470,41 @@ class CParser(object): 'linphone_vcard_get_belcard'] # manually wrapped self.classBl = ['LpConfig'] # temporarly blacklisted + for bl in classBlAppend: + self.classBl.append(bl) # list of classes that must be concidered as refcountable even if # they are no ref()/unref() methods self.forcedRefcountableClasses = ['LinphoneFactory'] + self.enum_relocations = { + 'LinphoneAccountCreatorActivationCodeStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorDomainStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorEmailStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorLanguageStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorPasswordStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorPhoneNumberStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorTransportStatus' : 'LinphoneAccountCreator', + 'LinphoneAccountCreatorUsernameStatus' : 'LinphoneAccountCreator', + 'LinphoneCallDir' : 'LinphoneCall', + 'LinphoneCallState' : 'LinphoneCall', + 'LinphoneCallStatus' : 'LinphoneCall', + 'LinphoneChatRoomState' : 'LinphoneChatRoom', + 'LinphoneChatMessageDirection' : 'LinphoneChatMessage', + 'LinphoneChatMessageState' : 'LinphoneChatMessage', + 'LinphoneCoreLogCollectionUploadState' : 'LinphoneCore', + 'LinphoneEventLogType' : 'LinphoneEventLog', + 'LinphoneFriendListStatus' : 'LinphoneFriendList', + 'LinphoneFriendListSyncStatus' : 'LinphoneFriendList', + 'LinphonePlayerState' : 'LinphonePlayer', + 'LinphonePresenceActivityType' : 'LinphonePresenceActivity', + 'LinphoneTunnelMode' : 'LinphoneTunnel' + } + self.cProject = cProject self.enumsIndex = {} - self.enums = [] for enum in self.cProject.enums: if enum.associatedTypedef is None: self.enumsIndex[enum.name] = None @@ -384,8 +513,6 @@ class CParser(object): self.classesIndex = {} self.interfacesIndex = {} - self.classes = [] - self.interfaces = [] for _class in self.cProject.classes: if _class.name not in self.classBl: if _class.name.endswith('Cbs'): @@ -409,6 +536,7 @@ class CParser(object): name.from_snake_case('linphone') self.namespace = Namespace(name) + self._pending_enums = [] def _is_blacklisted(self, name): if type(name) is metaname.MethodName: @@ -422,23 +550,34 @@ class CParser(object): for enum in self.cProject.enums: try: self.parse_enum(enum) - except Error as e: - print('Could not parse \'{0}\' enum: {1}'.format(enum.name, e.args[0])) + except BlacklistedSymbolError as e: + logger.debug(e) - for _class in self.cProject.classes: + for class_ in self.cProject.classes: try: - self.parse_class(_class) - except BlacklistedException: - pass - except Error as e: - print('Could not parse \'{0}\' class: {1}'.format(_class.name, e.args[0])) - + self.parse_class(class_) + except BlacklistedSymbolError as e: + logger.debug(e) + self._treat_pending_enums() self._clean_all_indexes() - self._sortall() self._fix_all_types() self._fix_all_docs() + def _treat_pending_enums(self): + for enum in self._pending_enums: + try: + enum_cname = enum.name.to_c() + parent_cname = self.enum_relocations[enum_cname] + newparent = self.classesIndex[parent_cname] + enum.parent.delenum(enum) + newparent.addenum(enum) + enum.name.from_c(enum_cname, namespace=newparent.name) + except KeyError: + reason = "cannot move the enum inside {0} enum because it doesn't exsist".format(parent_cname) + raise ParsingError(reason, context=enum.name) + self._pending_enums = [] + def _clean_all_indexes(self): for index in [self.classesIndex, self.interfacesIndex, self.methodsIndex]: self._clean_index(index) @@ -452,15 +591,6 @@ class CParser(object): for key in keysToRemove: del index[key] - def _sortall(self): - self.enums.sort() - self.classes.sort() - self.interfaces.sort() - for class_ in self.classes: - class_.sort() - for interface in self.interfaces: - interface.sort() - def _class_is_refcountable(self, _class): if _class.name in self.forcedRefcountableClasses: return True @@ -494,7 +624,7 @@ class CParser(object): self._fix_all_types_in_method(method) def _fix_all_types_in_interface(self, interface): - for method in interface.methods: + for method in interface.instanceMethods: self._fix_all_types_in_method(method) def _fix_all_types_in_method(self, method): @@ -502,8 +632,8 @@ class CParser(object): self._fix_type(method.returnType) for arg in method.args: self._fix_type(arg.type) - except Error as e: - print('warning: some types could not be fixed in {0}() function: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0])) + except ParsingError as e: + raise ParsingError(e, method.name) def _fix_type(self, _type): if isinstance(_type, EnumType) and _type.desc is None: @@ -524,7 +654,7 @@ class CParser(object): if _type.containedTypeName is not None: _type.containedTypeDesc = self.parse_c_base_type(_type.containedTypeName) else: - raise Error('bctbx_list_t type without specified contained type') + raise ParsingError('bctbx_list_t type without specified contained type') def _fix_all_docs(self): for _class in self.classesIndex.values(): @@ -543,17 +673,12 @@ class CParser(object): obj.detailedDescription.resolve_all_references(self) def parse_enum(self, cenum): - if 'associatedTypedef' in dir(cenum): - nameStr = cenum.associatedTypedef.name - else: - nameStr = cenum.name - name = metaname.EnumName() - name.from_camel_case(nameStr, namespace=self.namespace.name) + name.from_camel_case(cenum.publicName, namespace=self.namespace.name) enum = Enum(name) enum.briefDescription = cenum.briefDoc enum.detailedDescription = cenum.detailedDoc - self.namespace.add_child(enum) + self.namespace.addenum(enum) for cEnumValue in cenum.values: valueName = metaname.EnumeratorName() @@ -565,26 +690,31 @@ class CParser(object): try: aEnumValue.value_from_string(cEnumValue.value) except ValueError: - raise Error('{0} enum value has an invalid definition ({1})'.format(cEnumValue.name, cEnumValue.value)) + reason = '{0} enum value has an invalid definition ({1})'.format(cEnumValue.name, cEnumValue.value) + context = metaname.EnumeratorName() + context.from_camel_case(cEnumValue.name) + raise ParsingError(reason, context) enum.add_enumerator(aEnumValue) - self.enumsIndex[nameStr] = enum - self.enums.append(enum) + self.enumsIndex[cenum.publicName] = enum + if cenum.publicName in self.enum_relocations: + self._pending_enums.append(enum) return enum def parse_class(self, cclass): if cclass.name in self.classBl: - raise BlacklistedException('{0} is blacklisted'.format(cclass.name)); + name = metaname.ClassName() + name.from_snake_case(cclass.name) + raise BlacklistedSymbolError(name) if cclass.name.endswith('Cbs'): _class = self._parse_listener(cclass) self.interfacesIndex[cclass.name] = _class - self.interfaces.append(_class) + self.namespace.addinterface(_class) else: _class = self._parse_class(cclass) self.classesIndex[cclass.name] = _class - self.classes.append(_class) - self.namespace.add_child(_class) + self.namespace.addclass(_class) return _class def _parse_class(self, cclass): @@ -602,8 +732,8 @@ class CParser(object): _class.add_property(absProperty) else: _class.listenerInterface = self.interfacesIndex[cproperty.getter.returnArgument.ctype] - except Error as e: - print('Could not parse {0} property in {1}: {2}'.format(cproperty.name, cclass.name, e.args[0])) + except BlacklistedSymbolError as e: + logger.debug(e) for cMethod in cclass.instanceMethods.values(): try: @@ -616,20 +746,15 @@ class CParser(object): pass else: _class.add_instance_method(method) - - except BlacklistedException: - pass - except Error as e: - print('Could not parse {0} function: {1}'.format(cMethod.name, e.args[0])) - + except BlacklistedSymbolError as e: + logger.debug(e) + for cMethod in cclass.classMethods.values(): try: method = self.parse_method(cMethod, type=Method.Type.Class, namespace=name) _class.add_class_method(method) - except BlacklistedException: - pass - except Error as e: - print('Could not parse {0} function: {1}'.format(cMethod.name, e.args[0])) + except BlacklistedSymbolError as e: + logger.debug(e) return _class @@ -651,27 +776,28 @@ class CParser(object): def _parse_listener(self, cclass): - name = metaname.InterfaceName() - name.from_camel_case(cclass.name, namespace=self.namespace.name) - - if name.words[len(name.words)-1] == 'cbs': - name.words[len(name.words)-1] = 'listener' - else: - raise Error('{0} is not a listener'.format(cclass.name)) - - listener = Interface(name) - listener.briefDescription = cclass.briefDoc - listener.detailedDescription = cclass.detailedDoc - - for property in cclass.properties.values(): - if property.name != 'user_data': - try: - method = self._parse_listener_property(property, listener, cclass.events) - listener.add_method(method) - except Error as e: - print('Could not parse property \'{0}\' of listener \'{1}\': {2}'.format(property.name, cclass.name, e.args[0])) - - return listener + try: + name = metaname.InterfaceName() + name.from_camel_case(cclass.name, namespace=self.namespace.name) + name.words[-1] = 'listener' + + listener = Interface(name) + listener.briefDescription = cclass.briefDoc + listener.detailedDescription = cclass.detailedDoc + + for property in cclass.properties.values(): + if property.name != 'user_data': + try: + method = self._parse_listener_property(property, listener, cclass.events) + listener.add_instance_methods(method) + except BlacklistedSymbolError as e: + logger.debug(e) + + return listener + except ParsingError as e: + context = metaname.ClassName() + context.from_camel_case(cclass.name) + raise ParsingError(e, context) def _parse_listener_property(self, property, listener, events): methodName = metaname.MethodName() @@ -684,12 +810,12 @@ class CParser(object): elif property.setter is not None and len(property.setter.arguments) == 2: eventName = property.setter.arguments[1].ctype else: - raise Error('event name for {0} property of {1} listener not found'.format(property.name, listener.name.to_snake_case(fullName=True))) + raise ParsingError('event name for {0} property of {1} listener not found'.format(property.name, listener.name.to_c())) try: event = events[eventName] except KeyError: - raise Error('invalid event name \'{0}\''.format(eventName)) + raise ParsingError('invalid event name \'{0}\''.format(eventName)) method = Method(methodName) method.returnType = self.parse_type(event.returnArgument) @@ -698,6 +824,8 @@ class CParser(object): argName.from_snake_case(arg.name) argument = Argument(argName, self.parse_type(arg)) method.add_arguments(argument) + method.briefDescription = event.briefDoc + method.detailedDescription = event.detailedDoc return method @@ -705,27 +833,30 @@ class CParser(object): name = metaname.MethodName() name.from_snake_case(cfunction.name, namespace=namespace) - if self._is_blacklisted(name): - raise BlacklistedException('{0} is blacklisted'.format(name.to_c())); - - method = Method(name, type=type) - method.briefDescription = cfunction.briefDoc - method.detailedDescription = cfunction.detailedDoc - method.deprecated = cfunction.deprecated - method.returnType = self.parse_type(cfunction.returnArgument) - - for arg in cfunction.arguments: - if type == Method.Type.Instance and arg is cfunction.arguments[0]: - method.isconst = ('const' in arg.completeType.split(' ')) - else: - aType = self.parse_type(arg) - argName = metaname.ArgName() - argName.from_snake_case(arg.name) - absArg = Argument(argName, aType) - method.add_arguments(absArg) - - self.methodsIndex[cfunction.name] = method - return method + try: + if self._is_blacklisted(name): + raise BlacklistedSymbolError(name) + + method = Method(name, type=type) + method.briefDescription = cfunction.briefDoc + method.detailedDescription = cfunction.detailedDoc + method.deprecated = cfunction.deprecated + method.returnType = self.parse_type(cfunction.returnArgument) + + for arg in cfunction.arguments: + if type == Method.Type.Instance and arg is cfunction.arguments[0]: + method.isconst = ('const' in arg.completeType.split(' ')) + else: + aType = self.parse_type(arg) + argName = metaname.ArgName() + argName.from_snake_case(arg.name) + absArg = Argument(argName, aType) + method.add_arguments(absArg) + + self.methodsIndex[cfunction.name] = method + return method + except ParsingError as e: + raise ParsingError(e, name) def parse_type(self, cType): if cType.ctype in self.cBaseType or re.match(self.regexFixedSizeInteger, cType.ctype): @@ -741,7 +872,7 @@ class CParser(object): elif cType.ctype.endswith('Mask'): absType = BaseType('integer', isUnsigned=True) else: - raise Error('Unknown C type \'{0}\''.format(cType.ctype)) + raise ParsingError('Unknown C type \'{0}\''.format(cType.ctype)) absType.cDecl = cType.completeType return absType @@ -790,7 +921,7 @@ class CParser(object): elif 'isref' not in param or param['isref'] is False: param['isref'] = True else: - raise Error('Unhandled double-pointer') + raise ParsingError('Unhandled double-pointer') else: matchCtx = re.match(self.regexFixedSizeInteger, elem) if matchCtx: @@ -800,13 +931,14 @@ class CParser(object): param['size'] = int(matchCtx.group(2)) if param['size'] not in [8, 16, 32, 64]: - raise Error('{0} C basic type has an invalid size ({1})'.format(cDecl, param['size'])) + raise ParsingError('{0} C basic type has an invalid size ({1})'.format(cDecl, param['size'])) if name is not None: return BaseType(name, **param) else: - raise Error('could not find type in \'{0}\''.format(cDecl)) + raise ParsingError('could not find type in \'{0}\''.format(cDecl)) + class Translator: @@ -824,6 +956,13 @@ class Translator: except KeyError: raise ValueError("Invalid language code: '{0}'".format(langCode)) + @staticmethod + def _namespace_to_name_translator_params(namespace): + return { + 'recursive': True, + 'topAncestor': namespace.name if namespace is not None else None + } + class CLikeLangTranslator(Translator): def translate_enumerator_value(self, value): @@ -836,8 +975,11 @@ class CLikeLangTranslator(Translator): else: raise TypeError('invalid enumerator value type: {0}'.format(value)) - def translate_argument(self, argument, **kargs): - return '{0} {1}'.format(argument.type.translate(self, **kargs), argument.name.translate(self.nameTranslator)) + def translate_argument(self, argument, hideArgName=False, namespace=None): + ret = argument.type.translate(self, namespace=namespace) + if not hideArgName: + ret += (' ' + argument.name.translate(self.nameTranslator)) + return ret class CLangTranslator(CLikeLangTranslator): @@ -847,19 +989,19 @@ class CLangTranslator(CLikeLangTranslator): self.falseConstantToken = 'FALSE' self.trueConstantToken = 'TRUE' - def translate_base_type(self, _type): + def translate_base_type(self, _type, **kargs): return _type.cDecl - def translate_enum_type(self, _type): + def translate_enum_type(self, _type, **kargs): return _type.cDecl - def translate_class_type(self, _type): + def translate_class_type(self, _type, **kargs): return _type.cDecl - def translate_list_type(self, _type): + def translate_list_type(self, _type, **kargs): return _type.cDecl - def translate_enumerator_value(self, value): + def translate_enumerator_value(self, value, **kargs): if value is None: return None elif isinstance(value, int): @@ -869,19 +1011,20 @@ class CLangTranslator(CLikeLangTranslator): else: raise TypeError('invalid enumerator value type: {0}'.format(value)) - def translate_method_as_prototype(self, method, **params): - _class = method.find_first_ancestor_by_type(Class) - params = '{const}{className} *obj'.format( - className=_class.name.to_c(), - const='const ' if method.isconst else '' - ) - for arg in method.args: - params += (', ' + arg.translate(self)) - - return '{returnType} {name}({params})'.format( - returnType=method.returnType.translate(self), + def translate_method_as_prototype(self, method, hideArguments=False, hideArgNames=False, hideReturnType=False, stripDeclarators=False, namespace=None): + _class = method.find_first_ancestor_by_type(Class,Interface) + params = [] + if not hideArguments: + params.append('{const}{className} *obj'.format( + className=_class.name.to_c(), + const='const ' if method.isconst and not stripDeclarators else '' + )) + for arg in method.args: + params.append(arg.translate(self, hideArgName=hideArgNames)) + return '{returnType}{name}({params})'.format( + returnType=(method.returnType.translate(self) + ' ') if not hideReturnType else '', name=method.name.translate(self.nameTranslator), - params=params + params=', '.join(params) ) @@ -893,7 +1036,7 @@ class CppLangTranslator(CLikeLangTranslator): self.trueConstantToken = 'true' self.ambigousTypes = [] - def translate_base_type(self, _type, showStdNs=True, namespace=None): + def translate_base_type(self, _type, namespace=None): if _type.name == 'void': if _type.isref: return 'void *' @@ -923,18 +1066,15 @@ class CppLangTranslator(CLikeLangTranslator): elif _type.name == 'status': res = 'linphone::Status' elif _type.name == 'string': - res = CppLangTranslator.prepend_std('string', showStdNs) + res = 'std::string' if type(_type.parent) is Argument: res += ' &' elif _type.name == 'string_array': - res = '{0}<{1}>'.format( - CppLangTranslator.prepend_std('list', showStdNs), - CppLangTranslator.prepend_std('string', showStdNs) - ) + res = 'std::list' if type(_type.parent) is Argument: res += ' &' else: - raise Error('\'{0}\' is not a base abstract type'.format(_type.name)) + raise TranslationError('\'{0}\' is not a base abstract type'.format(_type.name)) if _type.isUnsigned: if _type.name == 'integer' and isinstance(_type.size, int): @@ -950,97 +1090,160 @@ class CppLangTranslator(CLikeLangTranslator): res += ' *' return res - def translate_enum_type(self, _type, showStdNs=True, namespace=None): - if _type.desc is None: - raise Error('{0} has not been fixed'.format(_type.name)) + def translate_enum_type(self, type_, namespace=None): + if type_.desc is None: + raise TranslationError('{0} has not been fixed'.format(type_.name)) + return type_.desc.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)) + + def translate_class_type(self, type_, namespace=None): + if type_.desc is None: + raise TranslationError('{0} has not been fixed'.format(type_.name)) + res = type_.desc.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)) - if namespace is not None: - nsName = namespace.name if namespace is not GlobalNs else None - else: - method = _type.find_first_ancestor_by_type(Method) - nsName = metaname.Name.find_common_parent(_type.desc.name, method.name) - - return _type.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) - - def translate_class_type(self, _type, showStdNs=True, namespace=None): - if _type.desc is None: - raise Error('{0} has not been fixed'.format(_type.name)) - - if namespace is not None: - nsName = namespace.name if namespace is not GlobalNs else None - else: - method = _type.find_first_ancestor_by_type(Method) - nsName = metaname.Name.find_common_parent(_type.desc.name, method.name) - - if _type.desc.name.to_c() in self.ambigousTypes: - nsName = None - - res = _type.desc.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName) - - if _type.desc.refcountable: - if _type.isconst: + if type_.desc.refcountable: + if type_.isconst: res = 'const ' + res - if type(_type.parent) is Argument: - return 'const {0}<{1}> &'.format( - CppLangTranslator.prepend_std('shared_ptr', showStdNs), - res - ) + if type(type_.parent) is Argument: + return 'const std::shared_ptr<{0}> &'.format(res) else: - return '{0}<{1}>'.format( - CppLangTranslator.prepend_std('shared_ptr', showStdNs), - res - ) + return 'std::shared_ptr<{0}>'.format(res) else: - if type(_type.parent) is Argument: + if type(type_.parent) is Argument: return 'const {0} &'.format(res) else: return '{0}'.format(res) - def translate_list_type(self, _type, showStdNs=True, namespace=None): + def translate_list_type(self, _type, namespace=None): if _type.containedTypeDesc is None: - raise Error('{0} has not been fixed'.format(_type.containedTypeName)) + raise TranslationError('{0} has not been fixed'.format(_type.containedTypeName)) elif isinstance(_type.containedTypeDesc, BaseType): res = _type.containedTypeDesc.translate(self) else: - res = _type.containedTypeDesc.translate(self, showStdNs=showStdNs, namespace=namespace) + res = _type.containedTypeDesc.translate(self, namespace=namespace) if type(_type.parent) is Argument: - return 'const {0}<{1} > &'.format( - CppLangTranslator.prepend_std('list', showStdNs), - res - ) + return 'const std::list<{0}> &'.format(res) else: - return '{0}<{1} >'.format( - CppLangTranslator.prepend_std('list', showStdNs), - res - ) + return 'std::list<{0}>'.format(res) - def translate_method_as_prototype(self, method, showStdNs=True, namespace=None): - _class = method.find_first_ancestor_by_type(Class, Interface) - if namespace is not None: - if _class.name.to_c() in self.ambigousTypes: - nsName = None - else: - nsName = namespace.name if namespace is not GlobalNs else None - else: - nsName = _class.name - - argsString = '' - argStrings = [] - for arg in method.args: - argStrings.append(arg.translate(self, showStdNs=showStdNs, namespace=namespace)) - argsString = ', '.join(argStrings) - - return '{_return} {name}({args}){const}'.format( - _return=method.returnType.translate(self, ), - name=method.name.translate(self.nameTranslator, recursive=True, topAncestor=nsName), - args=argsString, - const=' const' if method.isconst else '' + def translate_method_as_prototype(self, method, hideArguments=False, hideArgNames=False, hideReturnType=False, stripDeclarators=False, namespace=None): + argsAsString = ', '.join([arg.translate(self, hideArgName=hideArgNames, namespace=namespace) for arg in method.args]) if not hideArguments else '' + return '{return_}{name}({args}){const}'.format( + return_=(method.returnType.translate(self, namespace=namespace) + ' ') if not hideReturnType else '', + name=method.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)), + args=argsAsString, + const=' const' if method.isconst and not stripDeclarators else '' + ) + + +class JavaLangTranslator(CLikeLangTranslator): + def __init__(self): + self.nameTranslator = metaname.Translator.get('Java') + self.nilToken = 'null' + self.falseConstantToken = 'false' + self.trueConstantToken = 'true' + + def translate_base_type(self, type_, native=False, jni=False, isReturn=False, namespace=None): + if type_.name == 'string': + if jni: + return 'jstring' + return 'String' + elif type_.name == 'integer': + if type_.size is not None and type_.isref: + if jni: + return 'jbyteArray' + return 'byte[]' + if jni: + return 'jint' + return 'int' + elif type_.name == 'boolean': + if jni: + return 'jboolean' + return 'boolean' + elif type_.name == 'floatant': + if jni: + return 'jfloat' + return 'float' + elif type_.name == 'size': + if jni: + return 'jint' + return 'int' + elif type_.name == 'time': + if jni: + return 'jlong' + return 'long' + elif type_.name == 'status': + if jni: + return 'jint' + if native: + return 'int' + return 'void' + elif type_.name == 'string_array': + if jni: + return 'jobjectArray' + return 'String[]' + elif type_.name == 'character': + if jni: + return 'jchar' + return 'char' + elif type_.name == 'void': + if isReturn: + return 'void' + if jni: + return 'jobject' + return 'Object' + return type_.name + + def translate_enum_type(self, _type, native=False, jni=False, isReturn=False, namespace=None): + if native: + return 'int' + elif jni: + return 'jint' + else: + return _type.desc.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)) + + def translate_class_type(self, _type, native=False, jni=False, isReturn=False, namespace=None): + if jni: + return 'jobject' + return _type.desc.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)) + + def translate_list_type(self, _type, native=False, jni=False, isReturn=False, namespace=None): + if jni: + if type(_type.containedTypeDesc) is ClassType: + return 'jobjectArray' + elif type(_type.containedTypeDesc) is BaseType: + if _type.containedTypeDesc.name == 'string': + return 'jobjectArray' + return _type.containedTypeDesc.translate(self, jni=True) + 'Array' + elif type(_type.containedTypeDesc) is EnumType: + ptrtype = _type.containedTypeDesc.translate(self, native=native) + ptrtype = '' + if type(_type.containedTypeDesc) is ClassType: + ptrtype = _type.containedTypeDesc.translate(self, native=native, namespace=namespace) + elif type(_type.containedTypeDesc) is BaseType: + ptrtype = _type.containedTypeDesc.translate(self, native=native, namespace=namespace) + elif type(_type.containedTypeDesc) is EnumType: + ptrtype = _type.containedTypeDesc.translate(self, native=native, namespace=namespace) + else: + if _type.containedTypeDesc: + raise Error('translation of bctbx_list_t of ' + _type.containedTypeDesc.name) + else: + raise Error('translation of bctbx_list_t of unknow type !') + return ptrtype + '[]' + + def translate_argument(self, arg, native=False, jni=False, hideArgName=False, namespace=None): + res = arg.type.translate(self, native=native, jni=jni, namespace=namespace) + if not hideArgName: + res += (' ' + arg.name.translate(self.nameTranslator)) + return res + + def translate_method_as_prototype(self, method, hideArguments=False, hideArgNames=False, hideReturnType=False, stripDeclarators=False, namespace=None): + return '{public}{returnType}{methodName}({arguments})'.format( + public='public ' if not stripDeclarators else '', + returnType=(method.returnType.translate(self, isReturn=True, namespace=namespace) + ' ') if not hideReturnType else '', + methodName=method.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)), + arguments=', '.join([arg.translate(self, hideArgName=hideArgNames, namespace=namespace) for arg in method.args]) if not hideArguments else '' ) - - @staticmethod - def prepend_std(string, prepend): - return 'std::' + string if prepend else string class CSharpLangTranslator(CLikeLangTranslator): @@ -1050,7 +1253,7 @@ class CSharpLangTranslator(CLikeLangTranslator): self.falseConstantToken = 'false' self.trueConstantToken = 'true' - def translate_base_type(self, _type, dllImport=True): + def translate_base_type(self, _type, dllImport=True, namespace=None): if _type.name == 'void': if _type.isref: return 'IntPtr' @@ -1095,20 +1298,20 @@ class CSharpLangTranslator(CLikeLangTranslator): else: return 'IEnumerable' else: - raise Error('\'{0}\' is not a base abstract type'.format(_type.name)) + raise TranslationError('\'{0}\' is not a base abstract type'.format(_type.name)) return res - def translate_enum_type(self, _type, dllImport=True): + def translate_enum_type(self, _type, dllImport=True, namespace=None): if dllImport and type(_type.parent) is Argument: return 'int' else: - return _type.desc.name.translate(self.nameTranslator) + return _type.desc.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)) - def translate_class_type(self, _type, dllImport=True): - return "IntPtr" if dllImport else _type.desc.name.translate(self.nameTranslator) + def translate_class_type(self, _type, dllImport=True, namespace=None): + return "IntPtr" if dllImport else _type.desc.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)) - def translate_list_type(self, _type, dllImport=True): + def translate_list_type(self, _type, dllImport=True, namespace=None): if dllImport: return 'IntPtr' else: @@ -1116,32 +1319,27 @@ class CSharpLangTranslator(CLikeLangTranslator): if _type.containedTypeDesc.name == 'string': return 'IEnumerable' else: - raise Error('translation of bctbx_list_t of basic C types is not supported') + raise TranslationError('translation of bctbx_list_t of basic C types is not supported') elif type(_type.containedTypeDesc) is ClassType: - ptrType = _type.containedTypeDesc.desc.name.translate(self.nameTranslator) + ptrType = _type.containedTypeDesc.desc.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)) return 'IEnumerable<' + ptrType + '>' else: if _type.containedTypeDesc: - raise Error('translation of bctbx_list_t of enums') + raise TranslationError('translation of bctbx_list_t of enums') else: - raise Error('translation of bctbx_list_t of unknow type !') + raise TranslationError('translation of bctbx_list_t of unknow type !') - def translate_argument(self, arg, dllImport=True): + def translate_argument(self, arg, dllImport=True, namespace=None): return '{0} {1}'.format( - arg.type.translate(self, dllImport=dllImport), + arg.type.translate(self, dllImport=dllImport, namespace=None), arg.name.translate(self.nameTranslator) ) - def translate_method_as_prototype(self, method): - kargs = { - 'static' : 'static ' if method.type == Method.Type.Class else '', - 'override' : 'override ' if method.name.translate(self.nameTranslator) == 'ToString' else '', - 'returnType' : method.returnType.translate(self, dllImport=False), - 'name' : method.name.translate(self.nameTranslator), - 'args' : '' - } - for arg in method.args: - if kargs['args'] != '': - kargs['args'] += ', ' - kargs['args'] += arg.translate(self, dllImport=False) - return '{static}{override}{returnType} {name}({args})'.format(**kargs) + def translate_method_as_prototype(self, method, hideArguments=False, hideArgNames=False, hideReturnType=False, stripDeclarators=False, namespace=None): + return '{static}{override}{returnType}{name}({args})'.format( + static = 'static ' if method.type == Method.Type.Class and not stripDeclarators else '', + override = 'override ' if method.name.translate(self.nameTranslator) == 'ToString' and not stripDeclarators else '', + returnType = (method.returnType.translate(self, dllImport=False, namespace=namespace) + ' ') if not hideReturnType else '', + name = method.name.translate(self.nameTranslator, **Translator._namespace_to_name_translator_params(namespace)), + args = ', '.join([arg.translate(self, dllImport=False, namespace=namespace) for arg in method.args]) if not hideArguments else '' + ) diff --git a/tools/genapixml.py b/tools/genapixml.py index 29a0dedf8..e3f699cff 100755 --- a/tools/genapixml.py +++ b/tools/genapixml.py @@ -17,15 +17,20 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import argparse +import logging import os import six import string import sys import xml.etree.ElementTree as ET import xml.dom.minidom as minidom + import metadoc +logger = logging.getLogger(__name__) + + class CObject: def __init__(self, name): self.name = name.strip() @@ -47,6 +52,10 @@ class CEnum(CObject): CObject.__init__(self, name) self.values = [] self.associatedTypedef = None + + @property + def publicName(self): + return self.associatedTypedef.name if self.associatedTypedef is not None else self.name def addValue(self, value): self.values.append(value) @@ -239,7 +248,6 @@ class CClass(CObject): class Project: def __init__(self): - self.verbose = False self.prettyPrint = False self.enums = [] self.__structs = [] @@ -251,37 +259,28 @@ class Project: def add(self, elem): if isinstance(elem, CClass): - if self.verbose: - print("Adding class " + elem.name) + logger.debug("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) + msg = 'Adding enum {0}'.format(elem.name) + for value in elem.values: + msg += ('\t{0}'.format(value)) + logger.debug(msg) 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) + msg = "Adding struct " + elem.name + for sm in elem.members: + msg += ('\t{0} {1}'.format(sm.ctype, sm.name)) + logger.debug(msg) self.__structs.append(elem) elif isinstance(elem, CTypedef): - if self.verbose: - print("Adding typedef " + elem.name) - print("\t" + elem.definition) + logger.debug('Adding typedef {0}\t{1}'.format(elem.name, 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)) + logger.debug('Adding event {0}\tReturns: {1}\tArguments: {2}'.format(elem.name, elem.returnArgument.ctype, 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)) + logger.debug('Adding event {0}\tReturns: {1}\tArguments: {2}'.format(elem.name, elem.returnArgument.ctype, elem.arguments)) self.__functions.append(elem) def __cleanDescription(self, descriptionNode): @@ -330,7 +329,7 @@ class Project: break if not structFound: name = td.definition[7:] - print("Structure with no associated typedef: " + name) + logger.warning("Structure with no associated typedef: " + name) st = CStruct(name) st.associatedTypedef = td self.add(st) @@ -461,6 +460,8 @@ class Project: definition = node.find('./definition').text if definition.startswith('typedef '): definition = definition[8 :] + briefDoc = self.docparser.parse_description(node.find('./briefdescription')) + detailedDoc = self.docparser.parse_description(node.find('./detaileddescription')) if name.endswith('Cb'): pos = definition.find("(*") if pos == -1: @@ -490,7 +491,14 @@ class Project: elif spacePos != -1: argType = argdef[0 : spacePos] argName = argdef[spacePos + 1 :] - argslist.addArgument(CArgument(argType, argName, self.enums, self.__structs)) + arg = CArgument(argType, argName, self.enums, self.__structs) + if arg.ctype == 'MSList' or arg.ctype == 'bctbx_list_t': + for argentry in node.findall("detaileddescription/para/parameterlist[@kind='param']/*"): + if argentry.find("parameternamelist[parametername='{0}']".format(argName)) is not None: + containedType = argentry.find("parameterdescription//bctbxlist") + arg.containedType = containedType.text if containedType is not None else None + break + argslist.addArgument(arg) if len(argslist) > 0: paramdescs = node.findall("detaileddescription/para/parameterlist[@kind='param']/parameteritem") if paramdescs: @@ -503,15 +511,15 @@ class Project: if arg.description == None: missingDocWarning += "\t'" + arg.name + "' parameter not documented\n"; if missingDocWarning != '': - print(name + ":\n" + missingDocWarning) + logger.warning(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.briefDoc = self.docparser.parse_description(node.find('./briefdescription')) - f.detailedDoc = self.docparser.parse_description(node.find('./detaileddescription')) + f.briefDoc = briefDoc f.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + f.detailedDoc = detailedDoc return f else: pos = definition.rfind(" " + name) @@ -522,9 +530,9 @@ class Project: if deprecatedNode is not None: td.deprecated = True td.briefDescription = ''.join(node.find('./briefdescription').itertext()).strip() - td.briefDoc = self.docparser.parse_description(node.find('./briefdescription')) - td.detailedDoc = self.docparser.parse_description(node.find('./detaileddescription')) + td.briefDoc = briefDoc td.detailedDescription = self.__cleanDescription(node.find('./detaileddescription')) + td.detailedDoc = detailedDoc return td return None @@ -599,7 +607,7 @@ class Project: if not f.location.endswith('.h'): missingDocWarning += "\tNot documented in a header file ('" + f.location + "')\n"; if missingDocWarning != '': - print(name + ":\n" + missingDocWarning) + logger.warning(name + ":\n" + missingDocWarning) return f def __findCFunction(self, tree): @@ -614,11 +622,10 @@ class Project: for f in xmlfiles: tree = None try: - if self.verbose: - print("Parsing XML file: " + f.name) + logger.debug("Parsing XML file: " + f) tree = ET.parse(f) except ET.ParseError as e: - print(e) + logger.error(e) if tree is not None: trees.append(tree) for tree in trees: @@ -639,7 +646,7 @@ class Project: for c in self.classes: for name, p in six.iteritems(c.properties): if p.getter is None and p.setter is not None: - print("Property '" + name + "' of class '" + c.name + "' has a setter but no getter") + logger.warning("Property '" + name + "' of class '" + c.name + "' has a setter but no getter") class Generator: @@ -764,7 +771,7 @@ class Generator: classNode.append(cclass.detailedDescription) def generate(self, project): - print("Generating XML document of Linphone API to '" + self.__outputfile.name + "'") + logger.info("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: @@ -797,7 +804,9 @@ def main(argv = None): args.outputfile = open('api.xml', 'w') project = Project() if args.verbose: - project.verbose = True + logger.setLogLevel(logging.DEBUG) + else: + logger.setLogLevel(logging.INFO) if args.pretty: project.prettyPrint = True project.initFromDir(args.xmldir) diff --git a/tools/metadoc.py b/tools/metadoc.py index f4de51a56..1e4967e08 100644 --- a/tools/metadoc.py +++ b/tools/metadoc.py @@ -14,8 +14,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -import metaname + import abstractapi +import logging +import metaname import re @@ -136,25 +138,43 @@ class Reference(ParagraphPart): ParagraphPart.__init__(self) self.cname = cname self.relatedObject = None - - def translate(self, docTranslator, **kargs): - return docTranslator.translate_reference(self, **kargs) + + @staticmethod + def make_ref_from_object(cname, obj): + if isinstance(obj, (abstractapi.Enum, abstractapi.Enumerator, abstractapi.Class, abstractapi.Interface)): + ref = ClassReference(cname) + elif isinstance(obj, abstractapi.Method): + ref = FunctionReference(cname) + else: + raise TypeError('cannot create documentation reference from {0}'.format(str(obj))) + ref.relatedObject = obj + return ref class ClassReference(Reference): + def translate(self, docTranslator, **kargs): + if self.relatedObject is None: + raise ReferenceTranslationError(self.cname) + return docTranslator.translate_class_reference(self, **kargs) + def resolve(self, api): try: self.relatedObject = api.classesIndex[self.cname] except KeyError: - print('doc reference pointing on an unknown object ({0})'.format(self.cname)) + logging.warning('doc reference pointing on an unknown object ({0})'.format(self.cname)) class FunctionReference(Reference): + def translate(self, docTranslator, **kargs): + if self.relatedObject is None: + raise ReferenceTranslationError(self.cname) + return docTranslator.translate_function_reference(self, **kargs) + def resolve(self, api): try: self.relatedObject = api.methodsIndex[self.cname] except KeyError: - print('doc reference pointing on an unknown object ({0})'.format(self.cname)) + logging.warning('doc reference pointing on an unknown object ({0})'.format(self.cname)) class Paragraph(MultiChildTreeNode): @@ -369,8 +389,21 @@ class Parser: return ClassReference(node.text) +class TranslationError(Exception): + pass + + +class ReferenceTranslationError(TranslationError): + def __init__(self, refName): + Exception.__init__(self, refName) + + def msg(self): + return '{0} reference could not been translated'.format(self.args[0]) + + class Translator: def __init__(self, langCode): + self.langCode = langCode self.textWidth = 80 self.nameTranslator = metaname.Translator.get(langCode) self.langTranslator = abstractapi.Translator.get(langCode) @@ -403,12 +436,13 @@ class Translator: else: if namespace is None: description = ref.find_root() - namespaceObj = description.relatedObject.find_first_ancestor_by_type(abstractapi.Namespace, abstractapi.Class) - namespace = namespaceObj.name - if namespace.is_prefix_of(ref.relatedObject.name): - commonName = namespace + namespace = description.relatedObject.find_first_ancestor_by_type(abstractapi.Namespace, abstractapi.Class) + if namespace is abstractapi.GlobalNs: + commonName = None + elif namespace.name.is_prefix_of(ref.relatedObject.name): + commonName = namespace.name else: - commonName = metaname.Name.find_common_parent(ref.relatedObject.name, namespace) + commonName = metaname.Name.find_common_parent(ref.relatedObject.name, namespace.name) return ref.relatedObject.name.translate(self.nameTranslator, recursive=True, topAncestor=commonName) def translate_keyword(self, keyword): @@ -431,8 +465,8 @@ class Translator: strPara += part else: strPara += part.translate(self) - except TranslationError as e: - print('warning: {0}'.format(e.msg())) + except ReferenceTranslationError: + strPara += part.cname return strPara @@ -477,29 +511,20 @@ class Translator: pass -class TranslationError(Exception): - pass - - -class ReferenceTranslationError(TranslationError): - def __init__(self, refName): - Exception.__init__(self, refName) - - def msg(self): - return '{0} reference could not be translated'.format(self.args[0]) - - class DoxygenTranslator(Translator): def _tag_as_brief(self, lines): if len(lines) > 0: lines[0] = '@brief ' + lines[0] - - def translate_reference(self, ref): - refStr = Translator.translate_reference(self, ref) + + def translate_class_reference(self, ref, **kargs): if isinstance(ref.relatedObject, (abstractapi.Class, abstractapi.Enum)): - return '#' + refStr - elif isinstance(ref.relatedObject, abstractapi.Method): - return refStr + '()' + return '#' + Translator.translate_reference(self, ref) + else: + raise ReferenceTranslationError(ref.cname) + + def translate_function_reference(self, ref, **kargs): + if isinstance(ref.relatedObject, abstractapi.Method): + return Translator.translate_reference(self, ref) + '()' else: raise ReferenceTranslationError(ref.cname) @@ -519,20 +544,29 @@ class DoxygenTranslator(Translator): return text +class JavaDocTranslator(DoxygenTranslator): + def __init__(self): + DoxygenTranslator.__init__(self, 'C') + + def _tag_as_brief(self, lines): + pass + + class SphinxTranslator(Translator): def __init__(self, langCode): Translator.__init__(self, langCode) if langCode == 'C': - self.domain = 'c' + self.domain = 'cpp' self.classDeclarator = 'type' + self.interfaceDeclarator = self.classDeclarator self.methodDeclarator = 'function' - self.enumDeclarator = 'type' - self.enumeratorDeclarator = 'var' - self.enumeratorReferencer = 'data' + self.enumDeclarator = 'enum' + self.enumeratorDeclarator = 'enumerator' self.methodReferencer = 'func' elif langCode == 'Cpp': self.domain = 'cpp' self.classDeclarator = 'class' + self.interfaceDeclarator = self.classDeclarator self.methodDeclarator = 'function' self.enumDeclarator = 'enum' self.enumeratorDeclarator = 'enumerator' @@ -541,14 +575,25 @@ class SphinxTranslator(Translator): elif langCode == 'CSharp': self.domain = 'csharp' self.classDeclarator = 'class' + self.interfaceDeclarator = self.classDeclarator self.methodDeclarator = 'method' self.enumDeclarator = 'enum' self.enumeratorDeclarator = 'value' self.namespaceDeclarator = 'namespace' self.classReferencer = 'type' + self.interfaceReferencer = self.classReferencer self.enumReferencer = 'type' self.enumeratorReferencer = 'enum' self.methodReferencer = 'meth' + elif langCode == 'Java': + self.domain = 'java' + self.classDeclarator = 'type' + self.interfaceDeclarator = self.classDeclarator + self.methodDeclarator = 'method' + self.enumDeclarator = 'type' + self.enumeratorDeclarator = 'field' + self.namespaceDeclarator = 'package' + self.methodReferencer = 'meth' else: raise ValueError('invalid language code: {0}'.format(langCode)) @@ -570,18 +615,30 @@ class SphinxTranslator(Translator): return self.get_declarator(typeName) except AttributeError: raise ValueError("'{0}' referencer type not supported".format(typeName)) - - def translate_reference(self, ref, label=None, namespace=None): - strRef = Translator.translate_reference(self, ref, absName=True) - kargs = { - 'tag' : self._sphinx_ref_tag(ref), - 'ref' : strRef, - } - kargs['label'] = label if label is not None else Translator.translate_reference(self, ref, namespace=namespace) - if isinstance(ref, FunctionReference): - kargs['label'] += '()' - - return ':{tag}:`{label} <{ref}>`'.format(**kargs) + + def translate_class_reference(self, ref, label=None, namespace=None): + return ':{tag}:`{label} <{ref}>`'.format( + tag=self._sphinx_ref_tag(ref), + label=label if label is not None else Translator.translate_reference(self, ref, namespace=namespace), + ref=Translator.translate_reference(self, ref, absName=True) + ) + + def translate_function_reference(self, ref, label=None, useNamespace=True, namespace=None): + if self.domain == 'csharp': + refStr = ref.relatedObject.name.translate(self.nameTranslator, **abstractapi.Translator._namespace_to_name_translator_params(namespace)) + else: + refStr = ref.relatedObject.translate_as_prototype(self.langTranslator, + hideArguments=self.domain != 'java', + hideArgNames=self.domain == 'java', + hideReturnType=True, + stripDeclarators=True, + namespace=namespace + ) + return ':{tag}:`{label} <{ref}>`'.format( + tag=self._sphinx_ref_tag(ref), + label=label if label is not None else '{0}()'.format(Translator.translate_reference(self, ref, namespace=namespace)), + ref=refStr + ) def translate_keyword(self, keyword): translatedKeyword = Translator.translate_keyword(self, keyword) @@ -631,9 +688,11 @@ class SandCastleTranslator(Translator): if len(lines) > 0: lines.insert(0, '') lines.append('') - - def translate_reference(self, ref): + + def translate_function_reference(self, ref): + refStr = Translator.translate_reference(self, ref, absName=True) + return ''.format(refStr) + + def translate_class_reference(self, ref): refStr = Translator.translate_reference(self, ref, absName=True) - if isinstance(ref, FunctionReference): - refStr += '()' return ''.format(refStr) diff --git a/tools/metaname.py b/tools/metaname.py index 6a76e6f71..e1efd8bff 100644 --- a/tools/metaname.py +++ b/tools/metaname.py @@ -103,7 +103,7 @@ class Name(object): res += elem.title() return res else: - return Name.to_camel_case(self.prev, fullName=True, lower=lower) + Name.to_camel_case(self) + return self.prev.to_camel_case(fullName=True, lower=lower) + self.to_camel_case() def concatenate(self, upper=False, fullName=False): if self.prev is None or not fullName: @@ -144,17 +144,24 @@ class Name(object): class ClassName(Name): - def to_c(self): + def to_c(self, addBrackets=False): return self.to_camel_case(fullName=True) - + + def from_c(self, name, **kargs): + self.from_camel_case(name, **kargs) + def translate(self, translator, **params): return translator.translate_class_name(self, **params) class InterfaceName(ClassName): - def to_c(self): + def to_c(self, addBrackets=False): return ClassName.to_c(self)[:-8] + 'Cbs' - + + def from_c(self, **kargs): + ClassName.from_c(self, **kargs) + self.words[-1] = 'listener' + def translate(self, translator, **params): return translator.translate_interface_name(self, **params) @@ -183,18 +190,27 @@ class MethodName(Name): self.overloadRef = int(suffix) del self.words[-1] - def to_c(self): + def to_c(self, addBrackets=False): suffix = ('_' + str(self.overloadRef)) if self.overloadRef > 0 else '' - return self.to_snake_case(fullName=True) + suffix + cName = self.to_snake_case(fullName=True) + suffix + if addBrackets: + cName += '()' + return cName + + def from_c(self, **kargs): + self.from_snake_case(**kargs) def translate(self, translator, **params): return translator.translate_method_name(self, **params) class ArgName(Name): - def to_c(self): + def to_c(self, addBrackets=False): return self.to_snake_case() + def from_c(self, **kargs): + self.from_snake_case(**kargs) + def translate(self, translator, **params): return translator.translate_argument_name(self, **params) @@ -318,9 +334,6 @@ class CppTranslator(JavaTranslator): JavaTranslator.__init__(self) self.nsSep = '::' self.keyWordEscapes = {'new' : '_new'} - - def translate_enumerator_name(self, name, **params): - return self.translate_enum_name(name.prev, **params) + name.to_camel_case() class CSharpTranslator(JavaTranslator): diff --git a/tools/python/apixml2python.py b/tools/python/apixml2python.py index 5c9ebc1e0..c0d57b85e 100755 --- a/tools/python/apixml2python.py +++ b/tools/python/apixml2python.py @@ -44,30 +44,21 @@ blacklisted_events = [ 'LinphoneCoreTextMessageReceivedCb' # not respecting naming convention ] 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_start_file_download', # callback function in parameter 'linphone_chat_message_state_to_string', # There is no use to wrap this function 'linphone_chat_room_send_chat_message', # Use linphone_chat_room_send_chat_message_2 instead - 'linphone_chat_room_send_message2', # callback function in parameter - 'linphone_config_for_each_entry', # to be handwritten because of callback - 'linphone_config_for_each_section', # to be handwritten because of callback 'linphone_config_get_range', # to be handwritten because of result via arguments 'linphone_config_load_dict_to_section', # missing LinphoneDictionary 'linphone_config_section_to_dict', # missing LinphoneDictionary 'linphone_core_add_listener', - 'linphone_core_can_we_add_call', # private function 'linphone_core_enable_log_collection', # need to handle class properties 'linphone_core_enable_logs', # unhandled argument type FILE 'linphone_core_enable_logs_with_cb', # callback function in parameter 'linphone_core_get_audio_port_range', # to be handwritten because of result via arguments 'linphone_core_get_default_proxy', - 'linphone_core_get_network_simulator_params', # missing OrtpNetworkSimulatorParams - 'linphone_core_get_supported_video_sizes', # missing MSVideoSizeDef 'linphone_core_get_tunnel', # blacklisted LinphoneTunnel - 'linphone_core_get_video_policy', # missing LinphoneVideoPolicy 'linphone_core_get_video_port_range', # to be handwritten because of result via arguments 'linphone_core_new', # replaced by linphone_factory_create_core 'linphone_core_new_with_config', # replaced by linphone_factory_create_core_with_config @@ -77,13 +68,7 @@ blacklisted_functions = [ 'linphone_core_set_log_collection_max_file_size', # need to handle class properties 'linphone_core_set_log_collection_path', # need to handle class properties 'linphone_core_set_log_collection_prefix', # need to handle class properties - 'linphone_core_set_log_file', # There is no use to wrap this function - 'linphone_core_set_log_handler', # Hand-written but put directly in the linphone module - 'linphone_core_set_log_level', # There is no use to wrap this function 'linphone_core_set_log_level_mask', # There is no use to wrap this function - 'linphone_core_set_network_simulator_params', # missing OrtpNetworkSimulatorParams - 'linphone_core_set_video_policy', # missing LinphoneVideoPolicy - 'linphone_nat_policy_get_stun_server_addrinfo', '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 diff --git a/wrappers/cpp/CMakeLists.txt b/wrappers/cpp/CMakeLists.txt index 5fedcd2b0..1e2e25a10 100644 --- a/wrappers/cpp/CMakeLists.txt +++ b/wrappers/cpp/CMakeLists.txt @@ -21,6 +21,8 @@ ############################################################################ add_custom_command(OUTPUT include/linphone++/linphone.hh src/linphone++.cc + COMMAND ${CMAKE_COMMAND} -E remove_directory include + COMMAND ${CMAKE_COMMAND} -E remove_directory src COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/genwrapper.py" "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml" DEPENDS ${PROJECT_SOURCE_DIR}/tools/genapixml.py ${PROJECT_SOURCE_DIR}/tools/metadoc.py @@ -32,7 +34,6 @@ add_custom_command(OUTPUT include/linphone++/linphone.hh src/linphone++.cc enums_header.mustache main_header.mustache linphone-doc - "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml/index.xml" ) add_library(linphone++ SHARED diff --git a/wrappers/cpp/class_header.mustache b/wrappers/cpp/class_header.mustache index 98da45224..abf06361c 100644 --- a/wrappers/cpp/class_header.mustache +++ b/wrappers/cpp/class_header.mustache @@ -29,10 +29,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. {{/includes}} #include "object.hh" -{{#_class}}{{#isfactory}} -#include "config.hh" -{{/isfactory}}{{/_class}} - {{#_class}}{{#isVcard}} namespace belcard { class BelCard; @@ -50,7 +46,7 @@ struct {{{privCClassName}}}; namespace linphone { {{#priorDeclarations}} - class {{{name}}}; + {{{declaration}}}; {{/priorDeclarations}} {{#_class}} @@ -71,8 +67,32 @@ namespace linphone { {{#friendClasses}} friend class {{name}}; {{/friendClasses}} - + public: + {{#enums}} + {{#doc}} + /** + {{#lines}} + * {{{line}}} + {{/lines}} + * + */ + {{/doc}} + enum class {{name}} { + {{#enumerators}} + {{#doc}} + /** + {{#lines}} + * {{{line}}} + {{/lines}} + */ + {{/doc}} + {{name}}{{#value}} = {{{value}}}{{/value}}{{#notLast}},{{/notLast}} + {{/enumerators}} + }; + + {{/enums}} + {{#isNotListener}} {{#isrefcountable}} {{{className}}}(void *ptr, bool takeRef=true); @@ -86,7 +106,7 @@ namespace linphone { {{/isnotrefcountable}} LINPHONECXX_PUBLIC {{{privCClassName}}} *cPtr() {return ({{{privCClassName}}} *)mPrivPtr;} {{/isNotListener}} - + {{#ismonolistenable}} LINPHONECXX_PUBLIC void setListener(const std::shared_ptr<{{{listenerClassName}}}> &listener); {{/ismonolistenable}} @@ -96,21 +116,13 @@ namespace linphone { LINPHONECXX_PUBLIC void addListener(const std::shared_ptr<{{{listenerClassName}}}> &listener); LINPHONECXX_PUBLIC void removeListener(const std::shared_ptr<{{{listenerClassName}}}> &listener); {{/ismultilistenable}} - - {{#isListener}} - LINPHONECXX_PUBLIC virtual ~{{{className}}}() = default; - {{/isListener}} - + public: - {{#isfactory}} - LINPHONECXX_PUBLIC std::shared_ptr createCore(const std::shared_ptr &listener, const std::string & configPath, const std::string & factoryConfigPath) const; - LINPHONECXX_PUBLIC std::shared_ptr createCoreWithConfig(const std::shared_ptr &listener, const std::shared_ptr & config) const; - {{/isfactory}} {{#isVcard}} LINPHONECXX_PUBLIC std::shared_ptr &getVcard(); {{/isVcard}} - - + + {{#methods}} /** {{#briefDoc}} @@ -126,7 +138,7 @@ namespace linphone { {{/detailedDoc}} */ LINPHONECXX_PUBLIC {{#deprecated}}LINPHONECXX_DEPRECATED {{/deprecated}}{{#isListener}}virtual {{/isListener}}{{{declPrototype}}}{{{suffix}}}; - + {{/methods}} {{#staticMethods}}; /** @@ -143,20 +155,20 @@ namespace linphone { {{/detailedDoc}} */ LINPHONECXX_PUBLIC {{#deprecated}}LINPHONECXX_DEPRECATED {{/deprecated}}static {{{declPrototype}}}; - + {{/staticMethods}} {{#ismultilistenable}} private: static void *createCallbacks(void *userData); {{/ismultilistenable}} - - + + {{#ismultilistenable}} private: void *mCallbacks; {{/ismultilistenable}} - + {{#isnotrefcountable}} private: void *mPrivPtr; diff --git a/wrappers/cpp/class_impl.mustache b/wrappers/cpp/class_impl.mustache index 8c3a83e70..f780ed6e5 100644 --- a/wrappers/cpp/class_impl.mustache +++ b/wrappers/cpp/class_impl.mustache @@ -39,7 +39,7 @@ static {{{returnType}}} {{{cbName}}}({{{declArgs}}}) { {{#ismultilistenable}} {{{cListenerName}}} *cbs = {{{currentCallbacksGetter}}}({{{firstArgName}}}); - std::list > &listeners = *(std::list > *){{{userDataGetter}}}(cbs); + std::list > listeners = *(std::list > *){{{userDataGetter}}}(cbs); for(auto it=listeners.begin(); it!=listeners.end(); it++) { std::shared_ptr<{{{cppListenerName}}}> listener = std::static_pointer_cast<{{{cppListenerName}}},Listener>(*it); {{{cppMethodCallingLine}}}; @@ -118,50 +118,6 @@ void *{{{className}}}::createCallbacks(void *userData) { } {{/ismultilistenable}} -{{#isfactory}} -std::shared_ptr Factory::createCore(const std::shared_ptr & listener, const std::string & configPath, const std::string & factoryConfigPath) const { - ::LinphoneCoreCbs *cbs = NULL; - std::list > listeners; - if (listener != nullptr) { - listeners.push_back(std::static_pointer_cast(listener)); - cbs = (::LinphoneCoreCbs *)Core::createCallbacks(&listeners); - } - - ::LinphoneFactory *factory = linphone_factory_get(); - ::LinphoneCore *core_ptr = linphone_factory_create_core(factory, cbs, StringUtilities::cppStringToC(configPath), StringUtilities::cppStringToC(factoryConfigPath)); - - if (cbs != NULL) { - linphone_core_remove_callbacks(core_ptr, cbs); - linphone_core_cbs_unref(cbs); - } - - std::shared_ptr cppCore = cPtrToSharedPtr((::belle_sip_object_t *)core_ptr, false); - if (listener != nullptr) cppCore->addListener(listener); - return cppCore; -} - -std::shared_ptr Factory::createCoreWithConfig(const std::shared_ptr & listener, const std::shared_ptr & config) const { - ::LinphoneCoreCbs *cbs = NULL; - std::list > listeners; - if (listener != nullptr) { - listeners.push_back(std::static_pointer_cast(listener)); - cbs = (::LinphoneCoreCbs *)Core::createCallbacks(&listeners); - } - - ::LinphoneFactory *factory = linphone_factory_get(); - ::LinphoneCore *core_ptr = linphone_factory_create_core_with_config(factory, cbs, (::LinphoneConfig *)sharedPtrToCPtr(config)); - - if (cbs != NULL) { - linphone_core_remove_callbacks(core_ptr, cbs); - linphone_core_cbs_unref(cbs); - } - - std::shared_ptr cppCore = cPtrToSharedPtr((::belle_sip_object_t *)core_ptr, false); - if (listener != nullptr) cppCore->addListener(listener); - return cppCore; -} -{{/isfactory}} - {{#isVcard}} std::shared_ptr &Vcard::getVcard() { return *(shared_ptr *)linphone_vcard_get_belcard((LinphoneVcard *)mPrivPtr); diff --git a/wrappers/cpp/enums_header.mustache b/wrappers/cpp/enums_header.mustache index 648a19e77..026f70e38 100644 --- a/wrappers/cpp/enums_header.mustache +++ b/wrappers/cpp/enums_header.mustache @@ -30,7 +30,7 @@ namespace linphone { * */ {{/doc}} - enum {{name}} { + enum class {{name}} { {{#enumerators}} {{#doc}} /** diff --git a/wrappers/cpp/genwrapper.py b/wrappers/cpp/genwrapper.py index 77b9b3b7c..c67edb99a 100755 --- a/wrappers/cpp/genwrapper.py +++ b/wrappers/cpp/genwrapper.py @@ -21,8 +21,10 @@ import pystache import re import argparse import os +import os.path import sys import errno +import logging sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools')) import genapixml as CApi @@ -34,19 +36,16 @@ import metaname class CppTranslator(object): sharedPtrTypeExtractor = re.compile('^(const )?std::shared_ptr<(.+)>( &)?$') - def __init__(self): - self.ambigousTypes = ['LinphonePayloadType'] + def __init__(self, rootNs=None): self.nameTranslator = metaname.Translator.get('Cpp') self.langTranslator = AbsApi.Translator.get('Cpp') self.langTranslator.ambigousTypes.append('LinphonePayloadType') self.docTranslator = metadoc.DoxygenTranslator('Cpp') - - def is_ambigous_type(self, _type): - return _type.name in self.ambigousTypes or (_type.name == 'list' and self.is_ambigous_type(_type.containedTypeDesc)) + self.rootNs = rootNs def translate_enum(self, enum): enumDict = {} - enumDict['name'] = enum.name.to_camel_case() + enumDict['name'] = enum.name.translate(self.nameTranslator) enumDict['doc'] = enum.briefDescription.translate(self.docTranslator) enumDict['enumerators'] = [] for enumerator in enum.enumerators: @@ -58,9 +57,12 @@ class CppTranslator(object): def translate_enumerator(self, enumerator): enumeratorDict = { 'name' : enumerator.name.translate(self.nameTranslator), - 'doc' : enumerator.briefDescription.translate(self.docTranslator), 'value' : enumerator.translate_value(self.langTranslator) } + try: + enumeratorDict['doc'] = enumerator.briefDescription.translate(self.docTranslator) + except metadoc.TranslationError as e: + logging.error(e.msg()) return enumeratorDict def translate_class(self, _class): @@ -77,12 +79,12 @@ class CppTranslator(object): 'isnotrefcountable' : not _class.refcountable, 'isNotListener' : True, 'isListener' : False, - 'isfactory' : (_class.name.to_c() == 'LinphoneFactory'), 'isVcard' : (_class.name.to_c() == 'LinphoneVcard'), 'className' : _class.name.translate(self.nameTranslator), 'cClassName' : '::' + _class.name.to_c(), 'privCClassName' : '_' + _class.name.to_c(), 'parentClassName' : 'Object' if _class.refcountable else None, + 'enums' : [], 'methods' : [], 'staticMethods' : [], 'wrapperCbs' : [], @@ -92,14 +94,17 @@ class CppTranslator(object): if _class.name.to_c() == 'LinphoneCore': classDict['friendClasses'].append({'name': 'Factory'}); - classDict['briefDoc'] = _class.briefDescription.translate(self.docTranslator, tagAsBrief=True) - classDict['detailedDoc'] = _class.detailedDescription.translate(self.docTranslator) + try: + classDict['briefDoc'] = _class.briefDescription.translate(self.docTranslator, tagAsBrief=True) + classDict['detailedDoc'] = _class.detailedDescription.translate(self.docTranslator) + except metadoc.TranslationError as e: + logging.error(e.msg()) if islistenable: classDict['listenerClassName'] = _class.listenerInterface.name.translate(self.nameTranslator) classDict['cListenerName'] = _class.listenerInterface.name.to_c() classDict['cppListenerName'] = _class.listenerInterface.name.translate(self.nameTranslator) - for method in _class.listenerInterface.methods: + for method in _class.listenerInterface.instanceMethods: classDict['wrapperCbs'].append(self._generate_wrapper_callback(_class, method)) if ismonolistenable: @@ -113,26 +118,20 @@ class CppTranslator(object): classDict['userDataSetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_set_user_data' classDict['userDataGetter'] = _class.listenerInterface.name.to_snake_case(fullName=True)[:-len('_listener')] + '_cbs_get_user_data' classDict['currentCallbacksGetter'] = _class.name.to_snake_case(fullName=True) + '_get_current_callbacks' + + for enum in _class.enums: + classDict['enums'].append(self.translate_enum(enum)) for _property in _class.properties: - try: - classDict['methods'] += self.translate_property(_property) - except AbsApi.Error as e: - print('error while translating {0} property: {1}'.format(_property.name.to_snake_case(), e.args[0])) + classDict['methods'] += self.translate_property(_property) for method in _class.instanceMethods: - try: - methodDict = self.translate_method(method) - classDict['methods'].append(methodDict) - except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0])) - + methodDict = self.translate_method(method) + classDict['methods'].append(methodDict) + for method in _class.classMethods: - try: - methodDict = self.translate_method(method) - classDict['staticMethods'].append(methodDict) - except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0])) + methodDict = self.translate_method(method) + classDict['staticMethods'].append(methodDict) return classDict @@ -174,12 +173,9 @@ class CppTranslator(object): 'isListener' : True, 'methods' : [] } - for method in interface.methods: - try: - methodDict = self.translate_method(method, genImpl=False) - intDict['methods'].append(methodDict) - except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0])) + for method in interface.instanceMethods: + methodDict = self.translate_method(method, genImpl=False) + intDict['methods'].append(methodDict) return intDict @@ -192,17 +188,21 @@ class CppTranslator(object): return res def translate_method(self, method, genImpl=True): - namespace = method.find_first_ancestor_by_type(AbsApi.Namespace) + namespace = method.find_first_ancestor_by_type(AbsApi.Class, AbsApi.Interface) methodDict = { - 'declPrototype': method.translate_as_prototype(self.langTranslator), - 'implPrototype': method.translate_as_prototype(self.langTranslator, namespace=namespace), + 'declPrototype': method.translate_as_prototype(self.langTranslator, namespace=namespace), + 'implPrototype': method.translate_as_prototype(self.langTranslator, namespace=AbsApi.GlobalNs), 'deprecated': method.deprecated, 'suffix': '', - 'briefDoc': method.briefDescription.translate(self.docTranslator, tagAsBrief=True) if method.briefDescription is not None else None, - 'detailedDoc': method.detailedDescription.translate(self.docTranslator) if method.detailedDescription is not None else None } + try: + methodDict['briefDoc'] = method.briefDescription.translate(self.docTranslator, tagAsBrief=True) if method.briefDescription is not None else None + methodDict['detailedDoc'] = method.detailedDescription.translate(self.docTranslator) if method.detailedDescription is not None else None + except metadoc.TranslationError as e: + logging.error(e.msg()) + if type(method.parent) is AbsApi.Interface: if isinstance(method.returnType, AbsApi.BaseType) and method.returnType.name == 'void': methodDict['suffix'] = ' {}' @@ -356,80 +356,79 @@ class ClassHeader(object): else: self._class = translator.translate_interface(_class) + self.rootNs = translator.rootNs self.define = '_{0}_HH'.format(_class.name.to_snake_case(upper=True, fullName=True)) self.filename = '{0}.hh'.format(_class.name.to_snake_case()) self.priorDeclarations = [] self.private_type = _class.name.to_camel_case(fullName=True) - self.includes = {'internal': [], 'external': []} - includes = self.needed_includes(_class) - for include in includes['internal']: - if _class.name.to_camel_case(fullName=True) == 'LinphoneCore' or (isinstance(_class, AbsApi.Interface) and _class.listenedClass is not None and include == _class.listenedClass.name.to_snake_case()): - if include == 'enums': - self.includes['internal'].append({'name': include}) - else: - className = metaname.ClassName() - className.from_snake_case(include) - self.priorDeclarations.append({'name': className.to_camel_case()}) - else: - self.includes['internal'].append({'name': include}) - - for include in includes['external']: - self.includes['external'].append({'name': include}) + self._populate_needed_includes(_class) - def needed_includes(self, _class): - includes = {'internal': [], 'external': []} - + def _populate_needed_includes(self, _class): if type(_class) is AbsApi.Class: for _property in _class.properties: if _property.setter is not None: - self._needed_includes_from_method(_property.setter, includes) + self._populate_needed_includes_from_method(_property.setter) if _property.getter is not None: - self._needed_includes_from_method(_property.getter, includes) + self._populate_needed_includes_from_method(_property.getter) if type(_class) is AbsApi.Class: methods = _class.classMethods + _class.instanceMethods else: - methods = _class.methods + methods = _class.instanceMethods for method in methods: - self._needed_includes_from_type(method.returnType, includes) + self._populate_needed_includes_from_type(method.returnType) for arg in method.args: - self._needed_includes_from_type(arg.type, includes) + self._populate_needed_includes_from_type(arg.type) if isinstance(_class, AbsApi.Class) and _class.listenerInterface is not None: - self._add_include(includes, 'internal', _class.listenerInterface.name.to_snake_case()) + decl = 'class ' + _class.listenerInterface.name.translate(metaname.Translator.get('Cpp')) + self._add_prior_declaration(decl) currentClassInclude = _class.name.to_snake_case() - if currentClassInclude in includes['internal']: - includes['internal'].remove(currentClassInclude) - - return includes + if currentClassInclude in self.includes['internal']: + self.includes['internal'].remove(currentClassInclude) - def _needed_includes_from_method(self, method, includes): - self._needed_includes_from_type(method.returnType, includes) + def _populate_needed_includes_from_method(self, method): + self._populate_needed_includes_from_type(method.returnType) for arg in method.args: - self._needed_includes_from_type(arg.type, includes) + self._populate_needed_includes_from_type(arg.type) - def _needed_includes_from_type(self, _type, includes): - if isinstance(_type, AbsApi.ClassType): - self._add_include(includes, 'external', 'memory') - if _type.desc is not None: - self._add_include(includes, 'internal', _type.desc.name.to_snake_case()) - elif isinstance(_type, AbsApi.EnumType): - self._add_include(includes, 'internal', 'enums') - elif isinstance(_type, AbsApi.BaseType): - if _type.name == 'integer' and isinstance(_type.size, int): - self._add_include(includes, 'external', 'cstdint') - elif _type.name == 'string': - self._add_include(includes, 'external', 'string') - elif isinstance(_type, AbsApi.ListType): - self._add_include(includes, 'external', 'list') - self._needed_includes_from_type(_type.containedTypeDesc, includes) + def _populate_needed_includes_from_type(self, type_): + translator = metaname.Translator.get('Cpp') + if isinstance(type_, AbsApi.ClassType): + class_ = type_.desc + if class_.parent == self.rootNs: + decl = 'class ' + class_.name.translate(translator) + self._add_prior_declaration(decl) + else: + rootClass = class_.find_first_ancestor_by_type(AbsApi.Namespace, priorAncestor=True) + self._add_include('internal', rootClass.name.to_snake_case()) + elif isinstance(type_, AbsApi.EnumType): + enum = type_.desc + if enum.parent == self.rootNs: + headerFile = 'enums' + else: + rootClass = enum.find_first_ancestor_by_type(AbsApi.Namespace, priorAncestor=True) + headerFile = rootClass.name.to_snake_case() + self._add_include('internal', headerFile) + elif isinstance(type_, AbsApi.BaseType): + if type_.name == 'integer' and isinstance(type_.size, int): + self._add_include('external', 'cstdint') + elif type_.name == 'string': + self._add_include('external', 'string') + elif isinstance(type_, AbsApi.ListType): + self._add_include('external', 'list') + self._populate_needed_includes_from_type(type_.containedTypeDesc) - def _add_include(self, includes, location, name): - if not name in includes[location]: - includes[location].append(name) + def _add_include(self, location, name): + if next((x for x in self.includes[location] if x['name']==name), None) is None: + self.includes[location].append({'name': name}) + + def _add_prior_declaration(self, decl): + if next((x for x in self.priorDeclarations if x['declaration']==decl), None) is None: + self.priorDeclarations.append({'declaration': decl}) class MainHeader(object): @@ -457,18 +456,16 @@ class GenWrapper(object): self.parser = AbsApi.CParser(project) self.parser.parse_all() - self.translator = CppTranslator() + self.translator = CppTranslator(self.parser.namespace) self.renderer = pystache.Renderer() self.mainHeader = MainHeader() self.impl = ClassImpl() def render_all(self): header = EnumsHeader(self.translator) - for item in self.parser.enumsIndex.items(): - if item[1] is not None: - header.add_enum(item[1]) - else: - print('warning: {0} enum won\'t be translated because of parsing errors'.format(item[0])) + + for enum in self.parser.namespace.enums: + header.add_enum(enum) self.render(header, self.includedir + '/enums.hh') self.mainHeader.add_include('enums.hh') @@ -494,44 +491,40 @@ class GenWrapper(object): def render_header(self, _class): if _class is not None: - try: - header = ClassHeader(_class, self.translator) - headerName = _class.name.to_snake_case() + '.hh' - self.mainHeader.add_include(headerName) - self.render(header, self.includedir + '/' + header.filename) - - if type(_class) is not AbsApi.Interface: - self.impl.classes.append(header._class) - - except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) - -def main(): - argparser = argparse.ArgumentParser(description='Generate source files for the C++ wrapper') - argparser.add_argument('xmldir', type=str, help='Directory where the XML documentation of the Linphone\'s API generated by Doxygen is placed') - argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.') - args = argparser.parse_args() - - includedir = args.outputdir + '/include/linphone++' - srcdir = args.outputdir + '/src' - - try: - os.makedirs(includedir) - except OSError as e: - if e.errno != errno.EEXIST: - print("Cannot create '{0}' directory: {1}".format(includedir, e.strerror)) - sys.exit(1) - - try: - os.makedirs(srcdir) - except OSError as e: - if e.errno != errno.EEXIST: - print("Cannot create '{0}' directory: {1}".format(srcdir, e.strerror)) - sys.exit(1) - - genwrapper = GenWrapper(includedir, srcdir, args.xmldir) - genwrapper.render_all() + header = ClassHeader(_class, self.translator) + headerName = _class.name.to_snake_case() + '.hh' + self.mainHeader.add_include(headerName) + self.render(header, self.includedir + '/' + header.filename) + + if type(_class) is not AbsApi.Interface: + self.impl.classes.append(header._class) if __name__ == '__main__': - main() + try: + argparser = argparse.ArgumentParser(description='Generate source files for the C++ wrapper') + argparser.add_argument('xmldir', type=str, help='Directory where the XML documentation of the Linphone\'s API generated by Doxygen is placed') + argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.') + argparser.add_argument('-v --verbose', help='Show warning and info traces.', action='store_true', default=False, dest='verbose_mode') + argparser.add_argument('-d --debug', help='Show all traces.', action='store_true', default=False, dest='debug_mode') + args = argparser.parse_args() + + if args.debug_mode: + loglevel = logging.DEBUG + elif args.verbose_mode: + loglevel = logging.INFO + else: + loglevel = logging.ERROR + logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel) + + includedir = args.outputdir + '/include/linphone++' + srcdir = args.outputdir + '/src' + if not os.path.exists(includedir): + os.makedirs(includedir) + if not os.path.exists(srcdir): + os.makedirs(srcdir) + + genwrapper = GenWrapper(includedir, srcdir, args.xmldir) + genwrapper.render_all() + except AbsApi.Error as e: + logging.critical(e) diff --git a/wrappers/csharp/CMakeLists.txt b/wrappers/csharp/CMakeLists.txt index 0be827872..00c4b4cb0 100644 --- a/wrappers/csharp/CMakeLists.txt +++ b/wrappers/csharp/CMakeLists.txt @@ -28,7 +28,6 @@ add_custom_command(OUTPUT LinphoneWrapper.cs genwrapper.py wrapper_impl.mustache linphone-doc - "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml/index.xml" ) add_custom_target(linphonecs ALL DEPENDS LinphoneWrapper.cs) diff --git a/wrappers/csharp/genwrapper.py b/wrappers/csharp/genwrapper.py index 9cfc6be44..83fd39ed4 100644 --- a/wrappers/csharp/genwrapper.py +++ b/wrappers/csharp/genwrapper.py @@ -17,9 +17,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import argparse +import logging import os -import sys import pystache +import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools')) import genapixml as CApi @@ -401,20 +402,20 @@ class CsharpTranslator(object): methodDict = self.translate_method(method, static=True, genImpl=True) classDict['dllImports'].append(methodDict) except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0])) + logging.error('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0])) for prop in _class.properties: try: classDict['dllImports'] += self.translate_property(prop) except AbsApi.Error as e: - print('error while translating {0} property: {1}'.format(prop.name.to_c(), e.args[0])) + logging.error('error while translating {0} property: {1}'.format(prop.name.to_c(), e.args[0])) for method in _class.instanceMethods: try: methodDict = self.translate_method(method, static=False, genImpl=True) classDict['dllImports'].append(methodDict) except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0])) + logging.error('Could not translate {0}: {1}'.format(method.name.to_c(), e.args[0])) return classDict @@ -469,12 +470,17 @@ def render(renderer, item, path): f.write(content) os.unlink(tmppath) -def main(): - argparser = argparse.ArgumentParser(description='Generate source files for the C++ wrapper') + +if __name__ == '__main__': + argparser = argparse.ArgumentParser(description='Generate source files for the C# wrapper') argparser.add_argument('xmldir', type=str, help='Directory where the XML documentation of the Linphone\'s API generated by Doxygen is placed') argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.') argparser.add_argument('-n --name', type=str, help='the name of the genarated source file', dest='outputfile', default='LinphoneWrapper.cs') + argparser.add_argument('-v --verbose', action='store_true', dest='verbose_mode', default=False, help='Verbose mode.') args = argparser.parse_args() + + loglevel = logging.INFO if args.verbose_mode else logging.ERROR + logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel) entries = os.listdir(args.outputdir) @@ -498,7 +504,7 @@ def main(): impl = EnumImpl(item[1], translator) enums.append(impl) else: - print('warning: {0} enum won\'t be translated because of parsing errors'.format(item[0])) + logging.warning('{0} enum won\'t be translated because of parsing errors'.format(item[0])) interfaces = [] classes = [] @@ -513,10 +519,7 @@ def main(): impl = InterfaceImpl(_class, translator) interfaces.append(impl) except AbsApi.Error as e: - print('Could not translate {0}: {1}'.format(_class.name.to_c(), e.args[0])) + logging.error('Could not translate {0}: {1}'.format(_class.name.to_c(), e.args[0])) wrapper = WrapperImpl(enums, interfaces, classes) render(renderer, wrapper, args.outputdir + "/" + args.outputfile) - -if __name__ == '__main__': - main() diff --git a/wrappers/csharp/wrapper_impl.mustache b/wrappers/csharp/wrapper_impl.mustache index ab4c5775d..91da3f494 100644 --- a/wrappers/csharp/wrapper_impl.mustache +++ b/wrappers/csharp/wrapper_impl.mustache @@ -184,9 +184,9 @@ namespace Linphone obj.handle = GCHandle.Alloc(obj, GCHandleType.WeakTrackResurrection); objPtr = GCHandle.ToIntPtr(obj.handle); #if WINDOWS_UWP - belle_sip_object_data_set(ptr, "cs_obj", objPtr, IntPtr.Zero); + belle_sip_object_data_set(ptr, "cs_obj", objPtr, IntPtr.Zero); #else - belle_sip_object_data_set(ptr, "cs_obj", objPtr, null); + belle_sip_object_data_set(ptr, "cs_obj", objPtr, null); #endif return obj; diff --git a/wrappers/java/CMakeLists.txt b/wrappers/java/CMakeLists.txt new file mode 100644 index 000000000..23344bf0e --- /dev/null +++ b/wrappers/java/CMakeLists.txt @@ -0,0 +1,48 @@ +############################################################################ +# CMakeLists.txt +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +############################################################################ + +set(jni_sources "${CMAKE_CURRENT_BINARY_DIR}/src/linphone_jni.cc") + +add_custom_command(OUTPUT "${jni_sources}" + COMMAND ${CMAKE_COMMAND} -E remove -f java/org/linphone/core/* src/* + COMMAND ${PYTHON_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/genwrapper.py" "${PROJECT_BINARY_DIR}/coreapi/help/doc/doxygen/xml" "-o" "${CMAKE_CURRENT_BINARY_DIR}" + DEPENDS ${PROJECT_SOURCE_DIR}/tools/genapixml.py ${LINPHONE_HEADER_FILES} + ${PROJECT_SOURCE_DIR}/tools/metaname.py + ${PROJECT_SOURCE_DIR}/tools/metadoc.py + ${PROJECT_SOURCE_DIR}/tools/abstractapi.py + genwrapper.py + java_class.mustache + java_enum.mustache + java_interface_stub.mustache + java_interface.mustache + jni.mustache + linphone-doc + COMMENT "Generating java wrapper" +) + +add_custom_target(linphonej ALL DEPENDS "${jni_sources}") + +set(LINPHONE_JNI_SOURCES "${jni_sources}" PARENT_SCOPE) + +install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/java" DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonej/") + +#install(DIRECTORY classes/ DESTINATION "${CMAKE_INSTALL_DATADIR}/linphonej/java/org/linphone/core/") diff --git a/gtk/fonis.c b/wrappers/java/classes/CoreException.java similarity index 61% rename from gtk/fonis.c rename to wrappers/java/classes/CoreException.java index ebd3e4d94..a37660931 100644 --- a/gtk/fonis.c +++ b/wrappers/java/classes/CoreException.java @@ -1,6 +1,6 @@ /* -linphone, gtk-glade interface. -Copyright (C) 2008 Simon MORLAT (simon.morlat@linphone.org) +CoreException.java +Copyright (C) 2010-2018 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 @@ -17,6 +17,23 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +package org.linphone.core; -#include "linphone.h" +@SuppressWarnings("serial") +public class CoreException extends Exception { + public CoreException() { + } + + public CoreException(String detailMessage) { + super(detailMessage); + } + + public CoreException(Throwable e) { + super(e); + } + + public CoreException(String detailMessage, Throwable e) { + super(detailMessage,e); + } +} diff --git a/coreapi/platform-helpers.cpp b/wrappers/java/classes/Utils.java similarity index 51% rename from coreapi/platform-helpers.cpp rename to wrappers/java/classes/Utils.java index 05bbc00e6..6e567552f 100644 --- a/coreapi/platform-helpers.cpp +++ b/wrappers/java/classes/Utils.java @@ -1,6 +1,6 @@ /* -linphone -Copyright (C) 2017 Belledonne Communications SARL +Utils.java +Copyright (C) 2010-2018 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 @@ -17,33 +17,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "private.h" +package org.linphone.core; +public class Utils { + public static String getPrefixFromE164(String e164) { + DialPlan[] dialPlans = Factory.instance().getDialPlans(); + DialPlan dialPlan = dialPlans[0]; + return String.valueOf(dialPlan.lookupCccFromE164(e164)); + } -namespace LinphonePrivate{ - -PlatformHelpers::~PlatformHelpers(){ + public static int getCccFromIso(String countryIso) { + DialPlan[] dialPlans = Factory.instance().getDialPlans(); + DialPlan dialPlan = dialPlans[0]; + return dialPlan.lookupCccFromIso(countryIso); + } } - -StubbedPlatformHelpers::StubbedPlatformHelpers(LinphoneCore *lc) : PlatformHelpers(lc){ -} - -void StubbedPlatformHelpers::setDnsServers(){ -} -void StubbedPlatformHelpers::acquireWifiLock(){ -} -void StubbedPlatformHelpers::releaseWifiLock(){ -} -void StubbedPlatformHelpers::acquireMcastLock(){ -} -void StubbedPlatformHelpers::releaseMcastLock(){ -} -void StubbedPlatformHelpers::acquireCpuLock(){ -} -void StubbedPlatformHelpers::releaseCpuLock(){ -} - -StubbedPlatformHelpers::~StubbedPlatformHelpers(){ -} - -} \ No newline at end of file diff --git a/wrappers/java/classes/tools/AndroidPlatformHelper.java b/wrappers/java/classes/tools/AndroidPlatformHelper.java new file mode 100644 index 000000000..469e7c42c --- /dev/null +++ b/wrappers/java/classes/tools/AndroidPlatformHelper.java @@ -0,0 +1,265 @@ +/* +AndroidPlatformHelper.java +Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +package org.linphone.core.tools; + +import org.linphone.mediastream.Log; +import org.linphone.mediastream.MediastreamerAndroidContext; +import org.linphone.mediastream.Version; + +import android.content.res.Resources; +import android.net.wifi.WifiManager; +import android.net.wifi.WifiManager.MulticastLock; +import android.net.wifi.WifiManager.WifiLock; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkInfo; +import android.os.PowerManager; +import android.os.PowerManager.WakeLock; +import android.os.Build; + +import java.net.InetAddress; +import java.util.List; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * This class is instanciated directly by the linphone library in order to access specific features only accessible in java. + **/ + +public class AndroidPlatformHelper { + private Context mContext; + private WifiManager.WifiLock mWifiLock; + private WifiManager.MulticastLock mMcastLock; + private ConnectivityManager mConnectivityManager; + private PowerManager mPowerManager; + private WakeLock mWakeLock; + private Resources mResources; + private String mLinphoneRootCaFile; + private String mRingSoundFile; + private String mRingbackSoundFile; + private String mPauseSoundFile; + private String mErrorToneFile; + private String mGrammarCpimFile; + private String mGrammarVcardFile ; + private String mUserCertificatePath; + + public AndroidPlatformHelper(Object ctx_obj) { + mContext = (Context) ctx_obj; + mResources = mContext.getResources(); + MediastreamerAndroidContext.setContext(mContext); + + WifiManager wifiMgr = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE); + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + mConnectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + + mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "AndroidPlatformHelper"); + mWakeLock.setReferenceCounted(true); + mMcastLock = wifiMgr.createMulticastLock("AndroidPlatformHelper"); + mMcastLock.setReferenceCounted(true); + mWifiLock = wifiMgr.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "AndroidPlatformHelper"); + mWifiLock.setReferenceCounted(true); + + String basePath = mContext.getFilesDir().getAbsolutePath(); + //make sure to follow same path as unix version of the sdk + mLinphoneRootCaFile = basePath + "/share/linphone/rootca.pem"; + mRingSoundFile = basePath + "/share/sounds/linphone/rings/notes_of_the_optimistic.mkv"; + mRingbackSoundFile = basePath + "/share/sounds/linphone/ringback.wav"; + mPauseSoundFile = basePath + "/share/sounds/linphone/rings/dont_wait_too_long.mkv"; + mErrorToneFile = basePath + "/share/sounds/linphone/incoming_chat.wav"; + mGrammarCpimFile = basePath + "/share/belr/grammars/cpim_grammar"; + mGrammarVcardFile = basePath + "/share/belr/grammars/vcard_grammar"; + mUserCertificatePath = basePath; + + try{ + copyAssetsFromPackage(); + }catch (IOException e) { + Log.e("AndroidPlatformHelper(): failed to install some resources."); + } + } + + + public Object getPowerManager() { + return mPowerManager; + } + + public String[] getDnsServers() { + if (mConnectivityManager == null || Build.VERSION.SDK_INT < Version.API23_MARSHMALLOW_60) + return null; + + if (mConnectivityManager.getActiveNetwork() == null + || mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()) == null) + return null; + + int i = 0; + List inetServers = null; + inetServers = mConnectivityManager.getLinkProperties(mConnectivityManager.getActiveNetwork()).getDnsServers(); + + String[] servers = new String[inetServers.size()]; + + for (InetAddress address : inetServers) { + servers[i++] = address.getHostAddress(); + } + Log.i("getDnsServers() returning"); + return servers; + } + + public String getDataPath() { + return mContext.getFilesDir().getAbsolutePath(); + } + + public String getConfigPath() { + return mContext.getFilesDir().getAbsolutePath(); + } + + public String getCachePath() { + return mContext.getCacheDir().getAbsolutePath(); + } + + public String getNativeLibraryDir(){ + ApplicationInfo info = mContext.getApplicationInfo(); + return info.nativeLibraryDir; + } + + public void acquireWifiLock() { + Log.i("acquireWifiLock()"); + mWifiLock.acquire(); + } + + public void releaseWifiLock() { + Log.i("releaseWifiLock()"); + mWifiLock.release(); + } + + public void acquireMcastLock() { + Log.i("acquireMcastLock()"); + mMcastLock.acquire(); + } + + public void releaseMcastLock() { + Log.i("releaseMcastLock()"); + mMcastLock.release(); + } + + public void acquireCpuLock() { + Log.i("acquireCpuLock()"); + mWakeLock.acquire(); + } + + public void releaseCpuLock() { + Log.i("releaseCpuLock()"); + mWakeLock.release(); + } + + private int getResourceIdentifierFromName(String name) { + int resId = mResources.getIdentifier(name, "raw", mContext.getPackageName()); + if (resId == 0) { + Log.d("App doesn't seem to embed resource " + name + "in it's res/raw/ directory, use linphone's instead"); + resId = mResources.getIdentifier(name, "raw", "org.linphone"); + if (resId == 0) { + Log.i("App doesn't seem to embed resource " + name + "in it's res/raw/ directory. Make sure this file is either brought as an asset or a resource"); + } + } + return resId; + } + + private void copyAssetsFromPackage() throws IOException { + Log.i("Starting copy from assets to application files directory"); + copyAssetsFromPackage(mContext, "org.linphone.core","."); + Log.i("Copy from assets done"); + Log.i("Starting copy from legacy resources to application files directory"); + /*legacy code for 3.X*/ + copyEvenIfExists(getResourceIdentifierFromName("cpim_grammar"), mGrammarCpimFile); + copyEvenIfExists(getResourceIdentifierFromName("vcard_grammar"), mGrammarVcardFile); + copyEvenIfExists(getResourceIdentifierFromName("rootca"), mLinphoneRootCaFile); + copyEvenIfExists(getResourceIdentifierFromName("notes_of_the_optimistic"), mRingSoundFile); + copyEvenIfExists(getResourceIdentifierFromName("ringback"), mRingbackSoundFile); + copyEvenIfExists(getResourceIdentifierFromName("hold"), mPauseSoundFile); + copyEvenIfExists(getResourceIdentifierFromName("incoming_chat"), mErrorToneFile); + Log.i("Copy from legacy resources done"); + } + + public void copyEvenIfExists(int ressourceId, String target) throws IOException { + File lFileToCopy = new File(target); + copyFromPackage(ressourceId, lFileToCopy); + } + + public void copyIfNotExist(int ressourceId, String target) throws IOException { + File lFileToCopy = new File(target); + if (!lFileToCopy.exists()) { + copyFromPackage(ressourceId, lFileToCopy); + } + } + + public void copyFromPackage(int ressourceId, File target) throws IOException { + if (ressourceId == 0) { + Log.i("Resource identifier null for target ["+target.getName()+"]"); + return; + } + if (!target.getParentFile().exists()) + target.getParentFile().mkdirs(); + + InputStream lInputStream = mResources.openRawResource(ressourceId); + FileOutputStream lOutputStream = new FileOutputStream(target); + int readByte; + byte[] buff = new byte[8048]; + while (( readByte = lInputStream.read(buff)) != -1) { + lOutputStream.write(buff,0, readByte); + } + lOutputStream.flush(); + lOutputStream.close(); + lInputStream.close(); + } + + public static void copyAssetsFromPackage(Context ctx,String fromPath, String toPath) throws IOException { + new File(ctx.getFilesDir().getPath()+"/"+toPath).mkdir(); + + for (String f :ctx.getAssets().list(fromPath)) { + String current_name = fromPath+"/"+f; + String current_dest = toPath+"/"+f; + InputStream lInputStream; + try { + lInputStream = ctx.getAssets().open(current_name); + } catch (IOException e) { + //probably a dir + copyAssetsFromPackage(ctx,current_name,current_dest); + continue; + } + FileOutputStream lOutputStream = new FileOutputStream(new File(ctx.getFilesDir().getPath()+"/"+current_dest));//ctx.openFileOutput (fromPath+"/"+f, 0); + + + int readByte; + byte[] buff = new byte[8048]; + while (( readByte = lInputStream.read(buff)) != -1) { + lOutputStream.write(buff,0, readByte); + } + lOutputStream.flush(); + lOutputStream.close(); + lInputStream.close(); + } + } +}; + + diff --git a/wrappers/java/classes/tools/H264Helper.java b/wrappers/java/classes/tools/H264Helper.java new file mode 100644 index 000000000..abebb882c --- /dev/null +++ b/wrappers/java/classes/tools/H264Helper.java @@ -0,0 +1,79 @@ +package org.linphone.core.tools; + + +import android.os.Build; + +import org.linphone.core.Core; +import org.linphone.mediastream.Log; + +/** + * Created by brieucviel on 09/12/2016. + */ + +public class H264Helper { + private static String FILTER_NAME_OPENH264_ENC = "MSOpenH264Enc" ; + private static String FILTER_NAME_OPENH264_DEC = "MSOpenH264Dec" ; + private static String FILTER_NAME_MEDIA_CODEC_ENC = "MSMediaCodecH264Enc" ; + private static String FILTER_NAME_MEDIA_CODEC_DEC = "MSMediaCodecH264Dec" ; + + public static String MODE_AUTO = "Auto" ; + public static String MODE_OPENH264 = "OpenH264" ; + public static String MODE_MEDIA_CODEC = "MediaCodec" ; + + + /** + * H264Helper + */ + public H264Helper() { + } + + + /** + * Define the Codec to use between MediaCodec and OpenH264 + * Possible mode are: + * - Auto to let the system choose in function of you OS version, + * - OpenH264 to enable OpenH264 Encoder and Decoder, + * - Mediacodec to enable Mediacodec only. + * @param mode String value between Auto, OpenH264 and MediaCodec + */ + public static void setH264Mode(String mode, Core linphoneCore){ + if(mode.equals(MODE_OPENH264)){ + Log.i("H264Helper"," setH264Mode MODE_OPENH264 - Mode = "+mode); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , true); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , true); + }else if(mode.equals(MODE_MEDIA_CODEC)){ + Log.i("H264Helper"," setH264Mode MODE_MEDIA_CODEC - Mode = "+mode); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , true); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , true); + }else if(mode.equals(MODE_AUTO)){ + Log.i("H264Helper"," setH264Mode MODE_AUTO - Mode = "+mode); + // if android >= 5.0 use MediaCodec + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + Log.i("H264Helper"," setH264Mode MODE_AUTO 1 - Mode = "+mode); + Log.i("H264Helper"," Openh264 disabled on the project, now using MediaCodec"); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , true); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , true); + } + //otherwise use OpenH264 + else{ + Log.i("H264Helper"," setH264Mode MODE_AUTO 2 - Mode = "+mode); + Log.i("H264Helper"," Openh264 enabled on the project"); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_DEC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_MEDIA_CODEC_ENC , false); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_DEC , true); + linphoneCore.getMediastreamerFactory().enableFilterFromName(FILTER_NAME_OPENH264_ENC , true); + } + }else { + Log.i("H264Helper"," Error: Openh264 mode not reconized !"); + } + Log.i("H264Helper"," setH264Mode - Mode = "+mode); + } + +} + diff --git a/wrappers/java/classes/tools/OpenH264DownloadHelper.java b/wrappers/java/classes/tools/OpenH264DownloadHelper.java new file mode 100644 index 000000000..eb35285a4 --- /dev/null +++ b/wrappers/java/classes/tools/OpenH264DownloadHelper.java @@ -0,0 +1,263 @@ +package org.linphone.core.tools; +/* +CodecDownloader.java +Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +import android.content.Context; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.ArrayList; + +import org.apache.commons.compress.compressors.bzip2.*; +import org.linphone.core.tools.OpenH264DownloadHelperListener; +import org.linphone.mediastream.Log; + +/** + * @author Erwan Croze + */ +public class OpenH264DownloadHelper { + private static boolean isDownloadEnabled; + + private OpenH264DownloadHelperListener openH264DownloadHelperListener; + private ArrayList userData; + private String fileDirection; + private String nameLib; + private String urlDownload; + private String nameFileDownload; + private String licenseMessage; + + /** + * Default values + * nameLib = "libopenh264-1.5.so" + * urlDownload = "http://ciscobinary.openh264.org/libopenh264-1.5.0-android19.so.bz2" + * nameFileDownload = "libopenh264-1.5.0-android19.so.bz2" + */ + public OpenH264DownloadHelper(Context context) { + userData = new ArrayList(); + licenseMessage = "OpenH264 Video Codec provided by Cisco Systems, Inc."; + nameLib = "libopenh264.so"; + urlDownload = "http://ciscobinary.openh264.org/libopenh264-1.5.0-android19.so.bz2"; + nameFileDownload = "libopenh264-1.5.0-android19.so.bz2"; + if (context.getFilesDir() != null) { + fileDirection = context.getFilesDir().toString(); + } + + File file = new File(context.getApplicationInfo().nativeLibraryDir+"/libmsopenh264.so"); + if (!file.exists()) { + Log.i("LinphoneCoreFactoryImpl"," libmsopenh264 not found, we disable the download of Openh264"); + isDownloadEnabled = false; + } + if (isCodecFound()) { + Log.i("OpenH264DownloadHelper"," Loading OpenH264 downloaded plugin:" + getFullPathLib()); + System.load(getFullPathLib()); + } else { + Log.i("OpenH264DownloadHelper"," Cannot load OpenH264 downloaded plugin"); + } + isDownloadEnabled = true; + } + + public static boolean isOpenH264DownloadEnabled() { + return isDownloadEnabled; + } + + public static void setOpenH264DownloadEnabled(boolean enabled) { + isDownloadEnabled = enabled; + } + + /** + * Set OpenH264DownloadHelperListener + * @param h264Listener + */ + public void setOpenH264HelperListener(OpenH264DownloadHelperListener h264Listener) { + openH264DownloadHelperListener = h264Listener; + } + + /** + * @return OpenH264DownloadHelperListener + */ + public OpenH264DownloadHelperListener getOpenH264DownloadHelperListener() { + return openH264DownloadHelperListener; + } + + /** + * @param index of object in UserData list + * constraints (index superior or egal to 0 and index inferior to userData.size()) + * @return object if constraints are met + */ + public Object getUserData(int index) { + if (index < 0 || index >= userData.size()) return null; + return userData.get(index); + } + + /** + * Adding of object into UserData list + * @param object + * @return index of object in UserData list + */ + public int setUserData(Object object) { + this.userData.add(object); + return this.userData.indexOf(object); + } + + /** + * @param index + * @param object + * constraints (index superior or egal to 0 and index inferior to userData.size()) + */ + public void setUserData(int index, Object object) { + if (index < 0 || index > userData.size()) return; + this.userData.add(index,object); + } + + /** + * @return size of UserData list + */ + public int getUserDataSize() { + return this.userData.size(); + } + + /** + * @return OpenH264 license message + */ + public String getLicenseMessage() { + return licenseMessage; + } + + /** + * Set filename to storage for OpenH264 codec + * @param name + */ + public void setNameLib(String name) { + nameLib = name; + } + + /** + * @return filename of OpenH264 codec + */ + public String getNameLib() { + return nameLib; + } + + /** + * @return path of the lib + */ + public String getFullPathLib() { + return this.fileDirection + "/" + this.getNameLib(); + } + + /** + * Set name download file + * @param name : must be the same name relative to the url + */ + public void setNameFileDownload(String name) { + nameFileDownload = name; + } + + /** + * Set new url + * @param url : must be a Cisco Url to OpenH264 and .bzip2 file + */ + public void setUrlDownload(String url) { + urlDownload = url; + } + + /** + * Indicates whether the lib exists + * Requirements : fileDirection and nameLib init + * @return file exists ? + */ + public boolean isCodecFound() { + return new File(fileDirection+"/" + nameLib).exists(); + } + + /** + * Try to download and load codec + * Requirements : + * fileDirection + * nameFileDownload + * urlDownload + * nameLib + * codecDownListener + */ + public void downloadCodec() { + Thread thread = new Thread(new Runnable() + { + @Override + public void run() + { + try { + String path = fileDirection+"/" + nameLib; + URL url = new URL(urlDownload); + HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection(); + urlConnection.connect(); + Log.i("OpenH264Downloader"," "); + InputStream inputStream = urlConnection.getInputStream(); + FileOutputStream fileOutputStream = new FileOutputStream(fileDirection+"/"+nameFileDownload); + int totalSize = urlConnection.getContentLength(); + openH264DownloadHelperListener.OnProgress(0,totalSize); + + Log.i("OpenH264Downloader"," Download file:" + nameFileDownload); + + byte[] buffer = new byte[4096]; + int bufferLength; + int total = 0; + while((bufferLength = inputStream.read(buffer))>0 ){ + total += bufferLength; + fileOutputStream.write(buffer, 0, bufferLength); + openH264DownloadHelperListener.OnProgress(total, totalSize); + } + + fileOutputStream.close(); + inputStream.close(); + + Log.i("OpenH264Downloader"," Uncompress file:" + nameFileDownload); + + FileInputStream in = new FileInputStream(fileDirection+"/"+nameFileDownload); + FileOutputStream out = new FileOutputStream(path); + BZip2CompressorInputStream bzIn = new BZip2CompressorInputStream(in); + + while ((bufferLength = bzIn.read(buffer))>0) { + out.write(buffer, 0, bufferLength); + } + in.close(); + out.close(); + bzIn.close(); + + Log.i("OpenH264Downloader"," Remove file:" + nameFileDownload); + new File(fileDirection+"/"+nameFileDownload).delete(); + + Log.i("OpenH264Downloader"," Loading plugin:" + path); + System.load(path); + openH264DownloadHelperListener.OnProgress(2,1); + } catch (FileNotFoundException e) { + openH264DownloadHelperListener.OnError(e.getLocalizedMessage()); + } catch (IOException e) { + openH264DownloadHelperListener.OnError(e.getLocalizedMessage()); + } + } + }); + thread.start(); + } +} diff --git a/wrappers/java/classes/tools/OpenH264DownloadHelperListener.java b/wrappers/java/classes/tools/OpenH264DownloadHelperListener.java new file mode 100644 index 000000000..d3d6faa88 --- /dev/null +++ b/wrappers/java/classes/tools/OpenH264DownloadHelperListener.java @@ -0,0 +1,18 @@ +package org.linphone.core.tools; + +public interface OpenH264DownloadHelperListener { + /** + * Called at the beginning of download with current < max Called + * at each iteration of download Called at the ending of download + * with current > max + * @param current: Size of file already downloaded + * @param max: Size of file we want to download + */ + void OnProgress(int current, int max); + + /** + * Called when we failed to download codec + * @param error: Error message + */ + void OnError(String error); +} diff --git a/wrappers/java/genwrapper.py b/wrappers/java/genwrapper.py new file mode 100755 index 000000000..1572e2381 --- /dev/null +++ b/wrappers/java/genwrapper.py @@ -0,0 +1,826 @@ +#!/usr/bin/python + +# Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +import argparse +import errno +import logging +import os +import pystache +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', 'tools')) +import genapixml as CApi +import abstractapi as AbsApi +import metadoc +import metaname + + +CORE_ACCESSOR_LIST = [ + 'Call', + 'ChatRoom', + 'Event', + 'Friend', + 'FriendList', + 'NatPolicy', + 'Player', + 'ProxyConfig' +] + + +class JNINameTranslator(metaname.Translator): + _instance = None + + @staticmethod + def get(): + if JNINameTranslator._instance is None: + JNINameTranslator._instance = JNINameTranslator() + return JNINameTranslator._instance + + def translate_class_name(self, name, **params): + translated_name = name.to_camel_case() + if name.prev is not None and type(name.prev) is not metaname.NamespaceName: + return name.prev.translate(self) + self._getseparator(name.prev) + translated_name + else: + return translated_name + + def translate_interface_name(self, name, **params): + return self.translate_class_name(name, **params) + + def translate_enum_name(self, name, **params): + return self.translate_class_name(name, **params) + + def translate_enumerator_name(self, name, **params): + raise NotImplemented() + + def translate_method_name(self, name, **params): + raise NotImplemented() + + def translate_namespace_name(self, name, **params): + translated_name = name.to_snake_case() + if name.prev is not None: + return name.prev.translate(self) + self._getseparator(name.prev) + translated_name + else: + return translated_name + + def translate_argument_name(self, name, **params): + raise NotImplemented() + + def translate_property_name(self, name, **params): + raise NotImplemented() + + def _getseparator(self, previous_name): + if isinstance(previous_name, metaname.NamespaceName): + return '/' + elif isinstance(previous_name, metaname.ClassName): + return '$' + else: + raise TypeError("no separator for '{0}' type".format(type(previous_name))) + + +class JNILangTranslator(AbsApi.Translator): + _instance = None + + @staticmethod + def get(): + if JNILangTranslator._instance is None: + JNILangTranslator._instance = JNILangTranslator() + return JNILangTranslator._instance + + def translate_base_type(self, type_): + if type_.name == 'string': + return 'Ljava/lang/String;' + elif type_.name == 'integer': + return 'I' + elif type_.name == 'boolean': + return 'Z' + elif type_.name == 'floatant': + return 'F' + elif type_.name == 'size': + return 'I' + elif type_.name == 'time': + return 'I' + elif type_.name == 'status': + return 'I' + elif type_.name == 'string_array': + return '[Ljava/lang/String;' + elif type_.name == 'character': + return 'C' + elif type_.name == 'void': + return 'V' + return type_.name + + +class JavaTranslator(object): + def __init__(self, packageName, exceptions): + self.exceptions = exceptions + package_dirs = packageName.split('.') + self.jni_package = '' + self.jni_path = '' + for directory in package_dirs: + self.jni_package += directory + '_' + self.jni_path += directory + '/' + + self.nameTranslator = metaname.Translator.get('Java') + self.langTranslator = AbsApi.Translator.get('Java') + self.docTranslator = metadoc.JavaDocTranslator() + + self.jninameTranslator = JNINameTranslator.get() + self.jnilangTranslator = JNILangTranslator.get() + + self.clangTranslator = AbsApi.Translator.get('C') + + def throws_exception(self, _type): + if not self.exceptions: + return False + if type(_type) is AbsApi.BaseType: + if _type.name == 'status': + return True + return False + + def translate_property(self, _property, _hasCoreAccessor): + properties = [] + if _property.getter is not None: + properties.append(self.translate_method(_property.getter, _hasCoreAccessor)) + if _property.setter is not None: + properties.append(self.translate_method(_property.setter, _hasCoreAccessor)) + return properties + + def translate_jni_property(self, class_, _property): + properties = [] + if _property.getter is not None: + properties.append(self.translate_jni_method(class_, _property.getter)) + if _property.setter is not None: + properties.append(self.translate_jni_method(class_, _property.setter)) + return properties + + def generate_listener(self, name, _class): + methodDict = {} + methodDict['return'] = 'void' + methodDict['return_native'] = 'void' + methodDict['return_keyword'] = '' + methodDict['convertInputClassArrayToLongArray'] = False + methodDict['name'] = name + methodDict['exception'] = False + methodDict['enumCast'] = False + methodDict['classCast'] = False + + methodDict['params'] = _class.name.to_camel_case() + 'Listener listener' + methodDict['native_params'] = 'long nativePtr, ' + _class.name.to_camel_case() + 'Listener listener' + methodDict['static_native_params'] = '' + methodDict['native_params_impl'] = 'nativePtr, listener' + + methodDict['deprecated'] = False + methodDict['doc'] = None + + return methodDict + + def generate_add_listener(self, _class): + return self.generate_listener('addListener', _class) + + def generate_remove_listener(self, _class): + return self.generate_listener('removeListener', _class) + + def generate_set_listener(self, _class): + return self.generate_listener('setListener', _class) + + def translate_method(self, _method, _hasCoreAccessor=False): + methodDict = {} + + namespace = _method.find_first_ancestor_by_type(AbsApi.Namespace) + + methodDict['return'] = _method.returnType.translate(self.langTranslator, isReturn=True, namespace=namespace) + methodDict['return_native'] = _method.returnType.translate(self.langTranslator, native=True, isReturn=True, namespace=namespace) + methodDict['return_keyword'] = '' if methodDict['return'] == 'void' else 'return ' + methodDict['hasReturn'] = not methodDict['return'] == 'void' + + methodDict['convertInputClassArrayToLongArray'] = False + + methodDict['name'] = _method.name.to_camel_case(lower=True) + methodDict['isNotGetCore'] = not methodDict['name'] == 'getCore' + methodDict['hasCoreAccessor'] = _hasCoreAccessor + methodDict['exception'] = self.throws_exception(_method.returnType) + + methodDict['enumCast'] = type(_method.returnType) is AbsApi.EnumType + methodDict['classCast'] = type(_method.returnType) is AbsApi.ClassType + + methodDict['params'] = ', '.join([arg.translate(self.langTranslator, namespace=namespace) for arg in _method.args]) + methodDict['native_params'] = ', '.join(['long nativePtr'] + [arg.translate(self.langTranslator, native=True, namespace=namespace) for arg in _method.args]) + methodDict['static_native_params'] = ', '.join([arg.translate(self.langTranslator, native=True, namespace=namespace) for arg in _method.args]) + methodDict['native_params_impl'] = ', '.join( + ['nativePtr'] + [arg.name.translate(self.nameTranslator) + ('.toInt()' if type(arg.type) is AbsApi.EnumType else '') for arg in _method.args]) + + methodDict['deprecated'] = _method.deprecated + methodDict['doc'] = _method.briefDescription.translate(self.docTranslator) if _method.briefDescription is not None else None + + return methodDict + + def translate_jni_method(self, class_, _method, static=False): + jni_blacklist = ['linphone_call_set_native_video_window_id', + 'linphone_core_set_native_preview_window_id', + 'linphone_core_set_native_video_window_id'] + + namespace = class_.find_first_ancestor_by_type(AbsApi.Namespace) + className = class_.name.translate(self.nameTranslator) + + methodDict = {'notEmpty': True} + methodDict['classCName'] = class_.name.to_c() + methodDict['className'] = className + methodDict['classImplName'] = className + 'Impl' + methodDict['isLinphoneFactory'] = (className == 'Factory') + methodDict['jniPath'] = self.jni_path + + methodDict['return'] = _method.returnType.translate(self.langTranslator, jni=True, isReturn=True, namespace=namespace) + methodDict['hasListReturn'] = methodDict['return'] == 'jobjectArray' + methodDict['hasByteArrayReturn'] = methodDict['return'] == 'jbyteArray' + methodDict['hasReturn'] = not methodDict['return'] == 'void' and not methodDict['hasListReturn'] and not methodDict['hasByteArrayReturn'] + methodDict['hasStringReturn'] = methodDict['return'] == 'jstring' + methodDict['hasNormalReturn'] = not methodDict['hasListReturn'] and not methodDict['hasStringReturn'] and not methodDict['hasByteArrayReturn'] + methodDict['name'] = 'Java_' + self.jni_package + className + 'Impl_' + _method.name.translate(self.nameTranslator) + methodDict['notStatic'] = not static + + if _method.name.to_c() == 'linphone_factory_create_core': + methodDict['c_name'] = 'linphone_factory_create_core_3' + elif _method.name.to_c() == 'linphone_factory_create_core_with_config': + methodDict['c_name'] = 'linphone_factory_create_core_with_config_3' + else: + methodDict['c_name'] = _method.name.to_c() + + methodDict['returnObject'] = methodDict['hasReturn'] and type(_method.returnType) is AbsApi.ClassType + methodDict['returnClassName'] = _method.returnType.translate(self.langTranslator, namespace=namespace) + methodDict['isRealObjectArray'] = False + methodDict['isStringObjectArray'] = False + methodDict['c_type_return'] = _method.returnType.translate(self.clangTranslator) + + if methodDict['c_name'] in jni_blacklist: + return {'notEmpty': False} + + if methodDict['hasListReturn']: + if type(_method.returnType) is AbsApi.BaseType and _method.returnType.name == 'string_array': + methodDict['isStringObjectArray'] = True + elif type(_method.returnType.containedTypeDesc) is AbsApi.BaseType: + methodDict['isStringObjectArray'] = True + elif type(_method.returnType.containedTypeDesc) is AbsApi.ClassType: + methodDict['isRealObjectArray'] = True + methodDict['objectCPrefix'] = 'linphone_' + _method.returnType.containedTypeDesc.desc.name.to_snake_case() + methodDict['objectClassCName'] = 'Linphone' + _method.returnType.containedTypeDesc.desc.name.to_camel_case() + methodDict['objectClassName'] = _method.returnType.containedTypeDesc.desc.name.to_camel_case() + methodDict['objectClassImplName'] = _method.returnType.containedTypeDesc.desc.name.to_camel_case() + 'Impl' + + methodDict['params'] = 'JNIEnv *env, jobject thiz, jlong ptr' + methodDict['params_impl'] = '' + methodDict['strings'] = [] + methodDict['objects'] = [] + methodDict['lists'] = [] + methodDict['array'] = [] + methodDict['bytes'] = [] + methodDict['returnedObjectGetter'] = '' + for arg in _method.args: + methodDict['params'] += ', ' + if static: + if arg is not _method.args[0]: + methodDict['params_impl'] += ', ' + else: + methodDict['params_impl'] += ', ' + + methodDict['params'] += arg.translate(self.langTranslator, jni=True, namespace=namespace) + argname = arg.name.translate(self.nameTranslator) + + if type(arg.type) is AbsApi.ClassType: + classCName = 'Linphone' + arg.type.desc.name.to_camel_case() + if classCName[-8:] == 'Listener': + classCName = 'Linphone' + arg.type.desc.name.to_camel_case()[:-8] + 'Cbs' + methodDict['objects'].append({'object': argname, 'objectClassCName': classCName}) + methodDict['params_impl'] += 'c_' + argname + + elif type(arg.type) is AbsApi.ListType: + isStringList = type(arg.type.containedTypeDesc) is AbsApi.BaseType and arg.type.containedTypeDesc.name == 'string' + isObjList = type(arg.type.containedTypeDesc) is AbsApi.ClassType + methodDict['lists'].append({'list': argname, 'isStringList': isStringList, 'isObjList': isObjList, 'objectClassCName': arg.type.containedTypeDesc.name}) + methodDict['params_impl'] += 'bctbx_list_' + argname + + elif type(arg.type) is AbsApi.EnumType: + argCType = arg.type.name + methodDict['params_impl'] += '(' + argCType + ') ' + argname + + elif type(arg.type) is AbsApi.BaseType: + if arg.type.name == 'integer' and arg.type.size is not None and arg.type.isref: + methodDict['bytes'].append({'bytesargname': argname, 'bytesargtype' : arg.type.translate(self.clangTranslator)}) + methodDict['params_impl'] += 'c_' + argname + elif arg.type.name == 'string': + methodDict['strings'].append({'string': argname}) + methodDict['params_impl'] += 'c_' + argname + else: + methodDict['params_impl'] += '(' + arg.type.translate(self.clangTranslator) + ')' + argname + else: + methodDict['params_impl'] += argname + + return methodDict + + def translate_class(self, _class): + classDict = { + 'methods': [], + 'jniMethods': [], + } + + classDict['isLinphoneFactory'] = _class.name.to_camel_case() == "Factory" + classDict['isLinphoneCore'] = _class.name.to_camel_case() == "Core" + hasCoreAccessor = _class.name.to_camel_case() in CORE_ACCESSOR_LIST + classDict['hasCoreAccessor'] = hasCoreAccessor + classDict['doc'] = _class.briefDescription.translate(self.docTranslator) if _class.briefDescription is not None else None + classDict['refCountable'] = _class.refcountable + + for _property in _class.properties: + try: + classDict['methods'] += self.translate_property(_property, hasCoreAccessor) + classDict['jniMethods'] += self.translate_jni_property(_class, _property) + except AbsApi.Error as e: + logging.error('error while translating {0} property: {1}'.format(_property.name.to_snake_case(), e.args[0])) + + for method in _class.instanceMethods: + try: + methodDict = self.translate_method(method, hasCoreAccessor) + jniMethodDict = self.translate_jni_method(_class, method) + classDict['methods'].append(methodDict) + classDict['jniMethods'].append(jniMethodDict) + except AbsApi.Error as e: + logging.error('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0])) + + for method in _class.classMethods: + try: + methodDict = self.translate_method(method, hasCoreAccessor) + jniMethodDict = self.translate_jni_method(_class, method, True) + classDict['methods'].append(methodDict) + classDict['jniMethods'].append(jniMethodDict) + except AbsApi.Error as e: + logging.error('Could not translate {0}: {1}'.format(method.name.to_snake_case(fullName=True), e.args[0])) + + islistenable = _class.listenerInterface is not None + if islistenable: + isMultiListener = (_class.multilistener) + if isMultiListener: + classDict['methods'].append(self.generate_add_listener(_class)) + classDict['methods'].append(self.generate_remove_listener(_class)) + else: + classDict['methods'].append(self.generate_set_listener(_class)) + + return classDict + + def translate_jni_interface(self, _class, className, _method): + methodDict = {} + methodDict['classCName'] = className.to_c() + methodDict['className'] = className.translate(self.nameTranslator) + methodDict['classImplName'] = methodDict['className'] + 'Impl' + methodDict['jniPath'] = self.jni_path + methodDict['cPrefix'] = _class.name.to_snake_case(fullName=True) + methodDict['callbackName'] = '_{0}_cb'.format(_method.name.to_snake_case(fullName=True)) + methodDict['jname'] = _method.name.translate(self.nameTranslator) + methodDict['return'] = _method.returnType.translate(self.clangTranslator) + methodDict['jniUpcallMethod'] = 'CallVoidMethod' + methodDict['isJniUpcallBasicType'] = False + methodDict['isJniUpcallObject'] = False + if type(_method.returnType) is AbsApi.ClassType: + methodDict['jniUpcallMethod'] = 'CallObjectMethod' + methodDict['isJniUpcallObject'] = True + methodDict['jniUpcallType'] = 'jobject' + elif type(_method.returnType) is AbsApi.BaseType: + if not _method.returnType.name == 'void': + methodDict['jniUpcallMethod'] = 'CallIntMethod' + methodDict['jniUpcallType'] = _method.returnType.translate(self.langTranslator, jni=True) + methodDict['isJniUpcallBasicType'] = True + methodDict['returnIfFail'] = '' if methodDict['return'] == 'void' else ' NULL' + methodDict['hasReturn'] = not methodDict['return'] == 'void' + methodDict['isSingleListener'] = not _class.multilistener + methodDict['isMultiListener'] = _class.multilistener + + methodDict['firstParam'] = '' + methodDict['jobjects'] = [] + methodDict['jenums'] = [] + methodDict['jstrings'] = [] + methodDict['params'] = '' + methodDict['jparams'] = '(' + methodDict['params_impl'] = '' + for arg in _method.args: + argname = arg.name.translate(self.nameTranslator) + if arg is not _method.args[0]: + methodDict['params'] += ', ' + methodDict['params_impl'] += ', ' + else: + methodDict['firstParam'] = argname + + methodDict['params'] += '{0} {1}'.format(arg.type.translate(self.clangTranslator), argname) + + if type(arg.type) is AbsApi.ClassType: + methodDict['jparams'] += 'L' + self.jni_path + arg.type.desc.name.to_camel_case() + ';' + methodDict['params_impl'] += 'j_' + argname + methodDict['jobjects'].append({'objectName': argname, 'className': arg.type.desc.name.to_camel_case(), }) + elif type(arg.type) is AbsApi.BaseType: + methodDict['jparams'] += arg.type.translate(self.jnilangTranslator) + if arg.type.name == 'string': + methodDict['params_impl'] += 'j_' + argname + methodDict['jstrings'].append({'stringName': argname,}) + else: + methodDict['params_impl'] += argname + elif type(arg.type) is AbsApi.EnumType: + methodDict['jparams'] += 'L' + self.jni_path + arg.type.desc.name.translate(self.jninameTranslator) + ';' + methodDict['params_impl'] += 'j_' + argname + methodDict['jenums'].append({'enumName': argname, 'cEnumPrefix': arg.type.desc.name.to_snake_case(fullName=True)}) + elif type(arg.type) is AbsApi.ListType: + methodDict['jparams'] += '[L' + self.jni_path + arg.type.containedTypeDesc.name + ';' + methodDict['params_impl'] += 'NULL' + + methodDict['jparams'] += ')' + if (methodDict['return'] == 'void'): + methodDict['jparams'] += 'V' + else: + if type(_method.returnType) is AbsApi.ClassType: + methodDict['jparams'] += 'L' + self.jni_path + _method.returnType.desc.name.to_camel_case() + ';' + elif type(_method.returnType) is AbsApi.BaseType: + methodDict['jparams'] += self.translate_java_jni_base_type_name(_method.returnType.name) + else: + pass #TODO + + return methodDict + + def translate_interface(self, _class): + interfaceDict = { + 'methods': [], + 'jniMethods': [], + } + + interfaceDict['doc'] = _class.briefDescription.translate(self.docTranslator) + + for method in _class.instanceMethods: + interfaceDict['methods'].append(self.translate_method(method)) + interfaceDict['jniMethods'].append(self.translate_jni_interface(_class.listenedClass, _class.name, method)) + + return interfaceDict + + def translate_enum(self, enum): + enumDict = { + 'jniMethods': [], + } + + enumDict['name'] = enum.name.to_camel_case() + enumDict['doc'] = enum.briefDescription.translate(self.docTranslator) + enumDict['values'] = [] + i = 0 + lastValue = None + + enumDict['jniPath'] = self.jni_path + + for enumerator in enum.enumerators: + enumValDict = {} + enumValDict['name'] = enumerator.name.to_camel_case() + enumValDict['doc'] = enumerator.briefDescription.translate(self.docTranslator) + if isinstance(enumerator.value, int): + lastValue = enumerator.value + enumValDict['value'] = str(enumerator.value) + elif isinstance(enumerator.value, AbsApi.Flag): + enumValDict['value'] = '1<<' + str(enumerator.value.position) + else: + if lastValue is not None: + enumValDict['value'] = lastValue + 1 + lastValue += 1 + else: + enumValDict['value'] = i + i += 1 + enumValDict['commarorsemicolon'] = ';' if i == len(enum.enumerators) else ',' + enumDict['values'].append(enumValDict) + + return enumDict + +########################################################################## + +class JavaEnum(object): + def __init__(self, package, _enum, translator): + javaNameTranslator = metaname.Translator.get('Java') + self._class = translator.translate_enum(_enum) + self.packageName = package + self.className = _enum.name.translate(javaNameTranslator) + self.cPrefix = _enum.name.to_snake_case(fullName=True) + self.filename = self.className + ".java" + self.values = self._class['values'] + self.doc = self._class['doc'] + self.jniName = _enum.name.translate(JNINameTranslator.get()) + +class JniInterface(object): + def __init__(self, javaClass, apiClass): + self.isSingleListener = (not apiClass.multilistener) + self.isMultiListener = (apiClass.multilistener) + self.className = javaClass.className + self.classCName = javaClass.cName + self.cPrefix = javaClass.cPrefix + self.callbacks = [] + listener = apiClass.listenerInterface + for method in listener.instanceMethods: + self.callbacks.append({ + 'callbackName': '_{0}_cb'.format(method.name.to_snake_case(fullName=True)), + 'callback': method.name.to_snake_case()[3:], # Remove the on_ + }) + +class JavaInterface(object): + def __init__(self, package, _interface, translator): + self._class = translator.translate_interface(_interface) + self.packageName = package + self.className = _interface.name.to_camel_case() + self.filename = self.className + ".java" + self.cPrefix = 'linphone_' + _interface.name.to_snake_case() + self.imports = [] + self.methods = self._class['methods'] + self.doc = self._class['doc'] + self.jniMethods = self._class['jniMethods'] + +class JavaInterfaceStub(object): + def __init__(self, _interface): + self.packageName = _interface.packageName + self.className = _interface.className + self.classNameStub = self.className + "Stub" + self.filename = self.className + "Stub.java" + self.methods = _interface.methods + +class JavaClass(object): + def __init__(self, package, _class, translator): + self._class = translator.translate_class(_class) + self.isLinphoneFactory = self._class['isLinphoneFactory'] + self.isLinphoneCore = self._class['isLinphoneCore'] + self.isNotLinphoneFactory = not self.isLinphoneFactory + self.cName = _class.name.to_c() + self.hasCoreAccessor = self._class['hasCoreAccessor'] + self.cPrefix = _class.name.to_snake_case(fullName=True) + self.packageName = package + self.className = _class.name.to_camel_case() + self.classImplName = self.className + "Impl" + self.refCountable = self._class['refCountable'] + self.factoryName = _class.name.to_snake_case() + self.filename = self.className + ".java" + self.imports = [] + self.methods = self._class['methods'] + self.jniMethods = self._class['jniMethods'] + self.doc = self._class['doc'] + self.enums = [] + for enum in _class.enums: + self.enums.append(JavaEnum(package, enum, translator)) + self.jniInterface = None + if _class.listenerInterface is not None: + self.jniInterface = JniInterface(self, _class) + + def add_enum(self, enum): + if enum.className.startswith(self.className): + enum.className = enum.className[len(self.className):] + self.enums.append(enum) + +class Jni(object): + def __init__(self, package): + self.enums = [] + self.interfaces = [] + self.callbacks = [] + self.objects = [] + self.methods = [] + self.jni_package = '' + self.jni_path = '' + self.coreListener = [] + package_dirs = package.split('.') + for directory in package_dirs: + self.jni_package += directory + '_' + self.jni_path += directory + '/' + + def add_enum(self, javaEnum): + obj = { + 'jniPrefix': self.jni_package, + 'jniPath': self.jni_path, + 'jniName': javaEnum.jniName, + 'cPrefix': javaEnum.cPrefix, + 'className': javaEnum.className, + } + self.enums.append(obj) + + def add_object(self, javaClass): + if javaClass.className == 'Factory': + return + obj = { + 'jniPrefix': self.jni_package, + 'jniPath': self.jni_path, + 'cPrefix': javaClass.cPrefix, + 'className': javaClass.className, + 'classCName': javaClass.cName, + 'classImplName': javaClass.classImplName, + 'refCountable': javaClass.refCountable + } + self.objects.append(obj) + + jniInterface = javaClass.jniInterface + if jniInterface is not None: + interface = { + 'isSingleListener': jniInterface.isSingleListener, + 'isMultiListener': jniInterface.isMultiListener, + 'classCName': jniInterface.classCName, + 'className': jniInterface.className, + 'cPrefix': jniInterface.cPrefix, + 'jniPackage': self.jni_package, + 'factoryName': javaClass.factoryName, + 'callbacksList': [] + } + for callback in jniInterface.callbacks: + interface['callbacksList'].append(callback) + if obj['className'] == 'Core': + self.coreListener.append(callback) + self.interfaces.append(interface) + + def add_callbacks(self, name, callbacks): + for callback in callbacks: + self.callbacks.append(callback) + + def add_methods(self, name, methods): + for method in methods: + self.methods.append(method) + +class Proguard(object): + def __init__(self, package): + self.package = package + self.classes = [] + self.enums = [] + self.listeners = [] + + def add_class(self, javaClass): + obj = { + 'package': self.package, + 'className': javaClass.className, + 'classImplName': javaClass.classImplName, + } + self.classes.append(obj) + + for javaEnum in javaClass.enums: + enumObj = { + 'package': self.package, + 'className': javaClass.className + "$" + javaEnum.className, + } + self.enums.append(enumObj) + + def add_enum(self, javaEnum): + obj = { + 'package': self.package, + 'className': javaEnum.className, + } + self.enums.append(obj) + + def add_interface(self, javaInterface): + obj = { + 'package': self.package, + 'className': javaInterface.className, + } + self.listeners.append(obj) + +########################################################################## + +class GenWrapper(object): + def __init__(self, srcdir, javadir, package, xmldir, exceptions): + self.srcdir = srcdir + self.javadir = javadir + self.package = package + self.exceptions = exceptions + + project = CApi.Project() + project.initFromDir(xmldir) + project.check() + + self.parser = AbsApi.CParser(project) + self.parser.functionBl = [ + 'linphone_factory_create_core_with_config', + 'linphone_factory_create_core', + 'linphone_factory_create_core_2', + 'linphone_factory_create_core_with_config_2', + 'linphone_vcard_get_belcard', + 'linphone_core_get_current_vtable', + 'linphone_factory_get', + 'linphone_factory_clean', + 'linphone_call_zoom_video', + 'linphone_core_get_zrtp_cache_db', + 'linphone_config_get_range' + ] + self.parser.parse_all() + self.translator = JavaTranslator(package, exceptions) + self.renderer = pystache.Renderer() + self.jni = Jni(package) + self.proguard = Proguard(package) + + self.enums = {} + self.interfaces = {} + self.classes = {} + + def render_all(self): + for _interface in self.parser.namespace.interfaces: + self.render_java_interface(_interface) + for _class in self.parser.namespace.classes: + self.render_java_class(_class) + for enum in self.parser.namespace.enums: + self.render_java_enum(enum) + + for name, value in self.enums.items(): + self.render(value, self.javadir + '/' + value.filename) + self.proguard.add_enum(value) + for name, value in self.interfaces.items(): + self.render(value, self.javadir + '/' + value.filename) + self.proguard.add_interface(value) + for name, value in self.classes.items(): + self.render(value, self.javadir + '/' + value.filename) + self.jni.add_object(value) + self.proguard.add_class(value) + + self.render(self.jni, self.srcdir + '/linphone_jni.cc') + self.render(self.proguard, self.srcdir + '/proguard.txt') + + def render(self, item, path): + tmppath = path + '.tmp' + content = '' + with open(tmppath, mode='w') as f: + f.write(self.renderer.render(item)) + with open(tmppath, mode='rU') as f: + content = f.read() + with open(path, mode='w') as f: + f.write(content) + os.unlink(tmppath) + + def render_java_enum(self, _class): + if _class is not None: + try: + javaenum = JavaEnum(self.package, _class, self.translator) + self.enums[javaenum.className] = javaenum + self.jni.add_enum(javaenum) + except AbsApi.Error as e: + logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) + + def render_java_interface(self, _class): + if _class is not None: + try: + javainterface = JavaInterface(self.package, _class, self.translator) + self.interfaces[javainterface.className] = javainterface + javaInterfaceStub = JavaInterfaceStub(javainterface) + self.interfaces[javaInterfaceStub.classNameStub] = javaInterfaceStub + except AbsApi.Error as e: + logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) + self.jni.add_callbacks(javainterface.className, javainterface.jniMethods) + + def render_java_class(self, _class): + if _class is not None: + try: + javaclass = JavaClass(self.package, _class, self.translator) + self.classes[javaclass.className] = javaclass + for enum in javaclass.enums: + self.jni.add_enum(enum) + except AbsApi.Error as e: + logging.error('Could not translate {0}: {1}'.format(_class.name.to_camel_case(fullName=True), e.args[0])) + self.jni.add_methods(javaclass.className, javaclass.jniMethods) + +########################################################################## + +if __name__ == '__main__': + argparser = argparse.ArgumentParser(description='Generate source files for the Java wrapper') + argparser.add_argument('xmldir', type=str, help='Directory where the XML documentation of the Linphone\'s API generated by Doxygen is placed') + argparser.add_argument('-o --output', type=str, help='the directory where to generate the source files', dest='outputdir', default='.') + argparser.add_argument('-p --package', type=str, help='the package name for the wrapper', dest='package', default='org.linphone.core') + argparser.add_argument('-n --name', type=str, help='the name of the genarated source file', dest='name', default='linphone_jni.cc') + argparser.add_argument('-e --exceptions', type=bool, help='enable the wrapping of LinphoneStatus into CoreException', dest='exceptions', default=False) + argparser.add_argument('-v --verbose', action='store_true', dest='verbose_mode', default=False, help='Verbose mode.') + args = argparser.parse_args() + + loglevel = logging.INFO if args.verbose_mode else logging.ERROR + logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel) + + srcdir = args.outputdir + '/src' + javadir = args.outputdir + '/java' + package_dirs = args.package.split('.') + for directory in package_dirs: + javadir += '/' + directory + + try: + os.makedirs(srcdir) + except OSError as e: + if e.errno != errno.EEXIST: + logging.critical("Cannot create '{0}' dircetory: {1}".format(srcdir, e.strerror)) + sys.exit(1) + + try: + os.makedirs(javadir) + except OSError as e: + if e.errno != errno.EEXIST: + logging.critical("Cannot create '{0}' dircetory: {1}".format(javadir, e.strerror)) + sys.exit(1) + + genwrapper = GenWrapper(srcdir, javadir, args.package, args.xmldir, args.exceptions) + genwrapper.render_all() diff --git a/wrappers/java/java_class.mustache b/wrappers/java/java_class.mustache new file mode 100644 index 000000000..4f62209f2 --- /dev/null +++ b/wrappers/java/java_class.mustache @@ -0,0 +1,232 @@ +/* +{{className}}.java +Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +package {{packageName}}; + +{{#imports}} +import {{import}} +{{/imports}} +{{#isLinphoneFactory}} +import android.content.Context; +import android.os.Build; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.linphone.mediastream.Log; +import org.linphone.mediastream.Version; +import org.linphone.core.tools.OpenH264DownloadHelper; +{{/isLinphoneFactory}} + +{{#doc}} +/** + {{#lines}} + * {{line}} + {{/lines}} + */ +{{/doc}} +public {{#isLinphoneFactory}}abstract class{{/isLinphoneFactory}}{{#isNotLinphoneFactory}}interface{{/isNotLinphoneFactory}} {{className}} { +{{#enums}} + enum {{{className}}} { + {{#values}} + {{#doc}} + /** + {{#lines}} + * {{line}} + {{/lines}} + */ + {{/doc}} + {{name}}({{value}}){{commarorsemicolon}} + + {{/values}} + protected final int mValue; + + private {{{className}}} (int value) { + mValue = value; + } + + static public {{{className}}} fromInt(int value) throws RuntimeException { + switch(value) { + {{#values}} + case {{value}}: return {{name}}; + {{/values}} + default: + throw new RuntimeException("Unhandled enum value " + value + " for {{{className}}}"); + } + } + + public int toInt() { + return mValue; + } + }; + +{{/enums}} +{{#isLinphoneFactory}} + static Factory _Factory; + + public static final synchronized Factory instance() { + try { + if (_Factory == null) { + _Factory = new FactoryImpl(0); // This value is not relevant, correct factory pointer will be used in JNI layer + } + } catch (Exception e) { + System.err.println("Cannot instanciate factory"); + } + return _Factory; + } + + abstract public OpenH264DownloadHelper createOpenH264DownloadHelper(Context context); + + /** + * Gets the LoggingService singleton + */ + abstract public LoggingService getLoggingService(); + + abstract public void setDebugMode(boolean enable, String tag); + + abstract public Core getCore(long ptr); + +{{/isLinphoneFactory}} +{{#isLinphoneCore}} + /** + * Gets the mediastreamer's factory + */ + public org.linphone.mediastream.Factory getMediastreamerFactory(); +{{/isLinphoneCore}} +{{#methods}} + {{#doc}} + /** + {{#lines}} + * {{line}} + {{/lines}} + */ + {{/doc}} + {{#deprecated}}@Deprecated + {{/deprecated}}{{#isLinphoneFactory}}abstract {{/isLinphoneFactory}}public {{return}} {{name}}({{params}}); + +{{/methods}} + /** + * Sets the object to store in this object user's data + */ + {{#isLinphoneFactory}}abstract {{/isLinphoneFactory}}public void setUserData(Object data); + + /** + * Gets the object stored in this object user's data + */ + {{#isLinphoneFactory}}abstract {{/isLinphoneFactory}}public Object getUserData(); +} + +class {{classImplName}} {{#isLinphoneFactory}}extends{{/isLinphoneFactory}}{{#isNotLinphoneFactory}}implements{{/isNotLinphoneFactory}} {{className}} { + + protected long nativePtr = 0; + protected Object userData = null;{{#hasCoreAccessor}} + protected Core core = null;{{/hasCoreAccessor}} + + protected {{classImplName}}(long ptr) { + nativePtr = ptr;{{#hasCoreAccessor}} + core = getCore();{{/hasCoreAccessor}} + } + +{{#isLinphoneFactory}} + private static boolean loadOptionalLibrary(String s) { + try { + System.loadLibrary(s); + return true; + } catch (Throwable e) { + android.util.Log.w("FactoryImpl", "Unable to load optional library " + s + ": " + e.getMessage()); + } + return false; + } + + static { + System.loadLibrary("c++_shared"); + loadOptionalLibrary("ffmpeg-linphone"); + System.loadLibrary("bctoolbox"); + System.loadLibrary("ortp"); + System.loadLibrary("mediastreamer_base"); + System.loadLibrary("mediastreamer_voip"); + System.loadLibrary("linphone"); + Version.dumpCapabilities(); + } + + public OpenH264DownloadHelper createOpenH264DownloadHelper(Context context) { + if (context == null) { + new CoreException("Cannot create OpenH264DownloadHelper"); + return null; + } + return new OpenH264DownloadHelper(context); + } + + private native Core getCore(long nativePtr, long ptr); + @Override + public Core getCore(long ptr) { + return getCore(nativePtr, ptr); + } + + @Override + public LoggingService getLoggingService() { + LoggingService l = new LoggingServiceImpl(0); + return l.get(); + } + + @Override + public native void setDebugMode(boolean enable, String tag); +{{/isLinphoneFactory}} + +{{#methods}} + private native {{return_native}} {{name}}({{native_params}}); + @Override + synchronized public {{return}} {{name}}({{params}}) {{#exception}}throws CoreException{{/exception}} { + {{#hasCoreAccessor}}{{#isNotGetCore}}synchronized(core) { {{/isNotGetCore}}{{/hasCoreAccessor}} + {{#exception}}int exceptionResult = {{/exception}}{{return_keyword}}{{#enumCast}}{{return}}.fromInt({{/enumCast}}{{#classCast}}({{return}}){{/classCast}}{{name}}({{native_params_impl}}){{#enumCast}}){{/enumCast}};{{#exception}} + if (exceptionResult != 0) throw new CoreException("{{name}} returned value " + exceptionResult);{{/exception}}{{#hasCoreAccessor}}{{#isNotGetCore}} + }{{/isNotGetCore}}{{/hasCoreAccessor}} + } + +{{/methods}} +{{#isLinphoneCore}} + private native org.linphone.mediastream.Factory getMediastreamerFactory(long nativePtr); + public org.linphone.mediastream.Factory getMediastreamerFactory() { + return getMediastreamerFactory(nativePtr); + } + +{{/isLinphoneCore}} +{{#isNotLinphoneFactory}} + private native void unref(long ptr); + protected void finalize() throws Throwable { + if (nativePtr != 0) { + unref(nativePtr); + nativePtr = 0; + } + super.finalize(); + } +{{/isNotLinphoneFactory}} + + @Override + public void setUserData(Object data) { + userData = data; + } + + @Override + public Object getUserData() { + return userData; + } +} diff --git a/wrappers/java/java_enum.mustache b/wrappers/java/java_enum.mustache new file mode 100644 index 000000000..7f9104f9b --- /dev/null +++ b/wrappers/java/java_enum.mustache @@ -0,0 +1,64 @@ +/* +{{className}}.java +Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +package {{packageName}}; + +{{#imports}} +import {{import}} +{{/imports}} + +{{#doc}} +/** + {{#lines}} + * {{line}} + {{/lines}} + */ +{{/doc}} +public enum {{{className}}} { +{{#values}} + {{#doc}} + /** + {{#lines}} + * {{line}} + {{/lines}} + */ + {{/doc}} + {{name}}({{{value}}}){{commarorsemicolon}} + +{{/values}} + protected final int mValue; + + private {{className}} (int value) { + mValue = value; + } + + static public {{className}} fromInt(int value) throws RuntimeException { + switch(value) { + {{#values}} + case {{{value}}}: return {{name}}; + {{/values}} + default: + throw new RuntimeException("Unhandled enum value " + value + " for {{className}}"); + } + } + + public int toInt() { + return mValue; + } +} diff --git a/wrappers/java/java_enum_old.mustache b/wrappers/java/java_enum_old.mustache new file mode 100644 index 000000000..a31a421bf --- /dev/null +++ b/wrappers/java/java_enum_old.mustache @@ -0,0 +1,65 @@ +/* +{{className}}.java +Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +package {{packageName}}; + +{{#imports}} +import {{import}} +{{/imports}} + +{{#doc}} +/** + {{#lines}} + * {{line}} + {{/lines}} + */ +{{/doc}} +static public class {{className}} { + static private Vector<{{className}}> values = new Vector<{{className}}>(); +{{#values}} + + {{#doc}} + /** + {{#lines}} + * {{line}} + {{/lines}} + */ + {{/doc}} + static public {{className}} {{name}} = new {{className}}({{value}}, {{name}}); +{{/values}} + + protected final int mValue; + private final String mStringValue; + + private {{className}}(int value, String stringValue) { + mValue = value; + values.addElement(this); + mStringValue = stringValue; + } + public static {{className}} fromInt(int value) { + for (int i = 0; i < values.size(); i++) { + {{className}} mstate = ({{className}}) values.elementAt(i); + if (mstate.mValue == value) return mstate; + } + throw new RuntimeException("{{className}} not found [" + value + "]"); + } + public String toString() { + return mStringValue; + } +} \ No newline at end of file diff --git a/wrappers/java/java_interface.mustache b/wrappers/java/java_interface.mustache new file mode 100644 index 000000000..22e964fba --- /dev/null +++ b/wrappers/java/java_interface.mustache @@ -0,0 +1,46 @@ +/* +{{className}}.java +Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +package {{packageName}}; + +{{#imports}} +import {{import}} +{{/imports}} + +{{#doc}} +/** + {{#lines}} + * {{line}} + {{/lines}} + */ +{{/doc}} +public interface {{className}} { +{{#methods}} + {{#doc}} + /** + {{#lines}} + * {{line}} + {{/lines}} + */ + {{/doc}} + {{#deprecated}}@Deprecated + {{/deprecated}}public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}}; + +{{/methods}} +} \ No newline at end of file diff --git a/wrappers/java/java_interface_stub.mustache b/wrappers/java/java_interface_stub.mustache new file mode 100644 index 000000000..513c74558 --- /dev/null +++ b/wrappers/java/java_interface_stub.mustache @@ -0,0 +1,37 @@ +/* +{{classNameStub}}.java +Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +package {{packageName}}; + +{{#imports}} +import {{import}} +{{/imports}} + +public class {{classNameStub}} implements {{className}} { +{{#methods}} + @Override + public {{return}} {{name}}({{params}}){{#exception}} throws CoreException{{/exception}} { + // Auto-generated method stub + {{#hasReturn}} + {{#classCast}}return null;{{/classCast}} + {{/hasReturn}} + } + +{{/methods}} +} \ No newline at end of file diff --git a/wrappers/java/jni.mustache b/wrappers/java/jni.mustache new file mode 100644 index 000000000..4da527dc2 --- /dev/null +++ b/wrappers/java/jni.mustache @@ -0,0 +1,559 @@ +/* +linphone_jni.cc +Copyright (C) 2017 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include +#include + +#include "belle-sip/object.h" +#include "mediastreamer2/mediastream.h" +#include "mediastreamer2/mscommon.h" +#include "mediastreamer2/msmediaplayer.h" +#include "mediastreamer2/msutils.h" +#include "mediastreamer2/devices.h" +#include "mediastreamer2/msjava.h" +#include "linphone/core_utils.h" +#include "linphone/core.h" +#include "linphone/tunnel.h" +#include "linphone/account_creator.h" +#include "linphone/wrapper_utils.h" +#include "linphone/lpconfig.h" + +#ifdef __ANDROID__ +#include +#endif /* __ANDROID__ */ + +static JavaVM *jvm = NULL; +static const char* LogDomain = "Linphone"; +static jmethodID loghandler_id; +static jobject handler_obj=NULL; + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *ajvm, void *reserved) { +#ifdef __ANDROID__ + ms_set_jvm(ajvm); +#endif /* __ANDROID__ */ + jvm = ajvm; + return JNI_VERSION_1_2; +} + +#define belle_sip_java_user_data_key "java_object" + +static const char* GetStringUTFChars(JNIEnv* env, jstring string) { + const char *cstring = string ? env->GetStringUTFChars(string, NULL) : NULL; + return cstring; +} + +static void ReleaseStringUTFChars(JNIEnv* env, jstring string, const char *cstring) { + if (string) env->ReleaseStringUTFChars(string, cstring); +} + +static jlong GetObjectNativePtr(JNIEnv *env, jobject object) { + jclass objClass = env->GetObjectClass(object); + jfieldID nativePtrId = env->GetFieldID(objClass, "nativePtr", "J"); + jlong nativePtr = env->GetLongField(object, nativePtrId); + return nativePtr; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void linphone_android_log_handler(int prio, char *str) { + char *current; + char *next; + + if (strlen(str) < 512) { + __android_log_write(prio, LogDomain, str); + } else { + current = str; + while ((next = strchr(current, '\n')) != NULL) { + + *next = '\0'; + if (next != str && next[-1] == '\r') + next[-1] = '\0'; + __android_log_write(prio, LogDomain, current); + current = next + 1; + } + __android_log_write(prio, LogDomain, current); + } +} + +static void linphone_android_ortp_log_handler(const char *domain, OrtpLogLevel lev, const char *fmt, va_list args) { + char* str = bctbx_strdup_vprintf(fmt, args); + const char *levname = "undef"; + + if (str == NULL) return; + + int prio; + switch(lev) { + case ORTP_DEBUG: prio = ANDROID_LOG_DEBUG; levname="debug"; break; + case ORTP_MESSAGE: prio = ANDROID_LOG_INFO; levname="message"; break; + case ORTP_WARNING: prio = ANDROID_LOG_WARN; levname="warning"; break; + case ORTP_ERROR: prio = ANDROID_LOG_ERROR; levname="error"; break; + case ORTP_FATAL: prio = ANDROID_LOG_FATAL; levname="fatal"; break; + default: prio = ANDROID_LOG_DEFAULT; break; + } + + if (handler_obj) { + JNIEnv *env = ms_get_jni_env(); + jstring jdomain = env->NewStringUTF(LogDomain); + jstring jlevname = env->NewStringUTF(levname); + jstring jstr = env->NewStringUTF(str); + env->CallVoidMethod(handler_obj, loghandler_id, jdomain, (jint)lev, jlevname, jstr, NULL); + if (jdomain) env->DeleteLocalRef(jdomain); + if (jlevname) env->DeleteLocalRef(jlevname); + if (jstr) env->DeleteLocalRef(jstr); + } else { + linphone_android_log_handler(prio, str); + } + bctbx_free(str); +} + +extern "C" void Java_org_linphone_core_FactoryImpl_setDebugMode(JNIEnv* env, jobject thiz, jboolean isDebug, jstring jdebugTag) { + if (isDebug) { + LogDomain = GetStringUTFChars(env, jdebugTag); + linphone_core_enable_logs_with_cb(linphone_android_ortp_log_handler); + } else { + linphone_core_disable_logs(); + } +} + +static jstring get_jstring_from_char(JNIEnv *env, const char* cString) { + int len; + jmethodID constructorString; + jbyteArray bytesArray = NULL; + jstring javaString = NULL; + jclass classString = env->FindClass("java/lang/String"); + if (classString == 0) { + ms_error("Cannot find java.lang.String class.\n"); + goto error; + } + + constructorString = env->GetMethodID(classString, "", "([BLjava/lang/String;)V"); + if (constructorString == 0) { + ms_error("Cannot find String method.\n"); + goto error; + } + + len = (int)strlen(cString); + bytesArray = env->NewByteArray(len); + + if (bytesArray) { + env->SetByteArrayRegion(bytesArray, 0, len, (jbyte *)cString); + jstring UTF8 = env->NewStringUTF("UTF8"); + javaString = (jstring)env->NewObject(classString, constructorString, bytesArray, UTF8); + env->DeleteLocalRef(bytesArray); + env->DeleteLocalRef(UTF8); + } + + error: + if (classString) env->DeleteLocalRef(classString); + + return javaString; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +class LinphoneJavaBindings { +public: + LinphoneJavaBindings(JNIEnv *env) { + ms_factory_class = (jclass)env->NewGlobalRef(env->FindClass("org/linphone/mediastream/Factory")); + ms_factory_class_constructor = env->GetMethodID(ms_factory_class, "", "(J)V"); + + {{#objects}} + {{cPrefix}}_class = (jclass)env->NewGlobalRef(env->FindClass("{{jniPath}}{{classImplName}}")); + {{cPrefix}}_class_constructor = env->GetMethodID({{cPrefix}}_class, "", "(J)V"); + {{/objects}} + + {{#enums}} + {{cPrefix}}_class = (jclass)env->NewGlobalRef(env->FindClass("{{jniPath}}{{jniName}}")); + {{cPrefix}}_class_constructor_from_int = env->GetStaticMethodID({{cPrefix}}_class, "fromInt", "(I)L{{jniPath}}{{jniName}};"); + {{/enums}} + } + + ~LinphoneJavaBindings() { + JNIEnv *env = 0; + jvm->AttachCurrentThread(&env,NULL); + + env->DeleteGlobalRef(ms_factory_class); + + {{#objects}} + env->DeleteGlobalRef({{cPrefix}}_class); + {{/objects}} + + {{#enums}} + env->DeleteGlobalRef({{cPrefix}}_class); + {{/enums}} + } + + jclass ms_factory_class; + jmethodID ms_factory_class_constructor; + + {{#objects}} + jclass {{cPrefix}}_class; + jmethodID {{cPrefix}}_class_constructor; + {{/objects}} + + {{#enums}} + jclass {{cPrefix}}_class; + jmethodID {{cPrefix}}_class_constructor_from_int; + {{/enums}} +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifdef __cplusplus +extern "C" { +#endif + +{{#objects}} +jobject get{{className}}(JNIEnv *env, {{classCName}} *cptr) { + jobject jobj = 0; + + if (cptr != NULL) { + void *up = belle_sip_object_data_get((belle_sip_object_t *)cptr, belle_sip_java_user_data_key); + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get()); + if (!ljb) { + ljb = new LinphoneJavaBindings(env); + linphone_factory_set_user_data(linphone_factory_get(), ljb); + } + + jclass {{cPrefix}}_class = ljb->{{cPrefix}}_class; + jmethodID {{cPrefix}}_constructor = ljb->{{cPrefix}}_class_constructor; + + if (up == NULL) { + jobj = env->NewObject({{cPrefix}}_class, {{cPrefix}}_constructor, (jlong)cptr); + belle_sip_object_data_set((belle_sip_object_t *)cptr, belle_sip_java_user_data_key, (void*)env->NewWeakGlobalRef(jobj), NULL); + {{#refCountable}}{{cPrefix}}_ref(cptr);{{/refCountable}} + } else { + jobj = env->NewLocalRef((jobject)up); + if (jobj == NULL) { + // Delete weak ref ? + env->DeleteWeakGlobalRef((jobject)up); + // takes implicit local ref + jobj = env->NewObject({{cPrefix}}_class, {{cPrefix}}_constructor, (jlong)cptr); + belle_sip_object_data_set((belle_sip_object_t *)cptr, belle_sip_java_user_data_key, (void*)env->NewWeakGlobalRef(jobj), NULL); + {{#refCountable}}{{cPrefix}}_ref(cptr);{{/refCountable}} + } + } + } + return jobj; +} + +void Java_{{jniPrefix}}{{classImplName}}_unref(JNIEnv* env, jobject thiz, jlong ptr) { + {{classCName}} *cptr = ({{classCName}}*)ptr; + jobject wref = (jobject)belle_sip_object_data_get((belle_sip_object_t *)cptr, belle_sip_java_user_data_key); + belle_sip_object_data_set((belle_sip_object_t *)cptr, belle_sip_java_user_data_key, NULL, NULL); + if (wref) { + env->DeleteWeakGlobalRef(wref); + } + {{#refCountable}}{{cPrefix}}_unref(cptr);{{/refCountable}} +} + +{{/objects}} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static inline void handle_possible_java_exception(JNIEnv *env, jobject listener) +{ + if (env->ExceptionCheck()) { + env->ExceptionDescribe(); + env->ExceptionClear(); + ms_error("Listener %p raised an exception",listener); + } +} + +{{#callbacks}} +static {{return}} {{callbackName}}({{params}}) { + JNIEnv *env = ms_get_jni_env(); + if (!env) { + ms_error("cannot attach VM"); + return{{returnIfFail}}; + } + + {{#isSingleListener}} + {{classCName}} *cbs = {{cPrefix}}_get_callbacks({{firstParam}}); + {{/isSingleListener}} + {{#isMultiListener}} + {{classCName}} *cbs = {{cPrefix}}_get_current_callbacks({{firstParam}}); + {{/isMultiListener}} + jobject jlistener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs); + + if (jlistener == NULL) { + ms_warning("{{callbackName}}() notification without listener"); + return{{returnIfFail}}; + } + + jclass jlistenerClass = (jclass) env->GetObjectClass(jlistener); + jmethodID jcallback = env->GetMethodID(jlistenerClass, "{{jname}}", "{{jparams}}"); + env->DeleteLocalRef(jlistenerClass); + + {{#jobjects}} + jobject j_{{objectName}} = get{{className}}(env, (Linphone{{className}} *){{objectName}}); + {{/jobjects}} + {{#jenums}} + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get()); + jobject j_{{enumName}} = env->CallStaticObjectMethod(ljb->{{cEnumPrefix}}_class, ljb->{{cEnumPrefix}}_class_constructor_from_int, (jint){{enumName}}); + {{/jenums}} + {{#jstrings}} + jstring j_{{stringName}} = {{stringName}} ? get_jstring_from_char(env, {{stringName}}) : NULL; + {{/jstrings}} + + {{#hasReturn}}{{jniUpcallType}} jni_upcall_result = {{/hasReturn}}env->{{jniUpcallMethod}}(jlistener, jcallback, {{params_impl}}); + {{#hasReturn}} + {{#isJniUpcallObject}} + {{return}} c_upcall_result = NULL; + if (jni_upcall_result) c_upcall_result = ({{return}})GetObjectNativePtr(env, jni_upcall_result); + {{/isJniUpcallObject}} + {{#isJniUpcallBasicType}} + {{return}} c_upcall_result = ({{return}}) jni_upcall_result; + {{/isJniUpcallBasicType}} + {{/hasReturn}} + + {{#jobjects}} + if (j_{{objectName}}) { + env->DeleteLocalRef(j_{{objectName}}); + } + {{/jobjects}} + {{#jenums}} + if (j_{{enumName}}) { + env->DeleteLocalRef(j_{{enumName}}); + } + {{/jenums}} + {{#jstrings}} + if (j_{{stringName}}) { + env->DeleteLocalRef(j_{{stringName}}); + } + {{/jstrings}} + + handle_possible_java_exception(env, jlistener); + {{#hasReturn}} + return c_upcall_result; + {{/hasReturn}} +} + +{{/callbacks}} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +{{#interfaces}} +{{#isSingleListener}} +void Java_{{jniPackage}}{{className}}Impl_setListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) { + {{classCName}} *cptr = ({{classCName}}*)ptr; + {{classCName}}Cbs *cbs = {{cPrefix}}_get_callbacks(cptr); + if (jlistener == NULL) { + jobject listener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs); + {{cPrefix}}_cbs_set_user_data(cbs, NULL); + if (listener != NULL) { + env->DeleteGlobalRef(listener); + } + } else { + jobject listener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs); + if (listener == NULL) { + listener = env->NewGlobalRef(jlistener); + } else { + if (env->IsSameObject(listener, jlistener)) { + return; + } else { + env->DeleteGlobalRef(listener); + listener = env->NewGlobalRef(jlistener); + } + } + {{cPrefix}}_cbs_set_user_data(cbs, listener); + {{#callbacksList}} + {{cPrefix}}_cbs_set_{{callback}}(cbs, {{callbackName}}); + {{/callbacksList}} + } +} +{{/isSingleListener}} + +{{#isMultiListener}} +void Java_{{jniPackage}}{{className}}Impl_addListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) { + if (jlistener == NULL) return; + {{classCName}} *cptr = ({{classCName}}*)ptr; + jobject listener = env->NewGlobalRef(jlistener); + {{classCName}}Cbs *cbs = linphone_factory_create_{{factoryName}}_cbs(NULL); + {{cPrefix}}_cbs_set_user_data(cbs, listener); + {{#callbacksList}} + {{cPrefix}}_cbs_set_{{callback}}(cbs, {{callbackName}}); + {{/callbacksList}} + {{cPrefix}}_add_callbacks(cptr, cbs); + {{cPrefix}}_cbs_unref(cbs); +} + +void Java_{{jniPackage}}{{className}}Impl_removeListener(JNIEnv* env, jobject thiz, jlong ptr, jobject jlistener) { + {{classCName}} *cptr = ({{classCName}}*)ptr; + const bctbx_list_t *cbs_list = {{cPrefix}}_get_callbacks_list(cptr); + bctbx_list_t *it; + for (it = (bctbx_list_t *)cbs_list; it != NULL; it = it->next) { + {{classCName}}Cbs *cbs = ({{classCName}}Cbs *)it->data; + jobject listener = (jobject) {{cPrefix}}_cbs_get_user_data(cbs); + if (env->IsSameObject(listener, jlistener)) { + {{cPrefix}}_cbs_set_user_data(cbs, NULL); + {{cPrefix}}_remove_callbacks(cptr, cbs); + env->DeleteGlobalRef(listener); + break; + } + } +} +{{/isMultiListener}} +{{/interfaces}} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +jobject Java_{{jni_package}}CoreImpl_getMediastreamerFactory(JNIEnv *env, jobject thiz, jlong ptr) { + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get()); + MSFactory *factory = linphone_core_get_ms_factory((LinphoneCore*)ptr); + return env->NewObject(ljb->ms_factory_class, ljb->ms_factory_class_constructor, (jlong)factory); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +{{#methods}} +{{#notEmpty}} +{{return}} {{name}}({{params}}) { + {{#notStatic}}{{classCName}} *cptr = ({{classCName}}*)ptr; + {{#isLinphoneFactory}}cptr = linphone_factory_get();{{/isLinphoneFactory}} + if (cptr == 0) { + return {{#hasReturn}}0{{/hasReturn}}{{#hasStringReturn}}0{{/hasStringReturn}}{{#hasListReturn}}0{{/hasListReturn}}{{#hasByteArrayReturn}}0{{/hasByteArrayReturn}}; + } + {{/notStatic}}{{#strings}} + const char* c_{{string}} = GetStringUTFChars(env, {{string}}); + {{/strings}}{{#bytes}} + {{bytesargtype}} c_{{bytesargname}} = ({{bytesargtype}})env->GetByteArrayElements({{bytesargname}}, NULL); + {{/bytes}}{{#objects}} + {{objectClassCName}}* c_{{object}} = NULL; + if ({{object}}) c_{{object}} = ({{objectClassCName}}*)GetObjectNativePtr(env, {{object}}); + {{/objects}}{{#lists}} + bctbx_list_t *bctbx_list_{{list}} = NULL; + int {{list}}_count = env->GetArrayLength({{list}}); + for (int i=0; i < {{list}}_count; i++) { + {{#isStringList}} + jstring obj = (jstring) env->GetObjectArrayElement({{list}}, i); + const char *str = GetStringUTFChars(env, obj); + if (str) { + bctbx_list_{{list}} = bctbx_list_append(bctbx_list_{{list}}, ms_strdup(str)); + ReleaseStringUTFChars(env, obj, str); + } + {{/isStringList}} + {{#isObjList}} + jobject obj = env->GetObjectArrayElement({{list}}, i); + bctbx_list_{{list}} = bctbx_list_append(bctbx_list_{{list}}, ({{objectClassCName}} *)GetObjectNativePtr(env, obj)); + {{/isObjList}} + } + {{/lists}}{{#hasListReturn}} + const bctbx_list_t *list = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}); + size_t count = bctbx_list_size(list); + {{#isRealObjectArray}} + LinphoneJavaBindings *ljb = (LinphoneJavaBindings *)linphone_factory_get_user_data(linphone_factory_get()); + jobjectArray jni_list_result = env->NewObjectArray((int)count, ljb->{{objectCPrefix}}_class, NULL);{{/isRealObjectArray}} + {{#isStringObjectArray}}jobjectArray jni_list_result = env->NewObjectArray((int)count, env->FindClass("java/lang/String"), env->NewStringUTF(""));{{/isStringObjectArray}} + for (size_t i = 0; i < count; i++) { + {{#isRealObjectArray}} + {{objectClassCName}}* c_object = ({{objectClassCName}}*)list->data; + jobject object = get{{objectClassName}}(env, c_object); + {{/isRealObjectArray}} + {{#isStringObjectArray}}const char *cstring = (const char *)list->data; + jstring object = cstring ? get_jstring_from_char(env, cstring) : 0;{{/isStringObjectArray}} + if (object != 0) { + env->SetObjectArrayElement(jni_list_result, (int)i, object); + {{#isRealObjectArray}}env->DeleteLocalRef(object);{{/isRealObjectArray}} + } + list = bctbx_list_next(list); + } + {{/hasListReturn}}{{#hasByteArrayReturn}} + {{c_type_return}} jni_result = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}); + if (!jni_result) return NULL; + size_t jni_result_length = strlen((const char *)jni_result); + jbyteArray array = env->NewByteArray((int)jni_result_length); + env->SetByteArrayRegion(array, 0, (int)jni_result_length, (const jbyte*)jni_result); + return array; + {{/hasByteArrayReturn}}{{#hasStringReturn}} + const char *c_string = {{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}){{#returnObject}}){{/returnObject}}; + jstring jni_result = (c_string != NULL) ? get_jstring_from_char(env, c_string) : NULL; + {{/hasStringReturn}}{{#hasNormalReturn}} + {{#hasReturn}}{{return}} jni_result = ({{return}}){{#returnObject}}get{{returnClassName}}(env, (Linphone{{returnClassName}} *){{/returnObject}}{{/hasReturn}}{{c_name}}({{#notStatic}}cptr{{/notStatic}}{{params_impl}}){{#returnObject}}){{/returnObject}}; + {{/hasNormalReturn}}{{#strings}} + ReleaseStringUTFChars(env, {{string}}, c_{{string}}); + {{/strings}}{{#bytes}} + env->ReleaseByteArrayElements({{bytesargname}}, (jbyte*)c_{{bytesargname}}, JNI_ABORT); + {{/bytes}}{{#hasReturn}}return jni_result;{{/hasReturn}}{{#hasListReturn}}return jni_list_result;{{/hasListReturn}} +} +{{/notEmpty}} +{{/methods}} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Manually wrapped +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Java_org_linphone_core_CallImpl_setNativeVideoWindowId(JNIEnv *env, jobject thiz, jlong ptr, jobject id) { + LinphoneCall *cptr = (LinphoneCall*)ptr; + jobject oldWindow = (jobject) linphone_call_get_native_video_window_id(cptr); + if (oldWindow == id) { + ms_warning("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): new id (%p) is the same as the current one, skipping...", id); + return; + } + if (id != NULL) { + id = env->NewGlobalRef(id); + ms_message("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): NewGlobalRef(%p)", id); + } else ms_message("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): setting to NULL"); + linphone_call_set_native_video_window_id(cptr, (void *)id); + if (oldWindow != NULL) { + ms_message("Java_org_linphone_core_CallImpl_setNativeVideoWindowId(): DeleteGlobalRef(%p)", oldWindow); + env->DeleteGlobalRef(oldWindow); + } +} + +void Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(JNIEnv *env, jobject thiz, jlong ptr, jobject id) { + LinphoneCore *cptr = (LinphoneCore*)ptr; + jobject oldWindow = (jobject) linphone_core_get_native_preview_window_id(cptr); + if (oldWindow == id) { + ms_warning("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): new id (%p) is the same as the current one, skipping...", id); + return; + } + if (id != NULL) { + id = env->NewGlobalRef(id); + ms_message("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): NewGlobalRef(%p)", id); + } else ms_message("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): setting to NULL"); + linphone_core_set_native_preview_window_id(cptr, (void *)id); + if (oldWindow != NULL) { + ms_message("Java_org_linphone_core_CoreImpl_setNativePreviewWindowId(): DeleteGlobalRef(%p)", oldWindow); + env->DeleteGlobalRef(oldWindow); + } +} + +void Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(JNIEnv *env, jobject thiz, jlong ptr, jobject id) { + LinphoneCore *cptr = (LinphoneCore*)ptr; + jobject oldWindow = (jobject) linphone_core_get_native_video_window_id(cptr); + if (oldWindow == id) { + ms_warning("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): new id (%p) is the same as the current one, skipping...", id); + return; + } + if (id != NULL) { + id = env->NewGlobalRef(id); + ms_message("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): NewGlobalRef(%p)", id); + } else ms_message("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): setting to NULL"); + linphone_core_set_native_video_window_id(cptr, (void *)id); + if (oldWindow != NULL) { + ms_message("Java_org_linphone_core_CoreImpl_setNativeVideoWindowId(): DeleteGlobalRef(%p)", oldWindow); + env->DeleteGlobalRef(oldWindow); + } +} + +jobject Java_org_linphone_core_FactoryImpl_getCore(JNIEnv *env, jobject thiz, jlong ptr, jlong lcPtr) { + return getCore(env, (LinphoneCore*)lcPtr); +} + +#ifdef __cplusplus +} +#endif diff --git a/wrappers/java/migration.sh b/wrappers/java/migration.sh new file mode 100755 index 000000000..98e4286ff --- /dev/null +++ b/wrappers/java/migration.sh @@ -0,0 +1,389 @@ +#!/bin/sh + +# 1st pass +find ./src/android/org/linphone/ -type f -exec sed -i -e "s/import org.linphone.tools/import org.linphone.core.tools/g; \ +s/import org.linphone.core.OpenH264DownloadHelperListener/import org.linphone.core.tools.OpenH264DownloadHelperListener/g; \ +s/import org.linphone.core.LinphoneCore.Transports/import org.linphone.core.Transports/g; \ +s/import org.linphone.core.LinphoneXmlRpcRequest.LinphoneXmlRpcRequestListener/import org.linphone.core.XmlRpcRequestListener/g; \ +s/import org.linphone.core.LinphoneXmlRpcRequestImpl/\/\/import org.linphone.core.XmlRpcRequestImpl/g; \ +s/import org.linphone.core.LinphoneXmlRpcSessionImpl/\/\/import org.linphone.core.XmlRpcSessionImpl/g; \ +s/LinphoneAccountCreator.LinphoneAccountCreatorListener/AccountCreatorListener/g; \ +s/AccountCreator.LinphoneAccountCreatorListener/AccountCreatorListener/g; \ +s/LinphoneCoreListenerBase/CoreListenerStub/g; \ +s/LinphoneCoreListener/CoreListener/g; \ +s/LinphoneChatMessage.LinphoneChatMessageListener/ChatMessageListener/g; \ +s/Core.LinphoneLimeState/Core.LimeState/g; \ +s/LinphoneLimeState/LimeState/g; \ +s/GlobalState.GlobalOn/Core.GlobalState.On/g; \ +s/RegistrationState.RegistrationOk/RegistrationState.Ok/g; \ +s/RegistrationState.RegistrationFailed/RegistrationState.Failed/g; \ +s/RegistrationState.RegistrationCleared/RegistrationState.Cleared/g; \ +s/RegistrationState.RegistrationProgress/RegistrationState.Progress/g; \ +s/RegistrationState.RegistrationNone/RegistrationState.None/g; \ +s/RemoteProvisioningState.ConfiguringSuccessful/ConfiguringState.Successful/g; \ +s/LinphoneCore.RemoteProvisioningState/Core.ConfiguringState/g; \ +s/RemoteProvisioningState/ConfiguringState/g; \ +s/ConfiguringFailed/Failed/g; \ +s/CallDirection/Call.Dir/g; \ +s/State.CallReleased/State.Released/g; \ +s/State.CallEnd/State.End/g; \ +s/State.CallUpdatedByRemote/State.UpdatedByRemote/g; \ +s/State.CallIncomingEarlyMedia/State.IncomingEarlyMedia/g; \ +s/State.CallUpdating/State.Updating/g; \ +s/LogCollectionUploadState.LogCollectionUploadStateInProgress/LogCollectionUploadState.InProgress/g; \ +s/LogCollectionUploadState.LogCollectionUploadStateDelivered/LogCollectionUploadState.Delivered/g; \ +s/LogCollectionUploadState.LogCollectionUploadStateNotDelivered/LogCollectionUploadState.NotDelivered/g; \ +s/AccountCreator.RequestStatus/AccountCreator.Status/g; \ +s/RequestStatus/Status/g; \ +s/AccountCreator.Status.Ok/AccountCreator.Status.RequestOk/g; \ +s/AccountCreator.PasswordCheck/AccountCreator.PasswordStatus/g; \ +s/AccountCreator.PhoneNumberCheck/AccountCreator.PhoneNumberStatus/g; \ +s/AccountCreator.EmailCheck/AccountCreator.EmailStatus/g; \ +s/AccountCreator.UsernameCheck/AccountCreator.UsernameStatus/g; \ +s/AccountCreator.Status.Failed/AccountCreator.Status.RequestFailed/g; \ +s/AccountCreator.Status.ErrorServer/AccountCreator.Status.ServerError/g; \ +s/PhoneNumberStatus.CountryCodeInvalid/PhoneNumberStatus.InvalidCountryCode/g; \ +s/Reason.Media/Reason.NotAcceptable/g; \ +s/Reason.BadCredentials/Reason.Forbidden/g; \ +s/TransportType.LinphoneTransportUdp/TransportType.Udp/g; \ +s/TransportType.LinphoneTransportTcp/TransportType.Tcp/g; \ +s/TransportType.LinphoneTransportTls/TransportType.Tls/g; \ +s/TransportType.LinphoneTransportDtls/TransportType.Dtls/g; \ +s/AddressFamily.INET_6.getInt()/AddressFamily.Inet6/g; \ +s/AddressFamily.INET.getInt()/AddressFamily.Inet/g; \ +s/LpConfig/Config/g; \ +s/LinphoneCoreException/CoreException/g; \ +s/LinphoneCoreFactory/Factory/g; \ +s/LinphoneAccountCreator/AccountCreator/g; \ +s/LinphoneAddress/Address/g; \ +s/LinphoneAuthInfo/AuthInfo/g; \ +s/LinphoneBuffer/Buffer/g; \ +s/LinphoneCallLog/CallLog/g; \ +s/LinphoneCallParams/CallParams/g; \ +s/LinphoneCallStats/CallStats/g; \ +s/LinphoneCall/Call/g; \ +s/LinphoneChatMessage/ChatMessage/g; \ +s/LinphoneChatRoom/ChatRoom/g; \ +s/LinphoneConferenceParams/ConferenceParams/g; \ +s/LinphoneConference/Conference/g; \ +s/LinphoneConfig/Config/g; \ +s/LinphoneContent/Content/g; \ +s/LinphoneCore/Core/g; \ +s/LinphoneEvent/Event/g; \ +s/LinphoneFriendList/FriendList/g; \ +s/LinphoneFriend/Friend/g; \ +s/LinphoneHeaders/Headers/g; \ +s/LinphoneImNotifyPolicy/ImNotifyPolicy/g; \ +s/LinphoneInfoMessage/InfoMessage/g; \ +s/LinphoneNatPolicy/NatPolicy/g; \ +s/LinphonePayloadType/PayloadType/g; \ +s/LinphonePlayer/Player/g; \ +s/LinphonePresence/Presence/g; \ +s/LinphonePrivacy/Privacy/g; \ +s/LinphoneProxyConfig/ProxyConfig/g; \ +s/LinphonePublishState/PublishState/g; \ +s/LinphoneRange/Range/g; \ +s/LinphoneStreamType/StreamType/g; \ +s/LinphoneSubscription/Subscription/g; \ +s/LinphoneTransports/Transports/g; \ +s/LinphoneTunnel/Tunnel/g; \ +s/LinphoneVcard/Vcard/g; \ +s/LinphoneXmlRpc/XmlRpc/g; \ +s/onAccountCreatorIsAccountUsed/onIsAccountExist/g; \ +s/onAccountCreatorAccountCreated/onCreateAccount/g; \ +s/onAccountCreatorAccountActivated/onActivateAccount/g; \ +s/onAccountCreatorAccountLinkedWithPhoneNumber/onLinkAccount/g; \ +s/onAccountCreatorPhoneNumberLinkActivated/onActivateAlias/g; \ +s/onAccountCreatorIsAccountActivated/onIsAccountActivated/g; \ +s/onAccountCreatorPhoneAccountRecovered/onRecoverAccount/g; \ +s/onAccountCreatorIsAccountLinked/onIsAccountLinked/g; \ +s/onAccountCreatorIsPhoneNumberUsed/onIsAliasUsed/g; \ +s/onAccountCreatorPasswordUpdated/onUpdateAccount/g; \ +s/(AccountCreator accountCreator, Status status)/(AccountCreator accountCreator, Status status, String resp)/g; \ +s/(AccountCreator accountCreator, AccountCreator.Status status)/(AccountCreator accountCreator, AccountCreator.Status status, String resp)/g; \ +s/onChatMessageStateChanged/onMsgStateChanged/g; \ +s/onChatMessageFileTransferProgressChanged/onFileTransferProgressIndication/g; \ +s/onChatMessageFileTransferSent/onFileTransferSend/g; \ +s/onChatMessageFileTransferReceived/onFileTransferRecv/g; \ +s/authInfoRequested/authInfoRequested_removed/g; \ +s/show(Core/show_removed(Core/g; \ +s/displayStatus/displayStatus_removed/g; \ +s/displayMessage/displayMessage_removed/g; \ +s/displayWarning/displayWarning_removed/g; \ +s/fileTransferProgressIndication/fileTransferProgressIndication_removed/g; \ +s/fileTransferRecv/fileTransferRecv_removed/g; \ +s/fileTransferSend/fileTransferSend_removed/g; \ +s/notifyReceived(Core lc, Event/onNotifyReceived(Core lc, Event/g; \ +s/notifyReceived/notifyReceived_removed/g; \ +s/ecCalibrationStatus/onEcCalibrationResult/g; \ +s/publishStateChanged/onPublishStateChanged/g; \ +s/messageReceivedUnableToDecrypted/messageReceivedUnableToDecrypted_removed/g; \ +s/callStatsUpdated/onCallStatsUpdated/g; \ +s/authenticationRequested/onAuthenticationRequested/g; \ +s/newSubscriptionRequest/onNewSubscriptionRequested/g; \ +s/notifyPresenceReceived/onNotifyPresenceReceived/g; \ +s/dtmfReceived/onDtmfReceived/g; \ +s/transferState/onTransferStateChanged/g; \ +s/infoReceived/onInfoReceived/g; \ +s/subscriptionStateChanged/onSubscriptionStateChanged/g; \ +s/globalState/onGlobalStateChanged/g; \ +s/registrationState/onRegistrationStateChanged/g; \ +s/configuringStatus/onConfiguringStatus/g; \ +s/messageReceived/onMessageReceived/g; \ +s/callState/onCallStateChanged/g; \ +s/callEncryptionChanged/onCallEncryptionChanged/g; \ +s/isComposingReceived/onIsComposingReceived/g; \ +s/uploadProgressIndication/onLogCollectionUploadProgressIndication/g; \ +s/uploadStateChanged/onLogCollectionUploadStateChanged/g; \ +s/friendListCreated/onFriendListCreated/g; \ +s/friendListRemoved/onFriendListRemoved/g; \ +s/networkReachableChanged/onNetworkReachable/g; \ +s/onFriendCreated/onContactCreated/g; \ +s/onFriendUpdated/onContactUpdated/g; \ +s/onFriendDeleted/onContactDeleted/g; \ +s/onFriendSyncStatusChanged/onSyncStatusChanged/g; \ +s/onXmlRpcRequestResponse/onResponse/g; \ +s/getFriendsLists()/getFriends()/g; \ +s/getFriendLists()/getFriendsLists()/g; \ +s/getFriendList(/getFriendsLists(/g; \ +s/getIdentity(/getIdentityAddress(/g; \ +s/isTunnelAvailable()/tunnelAvailable()/g; \ +s/tunnelSetMode(/getTunnel().setMode(/g; \ +s/tunnelAddServer(/getTunnel().addServer(/g; \ +s/tunnelCleanServers(/getTunnel().cleanServers(/g; \ +s/setZrtpSecretsCache(/setZrtpSecretsFile(/g; \ +s/setRootCA(/setRootCa(/g; \ +s/isInComingInvitePending()/isIncomingInvitePending()/g; \ +s/getAudioCodecs()/getAudioPayloadTypes()/g; \ +s/getVideoCodecs()/getVideoPayloadTypes()/g; \ +s/getMime()/getMimeType()/g; \ +s/getFrom()/getFromAddress()/g; \ +s/getTo()/getToAddress()/g; \ +s/getUserName()/getUsername()/g; \ +s/getLimeEncryption()/limeEnabled()/g; \ +s/getDirection/getDir/g; \ +s/.getVideoEnabled()/.videoEnabled()/g; \ +s/.getDataAsString()/.getStringBuffer()/g; \ +s/getEventName()/getName()/g; \ +s/setPlaybackGain(/setPlaybackGainDb(/g; \ +s/isIncall()/inCall()/g; \ +s/setVideoEnabled(/enableVideo(/g; \ +s/setAudioBandwidth(/setAudioBandwidthLimit(/g; \ +s/isAuthenticationTokenVerified()/getAuthenticationTokenVerified()/g; \ +s/\(\s*\)\([a-zA-Z()\.]*\)isMicMuted()/\1!\2micEnabled()/g; \ +s/isLowBandwidthEnabled()/lowBandwidthEnabled()/g; \ +s/muteMic(/enableMic(!/g; \ +s/getRate()/getClockRate()/g; \ +s/getSentVideoSize()/getSentVideoDefinition()/g; \ +s/getReceivedVideoSize()/getReceivedVideoDefinition()/g; \ +s/getUsedAudioCodec()/getUsedAudioPayloadType()/g; \ +s/getUsedVideoCodec()/getUsedVideoPayloadType()/g; \ +s/setVideoWindow(/setNativeVideoWindowId(/g; \ +s/setPreviewWindow(/setNativePreviewWindowId(/g; \ +s/islimeAvailable()/limeAvailable()/g; \ +s/createChatMessage(/createMessage(/g; \ +s/message.getStatus()/message.getState()/g; \ +s/reSend()/resend()/g; \ +s/setAppData(/setAppdata(/g; \ +s/getAppData()/getAppdata()/g; \ +s/getOrCreateChatRoom(/getChatRoomFromUri(/g; \ +s/findFriendByAddress(/findFriend(/g; \ +s/getTimestamp()/getStartDate()/g; \ +s/lpc.getAddress()/lpc.getIdentityAddress()/g; \ +s/cfg.getAddress()/cfg.getIdentityAddress()/g; \ +s/prxCfg.getAddress()/prxCfg.getIdentityAddress()/g; \ +s/proxy.getAddress()/proxy.getIdentityAddress()/g; \ +s/getProxyConfig(n).getAddress()/getProxyConfig(n).getIdentityAddress()/g; \ +s/getCallDuration()/getDuration()/g; \ +s/isVCardSupported()/vcardSupported()/g; \ +s/getPresenceModelForUri(/getPresenceModelForUriOrTel(/g; \ +s/setAvpfRRInterval(/setAvpfRrInterval(/g; \ +s/getAvpfRRInterval(/getAvpfRrInterval(/g; \ +s/hasBuiltInEchoCanceler()/hasBuiltinEchoCanceller()/g; \ +s/getProxy()/getServerAddr()/g; \ +s/setProxy(/setServerAddr(/g; \ +s/setIdentity(/setIdentityAddress(/g; \ +s/setUserId(/setUserid(/g; \ +s/getUserId(/getUserid(/g; \ +s/getAuthInfosList(/getAuthInfoList(/g; \ +s/getSignalingTransportPorts()/getTransports()/g; \ +s/setSignalingTransportPorts(/setTransports(/g; \ +s/isIpv6Enabled()/ipv6Enabled()/g; \ +s/isAdaptiveRateControlEnabled()/adaptiveRateControlEnabled()/g; \ +s/setLimeEncryption(/enableLime(/g; \ +s/.value()/.toInt()/g; \ +s/clearAuthInfos()/clearAllAuthInfo()/g; \ +s/clearProxyConfigs()/clearProxyConfig()/g; \ +s/isVideoSupported()/videoSupported()/g; \ +s/getReceivedVideoDefinition().width/getReceivedVideoDefinition().getWidth()/g; \ +s/getReceivedVideoDefinition().height/getReceivedVideoDefinition().getHeight()/g; \ +s/VideoDefinition().toDisplayableString()/VideoDefinition().getName()/g; \ +s/isAccountUsed()/isAccountExist()/g; \ +s/loadXmlFile(/loadFromXmlFile(/g; \ +s/activatePhoneNumberLink()/activateAlias()/g; \ +s/isPhoneNumberUsed()/isAliasUsed()/g; \ +s/recoverPhoneAccount()/recoverAccount()/g; \ +s/isLimeEncryptionAvailable()/limeAvailable()/g; \ +s/getUseRfc2833ForDtmfs/getUseRfc2833ForDtmf/g; \ +s/setUseRfc2833ForDtmfs/setUseRfc2833ForDtmf/g; \ +s/getUseSipInfoForDtmfs/getUseInfoForDtmf/g; \ +s/setUseSipInfoForDtmfs/setUseInfoForDtmf/g; \ +s/getIncomingTimeout/getIncTimeout/g; \ +s/setIncomingTimeout/setIncTimeout/g; \ +s/migrateCallLogs()/migrateLogsFromRcToDb()/g; \ +s/setRLSUri/setRlsUri/g; \ +s/hasCrappyOpenGL(/hasCrappyOpengl(/g; \ +s/needsEchoCalibration(/isEchoCancellerCalibrationRequired(/g; \ +s/getCountryCode()/getCountryCallingCode()/g; \ +s/isEchoCancellationEnabled()/echoCancellationEnabled()/g; \ +s/startEchoCalibration(/startEchoCancellerCalibration(/g; \ +s/.isRegistered()/.getState() == RegistrationState.Ok/g; \ +s/\(\s*\)\([a-zA-Z()\.]*\)isInConference()/\1\2getConference() != null/g; \ +s/getAudioStats()/getStats(StreamType.Audio)/g; \ +s/getVideoStats()/getStats(StreamType.Video)/g; \ +s/getVcardToString()/getVcard().asVcard4String()/g; \ +s/getVideoAutoAcceptPolicy(/getVideoActivationPolicy().getAutomaticallyAccept(/g; \ +s/getVideoAutoInitiatePolicy()/getVideoActivationPolicy().getAutomaticallyInitiate()/g; \ +s/setFamilyName(/getVcard().setFamilyName(/g; \ +s/setGivenName(/getVcard().setGivenName(/g; \ +s/\.setOrganization(/\.getVcard().setOrganization(/g; \ +s/getFamilyName()/getVcard().getFamilyName()/g; \ +s/getGivenName()/getVcard().getGivenName()/g; \ +s/\.getOrganization()/\.getVcard().getOrganization()/g; \ +s/enableAvpf(/setAvpfMode(AVPFMode.Enabled)/g; \ +s/transports.udp\s*=\s*\([a-zA-Z0-9_]*\)/transports.setUdpPort(\1)/g; \ +s/transports.tcp\s*=\s*\([a-zA-Z0-9_]*\)/transports.setTcpPort(\1)/g; \ +s/transports.tls\s*=\s*\([a-zA-Z0-9_]*\)/transports.setTlsPort(\1)/g; \ +s/transports.udp/transports.getUdpPort()/g; \ +s/transports.tcp/transports.getTcpPort()/g; \ +s/transports.tls/transports.getTlsPort()/g; \ +s/getPrimaryContactUsername()/getPrimaryContactParsed().getUsername()/g; \ +s/getPrimaryContactDisplayName()/getPrimaryContactParsed().getDisplayName()/g; \ +s/.sendDtmf(/.getCurrentCall().sendDtmf(/g; \ +s/content.getData() == null/content.getSize() == 0/g; \ +s/lc.downloadOpenH264Enabled()/OpenH264DownloadHelper.isOpenH264DownloadEnabled()/g; \ +s/LinphoneManager.getLc().downloadOpenH264Enabled()/OpenH264DownloadHelper.isOpenH264DownloadEnabled()/g; \ +s/getLc().enableDownloadOpenH264(/OpenH264DownloadHelper.setOpenH264DownloadEnabled(/g; \ +s/enableDownloadOpenH264(/OpenH264DownloadHelper.enableDownloadOpenH264(/g; \ +s/mLc.destroy()/mLc = null/g; \ +s/getAllDialPlan()/getDialPlans()/g; \ +s/getCountryName()/getCountry()/g; \ +s/getMSFactory()/getMediastreamerFactory()/g; \ +s/accountCreator.getPrefix(/org.linphone.core.Utils.getPrefixFromE164(/g; \ +s/proxyConfig.lookupCCCFromIso(/org.linphone.core.Utils.getCccFromIso(/g; \ +s/linkPhoneNumberWithAccount()/linkAccount()/g; \ +s/zoomVideo(/zoom(/g; \ +s/mLc.setCpuCount(/\/\/mLc.setCpuCount(/g; \ +s/new XmlRpcRequestImpl(/xmlRpcSession.createRequest(/g; \ +s/new XmlRpcSessionImpl(LinphoneManager.getLcIfManagerNotDestroyedOrNull(), /LinphoneManager.getLcIfManagerNotDestroyedOrNull().createXmlRpcSession(/g; \ +s/FriendImpl/Friend/g; \ +s/PresenceActivityType/PresenceActivity.Type/g; \ +s/org\.linphone\.core\.VideoSize/org.linphone.core.VideoDefinition/g;" {} \; + +# 2nd pass +find ./src/android/org/linphone/ -type f -exec sed -i -e "s/Address\.TransportType/TransportType/g; \ +s/\(CallLog\.\)\?CallStatus\([^[:alnum:]_]\)/Call.Status\2/g; \ +s/CallStats\.AddressFamily/AddressFamily/g; \ +s/CallStats\.StreamType/StreamType/g; \ +s/Core\.AuthMethod/AuthMethod/g; \ +s/Core\.ConfiguringState/ConfiguringState/g; \ +s/Core\.EcCalibratorStatus/EcCalibratorStatus/g; \ +s/Core\.GlobalState/GlobalState/g; \ +s/Core\.LimeState/LimeState/g; \ +s/Core\.LogCollectionState/LogCollectionState/g; \ +s/Core\.MediaEncryption/MediaEncryption/g; \ +s/Core\.RegistrationState/RegistrationState/g; \ +s/Core\.TunnelMode/Tunnel.Mode/g; \ +s/Core\.VersionUpdateCheckResult/VersionUpdateCheckResult/g; \ +s/Event\.PublishState/PublishState/g; \ +s/Friend\.SubscribePolicy/SubscribePolicy/g; \ +s/XmlRpcRequest\.ArgType/XmlRpcArgType/g; \ +s/XmlRpcRequest\.Status/XmlRpcStatus/g; \ +s/org\.linphone\.core\.PresenceActivity\.Type/org.linphone.core.PresenceActivity/g;" {} \; + + +# Manual changes required: +# +# Some callbacks no longer exist, their name will be "removed", remove them +# +# This script may create build errors in your application, especially if you defined methods that have the same name as methods +# of the linphone SDK. For example, with the Linphone application we get errors for the enableAVPF(int n, boolean enabled) method of +# LinphonePreferences that is wrongly replaced into setAVPFMode(AVPFMode.Enabled)int n, boolean enabled). +# +# You may need to import some classes, eg. AccountCreatorListener, AVPFMode, Call, ChatMessageListener, ConfiguringState, LimeState, +# MediaEncryption, RegistrationState, StreamType, VideoDefinition, XmlRpcArgType... +# +# If you are using the LinphoneContact class, some getVcard() method may have been wrongly introduced by this script that you will need +# to delete. +# +# Some methods that used to take or return String or LinphoneAddress now take the other +# +# createAddress, addAddress, addFriend, acceptCall, acceptCallWithParams no longer throw a CoreException +# +# AccountCreator's Status.Ok must be renamed in Status.RequestOk +# +# VideoDevices were int, now are String +# +# XmlRpcSessionImpl => XmlRpcSession +# +# getFriendsLists() returned Friend[], now is a FriendList[] +# +# No need anymore to cast to a Impl class to be able to use setUserData or getUserData +# +# findFriend now takes an Address instead of a String +# +# createOpenH264DownloadHelper() now takes a Context +# +# Factory.createCore(this, mConfigFile, mLinphoneFactoryConfigFile, null, c) => createCore(this, mConfigFile, mLinphoneFactoryConfigFile) +# +# startEchoTester and stopEchoTester now return void +# +# createProxyConfig no longer takes any parameter +# +# setPrimaryContact only takes one String argument +# +# AdaptiveRateAlgorithm was an enum, now is replaced by a String in the methods that were using it +# +# createAddress(userName,domain,null); no longer exists +# +# Buffer.setContent now takes the size as second parameter +# +# ChatMessageListener onFileTransferSend now returns the Buffer instead of having it as part of his arguments +# +# Core.startEchoCancellerCalibration no longer takes a parameter +# +# XmlRpcSession.createRequest takes first the return arg type and then the name of the method, until now it was the other way around +# +# ProxyConfig.normalizePhoneNumber returns null if it fails instead of the value given as parameter in the previous version! +# +# ChatMessage.getStorageId() no longer exists +# +# ChatRoom.getHistory() no needs an integer parameter corresponding to the number of messages to get (use 0 to get the full history) +# +# Factory.createContent() no longer takes arguments. Use the Content methods to fill the content. +# +# AccountCreator.updatePassword() no longer exist. Use setPassword() and updateAccount() instead. + +# # Factory +#Factory.createAccountCreator() => Core.createAccountCreator() +#Factory.createPresenceModel() => Core.createPresenceModel() & PresenceModel.setActivity() +#Factory.instance().enableLogCollection(isDebugEnabled); now takes a LogCollectionState + +# # Core +#Core.getVideoDevice and Core.setVideoDevice now takes/returns String instead of int +#Core.getSupportedVideoSizes() => Factory.getSupportedVideoDefinitions() +#Core.removeFriend() => FriendList.removeFriend() +#Core.getFriendsLists() => now returns a FriendList[] instead of a Friend[] +#Core.enableSpeaker / isSpeakerEnabled() => mAudioManager.setSpeakerphoneOn(speakerOn); +#Core.enableVideo(true, true) => Core.enableVideoCapture(bool) & Core.enableVideoDisplay(bool) +#Core.setVideoPolicy(initiate, accept) => Core.getVideoActivationPolicy().setAutomaticallyInitiate(initiate) & Core.getVideoActivationPolicy().setAutomaticallyAccept(accept) + +# # Other +#CallParams.getJitterBufferSize() => CallStatsImpl.getJitterBufferSizeMs() +#Core.findAuthInfo was (username, realm, domain) now is (realm, username, domain) + +# # Payloads +#Core.enablePayloadType() => PayloadType.enable() +#Core.isPayloadTypeEnabled() => PayloadType.enabled() +#Core.payloadTypeIsVbr() => PayloadType.isVbr() +#Core.setPayloadTypeBitrate() => PayloadType.setNormalBitrate() diff --git a/wrappers/java/proguard.mustache b/wrappers/java/proguard.mustache new file mode 100644 index 000000000..65dd2ed12 --- /dev/null +++ b/wrappers/java/proguard.mustache @@ -0,0 +1,30 @@ +# Don't warn stuff that we are not "proguarding", warnings would make the build fail. +-dontwarn org.linphone.** + +# The following interfaces and classes are referenced from JNI +{{#classes}} +-keep interface {{package}}.{{className}} {*;} +-keep class {{package}}.{{classImplName}} {*;} +{{/classes}} + +# The following enums are referenced from JNI +{{#enums}} +-keep class {{package}}.{{className}} {*;} +{{/enums}} + +# The following listeners are referenced from JNI +{{#listeners}} +-keep class {{package}}.{{className}} {*;} +{{/listeners}} + +# Liblinphone tools +-keep class org.linphone.core.tools.* {*;} + +# Mediastreamer classes +-keep class org.linphone.mediastream.Factory {*;} +-keep class org.linphone.mediastream.MediastreamerAndroidContext {*;} +-keep class org.linphone.mediastream.video.capture.AndroidVideoApi9JniWrapper {*;} +-keep class org.linphone.mediastream.video.capture.AndroidVideoApi8JniWrapper {*;} +-keep class org.linphone.mediastream.video.capture.AndroidVideoApi5JniWrapper {*;} +-keep class org.linphone.mediastream.video.AndroidVideoWindowImpl {*;} +-keep class org.linphone.mediastream.Version {*;}